[llvm-commits] [llvm] r55099 - 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
Wed Aug 20 18:41:08 PDT 2008


Author: djg
Date: Wed Aug 20 20:41:07 2008
New Revision: 55099

URL: http://llvm.org/viewvc/llvm-project?rev=55099&view=rev
Log:
Basic fast-isel support for instructions with constant int operands.

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=55099&r1=55098&r2=55099&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/FastISel.h (original)
+++ llvm/trunk/include/llvm/CodeGen/FastISel.h Wed Aug 20 20:41:07 2008
@@ -88,8 +88,15 @@
   ///
   virtual unsigned FastEmit_ri(MVT::SimpleValueType VT,
                                ISD::NodeType Opcode,
-                               unsigned Op0, uint64_t Imm,
-                               MVT::SimpleValueType ImmType);
+                               unsigned Op0, uint64_t Imm);
+
+  /// 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.
+  ///
+  virtual unsigned FastEmit_rri(MVT::SimpleValueType VT,
+                                ISD::NodeType Opcode,
+                                unsigned Op0, unsigned Op1, uint64_t Imm);
 
   /// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries
   /// to emit an instruction with an immediate operand using FastEmit_ri.
@@ -106,20 +113,34 @@
   unsigned FastEmitInst_(unsigned MachineInstOpcode,
                          const TargetRegisterClass *RC);
 
-  /// FastEmitInst_ - Emit a MachineInstr with one register operand
+  /// FastEmitInst_r - Emit a MachineInstr with one register operand
   /// and a result register in the given register class.
   ///
   unsigned FastEmitInst_r(unsigned MachineInstOpcode,
                           const TargetRegisterClass *RC,
                           unsigned Op0);
 
-  /// FastEmitInst_ - Emit a MachineInstr with two register operands
+  /// FastEmitInst_rr - Emit a MachineInstr with two register operands
   /// and a result register in the given register class.
   ///
   unsigned FastEmitInst_rr(unsigned MachineInstOpcode,
                            const TargetRegisterClass *RC,
                            unsigned Op0, unsigned Op1);
 
+  /// FastEmitInst_ri - Emit a MachineInstr with two register operands
+  /// and a result register in the given register class.
+  ///
+  unsigned FastEmitInst_ri(unsigned MachineInstOpcode,
+                           const TargetRegisterClass *RC,
+                           unsigned Op0, uint64_t Imm);
+
+  /// FastEmitInst_rri - Emit a MachineInstr with two register operands,
+  /// an immediate, and a result register in the given register class.
+  ///
+  unsigned FastEmitInst_rri(unsigned MachineInstOpcode,
+                            const TargetRegisterClass *RC,
+                            unsigned Op0, unsigned Op1, uint64_t Imm);
+
 private:
   unsigned createResultReg(const TargetRegisterClass *RC);
 

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

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Wed Aug 20 20:41:07 2008
@@ -26,15 +26,33 @@
 ///
 bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
                               DenseMap<const Value*, unsigned> &ValueMap) {
+  MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
+  if (VT == MVT::Other || !VT.isSimple())
+    // Unhandled type. Halt "fast" selection and bail.
+    return false;
+
   unsigned Op0 = ValueMap[I->getOperand(0)];
-  unsigned Op1 = ValueMap[I->getOperand(1)];
-  if (Op0 == 0 || Op1 == 0)
+  if (Op0 == 0)
     // Unhandled operand. Halt "fast" selection and bail.
     return false;
 
-  MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
-  if (VT == MVT::Other || !VT.isSimple())
-    // Unhandled type. Halt "fast" selection and bail.
+  // Check if the second operand is a constant and handle it appropriately.
+  if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
+    unsigned ResultReg = FastEmit_ri_(VT.getSimpleVT(), ISDOpcode, Op0,
+                                      CI->getZExtValue(), 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.
     return false;
 
   unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), ISDOpcode, Op0, Op1);
