Chris Lattner | 5930d3d | 2005-11-16 22:59:19 +0000 | [diff] [blame^] | 1 | //===- X86ISelDAGToDAG.cpp - A DAG pattern matching inst selector for X86 -===// |
Chris Lattner | 655e7df | 2005-11-16 01:54:32 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the Evan Cheng and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file defines a DAG pattern matching instruction selector for X86, |
| 11 | // converting from a legalized dag to a X86 dag. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #include "X86.h" |
| 16 | #include "X86Subtarget.h" |
| 17 | #include "X86ISelLowering.h" |
| 18 | #include "llvm/CodeGen/MachineFunction.h" |
| 19 | #include "llvm/CodeGen/SelectionDAGISel.h" |
| 20 | #include "llvm/Target/TargetMachine.h" |
| 21 | #include "llvm/Support/Debug.h" |
| 22 | #include "llvm/ADT/Statistic.h" |
| 23 | using namespace llvm; |
| 24 | |
| 25 | //===----------------------------------------------------------------------===// |
| 26 | // Pattern Matcher Implementation |
| 27 | //===----------------------------------------------------------------------===// |
| 28 | |
| 29 | namespace { |
| 30 | Statistic<> |
| 31 | NumFPKill("x86-codegen", "Number of FP_REG_KILL instructions added"); |
| 32 | |
| 33 | //===--------------------------------------------------------------------===// |
| 34 | /// ISel - X86 specific code to select X86 machine instructions for |
| 35 | /// SelectionDAG operations. |
| 36 | /// |
| 37 | class X86DAGToDAGISel : public SelectionDAGISel { |
| 38 | /// ContainsFPCode - Every instruction we select that uses or defines a FP |
| 39 | /// register should set this to true. |
| 40 | bool ContainsFPCode; |
| 41 | |
| 42 | /// X86Lowering - This object fully describes how to lower LLVM code to an |
| 43 | /// X86-specific SelectionDAG. |
| 44 | X86TargetLowering X86Lowering; |
| 45 | |
| 46 | /// Subtarget - Keep a pointer to the X86Subtarget around so that we can |
| 47 | /// make the right decision when generating code for different targets. |
| 48 | const X86Subtarget *Subtarget; |
| 49 | public: |
| 50 | X86DAGToDAGISel(TargetMachine &TM) |
| 51 | : SelectionDAGISel(X86Lowering), X86Lowering(TM) { |
| 52 | Subtarget = &TM.getSubtarget<X86Subtarget>(); |
| 53 | } |
| 54 | |
| 55 | virtual const char *getPassName() const { |
| 56 | return "X86 DAG->DAG Instruction Selection"; |
| 57 | } |
| 58 | |
| 59 | /// InstructionSelectBasicBlock - This callback is invoked by |
| 60 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. |
| 61 | virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); |
| 62 | |
| 63 | // Include the pieces autogenerated from the target description. |
| 64 | #include "X86GenDAGISel.inc" |
| 65 | |
| 66 | private: |
| 67 | SDOperand Select(SDOperand N); |
| 68 | |
| 69 | /// getI16Imm - Return a target constant with the specified value, of type |
| 70 | /// i16. |
| 71 | inline SDOperand getI16Imm(unsigned Imm) { |
| 72 | return CurDAG->getTargetConstant(Imm, MVT::i16); |
| 73 | } |
| 74 | |
| 75 | /// getI32Imm - Return a target constant with the specified value, of type |
| 76 | /// i32. |
| 77 | inline SDOperand getI32Imm(unsigned Imm) { |
| 78 | return CurDAG->getTargetConstant(Imm, MVT::i32); |
| 79 | } |
| 80 | }; |
| 81 | } |
| 82 | |
| 83 | /// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel |
| 84 | /// when it has created a SelectionDAG for us to codegen. |
| 85 | void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { |
| 86 | DEBUG(BB->dump()); |
| 87 | |
| 88 | // Codegen the basic block. |
| 89 | DAG.setRoot(Select(DAG.getRoot())); |
| 90 | DAG.RemoveDeadNodes(); |
| 91 | |
| 92 | // Emit machine code to BB. |
| 93 | ScheduleAndEmitDAG(DAG); |
| 94 | } |
| 95 | |
| 96 | SDOperand X86DAGToDAGISel::Select(SDOperand Op) { |
| 97 | SDNode *N = Op.Val; |
| 98 | MVT::ValueType OpVT = Op.getValueType(); |
| 99 | unsigned Opc; |
| 100 | |
| 101 | if (N->getOpcode() >= ISD::BUILTIN_OP_END) |
| 102 | return Op; // Already selected. |
| 103 | |
| 104 | switch (N->getOpcode()) { |
| 105 | default: break; |
Chris Lattner | 655e7df | 2005-11-16 01:54:32 +0000 | [diff] [blame] | 106 | case ISD::RET: { |
| 107 | SDOperand Chain = Select(N->getOperand(0)); // Token chain. |
| 108 | switch (N->getNumOperands()) { |
| 109 | default: |
| 110 | assert(0 && "Unknown return instruction!"); |
| 111 | case 3: |
| 112 | assert(0 && "Not yet handled return instruction!"); |
| 113 | break; |
| 114 | case 2: { |
| 115 | SDOperand Val = Select(N->getOperand(1)); |
| 116 | switch (N->getOperand(1).getValueType()) { |
| 117 | default: |
| 118 | assert(0 && "All other types should have been promoted!!"); |
| 119 | case MVT::i32: |
| 120 | Chain = CurDAG->getCopyToReg(Chain, X86::EAX, Val); |
| 121 | break; |
| 122 | case MVT::f32: |
| 123 | case MVT::f64: |
| 124 | assert(0 && "Not yet handled return instruction!"); |
| 125 | break; |
| 126 | } |
| 127 | } |
| 128 | case 1: |
| 129 | break; |
| 130 | } |
| 131 | if (X86Lowering.getBytesToPopOnReturn() == 0) |
| 132 | CurDAG->SelectNodeTo(N, X86::RET, MVT::Other, Chain); |
| 133 | else |
| 134 | CurDAG->SelectNodeTo(N, X86::RET, MVT::Other, Chain, |
| 135 | getI16Imm(X86Lowering.getBytesToPopOnReturn())); |
| 136 | |
| 137 | return SDOperand(N, 0); |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | return SelectCode(Op); |
| 142 | } |
| 143 | |
| 144 | /// createX86ISelDag - This pass converts a legalized DAG into a |
| 145 | /// X86-specific DAG, ready for instruction scheduling. |
| 146 | /// |
| 147 | FunctionPass *llvm::createX86ISelDag(TargetMachine &TM) { |
| 148 | return new X86DAGToDAGISel(TM); |
| 149 | } |