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

Vikram Adve vadve at cs.uiuc.edu
Sun May 25 17:00:00 PDT 2003


Changes in directory llvm/lib/Target/Sparc:

SparcInstrSelection.cpp updated: 1.92 -> 1.93

---
Log message:

Bug fix: right shift for int divide-by-power-of-2 was incorrect for
negative values.  Need to add one to a negative value before right shift!


---
Diffs of the changes:

Index: llvm/lib/Target/Sparc/SparcInstrSelection.cpp
diff -u llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.92 llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.93
--- llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.92	Sun May 25 10:59:47 2003
+++ llvm/lib/Target/Sparc/SparcInstrSelection.cpp	Sun May 25 16:59:47 2003
@@ -774,7 +774,7 @@
 // create a cheaper instruction.
 // This returns the approximate cost of the instructions generated,
 // which is used to pick the cheapest when both operands are constant.
-static inline unsigned
+static unsigned
 CreateMulConstInstruction(const TargetMachine &target, Function* F,
                           Value* lval, Value* rval, Instruction* destVal,
                           std::vector<MachineInstr*>& mvec,
@@ -927,7 +927,7 @@
 
 
 // Return if we cannot exploit constant to create a cheaper instruction
-static inline void
+static void
 CreateDivConstInstruction(TargetMachine &target,
                           const InstructionNode* instrNode,
                           std::vector<MachineInstr*>& mvec)
@@ -937,7 +937,7 @@
   if (!isa<Constant>(constOp))
     return;
 
-  Value* DestVal = instrNode->getValue();
+  Instruction* destVal = instrNode->getInstruction();
   unsigned ZeroReg = target.getRegInfo().getZeroRegNum();
   
   // Cases worth optimizing are:
@@ -960,18 +960,55 @@
           
       if (C == 1) {
         mvec.push_back(BuildMI(V9::ADD, 3).addReg(LHS).addMReg(ZeroReg)
-                       .addRegDef(DestVal));
+                       .addRegDef(destVal));
       } else if (isPowerOf2(C, pow)) {
-        unsigned opCode= ((resultType->isSigned())
-                          ? (resultType==Type::LongTy) ? V9::SRAX : V9::SRA
-                          : (resultType==Type::LongTy) ? V9::SRLX : V9::SRL);
-        mvec.push_back(BuildMI(opCode, 3).addReg(LHS).addZImm(pow)
-                       .addRegDef(DestVal));
+        unsigned opCode;
+        Value* shiftOperand;
+
+        if (resultType->isSigned()) {
+          // The result may be negative and we need to add one before shifting 
+          // a negative value.  Use:
+          //      srl i0, 31, x0; add x0, i0, i1         (if i0 is <= 32 bits)
+          // or
+          //      srlx i0, 63, x0; add x0, i0, i1         (if i0 is 64 bits)
+          // to compute i1=i0+1 if i0 < 0 and i1=i0 otherwise.  
+          // 
+          TmpInstruction *srlTmp, *addTmp;
+          MachineCodeForInstruction& mcfi
+            = MachineCodeForInstruction::get(destVal);
+          srlTmp = new TmpInstruction(resultType, LHS, 0, "getSign");
+          addTmp = new TmpInstruction(resultType, LHS, srlTmp, "incIfNeg");
+          mcfi.addTemp(srlTmp);
+          mcfi.addTemp(addTmp);
+
+          // Create the SRL or SRLX instruction to get the sign bit
+          mvec.push_back(BuildMI((resultType==Type::LongTy)? V9::SRLX:V9::SRL,3)
+                         .addReg(LHS)
+                         .addSImm((resultType==Type::LongTy)? 63 : 31)
+                         .addRegDef(srlTmp));
+
+          // Create the ADD instruction to add 1 for negative values
+          mvec.push_back(BuildMI(V9::ADD, 3).addReg(LHS).addReg(srlTmp)
+                         .addRegDef(addTmp));
+
+          // Get the shift operand and "right-shift" opcode to do the divide
+          shiftOperand = addTmp;
+          opCode = (resultType==Type::LongTy) ? V9::SRAX : V9::SRA;
+        }
+        else {
+          // Get the shift operand and "right-shift" opcode to do the divide
+          shiftOperand = LHS;
+          opCode = (resultType==Type::LongTy) ? V9::SRLX : V9::SRL;
+        }
+
+        // Now do the actual shift!
+        mvec.push_back(BuildMI(opCode, 3).addReg(shiftOperand).addZImm(pow)
+                       .addRegDef(destVal));
       }
           
       if (needNeg && (C == 1 || isPowerOf2(C, pow))) {
         // insert <reg = SUB 0, reg> after the instr to flip the sign
-        mvec.push_back(CreateIntNegInstruction(target, DestVal));
+        mvec.push_back(CreateIntNegInstruction(target, destVal));
       }
     }
   } else {
@@ -982,7 +1019,7 @@
           (dval < 0) ? (resultType == Type::FloatTy? V9::FNEGS : V9::FNEGD)
           : (resultType == Type::FloatTy? V9::FMOVS : V9::FMOVD);
               
-        mvec.push_back(BuildMI(opCode, 2).addReg(LHS).addRegDef(DestVal));
+        mvec.push_back(BuildMI(opCode, 2).addReg(LHS).addRegDef(destVal));
       } 
     }
   }





More information about the llvm-commits mailing list