[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