[llvm-commits] [llvm] r55401 - in /llvm/trunk: include/llvm/CodeGen/FastISel.h lib/CodeGen/SelectionDAG/FastISel.cpp test/CodeGen/X86/fast-isel.ll utils/TableGen/FastISelEmitter.cpp

Dan Gohman gohman at apple.com
Tue Aug 26 18:09:56 PDT 2008


Author: djg
Date: Tue Aug 26 20:09:54 2008
New Revision: 55401

URL: http://llvm.org/viewvc/llvm-project?rev=55401&view=rev
Log:
Basic FastISel support for floating-point constants.

Modified:
    llvm/trunk/include/llvm/CodeGen/FastISel.h
    llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
    llvm/trunk/test/CodeGen/X86/fast-isel.ll
    llvm/trunk/utils/TableGen/FastISelEmitter.cpp

Modified: llvm/trunk/include/llvm/CodeGen/FastISel.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/FastISel.h?rev=55401&r1=55400&r2=55401&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/FastISel.h (original)
+++ llvm/trunk/include/llvm/CodeGen/FastISel.h Tue Aug 26 20:09:54 2008
@@ -20,6 +20,7 @@
 
 namespace llvm {
 
+class ConstantFP;
 class MachineBasicBlock;
 class MachineFunction;
 class MachineRegisterInfo;
@@ -93,6 +94,15 @@
                                ISD::NodeType Opcode,
                                unsigned Op0, uint64_t Imm);
 
+  /// FastEmit_rf - This method is called by target-independent code
+  /// to request that an instruction with the given type, opcode, and
+  /// register and floating-point immediate operands be emitted.
+  ///
+  virtual unsigned FastEmit_rf(MVT::SimpleValueType VT,
+                               MVT::SimpleValueType RetVT,
+                               ISD::NodeType Opcode,
+                               unsigned Op0, ConstantFP *FPImm);
+
   /// FastEmit_rri - This method is called by target-independent code
   /// to request that an instruction with the given type, opcode, and
   /// register and immediate operands be emitted.
@@ -111,6 +121,15 @@
                         unsigned Op0, uint64_t Imm,
                         MVT::SimpleValueType ImmType);
   
+  /// FastEmit_rf_ - This method is a wrapper of FastEmit_rf. It first tries
+  /// to emit an instruction with an immediate operand using FastEmit_rf.
+  /// If that fails, it materializes the immediate into a register and try
+  /// FastEmit_rr instead.
+  unsigned FastEmit_rf_(MVT::SimpleValueType VT,
+                        ISD::NodeType Opcode,
+                        unsigned Op0, ConstantFP *FPImm,
+                        MVT::SimpleValueType ImmType);
+  
   /// FastEmit_i - This method is called by target-independent code
   /// to request that an instruction with the given type, opcode, and
   /// immediate operand be emitted.
@@ -119,6 +138,14 @@
                               ISD::NodeType Opcode,
                               uint64_t Imm);
 
+  /// FastEmit_f - This method is called by target-independent code
+  /// to request that an instruction with the given type, opcode, and
+  /// floating-point immediate operand be emitted.
+  virtual unsigned FastEmit_f(MVT::SimpleValueType VT,
+                              MVT::SimpleValueType RetVT,
+                              ISD::NodeType Opcode,
+                              ConstantFP *FPImm);
+
   /// FastEmitInst_ - Emit a MachineInstr with no operands and a
   /// result register in the given register class.
   ///
@@ -146,6 +173,13 @@
                            const TargetRegisterClass *RC,
                            unsigned Op0, uint64_t Imm);
 
+  /// FastEmitInst_rf - Emit a MachineInstr with two register operands
+  /// and a result register in the given register class.
+  ///
+  unsigned FastEmitInst_rf(unsigned MachineInstOpcode,
+                           const TargetRegisterClass *RC,
+                           unsigned Op0, ConstantFP *FPImm);
+
   /// FastEmitInst_rri - Emit a MachineInstr with two register operands,
   /// an immediate, and a result register in the given register class.
   ///

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=55401&r1=55400&r2=55401&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Tue Aug 26 20:09:54 2008
@@ -56,6 +56,20 @@
     return true;
   }
 
+  // Check if the second operand is a constant float.
+  if (ConstantFP *CF = dyn_cast<ConstantFP>(I->getOperand(1))) {
+    unsigned ResultReg = FastEmit_rf_(VT.getSimpleVT(), ISDOpcode, Op0,
+                                      CF, VT.getSimpleVT());
+    if (ResultReg == 0)
+      // Target-specific code wasn't able to find a machine opcode for
+      // the given ISD opcode and type. Halt "fast" selection and bail.
+      return false;
+
+    // We successfully emitted code for the given LLVM Instruction.
+    ValueMap[I] = ResultReg;
+    return true;
+  }
+
   unsigned Op1 = ValueMap[I->getOperand(1)];
   if (Op1 == 0)
     // Unhandled operand. Halt "fast" selection and bail.
@@ -451,12 +465,23 @@
   return 0;
 }
 
+unsigned FastISel::FastEmit_f(MVT::SimpleValueType, MVT::SimpleValueType,
+                              ISD::NodeType, ConstantFP * /*FPImm*/) {
+  return 0;
+}
+
 unsigned FastISel::FastEmit_ri(MVT::SimpleValueType, MVT::SimpleValueType,
                                ISD::NodeType, unsigned /*Op0*/,
                                uint64_t /*Imm*/) {
   return 0;
 }
 
