[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp

Nate Begeman natebegeman at mac.com
Thu Mar 31 15:55:51 PST 2005



Changes in directory llvm/lib/Target/PowerPC:

PPC32ISelPattern.cpp updated: 1.22 -> 1.23
---
Log message:

fsel generation for f32 and f64 select
generate compare immediate for integer compare with constant
fold setcc into branch
fold setcc into select

Code generation quality for Shootout is now on par with the Simple ISel


---
Diffs of the changes:  (+181 -35)

 PPC32ISelPattern.cpp |  216 ++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 181 insertions(+), 35 deletions(-)


Index: llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp
diff -u llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.22 llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.23
--- llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.22	Wed Mar 30 20:05:53 2005
+++ llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp	Thu Mar 31 17:55:40 2005
@@ -54,6 +54,9 @@
       setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
       setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand);
 
+      addLegalFPImmediate(+0.0); // Necessary for FSEL
+      addLegalFPImmediate(-0.0); // 
+
       computeRegisterProperties();
     }
 
@@ -478,7 +481,7 @@
 /// placed in Imm.
 ///
 static unsigned canUseAsImmediateForOpcode(SDOperand N, unsigned Opcode,
-                                           unsigned& Imm) {
+                                           unsigned& Imm, bool U = false) {
   if (N.getOpcode() != ISD::Constant) return 0;
 
   int v = (int)cast<ConstantSDNode>(N)->getSignExtended();
@@ -498,9 +501,33 @@
   case ISD::MUL:
     if (v <= 32767 && v >= -32768) { Imm = v & 0xFFFF; return 1; }
     break;
+  case ISD::SETCC:
+    if (U && (v >= 0 && v <= 65535)) { Imm = v & 0xFFFF; return 1; }
+    if (!U && (v <= 32767 && v >= -32768)) { Imm = v & 0xFFFF; return 1; }
+    break;
   }
   return 0;
 }
+
+/// getBCCForSetCC - Returns the PowerPC condition branch mnemonic corresponding
+/// to Condition.  If the Condition is unordered or unsigned, the bool argument
+/// U is set to true, otherwise it is set to false.
+static unsigned getBCCForSetCC(unsigned Condition, bool& U) {
+  U = false;
+  switch (Condition) {
+  default: assert(0 && "Unknown condition!"); abort();
+  case ISD::SETEQ:  return PPC::BEQ;
+  case ISD::SETNE:  return PPC::BNE;
+  case ISD::SETULT: U = true;
+  case ISD::SETLT:  return PPC::BLT;
+  case ISD::SETULE: U = true;
+  case ISD::SETLE:  return PPC::BLE;
+  case ISD::SETUGT: U = true;
+  case ISD::SETGT:  return PPC::BGT;
+  case ISD::SETUGE: U = true;
+  case ISD::SETGE:  return PPC::BGE;
+  }
+}
 }
 
 /// getGlobalBaseReg - Output the instructions required to put the
@@ -539,15 +566,39 @@
   assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
   MachineBasicBlock *Dest = 
     cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
-  unsigned Opc;
-  
+
+  unsigned Opc, Tmp1, Tmp2;
   Select(N.getOperand(0));  //chain
-  SDOperand CC = N.getOperand(1);
-  
-  //Give up and do the stupid thing
-  unsigned Tmp1 = SelectExpr(CC);
-  BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(0);
-  BuildMI(BB, PPC::BNE, 2).addReg(PPC::CR0).addMBB(Dest);
+
+  // If the first operand to the select is a SETCC node, then we can fold it
+  // into the branch that selects which value to return.
+  SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(N.getOperand(1).Val);
+  if (SetCC && N.getOperand(1).getOpcode() == ISD::SETCC &&
+      MVT::isInteger(SetCC->getOperand(0).getValueType())) {
+    bool U;
+    Opc = getBCCForSetCC(SetCC->getCondition(), U);
+    Tmp1 = SelectExpr(SetCC->getOperand(0));
+
+    // Pass the optional argument U to canUseAsImmediateForOpcode for SETCC,
+    // so that it knows whether the SETCC immediate range is signed or not.
+    if (1 == canUseAsImmediateForOpcode(SetCC->getOperand(1), ISD::SETCC, 
+                                        Tmp2, U)) {
+      if (U)
+        BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(Tmp2);
+      else
+        BuildMI(BB, PPC::CMPWI, 2, PPC::CR0).addReg(Tmp1).addSImm(Tmp2);
+    } else {
+      Tmp2 = SelectExpr(SetCC->getOperand(1));
+      BuildMI(BB, U ? PPC::CMPLW : PPC::CMPW, 2, PPC::CR0).addReg(Tmp1)
+      .addReg(Tmp2);
+    }
+  } else {
+    Tmp1 = SelectExpr(N.getOperand(1));
+    BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(0);
+    Opc = PPC::BNE;
+  }
+
+  BuildMI(BB, Opc, 2).addReg(PPC::CR0).addMBB(Dest);
   return;
 }
 