@@ -67,7 +85,7 @@
         uint64_t Offs = TD.getStructLayout(StTy)->getElementOffset(Field);
         // FIXME: This can be optimized by combining the add with a
         // subsequent one.
-        N = FastEmit_ri(VT.getSimpleVT(), ISD::ADD, N, Offs, VT.getSimpleVT());
+        N = FastEmit_ri_(VT.getSimpleVT(), ISD::ADD, N, Offs, VT.getSimpleVT());
         if (N == 0)
           // Unhandled operand. Halt "fast" selection and bail.
           return false;
@@ -81,7 +99,7 @@
         if (CI->getZExtValue() == 0) continue;
         uint64_t Offs = 
           TD.getABITypeSize(Ty)*cast<ConstantInt>(CI)->getSExtValue();
-        N = FastEmit_ri(VT.getSimpleVT(), ISD::ADD, N, Offs, VT.getSimpleVT());
+        N = FastEmit_ri_(VT.getSimpleVT(), ISD::ADD, N, Offs, VT.getSimpleVT());
         if (N == 0)
           // Unhandled operand. Halt "fast" selection and bail.
           return false;
@@ -108,8 +126,8 @@
 
       // FIXME: If multiple is power of two, turn it into a shift. The
       // optimization should be in FastEmit_ri?
-      IdxN = FastEmit_ri(VT.getSimpleVT(), ISD::MUL, IdxN,
-                         ElementSize, VT.getSimpleVT());
+      IdxN = FastEmit_ri_(VT.getSimpleVT(), ISD::MUL, IdxN,
+                          ElementSize, VT.getSimpleVT());
       if (IdxN == 0)
         // Unhandled operand. Halt "fast" selection and bail.
         return false;
@@ -226,13 +244,18 @@
   return 0;
 }
 