+unsigned FastISel::FastEmit_rf(MVT::SimpleValueType, MVT::SimpleValueType,
+                               ISD::NodeType, unsigned /*Op0*/,
+                               ConstantFP * /*FPImm*/) {
+  return 0;
+}
+
 unsigned FastISel::FastEmit_rri(MVT::SimpleValueType, MVT::SimpleValueType,
                                 ISD::NodeType,
                                 unsigned /*Op0*/, unsigned /*Op1*/,
@@ -483,6 +508,45 @@
   return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg);
 }
 
+/// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries
+/// to emit an instruction with a floating-point immediate operand using
+/// FastEmit_rf. If that fails, it materializes the immediate into a register
+/// and try FastEmit_rr instead.
+unsigned FastISel::FastEmit_rf_(MVT::SimpleValueType VT, ISD::NodeType Opcode,
+                                unsigned Op0, ConstantFP *FPImm,
+                                MVT::SimpleValueType ImmType) {
+  unsigned ResultReg = 0;
+  // First check if immediate type is legal. If not, we can't use the rf form.
+  if (TLI.getOperationAction(ISD::Constant, ImmType) == TargetLowering::Legal)
+    ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, FPImm);
+  if (ResultReg != 0)
+    return ResultReg;
+
+  // Materialize the constant in a register.
+  unsigned MaterialReg = FastEmit_f(ImmType, ImmType, ISD::ConstantFP, FPImm);
+  if (MaterialReg == 0) {
+    const APFloat &Flt = FPImm->getValueAPF();
+    MVT IntVT = TLI.getPointerTy();
+
+    uint64_t x[2];
+    uint32_t IntBitWidth = IntVT.getSizeInBits();
+    if (Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true,
+                             APFloat::rmTowardZero) != APFloat::opOK)
+      return 0;
+    APInt IntVal(IntBitWidth, 2, x);
+
+    unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(),
+                                     ISD::Constant, IntVal.getZExtValue());
+    if (IntegerReg == 0)
+      return 0;
+    MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT,
+                             ISD::SINT_TO_FP, IntegerReg);
+    if (MaterialReg == 0)
+      return 0;
+  }
+  return FastEmit_rr(VT, VT, Opcode, Op0, MaterialReg);
+}
+
 unsigned FastISel::createResultReg(const TargetRegisterClass* RC) {
   return MRI.createVirtualRegister(RC);
 }
@@ -526,6 +590,16 @@
   return ResultReg;
 }
 
+unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode,
+                                   const TargetRegisterClass *RC,
+                                   unsigned Op0, ConstantFP *FPImm) {
+  unsigned ResultReg = createResultReg(RC);
+  const TargetInstrDesc &II = TII.get(MachineInstOpcode);
+
+  BuildMI(MBB, II, ResultReg).addReg(Op0).addFPImm(FPImm);
+  return ResultReg;
+}
+
 unsigned FastISel::FastEmitInst_rri(unsigned MachineInstOpcode,
                                     const TargetRegisterClass *RC,
                                     unsigned Op0, unsigned Op1, uint64_t Imm) {

Modified: llvm/trunk/test/CodeGen/X86/fast-isel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fast-isel.ll?rev=55401&r1=55400&r2=55401&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/X86/fast-isel.ll (original)
+++ llvm/trunk/test/CodeGen/X86/fast-isel.ll Tue Aug 26 20:09:54 2008
@@ -35,10 +35,11 @@
   %t0 = add double %r, %s
   %t1 = mul double %t0, %s
   %t2 = sub double %t1, %s
+  %t3 = add double %t2, 707.0
   br label %exit
 
 exit:
-  ret double %t2
+  ret double %t3
 }
 
 define i32 @cast(){

Modified: llvm/trunk/utils/TableGen/FastISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/FastISelEmitter.cpp?rev=55401&r1=55400&r2=55401&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/FastISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/FastISelEmitter.cpp Tue Aug 26 20:09:54 2008
@@ -68,6 +68,11 @@
       Operands.push_back("i");
       return true;
     }
+    if (!InstPatNode->isLeaf() &&
+        InstPatNode->getOperator()->getName() == "fpimm") {
+      Operands.push_back("f");
+      return true;
+    }
     
     const CodeGenRegisterClass *DstRC = 0;
     
@@ -87,6 +92,10 @@
           Operands.push_back("i");
           return true;
         }
+        if (Op->getOperator()->getName() == "fpimm") {
+          Operands.push_back("f");
+          return true;
+        }
         // For now, ignore fpimm and other non-leaf nodes.
         return false;
       }
@@ -122,6 +131,8 @@
         OS << "unsigned Op" << i;
       } else if (Operands[i] == "i") {
         OS << "uint64_t imm" << i;
+      } else if (Operands[i] == "f") {
+        OS << "ConstantFP *f" << i;
       } else {
         assert("Unknown operand kind!");
         abort();
@@ -137,6 +148,8 @@
         OS << "Op" << i;
       } else if (Operands[i] == "i") {
         OS << "imm" << i;
+      } else if (Operands[i] == "f") {
+        OS << "f" << i;
       } else {
         assert("Unknown operand kind!");
         abort();





More information about the llvm-commits mailing list