@@ -565,10 +616,77 @@
     assert(0 && "Node not handled!\n");
 
   case ISD::SELECT: {
-    Tmp1 = SelectExpr(N.getOperand(0)); //Cond
-
-    // FIXME: generate FSEL here
-
+    // Attempt to generate FSEL.  We can do this whenever we have an FP result,
+    // and an FP comparison in the SetCC node.
+    SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(N.getOperand(0).Val);
+    if (SetCC && N.getOperand(0).getOpcode() == ISD::SETCC &&
+        !MVT::isInteger(SetCC->getOperand(0).getValueType()) &&
+        SetCC->getCondition() != ISD::SETEQ &&
+        SetCC->getCondition() != ISD::SETNE) {
+      MVT::ValueType VT = SetCC->getOperand(0).getValueType();
+      Tmp1 = SelectExpr(SetCC->getOperand(0));   // Val to compare against
+      unsigned TV = SelectExpr(N.getOperand(1)); // Use if TRUE
+      unsigned FV = SelectExpr(N.getOperand(2)); // Use if FALSE
+      
+      ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1));
+      if (CN && (CN->isExactlyValue(-0.0) || CN->isExactlyValue(0.0))) {
+        switch(SetCC->getCondition()) {
+        default: assert(0 && "Invalid FSEL condition"); abort();
+        case ISD::SETULT:
+        case ISD::SETLT:
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp1).addReg(FV).addReg(TV);
+          return Result;
+        case ISD::SETUGE:
+        case ISD::SETGE:
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp1).addReg(TV).addReg(FV);
+          return Result;
+        case ISD::SETUGT:
+        case ISD::SETGT: {
+          Tmp2 = MakeReg(VT);
+          BuildMI(BB, PPC::FNEG, 1, Tmp2).addReg(Tmp1);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp2).addReg(FV).addReg(TV);
+          return Result;
+        }
+        case ISD::SETULE:
+        case ISD::SETLE: {
+          Tmp2 = MakeReg(VT);
+          BuildMI(BB, PPC::FNEG, 1, Tmp2).addReg(Tmp1);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp2).addReg(TV).addReg(FV);
+          return Result;
+        }
+        }
+      } else {
+        Opc = (MVT::f64 == VT) ? PPC::FSUB : PPC::FSUBS;
+        Tmp2 = SelectExpr(SetCC->getOperand(1));
+        Tmp3 =  MakeReg(VT);
+        switch(SetCC->getCondition()) {
+        default: assert(0 && "Invalid FSEL condition"); abort();
+        case ISD::SETULT:
+        case ISD::SETLT:
+          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(FV).addReg(TV);
+          return Result;
+        case ISD::SETUGE:
+        case ISD::SETGE:
+          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(TV).addReg(FV);
+          return Result;
+        case ISD::SETUGT:
+        case ISD::SETGT:
+          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp2).addReg(Tmp1);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(FV).addReg(TV);
+          return Result;
+        case ISD::SETULE:
+        case ISD::SETLE:
+          BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp2).addReg(Tmp1);
+          BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(TV).addReg(FV);
+          return Result;
+        }
+      }
+      assert(0 && "Should never get here");
+      return 0;
+    }
+    
     // Create an iterator with which to insert the MBB for copying the false 
     // value and the MBB to hold the PHI instruction for this SetCC.
     MachineBasicBlock *thisMBB = BB;
@@ -582,6 +700,7 @@
     //   cmpTY cr0, r1, r2
     //   bCC copy1MBB
     //   fallthrough --> copy0MBB
+    Tmp1 = SelectExpr(N.getOperand(0)); //Cond
     BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(0);
     MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
     MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
@@ -1085,24 +1204,29 @@
       bool U = false;
       bool IsInteger = MVT::isInteger(SetCC->getOperand(0).getValueType());
       
-      switch (SetCC->getCondition()) {
-      default: Node->dump(); assert(0 && "Unknown comparison!");
-      case ISD::SETEQ:  Opc = PPC::BEQ; break;
-      case ISD::SETNE:  Opc = PPC::BNE; break;
-      case ISD::SETULT: U = true;
-      case ISD::SETLT:  Opc = PPC::BLT; break;
-      case ISD::SETULE: U = true;
-      case ISD::SETLE:  Opc = PPC::BLE; break;
-      case ISD::SETUGT: U = true;
-      case ISD::SETGT:  Opc = PPC::BGT; break;
-      case ISD::SETUGE: U = true;
-      case ISD::SETGE:  Opc = PPC::BGE; break;
-      }
-      
       // FIXME: Is there a situation in which we would ever need to emit fcmpo?
       static const unsigned CompareOpcodes[] = 
         { PPC::FCMPU, PPC::FCMPU, PPC::CMPW, PPC::CMPLW };
