[llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp

Chris Lattner lattner at cs.uiuc.edu
Tue Mar 30 16:40:01 PST 2004


Changes in directory llvm/lib/Target/X86:

InstSelectSimple.cpp updated: 1.198 -> 1.199

---
Log message:

Fold comparisons into select instructions, making much better code and
using our broad selection of movcc instructions.  :)



---
Diffs of the changes:  (+86 -30)

Index: llvm/lib/Target/X86/InstSelectSimple.cpp
diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.198 llvm/lib/Target/X86/InstSelectSimple.cpp:1.199
--- llvm/lib/Target/X86/InstSelectSimple.cpp:1.198	Tue Mar 30 15:22:00 2004
+++ llvm/lib/Target/X86/InstSelectSimple.cpp	Tue Mar 30 16:39:09 2004
@@ -743,19 +743,20 @@
 }
 
 
-// canFoldSetCCIntoBranch - Return the setcc instruction if we can fold it into
-// the conditional branch instruction which is the only user of the cc
-// instruction.  This is the case if the conditional branch is the only user of
-// the setcc, and if the setcc is in the same basic block as the conditional
-// branch.  We also don't handle long arguments below, so we reject them here as
-// well.
+// canFoldSetCCIntoBranchOrSelect - Return the setcc instruction if we can fold
+// it into the conditional branch or select instruction which is the only user
+// of the cc instruction.  This is the case if the conditional branch is the
+// only user of the setcc, and if the setcc is in the same basic block as the
+// conditional branch.  We also don't handle long arguments below, so we reject
+// them here as well.
 //
-static SetCondInst *canFoldSetCCIntoBranch(Value *V) {
+static SetCondInst *canFoldSetCCIntoBranchOrSelect(Value *V) {
   if (SetCondInst *SCI = dyn_cast<SetCondInst>(V))
-    if (SCI->hasOneUse() && isa<BranchInst>(SCI->use_back()) &&
-        SCI->getParent() == cast<BranchInst>(SCI->use_back())->getParent()) {
-      const Type *Ty = SCI->getOperand(0)->getType();
-      if (Ty != Type::LongTy && Ty != Type::ULongTy)
+    if (SCI->hasOneUse()) {
+      Instruction *User = cast<Instruction>(SCI->use_back());
+      if ((isa<BranchInst>(User) || isa<SelectInst>(User)) &&
+          SCI->getParent() == User->getParent() &&
+          getClassB(SCI->getOperand(0)->getType()) != cLong)
         return SCI;
     }
   return 0;
@@ -907,7 +908,8 @@
 /// register, then move it to wherever the result should be. 
 ///
 void ISel::visitSetCondInst(SetCondInst &I) {
-  if (canFoldSetCCIntoBranch(&I)) return;  // Fold this into a branch...
+  if (canFoldSetCCIntoBranchOrSelect(&I))
+    return;  // Fold this into a branch or select.
 
   unsigned DestReg = getReg(I);
   MachineBasicBlock::iterator MII = BB->end();
@@ -963,28 +965,82 @@
       FalseVal = ConstantExpr::getCast(F, Type::ShortTy);
   }
 
-  // Get the value being branched on, and use it to set the condition codes.
-  unsigned CondReg = getReg(Cond, MBB, IP);
-  BuildMI(*MBB, IP, X86::CMP8ri, 2).addReg(CondReg).addImm(0);
+  
+  unsigned Opcode;
+  if (SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(Cond)) {
+    // We successfully folded the setcc into the select instruction.
+    
+    unsigned OpNum = getSetCCNumber(SCI->getOpcode());
+    OpNum = EmitComparison(OpNum, SCI->getOperand(0), SCI->getOperand(1), MBB,
+                           IP);
+
+    const Type *CompTy = SCI->getOperand(0)->getType();
+    bool isSigned = CompTy->isSigned() && getClassB(CompTy) != cFP;
+  
+    // LLVM  -> X86 signed  X86 unsigned
+    // -----    ----------  ------------
+    // seteq -> cmovNE      cmovNE
+    // setne -> cmovE       cmovE
+    // setlt -> cmovGE      cmovAE
+    // setge -> cmovL       cmovB
+    // setgt -> cmovLE      cmovBE
+    // setle -> cmovG       cmovA
+    // ----
+    //          cmovNS              // Used by comparison with 0 optimization
+    //          cmovS
+    
+    switch (SelectClass) {
+    default:
+    case cFP:
+      assert(0 && "We don't support floating point selects yet, they should "
+             "have been lowered!");
+    case cByte:
+    case cShort: {
+      static const unsigned OpcodeTab[2][8] = {
+        { X86::CMOVNE16rr, X86::CMOVE16rr, X86::CMOVAE16rr, X86::CMOVB16rr,
+          X86::CMOVBE16rr, X86::CMOVA16rr, 0, 0 },
+        { X86::CMOVNE16rr, X86::CMOVE16rr, X86::CMOVGE16rr, X86::CMOVL16rr,
+          X86::CMOVLE16rr, X86::CMOVG16rr, X86::CMOVNS16rr, X86::CMOVS16rr },
+      };
+      Opcode = OpcodeTab[isSigned][OpNum];
+      break;
+    }
+    case cInt:
+    case cLong: {
+      static const unsigned OpcodeTab[2][8] = {
+        { X86::CMOVNE32rr, X86::CMOVE32rr, X86::CMOVAE32rr, X86::CMOVB32rr,
+          X86::CMOVBE32rr, X86::CMOVA32rr, 0, 0 },
+        { X86::CMOVNE32rr, X86::CMOVE32rr, X86::CMOVGE32rr, X86::CMOVL32rr,
+          X86::CMOVLE32rr, X86::CMOVG32rr, X86::CMOVNS32rr, X86::CMOVS32rr },
+      };
+      Opcode = OpcodeTab[isSigned][OpNum];
+      break;
+    }
+    }
+  } else {
+    // Get the value being branched on, and use it to set the condition codes.
+    unsigned CondReg = getReg(Cond, MBB, IP);
+    BuildMI(*MBB, IP, X86::CMP8ri, 2).addReg(CondReg).addImm(0);
+    switch (SelectClass) {
+    default:
+    case cFP:
+      assert(0 && "We don't support floating point selects yet, they should "
+             "have been lowered!");
+    case cByte:
+    case cShort:
+      Opcode = X86::CMOVE16rr;
+      break;
+    case cInt:
+    case cLong:
+      Opcode = X86::CMOVE32rr;
+      break;
+    }
+  }
 
   unsigned TrueReg  = getReg(TrueVal, MBB, IP);
   unsigned FalseReg = getReg(FalseVal, MBB, IP);
   unsigned RealDestReg = DestReg;
-  unsigned Opcode;
 
-  switch (SelectClass) {
-  case cFP:
-    assert(0 && "We don't support floating point selects yet, they should "
-           "have been lowered!");
-  case cByte:
-  case cShort:
-    Opcode = X86::CMOVE16rr;
-    break;
-  case cInt:
-  case cLong:
-    Opcode = X86::CMOVE32rr;
-    break;
-  }
 
   // Annoyingly enough, X86 doesn't HAVE 8-bit conditional moves.  Because of
   // this, we have to promote the incoming values to 16 bits, perform a 16-bit
@@ -1126,7 +1182,7 @@
   }
 
   // See if we can fold the setcc into the branch itself...
-  SetCondInst *SCI = canFoldSetCCIntoBranch(BI.getCondition());
+  SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(BI.getCondition());
   if (SCI == 0) {
     // Nope, cannot fold setcc into this branch.  Emit a branch on a condition
     // computed some other way...





More information about the llvm-commits mailing list