[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