-unsigned FastISel::FastEmit_i(MVT::SimpleValueType, uint64_t) {
+unsigned FastISel::FastEmit_i(MVT::SimpleValueType, uint64_t /*Imm*/) {
   return 0;
 }
 
 unsigned FastISel::FastEmit_ri(MVT::SimpleValueType, ISD::NodeType,
-                               unsigned /*Op0*/, uint64_t Imm,
-                               MVT::SimpleValueType ImmType) {
+                               unsigned /*Op0*/, uint64_t /*Imm*/) {
+  return 0;
+}
+
+unsigned FastISel::FastEmit_rri(MVT::SimpleValueType, ISD::NodeType,
+                                unsigned /*Op0*/, unsigned /*Op1*/,
+                                uint64_t /*Imm*/) {
   return 0;
 }
 
@@ -241,20 +264,27 @@
 /// If that fails, it materializes the immediate into a register and try
 /// FastEmit_rr instead.
 unsigned FastISel::FastEmit_ri_(MVT::SimpleValueType VT, ISD::NodeType Opcode,
-                               unsigned Op0, uint64_t Imm,
-                               MVT::SimpleValueType ImmType) {
+                                unsigned Op0, uint64_t Imm,
+                                MVT::SimpleValueType ImmType) {
   unsigned ResultReg = 0;
   // First check if immediate type is legal. If not, we can't use the ri form.
   if (TLI.getOperationAction(ISD::Constant, ImmType) == TargetLowering::Legal)
-    ResultReg = FastEmit_ri(VT, Opcode, Op0, Imm, ImmType);
+    ResultReg = FastEmit_ri(VT, Opcode, Op0, Imm);
   if (ResultReg != 0)
     return ResultReg;
-  return FastEmit_rr(VT, Opcode, Op0, FastEmit_i(ImmType, Imm));
+  unsigned MaterialReg = FastEmit_i(ImmType, Imm);
+  if (MaterialReg == 0)
+    return 0;
+  return FastEmit_rr(VT, Opcode, Op0, MaterialReg);
+}
+
+unsigned FastISel::createResultReg(const TargetRegisterClass* RC) {
+  return MRI.createVirtualRegister(RC);
 }
 
 unsigned FastISel::FastEmitInst_(unsigned MachineInstOpcode,
                                  const TargetRegisterClass* RC) {
-  unsigned ResultReg = MRI.createVirtualRegister(RC);
+  unsigned ResultReg = createResultReg(RC);
   const TargetInstrDesc &II = TII.get(MachineInstOpcode);
 
   BuildMI(MBB, II, ResultReg);
@@ -264,7 +294,7 @@
 unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode,
                                   const TargetRegisterClass *RC,
                                   unsigned Op0) {
-  unsigned ResultReg = MRI.createVirtualRegister(RC);
+  unsigned ResultReg = createResultReg(RC);
   const TargetInstrDesc &II = TII.get(MachineInstOpcode);
 
   BuildMI(MBB, II, ResultReg).addReg(Op0);
@@ -274,9 +304,29 @@
 unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
                                    const TargetRegisterClass *RC,
                                    unsigned Op0, unsigned Op1) {
-  unsigned ResultReg = MRI.createVirtualRegister(RC);
+  unsigned ResultReg = createResultReg(RC);
   const TargetInstrDesc &II = TII.get(MachineInstOpcode);
 
   BuildMI(MBB, II, ResultReg).addReg(Op0).addReg(Op1);
   return ResultReg;
 }
+
+unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode,
+                                   const TargetRegisterClass *RC,
+                                   unsigned Op0, uint64_t Imm) {
+  unsigned ResultReg = createResultReg(RC);
+  const TargetInstrDesc &II = TII.get(MachineInstOpcode);
+
+  BuildMI(MBB, II, ResultReg).addReg(Op0).addImm(Imm);
+  return ResultReg;
+}
+
+unsigned FastISel::FastEmitInst_rri(unsigned MachineInstOpcode,
+                                    const TargetRegisterClass *RC,
+                                    unsigned Op0, unsigned Op1, uint64_t Imm) {
+  unsigned ResultReg = createResultReg(RC);
+  const TargetInstrDesc &II = TII.get(MachineInstOpcode);
+
+  BuildMI(MBB, II, ResultReg).addReg(Op0).addReg(Op1).addImm(Imm);
+  return ResultReg;
+}

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=55099&r1=55098&r2=55099&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/X86/fast-isel.ll (original)
+++ llvm/trunk/test/CodeGen/X86/fast-isel.ll Wed Aug 20 20:41:07 2008
@@ -16,10 +16,11 @@
   %t3 = and i32 %t2, %s
   %t4 = or i32 %t3, %s
   %t5 = xor i32 %t4, %s
+  %t6 = add i32 %t5, 2
   br label %exit
 
 exit:
-  ret i32 %t5
+  ret i32 %t6
 }
 
 define double @bar(double* %p, double* %q) {

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

==============================================================================
--- llvm/trunk/utils/TableGen/FastISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/FastISelEmitter.cpp Wed Aug 20 20:41:07 2008
@@ -66,16 +66,31 @@
                   const CodeGenRegisterClass *DstRC) {
     for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
       TreePatternNode *Op = InstPatNode->getChild(i);
-      if (!Op->isLeaf())
-        return false;
       // For now, filter out any operand with a predicate.
       if (!Op->getPredicateFn().empty())
         return false;
+      // For now, filter out any operand with multiple values.
+      if (Op->getExtTypes().size() != 1)
+        return false;
+      // For now, all the operands must have the same type.
+      if (Op->getTypeNum(0) != VT)
+        return false;
+      if (!Op->isLeaf()) {
+        if (Op->getOperator()->getName() == "imm") {
+          Operands.push_back("i");
+          return true;
+        }
+        // For now, ignore fpimm and other non-leaf nodes.
+        return false;
+      }
       DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue());
       if (!OpDI)
         return false;
       Record *OpLeafRec = OpDI->getDef();
