initial step at adding a dag-to-dag isel for X86 backend. Patch contributed
authorChris Lattner <sabre@nondot.org>
Wed, 16 Nov 2005 01:54:32 +0000 (01:54 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 16 Nov 2005 01:54:32 +0000 (01:54 +0000)
by Evan Cheng!

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

lib/Target/X86/Makefile
lib/Target/X86/X86ISelDAGToDAG.cpp [new file with mode: 0644]
lib/Target/X86/X86TargetMachine.cpp

index 423f1bfac88e4723d2205eab00b2c828d236e10f..67c5dc4d900648a6f8a2f768deacbfd5c397472e 100644 (file)
@@ -13,7 +13,7 @@ TARGET = X86
 BUILT_SOURCES = X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \
                 X86GenRegisterInfo.inc X86GenInstrNames.inc \
                 X86GenInstrInfo.inc X86GenAsmWriter.inc \
-                X86GenAsmWriter1.inc
+                X86GenAsmWriter1.inc X86GenDAGISel.inc 
 
 include $(LEVEL)/Makefile.common
 
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
new file mode 100644 (file)
index 0000000..35db929
--- /dev/null
@@ -0,0 +1,163 @@
+//===-- X86ISelPattern.cpp - A DAG pattern matching inst selector for X86 -===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the Evan Cheng and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a DAG pattern matching instruction selector for X86,
+// converting from a legalized dag to a X86 dag.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86.h"
+#include "X86Subtarget.h"
+#include "X86ISelLowering.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/ADT/Statistic.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+//                      Pattern Matcher Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+  Statistic<>
+  NumFPKill("x86-codegen", "Number of FP_REG_KILL instructions added");
+
+  //===--------------------------------------------------------------------===//
+  /// ISel - X86 specific code to select X86 machine instructions for
+  /// SelectionDAG operations.
+  ///
+  class X86DAGToDAGISel : public SelectionDAGISel {
+    /// ContainsFPCode - Every instruction we select that uses or defines a FP
+    /// register should set this to true.
+    bool ContainsFPCode;
+
+    /// X86Lowering - This object fully describes how to lower LLVM code to an
+    /// X86-specific SelectionDAG.
+    X86TargetLowering X86Lowering;
+
+    /// Subtarget - Keep a pointer to the X86Subtarget around so that we can
+    /// make the right decision when generating code for different targets.
+    const X86Subtarget *Subtarget;
+  public:
+    X86DAGToDAGISel(TargetMachine &TM)
+      : SelectionDAGISel(X86Lowering), X86Lowering(TM) {
+      Subtarget = &TM.getSubtarget<X86Subtarget>();
+    }
+
+    virtual const char *getPassName() const {
+      return "X86 DAG->DAG Instruction Selection";
+    }
+
+    /// InstructionSelectBasicBlock - This callback is invoked by
+    /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
+    virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
+
+// Include the pieces autogenerated from the target description.
+#include "X86GenDAGISel.inc"
+
+  private:
+    SDOperand Select(SDOperand N);
+
+    /// getI16Imm - Return a target constant with the specified value, of type
+    /// i16.
+    inline SDOperand getI16Imm(unsigned Imm) {
+      return CurDAG->getTargetConstant(Imm, MVT::i16);
+    }
+
+    /// getI32Imm - Return a target constant with the specified value, of type
+    /// i32.
+    inline SDOperand getI32Imm(unsigned Imm) {
+      return CurDAG->getTargetConstant(Imm, MVT::i32);
+    }
+  };
+}
+
+/// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel
+/// when it has created a SelectionDAG for us to codegen.
+void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
+  DEBUG(BB->dump());
+
+  // Codegen the basic block.
+  DAG.setRoot(Select(DAG.getRoot()));
+  DAG.RemoveDeadNodes();
+
+  // Emit machine code to BB. 
+  ScheduleAndEmitDAG(DAG);
+}
+
+SDOperand X86DAGToDAGISel::Select(SDOperand Op) {
+  SDNode *N = Op.Val;
+  MVT::ValueType OpVT = Op.getValueType();
+  unsigned Opc;
+
+  if (N->getOpcode() >= ISD::BUILTIN_OP_END)
+    return Op;   // Already selected.
+  
+  switch (N->getOpcode()) {
+    default: break;
+    case ISD::Constant: {
+      switch (OpVT) {
+        default: assert(0 && "Cannot use constants of this type!");
+        case MVT::i1:
+        case MVT::i8:  Opc = X86::MOV8ri;  break;
+        case MVT::i16: Opc = X86::MOV16ri; break;
+        case MVT::i32: Opc = X86::MOV32ri; break;
+      }
+      unsigned CVal = cast<ConstantSDNode>(N)->getValue();
+      SDOperand Op1 = CurDAG->getTargetConstant(CVal, OpVT);
+      CurDAG->SelectNodeTo(N, Opc, OpVT, Op1);
+      return Op;
+    }
+
+    case ISD::RET: {
+      SDOperand Chain = Select(N->getOperand(0));     // Token chain.
+      switch (N->getNumOperands()) {
+        default:
+          assert(0 && "Unknown return instruction!");
+        case 3:
+          assert(0 && "Not yet handled return instruction!");
+          break;
+        case 2: {
+          SDOperand Val = Select(N->getOperand(1));
+          switch (N->getOperand(1).getValueType()) {
+            default:
+              assert(0 && "All other types should have been promoted!!");
+            case MVT::i32:
+              Chain = CurDAG->getCopyToReg(Chain, X86::EAX, Val);
+              break;
+            case MVT::f32:
+            case MVT::f64:
+              assert(0 && "Not yet handled return instruction!");
+              break;
+          }
+        }
+        case 1:
+          break;
+      }
+      if (X86Lowering.getBytesToPopOnReturn() == 0)
+        CurDAG->SelectNodeTo(N, X86::RET, MVT::Other, Chain);
+      else
+        CurDAG->SelectNodeTo(N, X86::RET, MVT::Other, Chain,
+                             getI16Imm(X86Lowering.getBytesToPopOnReturn()));
+
+      return SDOperand(N, 0);
+    }
+  }
+
+  return SelectCode(Op);
+}
+
+/// createX86ISelDag - This pass converts a legalized DAG into a 
+/// X86-specific DAG, ready for instruction scheduling.
+///
+FunctionPass *llvm::createX86ISelDag(TargetMachine &TM) {
+  return new X86DAGToDAGISel(TM);
+}
index 4862a230cb0914a2a8bb5c02ad480ecb1dc281e8..1d87152d1096601d26812c5f99a44407738f441a 100644 (file)
@@ -47,6 +47,9 @@ namespace {
                 cl::location(X86ScalarSSE),
                 cl::init(false));
 
