-- Use size of pointer element type instead of pointer type in array offsets!
authorVikram S. Adve <vadve@cs.uiuc.edu>
Thu, 5 Sep 2002 18:32:13 +0000 (18:32 +0000)
committerVikram S. Adve <vadve@cs.uiuc.edu>
Thu, 5 Sep 2002 18:32:13 +0000 (18:32 +0000)
-- A few bug fixes in casting between floats and ints.
-- Use SRL reg, 0 instead of AND reg, 0xffffffff to clear high 32 bits.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3579 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/SparcV9/SparcV9InstrSelection.cpp

index a68331b53ed3ca15dfcf838218857c4111d6ded3..368afbb4ec9725ae23bfaa0f3b5ca68b2f602304 100644 (file)
@@ -319,6 +319,20 @@ CreateConvertToIntInstr(Type::PrimitiveID destTID, Value* srcVal,Value* destVal)
 // 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.
+//
+// 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 int.  (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 int) V;
+// 
 static void
 CreateCodeToConvertFloatToInt(const TargetMachine& target,
                               Value* opVal,
@@ -331,9 +345,9 @@ CreateCodeToConvertFloatToInt(const TargetMachine& target,
   // 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.
   // 
-  const Type* destTypeToUse = (destI->getType() == Type::LongTy)? Type::DoubleTy
-                                                                : Type::FloatTy;
-  Value* destForCast = new TmpInstruction(destTypeToUse, opVal);
+  size_t destSize = target.DataLayout.getTypeSize(destI->getType());
+  const Type* destTypeToUse = (destSize > 4)? Type::DoubleTy : Type::FloatTy;
+  TmpInstruction* destForCast = new TmpInstruction(destTypeToUse, opVal);
   mcfi.addTemp(destForCast);
 
   // Create the fp-to-int conversion code
@@ -344,7 +358,7 @@ CreateCodeToConvertFloatToInt(const TargetMachine& target,
   // Create the fpreg-to-intreg copy code
   target.getInstrInfo().
     CreateCodeToCopyFloatToInt(target, destI->getParent()->getParent(),
-                               (TmpInstruction*)destForCast, destI, mvec, mcfi);
+                               destForCast, destI, mvec, mcfi);
 }
 
 
@@ -990,28 +1004,34 @@ SetOperandsForMemInstr(vector<MachineInstr*>& mvec,
           // offset.  (An extra leading zero offset, if any, can be ignored.)
           // Generate code sequence to compute address from index.
           // 
-          assert(idxVec.size() == 1U + IsZero(idxVec[0])
+          bool firstIdxIsZero = IsZero(idxVec[0]);
+          assert(idxVec.size() == 1U + firstIdxIsZero 
                  && "Array refs must be lowered before Instruction Selection");
 
-          Value* idxVal = idxVec[IsZero(idxVec[0])];
+          Value* idxVal = idxVec[firstIdxIsZero];
           assert(! isa<Constant>(idxVal) && "Need to sign-extend uint to 64b!");
 
           vector<MachineInstr*> mulVec;
           Instruction* addr = new TmpInstruction(Type::UIntTy, memInst);
           MachineCodeForInstruction::get(memInst).addTemp(addr);
 
+          // Get the array type indexed by idxVal, and compute its element size.
           // The call to getTypeSize() will fail if size is not constant.
-          unsigned int eltSize =
-            target.DataLayout.getTypeSize(ptrType->getElementType());
-          assert(eltSize > 0 && "Invalid or non-const array element size");
-          ConstantUInt* eltVal = ConstantUInt::get(Type::UIntTy, eltSize);
+          const Type* vecType = (firstIdxIsZero
+                                 ? GetElementPtrInst::getIndexedType(ptrType,
+                                           std::vector<Value*>(1U, idxVec[0]),
+                                           /*AllowCompositeLeaf*/ true)
+                                 : ptrType);
+          const Type* eltType = cast<SequentialType>(vecType)->getElementType();
+          ConstantUInt* eltSizeVal = ConstantUInt::get(Type::UIntTy,
+                                       target.DataLayout.getTypeSize(eltType));
 
           // CreateMulInstruction() folds constants intelligently enough.
           CreateMulInstruction(target,
                                memInst->getParent()->getParent(),
-                               idxVal,         /* lval, not likely const */
-                               eltVal,         /* rval, likely constant */
-                               addr,           /* result*/
+                               idxVal,         /* lval, not likely to be const*/
+                               eltSizeVal,     /* rval, likely to be constant */
+                               addr,           /* result */
                                mulVec,
                                MachineCodeForInstruction::get(memInst),
                                INVALID_MACHINE_OPCODE);
@@ -1531,11 +1551,11 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
 
         break;
       }  
-      
+
       case  31:        // reg:   ToFloatTy(reg):
       case  32:        // reg:   ToDoubleTy(reg):
       case 232:        // reg:   ToDoubleTy(Constant):
-        
+
         // If this instruction has a parent (a user) in the tree 
         // and the user is translated as an FsMULd instruction,
         // then the cast is unnecessary.  So check that first.
@@ -1572,18 +1592,18 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
                     // register used: single-prec for a 32-bit int or smaller,
                     // double-prec for a 64-bit int.
                     // 
-                    const Type* srcTypeToUse =
-                      (leftVal->getType() == Type::LongTy)? Type::DoubleTy
-                                                          : Type::FloatTy;
-                    
-                    srcForCast = new TmpInstruction(srcTypeToUse, dest);
+                    uint64_t srcSize =
+                      target.DataLayout.getTypeSize(leftVal->getType());
+                    Type* tmpTypeToUse =
+                      (srcSize <= 4)? Type::FloatTy : Type::DoubleTy;
+                    srcForCast = new TmpInstruction(tmpTypeToUse, dest);
                     MachineCodeForInstruction &destMCFI = 
                       MachineCodeForInstruction::get(dest);
                     destMCFI.addTemp(srcForCast);
-                    
+
                     target.getInstrInfo().CreateCodeToCopyIntToFloat(target,
                          dest->getParent()->getParent(),
-                         leftVal, (TmpInstruction*) srcForCast,
+                         leftVal, cast<Instruction>(srcForCast),
                          mvec, destMCFI);
                   }
                 else
@@ -2150,7 +2170,7 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
       if (dest->getType()->isUnsigned())
         {
           unsigned destSize = target.DataLayout.getTypeSize(dest->getType());
-          if (destSize < target.DataLayout.getIntegerRegize())
+          if (destSize <= 4)
             { // Mask high bits.  Use a TmpInstruction to represent the
               // intermediate result before masking.  Since those instructions
               // have already been generated, go back and substitute tmpI
@@ -2162,12 +2182,11 @@ GetInstructionsByRule(InstructionNode* subtreeRoot,
               for (unsigned i=0, N=mvec.size(); i < N; ++i)
                 mvec[i]->substituteValue(dest, tmpI);
 
-              M = Create3OperandInstr(AND, tmpI,
-                                      ConstantUInt::get(Type::ULongTy,
-                                              ((uint64_t) 1 << 8*destSize) - 1),
-                                      dest);
+              M = Create3OperandInstr_UImmed(SRL, tmpI, 4-destSize, dest);
               mvec.push_back(M);
             }
+          else if (destSize < target.DataLayout.getIntegerRegize())
+            assert(0 && "Unsupported type size: 32 < size < 64 bits");
         }
     }
 }