[llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInstrSelection.cpp

Vikram Adve vadve at cs.uiuc.edu
Wed Aug 6 13:49:01 PDT 2003


Changes in directory llvm/lib/Target/Sparc:

SparcInstrSelection.cpp updated: 1.111 -> 1.112

---
Log message:

1. Bug fix: was using SLL instead of SLLX for ULongTy.  Chump.
2. Handle fp-to-uint conversions directly here instead of relying on
   a pre-transformation to replace them with the 2-step conversion.
3. Use size rather than explicitly checking types when deciding what
   opcodes to use, wherever possible.  This is less error prone (the
   bug fix above was not the first time!).
4. Float-to-pointer casts shd now work though this hasn't been tested.


---
Diffs of the changes:

Index: llvm/lib/Target/Sparc/SparcInstrSelection.cpp
diff -u llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.111 llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.112
--- llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.111	Tue Aug  5 11:59:24 2003
+++ llvm/lib/Target/Sparc/SparcInstrSelection.cpp	Wed Aug  6 13:48:40 2003
@@ -493,64 +493,66 @@
 
 
 static inline MachineOpCode
-ChooseConvertToFloatInstr(OpLabel vopCode, const Type* opType)
+ChooseConvertToFloatInstr(const TargetMachine& target,
+                          OpLabel vopCode, const Type* opType)
 {
   assert((vopCode == ToFloatTy || vopCode == ToDoubleTy) &&
          "Unrecognized convert-to-float opcode!");
+  assert((opType->isIntegral() || opType->isFloatingPoint() ||
+          isa<PointerType>(opType))
+         && "Trying to convert a non-scalar type to FLOAT/DOUBLE?");
 
   MachineOpCode opCode = V9::INVALID_OPCODE;
-  
-  if (opType == Type::SByteTy || opType == Type::UByteTy ||
-      opType == Type::ShortTy || opType == Type::UShortTy ||
-      opType == Type::IntTy   || opType == Type::UIntTy)
-      opCode = (vopCode == ToFloatTy? V9::FITOS : V9::FITOD);
-  else if (opType == Type::LongTy || opType == Type::ULongTy ||
-           isa<PointerType>(opType))
-      opCode = (vopCode == ToFloatTy? V9::FXTOS : V9::FXTOD);
-  else if (opType == Type::FloatTy)
-      opCode = (vopCode == ToFloatTy? V9::INVALID_OPCODE : V9::FSTOD);
+
+  unsigned opSize = target.getTargetData().getTypeSize(opType);
+
+  if (opType == Type::FloatTy)
+    opCode = (vopCode == ToFloatTy? V9::NOP : V9::FSTOD);
   else if (opType == Type::DoubleTy)
-      opCode = (vopCode == ToFloatTy? V9::FDTOS : V9::INVALID_OPCODE);
-  else
-    assert(0 && "Trying to convert a non-scalar type to DOUBLE?");
+    opCode = (vopCode == ToFloatTy? V9::FDTOS : V9::NOP);
+  else if (opSize <= 4)
+    opCode = (vopCode == ToFloatTy? V9::FITOS : V9::FITOD);
+  else {
+    assert(opSize == 8 && "Unrecognized type size > 4 and < 8!");
+    opCode = (vopCode == ToFloatTy? V9::FXTOS : V9::FXTOD);
+  }
   
   return opCode;
 }
 
 static inline MachineOpCode 
-ChooseConvertFPToIntInstr(Type::PrimitiveID tid, const Type* opType)
+ChooseConvertFPToIntInstr(const TargetMachine& target,
+                          const Type* destType, const Type* opType)
 {
-  MachineOpCode opCode = V9::INVALID_OPCODE;;
-
   assert((opType == Type::FloatTy || opType == Type::DoubleTy)
          && "This function should only be called for FLOAT or DOUBLE");
+  assert((destType->isIntegral() || isa<PointerType>(destType))
+         && "Trying to convert FLOAT/DOUBLE to a non-scalar type?");
 
-  // SPARC does not have a float-to-uint conversion, only a float-to-int.
-  // For converting an FP value to uint32_t, we first need to convert to
-  // uint64_t and then to uint32_t, or we may overflow the signed int
-  // representation even for legal uint32_t values.  This expansion is
-  // done by the Preselection pass.
-  // 
-  if (tid == Type::UIntTyID) {
-    assert(tid != Type::UIntTyID && "FP-to-uint conversions must be expanded"
-           " into FP->long->uint for SPARC v9:  SO RUN PRESELECTION PASS!");
-  } else if (tid == Type::SByteTyID || tid == Type::ShortTyID || 
-             tid == Type::IntTyID   || tid == Type::UByteTyID ||
-             tid == Type::UShortTyID) {
+  MachineOpCode opCode = V9::INVALID_OPCODE;
+
+  unsigned destSize = target.getTargetData().getTypeSize(destType);
+
+  if (destType == Type::UIntTy)
+    assert(destType != Type::UIntTy && "Expand FP-to-uint beforehand.");
+  else if (destSize <= 4)
     opCode = (opType == Type::FloatTy)? V9::FSTOI : V9::FDTOI;
-  } else if (tid == Type::LongTyID || tid == Type::ULongTyID) {
-      opCode = (opType == Type::FloatTy)? V9::FSTOX : V9::FDTOX;
-  } else
-    assert(0 && "Should not get here, Mo!");
+  else {
+    assert(destSize == 8 && "Unrecognized type size > 4 and < 8!");
+    opCode = (opType == Type::FloatTy)? V9::FSTOX : V9::FDTOX;
+  }
 
   return opCode;
 }
 
-MachineInstr*
-CreateConvertFPToIntInstr(Type::PrimitiveID destTID,
-                          Value* srcVal, Value* destVal)
+static MachineInstr*
+CreateConvertFPToIntInstr(const TargetMachine& target,
+                          Value* srcVal,
+                          Value* destVal,
+                          const Type* destType)
 {
-  MachineOpCode opCode = ChooseConvertFPToIntInstr(destTID, srcVal->getType());
+  MachineOpCode opCode = ChooseConvertFPToIntInstr(target, destType,
+                                                   srcVal->getType());
   assert(opCode != V9::INVALID_OPCODE && "Expected to need conversion!");
   return BuildMI(opCode, 2).addReg(srcVal).addRegDef(destVal);
 }
@@ -558,19 +560,11 @@
 // CreateCodeToConvertFloatToInt: Convert FP value to signed or unsigned integer
 // The FP value must be converted to the dest type in an FP register,
 // and the result is then copied from FP to int register via memory.
-//
+// SPARC does not have a float-to-uint conversion, only a float-to-int (fdtoi).
 // Since fdtoi converts to signed integers, any FP value V between MAXINT+1
-// and MAXUNSIGNED (i.e., 2^31 <= V <= 2^32-1) would be converted incorrectly
-// *only* when converting to an unsigned.  (Unsigned byte, short or long
-// don't have this problem.)
-// For unsigned int, we therefore have to generate the code sequence:
-// 
-//      if (V > (float) MAXINT) {
-//        unsigned result = (unsigned) (V  - (float) MAXINT);
-//        result = result + (unsigned) MAXINT;
-//      }
-//      else
-//        result = (unsigned) V;
+// and MAXUNSIGNED (i.e., 2^31 <= V <= 2^32-1) would be converted incorrectly.
+// Therefore, for converting an FP value to uint32_t, we first need to convert
+// to uint64_t and then to uint32_t.
 // 
 static void
 CreateCodeToConvertFloatToInt(const TargetMachine& target,
@@ -579,24 +573,46 @@
                               std::vector<MachineInstr*>& mvec,
                               MachineCodeForInstruction& mcfi)
 {
+  Function* F = destI->getParent()->getParent();
+
   // Create a temporary to represent the FP register into which the
   // int value will placed after conversion.  The type of this temporary
   // depends on the type of FP register to use: single-prec for a 32-bit
   // int or smaller; double-prec for a 64-bit int.
   // 
   size_t destSize = target.getTargetData().getTypeSize(destI->getType());
-  const Type* destTypeToUse = (destSize > 4)? Type::DoubleTy : Type::FloatTy;
-  TmpInstruction* destForCast = new TmpInstruction(mcfi, destTypeToUse, opVal);
 
-  // Create the fp-to-int conversion code
-  MachineInstr* M =CreateConvertFPToIntInstr(destI->getType()->getPrimitiveID(),
-                                             opVal, destForCast);
-  mvec.push_back(M);
+  const Type* castDestType = destI->getType(); // type for the cast instr result
+  const Type* castDestRegType;          // type for cast instruction result reg
+  TmpInstruction* destForCast;          // dest for cast instruction
+  Instruction* fpToIntCopyDest = destI; // dest for fp-reg-to-int-reg copy instr
+
+  // For converting an FP value to uint32_t, we first need to convert to
+  // uint64_t and then to uint32_t, as explained above.
+  if (destI->getType() == Type::UIntTy) {
+    castDestType    = Type::ULongTy;       // use this instead of type of destI
+    castDestRegType = Type::DoubleTy;      // uint64_t needs 64-bit FP register.
+    destForCast     = new TmpInstruction(mcfi, castDestRegType, opVal);
+    fpToIntCopyDest = new TmpInstruction(mcfi, castDestType, destForCast);
+  }
+  else {
+    castDestRegType = (destSize > 4)? Type::DoubleTy : Type::FloatTy;
+    destForCast = new TmpInstruction(mcfi, castDestRegType, opVal);
+  }
+
+  // Create the fp-to-int conversion instruction (src and dest regs are FP regs)
+  mvec.push_back(CreateConvertFPToIntInstr(target, opVal, destForCast,
+                                           castDestType));
 
   // Create the fpreg-to-intreg copy code
-  target.getInstrInfo().
-    CreateCodeToCopyFloatToInt(target, destI->getParent()->getParent(),
-                               destForCast, destI, mvec, mcfi);
+  target.getInstrInfo().CreateCodeToCopyFloatToInt(target, F, destForCast,
+                                                   fpToIntCopyDest, mvec, mcfi);
+
+  // Create the uint64_t to uint32_t conversion, if needed
+  if (destI->getType() == Type::UIntTy)
+    target.getInstrInfo().
+      CreateZeroExtensionInstructions(target, F, fpToIntCopyDest, destI,
+                                      /*numLowBits*/ 32, mvec, mcfi);
 }
 
 
@@ -992,6 +1008,7 @@
       } else if (isPowerOf2(C, pow)) {
         unsigned opCode;
         Value* shiftOperand;
+        unsigned opSize = target.getTargetData().getTypeSize(resultType);
 
         if (resultType->isSigned()) {
           // For N / 2^k, if the operand N is negative,
@@ -1020,15 +1037,13 @@
           addTmp = new TmpInstruction(mcfi, resultType, LHS, srlTmp,"incIfNeg");
 
           // Create the SRA or SRAX instruction to get the sign bit
-          mvec.push_back(BuildMI((resultType==Type::LongTy) ?
-                                 V9::SRAXi6 : V9::SRAi5, 3)
+          mvec.push_back(BuildMI((opSize > 4)? V9::SRAXi6 : V9::SRAi5, 3)
                          .addReg(LHS)
                          .addSImm((resultType==Type::LongTy)? pow-1 : 31)
                          .addRegDef(sraTmp));
 
           // Create the SRL or SRLX instruction to get the sign bit
-          mvec.push_back(BuildMI((resultType==Type::LongTy) ?
-                                 V9::SRLXi6 : V9::SRLi5, 3)
+          mvec.push_back(BuildMI((opSize > 4)? V9::SRLXi6 : V9::SRLi5, 3)
                          .addReg(sraTmp)
                          .addSImm((resultType==Type::LongTy)? 64-pow : 32-pow)
                          .addRegDef(srlTmp));
@@ -1039,11 +1054,11 @@
 
           // Get the shift operand and "right-shift" opcode to do the divide
           shiftOperand = addTmp;
-          opCode = (resultType==Type::LongTy) ? V9::SRAXi6 : V9::SRAi5;
+          opCode = (opSize > 4)? V9::SRAXi6 : V9::SRAi5;
         } else {
           // Get the shift operand and "right-shift" opcode to do the divide
           shiftOperand = LHS;
-          opCode = (resultType==Type::LongTy) ? V9::SRLXi6 : V9::SRLi5;
+          opCode = (opSize > 4)? V9::SRLXi6 : V9::SRLi5;
         }
 
         // Now do the actual shift!
@@ -1860,7 +1875,7 @@
         } else if (opType->isFloatingPoint()) {
 
           CreateCodeToConvertFloatToInt(target, opVal, destI, mvec, mcfi);
-          if (destI->getType()->isUnsigned())
+          if (destI->getType()->isUnsigned() && destI->getType() !=Type::UIntTy)
             maskUnsignedResult = true; // not handled by fp->int code
 
         } else if (isIntegral) {
@@ -1928,9 +1943,9 @@
         if (forwardOperandNum != 0) {    // we do need the cast
           Value* leftVal = subtreeRoot->leftChild()->getValue();
           const Type* opType = leftVal->getType();
-          MachineOpCode opCode=ChooseConvertToFloatInstr(
+          MachineOpCode opCode=ChooseConvertToFloatInstr(target,
                                        subtreeRoot->getOpLabel(), opType);
-          if (opCode == V9::INVALID_OPCODE) {  // no conversion needed
+          if (opCode == V9::NOP) {      // no conversion needed
             forwardOperandNum = 0;      // forward first operand to user
           } else {
             // If the source operand is a non-FP type it must be
@@ -2753,9 +2768,10 @@
         const Type* opType = argVal1->getType();
         assert((opType->isInteger() || isa<PointerType>(opType)) &&
                "Shl unsupported for other types");
+        unsigned opSize = target.getTargetData().getTypeSize(opType);
         
         CreateShiftInstructions(target, shlInstr->getParent()->getParent(),
-                                (opType == Type::LongTy)? V9::SLLXr6:V9::SLLr5,
+                                (opSize > 4)? V9::SLLXr6:V9::SLLr5,
                                 argVal1, argVal2, 0, shlInstr, mvec,
                                 MachineCodeForInstruction::get(shlInstr));
         break;
@@ -2766,9 +2782,10 @@
         const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
         assert((opType->isInteger() || isa<PointerType>(opType)) &&
                "Shr unsupported for other types");
+        unsigned opSize = target.getTargetData().getTypeSize(opType);
         Add3OperandInstr(opType->isSigned()
-                         ? (opType == Type::LongTy ? V9::SRAXr6 : V9::SRAr5)
-                         : (opType == Type::ULongTy ? V9::SRLXr6 : V9::SRLr5),
+                         ? (opSize > 4? V9::SRAXr6 : V9::SRAr5)
+                         : (opSize > 4? V9::SRLXr6 : V9::SRLr5),
                          subtreeRoot, mvec);
         break;
       }





More information about the llvm-commits mailing list