From ac0c8680ad53c08189c23f39c79a2147378692df Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 11 Aug 2003 14:59:22 +0000 Subject: [PATCH] Add support for a pattern matching instruction selector. This is still in the early implementation phases, so it is disabled by default git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7719 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/InstSelectPattern.cpp | 117 +++++++++++++++++++++++++++++++++++ lib/Target/X86/Makefile | 25 ++++---- lib/Target/X86/X86.h | 6 ++ lib/Target/X86/X86ISelPattern.cpp | 117 +++++++++++++++++++++++++++++++++++ lib/Target/X86/X86TargetMachine.cpp | 7 ++- 5 files changed, 260 insertions(+), 12 deletions(-) create mode 100644 lib/Target/X86/InstSelectPattern.cpp create mode 100644 lib/Target/X86/X86ISelPattern.cpp diff --git a/lib/Target/X86/InstSelectPattern.cpp b/lib/Target/X86/InstSelectPattern.cpp new file mode 100644 index 00000000000..4b9e381ec17 --- /dev/null +++ b/lib/Target/X86/InstSelectPattern.cpp @@ -0,0 +1,117 @@ +//===-- InstSelectPattern.cpp - A pattern matching inst selector for X86 --===// +// +// This file defines a pattern matching instruction selector for X86. +// +// FIXME: we could allocate one big array of unsigneds to use as the backing +// store for all of the nodes costs arrays. +// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/SSARegMap.h" + +#include "X86RegisterInfo.h" + +// Include the generated instruction selector... +#include "X86GenInstrSelector.inc" + + +//===----------------------------------------------------------------------===// +// User code +// + + +namespace { + struct ISel : public FunctionPass, SelectionDAGTargetBuilder { + TargetMachine &TM; + ISel(TargetMachine &tm) : TM(tm) {} + int VarArgsFrameIndex; // FrameIndex for start of varargs area + + bool runOnFunction(Function &Fn) { + MachineFunction &MF = MachineFunction::construct(&Fn, TM); + SelectionDAG DAG(MF, TM, *this); + + std::cerr << "\n\n\n=== " + << DAG.getMachineFunction().getFunction()->getName() << "\n"; + + DAG.dump(); + X86ISel(DAG).generateCode(); + std::cerr << "\n\n\n"; + return true; + } + + public: // Implementation of the SelectionDAGTargetBuilder class... + /// expandArguments - Add nodes to the DAG to indicate how to load arguments + /// off of the X86 stack. + void expandArguments(SelectionDAG &SD, MachineFunction &MF); + }; +} + + +void ISel::expandArguments(SelectionDAG &SD, MachineFunction &F) { + // Add DAG nodes to load the arguments... On entry to a function on the X86, + // the stack frame looks like this: + // + // [ESP] -- return address + // [ESP + 4] -- first argument (leftmost lexically) + // [ESP + 8] -- second argument, if first argument is four bytes in size + // ... + // + unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot + MachineFrameInfo *MFI = F.getFrameInfo(); + const Function &Fn = *F.getFunction(); + + for (Function::const_aiterator I = Fn.abegin(), E = Fn.aend(); I != E; ++I) { + MVT::ValueType ObjectVT = SD.getValueType(I->getType()); + unsigned ArgIncrement = 4; + unsigned ObjSize; + switch (ObjectVT) { + default: assert(0 && "Unhandled argument type!"); + case MVT::i8: ObjSize = 1; break; + case MVT::i16: ObjSize = 2; break; + case MVT::i32: ObjSize = 4; break; + case MVT::i64: ObjSize = ArgIncrement = 8; break; + case MVT::f32: ObjSize = 4; break; + case MVT::f64: ObjSize = ArgIncrement = 8; break; + } + // Create the frame index object for this incoming parameter... + int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); + + // Create the SelectionDAG nodes corresponding to a load from this parameter + // FIXME: + SelectionDAGNode *FIN = new SelectionDAGNode(ISD::FrameIndex, MVT::i32); + FIN->addValue(new ReducedValue_FrameIndex_i32(FI)); + + SelectionDAGNode *Arg + = new SelectionDAGNode(ISD::Load, ObjectVT, F.begin(), FIN); + + // Add the SelectionDAGNodes to the SelectionDAG... note that there is no + // reason to add chain nodes here. We know that no loads ore stores will + // ever alias these loads, so we are free to perform the load at any time in + // the function + SD.addNode(FIN); + SD.addNodeForValue(Arg, I); + + ArgOffset += ArgIncrement; // Move on to the next argument... + } + + // If the function takes variable number of arguments, make a frame index for + // the start of the first vararg value... for expansion of llvm.va_start. + if (Fn.getFunctionType()->isVarArg()) + VarArgsFrameIndex = MFI->CreateFixedObject(1, ArgOffset); +} + + +/// createX86PatternInstructionSelector - This pass converts an LLVM function +/// into a machine code representation using pattern matching and a machine +/// description file. +/// +Pass *createX86PatternInstructionSelector(TargetMachine &TM) { + return new ISel(TM); +} diff --git a/lib/Target/X86/Makefile b/lib/Target/X86/Makefile index ff4ab7c0194..ee4cf8c85cc 100644 --- a/lib/Target/X86/Makefile +++ b/lib/Target/X86/Makefile @@ -5,22 +5,25 @@ include $(LEVEL)/Makefile.common # Make sure that tblgen is run, first thing. $(SourceDepend): X86GenRegisterInfo.h.inc X86GenRegisterNames.inc \ X86GenRegisterInfo.inc X86GenInstrNames.inc \ - X86GenInstrInfo.inc + X86GenInstrInfo.inc X86GenInstrSelector.inc -X86GenRegisterNames.inc: X86.td X86RegisterInfo.td $(TBLGEN) - $(TBLGEN) X86.td -gen-register-enums -o $@ +X86GenRegisterNames.inc: X86.td X86RegisterInfo.td ../Target.td $(TBLGEN) + $(TBLGEN) $< -gen-register-enums -o $@ -X86GenRegisterInfo.h.inc: X86.td X86RegisterInfo.td $(TBLGEN) - $(TBLGEN) X86.td -gen-register-desc-header -o $@ +X86GenRegisterInfo.h.inc: X86.td X86RegisterInfo.td ../Target.td $(TBLGEN) + $(TBLGEN) $< -gen-register-desc-header -o $@ -X86GenRegisterInfo.inc: X86.td X86RegisterInfo.td $(TBLGEN) - $(TBLGEN) X86.td -gen-register-desc -o $@ +X86GenRegisterInfo.inc: X86.td X86RegisterInfo.td ../Target.td $(TBLGEN) + $(TBLGEN) $< -gen-register-desc -o $@ -X86GenInstrNames.inc: X86.td X86InstrInfo.td $(TBLGEN) - $(TBLGEN) X86.td -gen-instr-enums -o $@ +X86GenInstrNames.inc: X86.td X86InstrInfo.td ../Target.td $(TBLGEN) + $(TBLGEN) $< -gen-instr-enums -o $@ -X86GenInstrInfo.inc: X86.td X86InstrInfo.td $(TBLGEN) - $(TBLGEN) X86.td -gen-instr-desc -o $@ +X86GenInstrInfo.inc: X86.td X86InstrInfo.td ../Target.td $(TBLGEN) + $(TBLGEN) $< -gen-instr-desc -o $@ + +X86GenInstrSelector.inc: X86.td X86InstrInfo.td ../Target.td $(TBLGEN) + $(TBLGEN) $< -gen-instr-selector -o $@ clean:: $(VERB) rm -f *.inc diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 61d3123ef6b..eec254cff2f 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -18,6 +18,12 @@ class Pass; /// Pass *createX86SimpleInstructionSelector(TargetMachine &TM); +/// createX86PatternInstructionSelector - This pass converts an LLVM function +/// into a machine code representation using pattern matching and a machine +/// description file. +/// +Pass *createX86PatternInstructionSelector(TargetMachine &TM); + /// createX86PeepholeOptimizer - Create a pass to perform X86 specific peephole /// optimizations. /// diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp new file mode 100644 index 00000000000..4b9e381ec17 --- /dev/null +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -0,0 +1,117 @@ +//===-- InstSelectPattern.cpp - A pattern matching inst selector for X86 --===// +// +// This file defines a pattern matching instruction selector for X86. +// +// FIXME: we could allocate one big array of unsigneds to use as the backing +// store for all of the nodes costs arrays. +// +//===----------------------------------------------------------------------===// + +#include "X86.h" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/SSARegMap.h" + +#include "X86RegisterInfo.h" + +// Include the generated instruction selector... +#include "X86GenInstrSelector.inc" + + +//===----------------------------------------------------------------------===// +// User code +// + + +namespace { + struct ISel : public FunctionPass, SelectionDAGTargetBuilder { + TargetMachine &TM; + ISel(TargetMachine &tm) : TM(tm) {} + int VarArgsFrameIndex; // FrameIndex for start of varargs area + + bool runOnFunction(Function &Fn) { + MachineFunction &MF = MachineFunction::construct(&Fn, TM); + SelectionDAG DAG(MF, TM, *this); + + std::cerr << "\n\n\n=== " + << DAG.getMachineFunction().getFunction()->getName() << "\n"; + + DAG.dump(); + X86ISel(DAG).generateCode(); + std::cerr << "\n\n\n"; + return true; + } + + public: // Implementation of the SelectionDAGTargetBuilder class... + /// expandArguments - Add nodes to the DAG to indicate how to load arguments + /// off of the X86 stack. + void expandArguments(SelectionDAG &SD, MachineFunction &MF); + }; +} + + +void ISel::expandArguments(SelectionDAG &SD, MachineFunction &F) { + // Add DAG nodes to load the arguments... On entry to a function on the X86, + // the stack frame looks like this: + // + // [ESP] -- return address + // [ESP + 4] -- first argument (leftmost lexically) + // [ESP + 8] -- second argument, if first argument is four bytes in size + // ... + // + unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot + MachineFrameInfo *MFI = F.getFrameInfo(); + const Function &Fn = *F.getFunction(); + + for (Function::const_aiterator I = Fn.abegin(), E = Fn.aend(); I != E; ++I) { + MVT::ValueType ObjectVT = SD.getValueType(I->getType()); + unsigned ArgIncrement = 4; + unsigned ObjSize; + switch (ObjectVT) { + default: assert(0 && "Unhandled argument type!"); + case MVT::i8: ObjSize = 1; break; + case MVT::i16: ObjSize = 2; break; + case MVT::i32: ObjSize = 4; break; + case MVT::i64: ObjSize = ArgIncrement = 8; break; + case MVT::f32: ObjSize = 4; break; + case MVT::f64: ObjSize = ArgIncrement = 8; break; + } + // Create the frame index object for this incoming parameter... + int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); + + // Create the SelectionDAG nodes corresponding to a load from this parameter + // FIXME: + SelectionDAGNode *FIN = new SelectionDAGNode(ISD::FrameIndex, MVT::i32); + FIN->addValue(new ReducedValue_FrameIndex_i32(FI)); + + SelectionDAGNode *Arg + = new SelectionDAGNode(ISD::Load, ObjectVT, F.begin(), FIN); + + // Add the SelectionDAGNodes to the SelectionDAG... note that there is no + // reason to add chain nodes here. We know that no loads ore stores will + // ever alias these loads, so we are free to perform the load at any time in + // the function + SD.addNode(FIN); + SD.addNodeForValue(Arg, I); + + ArgOffset += ArgIncrement; // Move on to the next argument... + } + + // If the function takes variable number of arguments, make a frame index for + // the start of the first vararg value... for expansion of llvm.va_start. + if (Fn.getFunctionType()->isVarArg()) + VarArgsFrameIndex = MFI->CreateFixedObject(1, ArgOffset); +} + + +/// createX86PatternInstructionSelector - This pass converts an LLVM function +/// into a machine code representation using pattern matching and a machine +/// description file. +/// +Pass *createX86PatternInstructionSelector(TargetMachine &TM) { + return new ISel(TM); +} diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 893e62fd4f7..2de30f7245d 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -20,6 +20,8 @@ namespace { cl::desc("Use Simple RA instead of Local RegAlloc")); cl::opt PrintCode("print-machineinstrs", cl::desc("Print generated machine code")); + cl::opt NoPatternISel("disable-pattern-isel", cl::init(true), + cl::desc("Use the 'simple' X86 instruction selector")); } // allocateX86TargetMachine - Allocate and return a subclass of TargetMachine @@ -59,7 +61,10 @@ bool X86TargetMachine::addPassesToJITCompile(PassManager &PM) { // FIXME: Implement the switch instruction in the instruction selector! PM.add(createLowerSwitchPass()); - PM.add(createX86SimpleInstructionSelector(*this)); + if (NoPatternISel) + PM.add(createX86SimpleInstructionSelector(*this)); + else + PM.add(createX86PatternInstructionSelector(*this)); // TODO: optional optimizations go here -- 2.11.0