+  cl::opt<bool> EnableX86DAGDAG("enable-x86-dag-isel", cl::Hidden,
+                      cl::desc("Enable DAG-to-DAG isel for X86"));
+  
   // FIXME: This should eventually be handled with target triples and
   // subtarget support!
   cl::opt<X86VectorEnum, true>
@@ -124,7 +127,10 @@ bool X86TargetMachine::addPassesToEmitFile(PassManager &PM, std::ostream &Out,
   PM.add(createUnreachableBlockEliminationPass());
 
   // Install an instruction selector.
-  PM.add(createX86ISelPattern(*this));
+  if (EnableX86DAGDAG)
+    PM.add(createX86ISelDag(*this));
+  else
+    PM.add(createX86ISelPattern(*this));
 
   // Run optional SSA-based machine code optimizations next...
   if (!NoSSAPeephole)
@@ -192,7 +198,10 @@ void X86JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
   PM.add(createUnreachableBlockEliminationPass());
 
   // Install an instruction selector.
-  PM.add(createX86ISelPattern(TM));
+  if (EnableX86DAGDAG)
+    PM.add(createX86ISelDag(TM));
+  else
+    PM.add(createX86ISelPattern(TM));
 
   // Run optional SSA-based machine code optimizations next...
   if (!NoSSAPeephole)