[llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp X86InstrInfo.def
Chris Lattner
lattner at cs.uiuc.edu
Thu Nov 7 12:00:02 PST 2002
Changes in directory llvm/lib/Target/X86:
InstSelectSimple.cpp updated: 1.21 -> 1.22
X86InstrInfo.def updated: 1.12 -> 1.13
---
Log message:
Add instruction selection code and tests for setcc instructions
---
Diffs of the changes:
Index: llvm/lib/Target/X86/InstSelectSimple.cpp
diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.21 llvm/lib/Target/X86/InstSelectSimple.cpp:1.22
--- llvm/lib/Target/X86/InstSelectSimple.cpp:1.21 Sat Nov 2 14:54:46 2002
+++ llvm/lib/Target/X86/InstSelectSimple.cpp Thu Nov 7 11:59:21 2002
@@ -8,6 +8,7 @@
#include "X86InstrInfo.h"
#include "llvm/Function.h"
#include "llvm/iTerminators.h"
+#include "llvm/iOperators.h"
#include "llvm/iOther.h"
#include "llvm/iPHINode.h"
#include "llvm/Type.h"
@@ -77,6 +78,7 @@
// Other operators
void visitShiftInst(ShiftInst &I);
+ void visitSetCondInst(SetCondInst &I);
void visitPHINode(PHINode &I);
void visitInstruction(Instruction &I) {
@@ -160,6 +162,157 @@
}
}
+/// SetCC instructions - Here we just emit boilerplate code to set a byte-sized
+/// register, then move it to wherever the result should be.
+/// We handle FP setcc instructions by pushing them, doing a
+/// compare-and-pop-twice, and then copying the concodes to the main
+/// processor's concodes (I didn't make this up, it's in the Intel manual)
+///
+void
+ISel::visitSetCondInst (SetCondInst & I)
+{
+ // The arguments are already supposed to be of the same type.
+ Value *var1 = I.getOperand (0);
+ Value *var2 = I.getOperand (1);
+ unsigned reg1 = getReg (var1);
+ unsigned reg2 = getReg (var2);
+ unsigned resultReg = getReg (I);
+ unsigned comparisonWidth = var1->getType ()->getPrimitiveSize ();
+ unsigned unsignedComparison = var1->getType ()->isUnsigned ();
+ unsigned resultWidth = I.getType ()->getPrimitiveSize ();
+ bool fpComparison = var1->getType ()->isFloatingPoint ();
+ if (fpComparison)
+ {
+ // Push the variables on the stack with fldl opcodes.
+ // FIXME: assuming var1, var2 are in memory, if not, spill to
+ // stack first
+ switch (comparisonWidth)
+ {
+ case 4:
+ BuildMI (BB, X86::FLDr4, 1, X86::NoReg).addReg (reg1);
+ break;
+ case 8:
+ BuildMI (BB, X86::FLDr8, 1, X86::NoReg).addReg (reg1);
+ break;
+ default:
+ visitInstruction (I);
+ break;
+ }
+ switch (comparisonWidth)
+ {
+ case 4:
+ BuildMI (BB, X86::FLDr4, 1, X86::NoReg).addReg (reg2);
+ break;
+ case 8:
+ BuildMI (BB, X86::FLDr8, 1, X86::NoReg).addReg (reg2);
+ break;
+ default:
+ visitInstruction (I);
+ break;
+ }
+ // (Non-trapping) compare and pop twice.
+ // FIXME: Result of comparison -> condition codes, not a register.
+ BuildMI (BB, X86::FUCOMPP, 0);
+ // Move fp status word (concodes) to ax.
+ BuildMI (BB, X86::FNSTSWr8, 1, X86::AX);
+ // Load real concodes from ax.
+ // FIXME: Once again, flags are not modeled.
+ BuildMI (BB, X86::SAHF, 0);
+ }
+ else
+ { // integer comparison
+ // Emit: cmp <var1>, <var2> (do the comparison). We can
+ // compare 8-bit with 8-bit, 16-bit with 16-bit, 32-bit with
+ // 32-bit.
+ // FIXME: Result of comparison -> condition codes, not a register.
+ switch (comparisonWidth)
+ {
+ case 1:
+ BuildMI (BB, X86::CMPrr8, 2,
+ X86::NoReg).addReg (reg1).addReg (reg2);
+ break;
+ case 2:
+ BuildMI (BB, X86::CMPrr16, 2,
+ X86::NoReg).addReg (reg1).addReg (reg2);
+ break;
+ case 4:
+ BuildMI (BB, X86::CMPrr32, 2,
+ X86::NoReg).addReg (reg1).addReg (reg2);
+ break;
+ case 8:
+ default:
+ visitInstruction (I);
+ break;
+ }
+ }
+ // Emit setOp instruction (extract concode; clobbers ax),
+ // using the following mapping:
+ // LLVM -> X86 signed X86 unsigned
+ // ----- ----- -----
+ // seteq -> sete sete
+ // setne -> setne setne
+ // setlt -> setl setb
+ // setgt -> setg seta
+ // setle -> setle setbe
+ // setge -> setge setae
+ switch (I.getOpcode ())
+ {
+ case Instruction::SetEQ:
+ BuildMI (BB, X86::SETE, 0, X86::AL);
+ break;
+ case Instruction::SetGE:
+ if (unsignedComparison)
+ BuildMI (BB, X86::SETAE, 0, X86::AL);
+ else
+ BuildMI (BB, X86::SETGE, 0, X86::AL);
+ break;
+ case Instruction::SetGT:
+ if (unsignedComparison)
+ BuildMI (BB, X86::SETA, 0, X86::AL);
+ else
+ BuildMI (BB, X86::SETG, 0, X86::AL);
+ break;
+ case Instruction::SetLE:
+ if (unsignedComparison)
+ BuildMI (BB, X86::SETBE, 0, X86::AL);
+ else
+ BuildMI (BB, X86::SETLE, 0, X86::AL);
+ break;
+ case Instruction::SetLT:
+ if (unsignedComparison)
+ BuildMI (BB, X86::SETB, 0, X86::AL);
+ else
+ BuildMI (BB, X86::SETL, 0, X86::AL);
+ break;
+ case Instruction::SetNE:
+ BuildMI (BB, X86::SETNE, 0, X86::AL);
+ break;
+ default:
+ visitInstruction (I);
+ break;
+ }
+ // Put it in the result using a move.
+ switch (resultWidth)
+ {
+ case 1:
+ BuildMI (BB, X86::MOVrr8, 1, resultReg).addReg (X86::AL);
+ break;
+ // FIXME: What to do about implicit destination registers?
+ // E.g., you don't specify it, but CBW is more like AX = CBW(AL).
+ case 2:
+ BuildMI (BB, X86::CBW, 0, X86::AX);
+ BuildMI (BB, X86::MOVrr16, 1, resultReg).addReg (X86::AX);
+ break;
+ case 4:
+ BuildMI (BB, X86::CWDE, 0, X86::EAX);
+ BuildMI (BB, X86::MOVrr32, 1, resultReg).addReg (X86::EAX);
+ break;
+ case 8:
+ default:
+ visitInstruction (I);
+ break;
+ }
+}
/// 'ret' instruction - Here we are interested in meeting the x86 ABI. As such,
Index: llvm/lib/Target/X86/X86InstrInfo.def
diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.12 llvm/lib/Target/X86/X86InstrInfo.def:1.13
--- llvm/lib/Target/X86/X86InstrInfo.def:1.12 Sat Nov 2 14:54:46 2002
+++ llvm/lib/Target/X86/X86InstrInfo.def Thu Nov 7 11:59:21 2002
@@ -66,7 +66,6 @@
I(IDIVrr16 , "idivw", 0, 0) // DA/r16=AX&DX F7/6
I(IDIVrr32 , "idivl", 0, 0) // DA/r32=EAX&DX F7/6
-
// Logical operators
I(ANDrr8 , "andb", 0, 0) // R8 &= R8 20/r
I(ANDrr16 , "andw", 0, 0) // R16 &= R16 21/r
@@ -98,11 +97,39 @@
I(SARrr32 , "sarl", 0, 0) // R32 >>= cl D3/7
I(SARir32 , "sarl", 0, 0) // R32 >>= imm8 C1/7 ib
+// Floating point loads
+I(FLDr4 , "flds", 0, 0) // push float D9/0
+I(FLDr8 , "fldl ", 0, 0) // push double DD/0
+
+// Floating point compares
+I(FUCOMPP , "fucompp", 0, 0) // compare+pop2x DA E9
+
+// Floating point flag ops
+I(FNSTSWr8 , "fnstsw", 0, 0) // AX = fp flags DF E0
+
+// Condition code ops, incl. set if equal/not equal/...
+I(SAHF , "sahf", 0, 0) // flags = AH 9E
+I(SETA , "seta", 0, 0) // R8 = > unsign 0F 97
+I(SETAE , "setae", 0, 0) // R8 = >=unsign 0F 93
+I(SETB , "setb", 0, 0) // R8 = < unsign 0F 92
+I(SETBE , "setbe", 0, 0) // R8 = <=unsign 0F 96
+I(SETE , "sete", 0, 0) // R8 = == 0F 94
+I(SETG , "setg", 0, 0) // R8 = > signed 0F 9F
+I(SETGE , "setge", 0, 0) // R8 = >=signed 0F 9D
+I(SETL , "setl", 0, 0) // R8 = < signed 0F 9C
+I(SETLE , "setle", 0, 0) // R8 = <=signed 0F 9E
+I(SETNE , "setne", 0, 0) // R8 = != 0F 95
+
+// Integer comparisons
+I(CMPrr8 , "cmpb", 0, 0) // compare R8,R8 38/r
+I(CMPrr16 , "cmpw", 0, 0) // compare R16,R16 39/r
+I(CMPrr32 , "cmpl", 0, 0) // compare R32,R32 39/r
-// Miscellaneous instructions...
+// Sign extenders
I(CBW , "cbw", 0, 0) // AH = signext(AL) 98
I(CWD , "cwd", 0, 0) // DX = signext(AX) 99
I(CWQ , "cwq", 0, 0) // EDX= signext(EAX) 99
+I(CWDE , "cwde", 0, 0) // EAX = extend AX 98
// At this point, I is dead, so undefine the macro
#undef I
More information about the llvm-commits
mailing list