-      // For now, only accept register operands.
+      // TODO: handle instructions which have physreg operands.
+      if (OpLeafRec->isSubClassOf("Register"))
+        return false;
+      // For now, the only other thing we accept is register operands.
       if (!OpLeafRec->isSubClassOf("RegisterClass"))
         return false;
       // For now, require the register operands' register classes to all
@@ -86,9 +101,6 @@
       // For now, all the operands must have the same register class.
       if (DstRC != RC)
         return false;
-      // For now, all the operands must have the same type.
-      if (Op->getTypeNum(0) != VT)
-        return false;
       Operands.push_back("r");
     }
     return true;
@@ -98,6 +110,8 @@
     for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
       if (Operands[i] == "r") {
         OS << "unsigned Op" << i;
+      } else if (Operands[i] == "i") {
+        OS << "uint64_t imm" << i;
       } else {
         assert("Unknown operand kind!");
         abort();
@@ -111,6 +125,8 @@
     for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
       if (Operands[i] == "r") {
         OS << "Op" << i;
+      } else if (Operands[i] == "i") {
+        OS << "imm" << i;
       } else {
         assert("Unknown operand kind!");
         abort();
@@ -239,13 +255,16 @@
         MVT::SimpleValueType VT = TI->first;
 
         OS << "  unsigned FastEmit_" << getLegalCName(Opcode)
-           << "_" << getLegalCName(getName(VT)) << "(";
+           << "_" << getLegalCName(getName(VT)) << "_";
+        Operands.PrintManglingSuffix(OS);
+        OS << "(";
         Operands.PrintParameters(OS);
         OS << ");\n";
       }
 
-      OS << "  unsigned FastEmit_" << getLegalCName(Opcode)
-         << "(MVT::SimpleValueType VT";
+      OS << "  unsigned FastEmit_" << getLegalCName(Opcode) << "_";
+      Operands.PrintManglingSuffix(OS);
+      OS << "(MVT::SimpleValueType VT";
       if (!Operands.empty())
         OS << ", ";
       Operands.PrintParameters(OS);
@@ -293,7 +312,9 @@
   
         OS << "unsigned FastISel::FastEmit_"
            << getLegalCName(Opcode)
-           << "_" << getLegalCName(getName(VT)) << "(";
+           << "_" << getLegalCName(getName(VT)) << "_";
+        Operands.PrintManglingSuffix(OS);
+        OS << "(";
         Operands.PrintParameters(OS);
         OS << ") {\n";
         OS << "  return FastEmitInst_";
@@ -310,7 +331,9 @@
 
       // Emit one function for the opcode that demultiplexes based on the type.
       OS << "unsigned FastISel::FastEmit_"
-         << getLegalCName(Opcode) << "(MVT::SimpleValueType VT";
+         << getLegalCName(Opcode) << "_";
+      Operands.PrintManglingSuffix(OS);
+      OS << "(MVT::SimpleValueType VT";
       if (!Operands.empty())
         OS << ", ";
       Operands.PrintParameters(OS);
@@ -321,7 +344,9 @@
         MVT::SimpleValueType VT = TI->first;
         std::string TypeName = getName(VT);
         OS << "  case " << TypeName << ": return FastEmit_"
-           << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "(";
+           << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";
+        Operands.PrintManglingSuffix(OS);
+        OS << "(";
         Operands.PrintArguments(OS);
         OS << ");\n";
       }
@@ -346,7 +371,9 @@
       const std::string &Opcode = I->first;
 
       OS << "  case " << Opcode << ": return FastEmit_"
-         << getLegalCName(Opcode) << "(VT";
+         << getLegalCName(Opcode) << "_";
+      Operands.PrintManglingSuffix(OS);
+      OS << "(VT";
       if (!Operands.empty())
         OS << ", ";
       Operands.PrintArguments(OS);





More information about the llvm-commits mailing list