From 9caa214f7252aa77c22d3e8be1119523b5f575d7 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 16 Nov 2005 01:54:32 +0000 Subject: [PATCH] initial step at adding a dag-to-dag isel for X86 backend. Patch contributed by Evan Cheng! llvm-svn: 24371 --- lib/Target/X86/Makefile | 2 +- lib/Target/X86/X86ISelDAGToDAG.cpp | 163 ++++++++++++++++++++++++++++ lib/Target/X86/X86TargetMachine.cpp | 13 ++- 3 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 lib/Target/X86/X86ISelDAGToDAG.cpp diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index 423f1bfac88..67c5dc4d900 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -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 index 00000000000..35db9297f74 --- /dev/null +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -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(); + } + + 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(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); +} diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 4862a230cb0..1d87152d109 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -47,6 +47,9 @@ namespace { cl::location(X86ScalarSSE), cl::init(false)); + cl::opt 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 @@ -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)