-      unsigned CompareOpc = CompareOpcodes[2 * IsInteger + U];
+
+      // Set the branch opcode to use below
+      Opc = getBCCForSetCC(SetCC->getCondition(), U);
+
+      // Try and use an integer compare with immediate, if applicable.  
+      // Normal setcc uses the sign-extended immediate range, unsigned setcc
+      // uses the zero extended immediate range.
+      if (IsInteger && 
+          1 == canUseAsImmediateForOpcode(N.getOperand(1), opcode, Tmp2, U)) {
+        Tmp1 = SelectExpr(N.getOperand(0));
+        if (U)
+          BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(Tmp2);
+        else
+          BuildMI(BB, PPC::CMPWI, 2, PPC::CR0).addReg(Tmp1).addSImm(Tmp2);
+      } else {
+        Tmp1 = SelectExpr(N.getOperand(0));
+        Tmp2 = SelectExpr(N.getOperand(1));
+        unsigned CompareOpc = CompareOpcodes[2 * IsInteger + U];
+        BuildMI(BB, CompareOpc, 2, PPC::CR0).addReg(Tmp1).addReg(Tmp2);
+      }
       
       // Create an iterator with which to insert the MBB for copying the false 
       // value and the MBB to hold the PHI instruction for this SetCC.
@@ -1116,9 +1240,6 @@
       //   cmpTY cr0, r1, r2
       //   %TrueValue = li 1
       //   bCC sinkMBB
-      Tmp1 = SelectExpr(N.getOperand(0));
-      Tmp2 = SelectExpr(N.getOperand(1));
-      BuildMI(BB, CompareOpc, 2, PPC::CR0).addReg(Tmp1).addReg(Tmp2);
       unsigned TrueValue = MakeReg(MVT::i32);
       BuildMI(BB, PPC::LI, 1, TrueValue).addSImm(1);
       MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
@@ -1152,8 +1273,6 @@
     return 0;
     
   case ISD::SELECT: {
-    Tmp1 = SelectExpr(N.getOperand(0)); //Cond
-
     // Create an iterator with which to insert the MBB for copying the false 
     // value and the MBB to hold the PHI instruction for this SetCC.
     MachineBasicBlock *thisMBB = BB;
@@ -1161,17 +1280,44 @@
     ilist<MachineBasicBlock>::iterator It = BB;
     ++It;
 
+    // If the first operand to the select is a SETCC node, then we can fold it
+    // into the branch that selects which value to return.
+    SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(N.getOperand(0).Val);
+    if (SetCC && N.getOperand(0).getOpcode() == ISD::SETCC &&
+        MVT::isInteger(SetCC->getOperand(0).getValueType())) {
+      bool U;
+      Opc = getBCCForSetCC(SetCC->getCondition(), U);
+      Tmp1 = SelectExpr(SetCC->getOperand(0));
+
+      // Pass the optional argument U to canUseAsImmediateForOpcode for SETCC,
+      // so that it knows whether the SETCC immediate range is signed or not.
+      if (1 == canUseAsImmediateForOpcode(SetCC->getOperand(1), ISD::SETCC, 
+                                          Tmp2, U)) {
+        if (U)
+          BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(Tmp2);
+        else
+          BuildMI(BB, PPC::CMPWI, 2, PPC::CR0).addReg(Tmp1).addSImm(Tmp2);
+      } else {
+        Tmp2 = SelectExpr(SetCC->getOperand(1));
+        BuildMI(BB, U ? PPC::CMPLW : PPC::CMPW, 2, PPC::CR0).addReg(Tmp1)
+          .addReg(Tmp2);
+      }
+    } else {
+      Tmp1 = SelectExpr(N.getOperand(0)); //Cond
+      BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(0);
+      Opc = PPC::BNE;
+    }
+
     //  thisMBB:
     //  ...
     //   TrueVal = ...
     //   cmpTY cr0, r1, r2
     //   bCC copy1MBB
     //   fallthrough --> copy0MBB
-    BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(0);
     MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
     MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
     unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
-    BuildMI(BB, PPC::BNE, 2).addReg(PPC::CR0).addMBB(sinkMBB);
+    BuildMI(BB, Opc, 2).addReg(PPC::CR0).addMBB(sinkMBB);
     MachineFunction *F = BB->getParent();
     F->getBasicBlockList().insert(It, copy0MBB);
     F->getBasicBlockList().insert(It, sinkMBB);






More information about the llvm-commits mailing list