Codegen FP select instructions into X86 conditional moves. Annoyingly enough
authorChris Lattner <sabre@nondot.org>
Wed, 31 Mar 2004 22:03:35 +0000 (22:03 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 31 Mar 2004 22:03:35 +0000 (22:03 +0000)
the X86 does not support a full set of fp cmove instructions, so we can't always
fold the condition into the select.  :(  Yuck.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12577 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/InstSelectSimple.cpp
lib/Target/X86/X86ISelSimple.cpp

index 35dc177e1d5a9899f628b7fa69302bff54e2a643..e60aed3c8aa9b38b95c32da9d1b03165d1d6592c 100644 (file)
@@ -990,10 +990,37 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
     //          cmovS
     
     switch (SelectClass) {
-    default:
-    case cFP:
-      assert(0 && "We don't support floating point selects yet, they should "
-             "have been lowered!");
+    default: assert(0 && "Unknown value class!");
+    case cFP: {
+      // Annoyingly, we don't have a full set of floating point conditional
+      // moves.  :(
+      static const unsigned OpcodeTab[2][8] = {
+        { X86::FCMOVNE, X86::FCMOVE, X86::FCMOVAE, X86::FCMOVB,
+          X86::FCMOVBE, X86::FCMOVA, 0, 0 },
+        { X86::FCMOVNE, X86::FCMOVE, 0, 0, 0, 0, 0, 0 },
+      };
+      Opcode = OpcodeTab[isSigned][OpNum];
+
+      // If opcode == 0, we hit a case that we don't support.  Output a setcc
+      // and compare the result against zero.
+      if (Opcode == 0) {
+        unsigned CompClass = getClassB(CompTy);
+        unsigned CondReg;
+        if (CompClass != cLong || OpNum < 2) {
+          CondReg = makeAnotherReg(Type::BoolTy);
+          // Handle normal comparisons with a setcc instruction...
+          BuildMI(*MBB, IP, SetCCOpcodeTab[isSigned][OpNum], 0, CondReg);
+        } else {
+          // Long comparisons end up in the BL register.
+          CondReg = X86::BL;
+        }
+        
+        // FIXME: Should generate a 'tst r, r'
+        BuildMI(*MBB, IP, X86::CMP8ri, 2).addReg(CondReg).addImm(0);
+        Opcode = X86::FCMOVE;
+      }
+      break;
+    }
     case cByte:
     case cShort: {
       static const unsigned OpcodeTab[2][8] = {
@@ -1020,20 +1047,15 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
   } else {
     // Get the value being branched on, and use it to set the condition codes.
     unsigned CondReg = getReg(Cond, MBB, IP);
+    // FIXME: Should generate a 'tst r, r'
     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!");
+    default: assert(0 && "Unknown value class!");
+    case cFP:    Opcode = X86::FCMOVE; break;
     case cByte:
-    case cShort:
-      Opcode = X86::CMOVE16rr;
-      break;
+    case cShort: Opcode = X86::CMOVE16rr; break;
     case cInt:
-    case cLong:
-      Opcode = X86::CMOVE32rr;
-      break;
+    case cLong:  Opcode = X86::CMOVE32rr; break;
     }
   }
 
index 35dc177e1d5a9899f628b7fa69302bff54e2a643..e60aed3c8aa9b38b95c32da9d1b03165d1d6592c 100644 (file)
@@ -990,10 +990,37 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
     //          cmovS
     
     switch (SelectClass) {
-    default:
-    case cFP:
-      assert(0 && "We don't support floating point selects yet, they should "
-             "have been lowered!");
+    default: assert(0 && "Unknown value class!");
+    case cFP: {
+      // Annoyingly, we don't have a full set of floating point conditional
+      // moves.  :(
+      static const unsigned OpcodeTab[2][8] = {
+        { X86::FCMOVNE, X86::FCMOVE, X86::FCMOVAE, X86::FCMOVB,
+          X86::FCMOVBE, X86::FCMOVA, 0, 0 },
+        { X86::FCMOVNE, X86::FCMOVE, 0, 0, 0, 0, 0, 0 },
+      };
+      Opcode = OpcodeTab[isSigned][OpNum];
+
+      // If opcode == 0, we hit a case that we don't support.  Output a setcc
+      // and compare the result against zero.
+      if (Opcode == 0) {
+        unsigned CompClass = getClassB(CompTy);
+        unsigned CondReg;
+        if (CompClass != cLong || OpNum < 2) {
+          CondReg = makeAnotherReg(Type::BoolTy);
+          // Handle normal comparisons with a setcc instruction...
+          BuildMI(*MBB, IP, SetCCOpcodeTab[isSigned][OpNum], 0, CondReg);
+        } else {
+          // Long comparisons end up in the BL register.
+          CondReg = X86::BL;
+        }
+        
+        // FIXME: Should generate a 'tst r, r'
+        BuildMI(*MBB, IP, X86::CMP8ri, 2).addReg(CondReg).addImm(0);
+        Opcode = X86::FCMOVE;
+      }
+      break;
+    }
     case cByte:
     case cShort: {
       static const unsigned OpcodeTab[2][8] = {
@@ -1020,20 +1047,15 @@ void ISel::emitSelectOperation(MachineBasicBlock *MBB,
   } else {
     // Get the value being branched on, and use it to set the condition codes.
     unsigned CondReg = getReg(Cond, MBB, IP);
+    // FIXME: Should generate a 'tst r, r'
     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!");
+    default: assert(0 && "Unknown value class!");
+    case cFP:    Opcode = X86::FCMOVE; break;
     case cByte:
-    case cShort:
-      Opcode = X86::CMOVE16rr;
-      break;
+    case cShort: Opcode = X86::CMOVE16rr; break;
     case cInt:
-    case cLong:
-      Opcode = X86::CMOVE32rr;
-      break;
+    case cLong:  Opcode = X86::CMOVE32rr; break;
     }
   }