Support add, sub, mul, div, rem on longs/ulongs (latter 3 by emitting libcalls).
Add a big comment containing my notes on how to do setcc for longs/ulongs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18086 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/Sparc/SparcV8ISelSimple.cpp b/lib/Target/Sparc/SparcV8ISelSimple.cpp
index eab7dd6..cb39503 100644
--- a/lib/Target/Sparc/SparcV8ISelSimple.cpp
+++ b/lib/Target/Sparc/SparcV8ISelSimple.cpp
@@ -86,6 +86,10 @@
BB = MBBMap[&LLVM_BB];
}
+ void emitOp64LibraryCall (MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator IP,
+ unsigned DestReg, const char *FuncName,
+ unsigned Op0Reg, unsigned Op1Reg);
void visitBinaryOperator(Instruction &I);
void visitShiftInst (ShiftInst &SI) { visitBinaryOperator (SI); }
void visitSetCondInst(SetCondInst &I);
@@ -1091,6 +1095,19 @@
I.op_begin ()+1, I.op_end (), outputReg);
}
+void V8ISel::emitOp64LibraryCall (MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator IP,
+ unsigned DestReg,
+ const char *FuncName,
+ unsigned Op0Reg, unsigned Op1Reg) {
+ BuildMI (*MBB, IP, V8::ORrr, 2, V8::O0).addReg (V8::G0).addReg (Op0Reg);
+ BuildMI (*MBB, IP, V8::ORrr, 2, V8::O1).addReg (V8::G0).addReg (Op0Reg+1);
+ BuildMI (*MBB, IP, V8::ORrr, 2, V8::O2).addReg (V8::G0).addReg (Op1Reg);
+ BuildMI (*MBB, IP, V8::ORrr, 2, V8::O3).addReg (V8::G0).addReg (Op1Reg+1);
+ BuildMI (*MBB, IP, V8::CALL, 1).addExternalSymbol (FuncName, true);
+ BuildMI (*MBB, IP, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (V8::O0);
+ BuildMI (*MBB, IP, V8::ORrr, 2, DestReg+1).addReg (V8::G0).addReg (V8::O1);
+}
void V8ISel::visitBinaryOperator (Instruction &I) {
unsigned DestReg = getReg (I);
@@ -1122,11 +1139,36 @@
ResultReg = makeAnotherReg (I.getType ());
if (Class == cLong) {
+ const char *FuncName;
DEBUG (std::cerr << "Class = cLong\n");
DEBUG (std::cerr << "Op0Reg = " << Op0Reg << ", " << Op0Reg+1 << "\n");
DEBUG (std::cerr << "Op1Reg = " << Op1Reg << ", " << Op1Reg+1 << "\n");
DEBUG (std::cerr << "ResultReg = " << ResultReg << ", " << ResultReg+1 << "\n");
DEBUG (std::cerr << "DestReg = " << DestReg << ", " << DestReg+1 << "\n");
+ switch (I.getOpcode ()) {
+ case Instruction::Add:
+ BuildMI (BB, V8::ADDCCrr, 2, ResultReg+1).addReg (Op0Reg+1)
+ .addReg (Op1Reg+1);
+ BuildMI (BB, V8::ADDXrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
+ return;
+ case Instruction::Sub:
+ BuildMI (BB, V8::SUBCCrr, 2, ResultReg+1).addReg (Op0Reg+1)
+ .addReg (Op1Reg+1);
+ BuildMI (BB, V8::SUBXrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
+ return;
+ case Instruction::Mul:
+ FuncName = I.getType ()->isSigned () ? "__mul64" : "__umul64";
+ emitOp64LibraryCall (BB, BB->end (), DestReg, FuncName, Op0Reg, Op1Reg);
+ return;
+ case Instruction::Div:
+ FuncName = I.getType ()->isSigned () ? "__div64" : "__udiv64";
+ emitOp64LibraryCall (BB, BB->end (), DestReg, FuncName, Op0Reg, Op1Reg);
+ return;
+ case Instruction::Rem:
+ FuncName = I.getType ()->isSigned () ? "__rem64" : "__urem64";
+ emitOp64LibraryCall (BB, BB->end (), DestReg, FuncName, Op0Reg, Op1Reg);
+ return;
+ }
}
// FIXME: support long, ulong.
@@ -1204,7 +1246,7 @@
// Nothing to do here.
break;
case cLong:
- // Only support and, or, xor.
+ // Only support and, or, xor here - others taken care of above.
if (OpCase < 3 || OpCase > 5) {
visitInstruction (I);
return;
@@ -1225,9 +1267,30 @@
const Type *Ty = I.getOperand (0)->getType ();
// Compare the two values.
- assert (getClass (Ty) != cLong && "can't setcc on longs yet");
if (getClass (Ty) < cLong) {
BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
+ } else if (getClass (Ty) == cLong) {
+ // Here is one way to open-code each of the setccs for SIGNED longs...
+ // I haven't checked it yet, but you *should* be able to just switch
+ // bl/bg/ble/bge with bcs/bgu/bleu/bcc to get the version for
+ // unsigned longs.
+ // setlt/setge subcc %left_1, %right_1, %g0
+ // ^^^^^^^^^^^ subxcc %left_0, %right_0, %g0
+ // bl/bge (as with ordinary setcc)
+ // setle/setgt subcc %g0, 1, %g0
+ // ^^^^^^^^^^^ subxcc %left_1, %right_1, %g0
+ // subxcc %left_0, %right_0, %g0
+ // ble/bg (as with ordinary setcc)
+ // seteq/setne xor %left_1, %right_1, %temp_0
+ // ^^^^^^^^^^^ xor %left_0, %right_0, %temp_1
+ // subcc %g0, %temp_1, %g0
+ // seteq setne
+ // ^^^^^ ^^^^^
+ // subx %g0, -1, %temp_2 addx %g0, 0, %temp_2
+ // subcc %g0, %temp_0, %g0
+ // subx %g0, -1, %temp_3 addx %g0, 0, %temp_3
+ // and %temp_2, %temp_3, %result or %temp_2, %temp_3, %result
+ assert (0 && "can't setcc on longs yet");
} else if (getClass (Ty) == cFloat) {
BuildMI(BB, V8::FCMPS, 2).addReg(Op0Reg).addReg(Op1Reg);
} else if (getClass (Ty) == cDouble) {