From: Chris Lattner Date: Sun, 28 Dec 2003 09:47:19 +0000 (+0000) Subject: implement support for the intrinsic lowering functionality X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4482715f3d1c165be82bd5aed07231f956e472ef;p=oota-llvm.git implement support for the intrinsic lowering functionality git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10629 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/InstSelectPattern.cpp b/lib/Target/X86/InstSelectPattern.cpp index e5182945646..a09d104d418 100644 --- a/lib/Target/X86/InstSelectPattern.cpp +++ b/lib/Target/X86/InstSelectPattern.cpp @@ -27,8 +27,7 @@ // Include the generated instruction selector... #include "X86GenInstrSelector.inc" - -namespace llvm { +using namespace llvm; namespace { struct ISel : public FunctionPass, SelectionDAGTargetBuilder { @@ -120,8 +119,7 @@ void ISel::expandCall(SelectionDAG &SD, CallInst &CI) { /// into a machine code representation using pattern matching and a machine /// description file. /// -FunctionPass *createX86PatternInstructionSelector(TargetMachine &TM) { +FunctionPass *llvm::createX86PatternInstructionSelector(TargetMachine &TM, + IntrinsicLowering &IL) { return new ISel(TM); } - -} // End llvm namespace diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp index b2b15c5b940..0e07579d739 100644 --- a/lib/Target/X86/InstSelectSimple.cpp +++ b/lib/Target/X86/InstSelectSimple.cpp @@ -19,6 +19,7 @@ #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" +#include "llvm/IntrinsicLowering.h" #include "llvm/Pass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -28,8 +29,7 @@ #include "llvm/Target/MRegisterInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/InstVisitor.h" - -namespace llvm { +using namespace llvm; /// BMI - A special BuildMI variant that takes an iterator to insert the /// instruction at as well as a basic block. This is the version for when you @@ -59,6 +59,7 @@ inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB, namespace { struct ISel : public FunctionPass, InstVisitor { TargetMachine &TM; + IntrinsicLowering &IL; MachineFunction *F; // The function we are compiling into MachineBasicBlock *BB; // The current MBB we are compiling int VarArgsFrameIndex; // FrameIndex for start of varargs area @@ -68,12 +69,17 @@ namespace { // MBBMap - Mapping between LLVM BB -> Machine BB std::map MBBMap; - ISel(TargetMachine &tm) : TM(tm), F(0), BB(0) {} + ISel(TargetMachine &tm, IntrinsicLowering &il) + : TM(tm), IL(il), F(0), BB(0) {} /// runOnFunction - Top level implementation of instruction selection for /// the entire function. /// bool runOnFunction(Function &Fn) { + // First pass over the function, lower any unknown intrinsic functions + // with the IntrinsicLowering class. + LowerUnknownIntrinsicFunctionCalls(Fn); + F = &MachineFunction::construct(&Fn, TM); // Create all of the machine basic blocks for the function... @@ -111,6 +117,11 @@ namespace { BB = MBBMap[&LLVM_BB]; } + /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the + /// function, lowering any calls to unknown intrinsic functions into the + /// equivalent LLVM code. + void LowerUnknownIntrinsicFunctionCalls(Function &F); + /// LoadArgumentsToVirtualRegs - Load all of the arguments to this function /// from the stack into virtual registers. /// @@ -1087,6 +1098,33 @@ void ISel::visitCallInst(CallInst &CI) { } +/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the +/// function, lowering any calls to unknown intrinsic functions into the +/// equivalent LLVM code. +void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) { + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) + if (CallInst *CI = dyn_cast(I++)) + if (Function *F = CI->getCalledFunction()) + switch (F->getIntrinsicID()) { + case Intrinsic::va_start: + case Intrinsic::va_copy: + case Intrinsic::va_end: + // We directly implement these intrinsics + break; + default: + // All other intrinsic calls we must lower. + Instruction *Before = CI->getPrev(); + IL.LowerIntrinsicCall(CI); + if (Before) { // Move iterator to instruction after call + I = Before; ++I; + } else { + I = BB->begin(); + } + } + +} + void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { unsigned TmpReg1, TmpReg2; switch (ID) { @@ -1103,17 +1141,7 @@ void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { return; case Intrinsic::va_end: return; // Noop on X86 - case Intrinsic::longjmp: - case Intrinsic::siglongjmp: - BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("abort", true); - return; - - case Intrinsic::setjmp: - case Intrinsic::sigsetjmp: - // Setjmp always returns zero... - BuildMI(BB, X86::MOVir32, 1, getReg(CI)).addZImm(0); - return; - default: assert(0 && "Unknown intrinsic for X86!"); + default: assert(0 && "Error: unknown intrinsics should have been lowered!"); } } @@ -2167,8 +2195,7 @@ void ISel::visitFreeInst(FreeInst &I) { /// into a machine code representation is a very simple peep-hole fashion. The /// generated code sucks but the implementation is nice and simple. /// -FunctionPass *createX86SimpleInstructionSelector(TargetMachine &TM) { - return new ISel(TM); +FunctionPass *llvm::createX86SimpleInstructionSelector(TargetMachine &TM, + IntrinsicLowering &IL) { + return new ISel(TM, IL); } - -} // End llvm namespace diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 35845fb0380..65c13bf001f 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -21,18 +21,21 @@ namespace llvm { class TargetMachine; class FunctionPass; +class IntrinsicLowering; /// createX86SimpleInstructionSelector - This pass converts an LLVM function /// into a machine code representation in a very simple peep-hole fashion. The /// generated code sucks but the implementation is nice and simple. /// -FunctionPass *createX86SimpleInstructionSelector(TargetMachine &TM); +FunctionPass *createX86SimpleInstructionSelector(TargetMachine &TM, + IntrinsicLowering &IL); /// createX86PatternInstructionSelector - This pass converts an LLVM function /// into a machine code representation using pattern matching and a machine /// description file. /// -FunctionPass *createX86PatternInstructionSelector(TargetMachine &TM); +FunctionPass *createX86PatternInstructionSelector(TargetMachine &TM, + IntrinsicLowering &IL); /// createX86SSAPeepholeOptimizerPass - Create a pass to perform SSA-based X86 /// specific peephole optimizations. diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp index e5182945646..a09d104d418 100644 --- a/lib/Target/X86/X86ISelPattern.cpp +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -27,8 +27,7 @@ // Include the generated instruction selector... #include "X86GenInstrSelector.inc" - -namespace llvm { +using namespace llvm; namespace { struct ISel : public FunctionPass, SelectionDAGTargetBuilder { @@ -120,8 +119,7 @@ void ISel::expandCall(SelectionDAG &SD, CallInst &CI) { /// into a machine code representation using pattern matching and a machine /// description file. /// -FunctionPass *createX86PatternInstructionSelector(TargetMachine &TM) { +FunctionPass *llvm::createX86PatternInstructionSelector(TargetMachine &TM, + IntrinsicLowering &IL) { return new ISel(TM); } - -} // End llvm namespace diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp index b2b15c5b940..0e07579d739 100644 --- a/lib/Target/X86/X86ISelSimple.cpp +++ b/lib/Target/X86/X86ISelSimple.cpp @@ -19,6 +19,7 @@ #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" +#include "llvm/IntrinsicLowering.h" #include "llvm/Pass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -28,8 +29,7 @@ #include "llvm/Target/MRegisterInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/InstVisitor.h" - -namespace llvm { +using namespace llvm; /// BMI - A special BuildMI variant that takes an iterator to insert the /// instruction at as well as a basic block. This is the version for when you @@ -59,6 +59,7 @@ inline static MachineInstrBuilder BMI(MachineBasicBlock *MBB, namespace { struct ISel : public FunctionPass, InstVisitor { TargetMachine &TM; + IntrinsicLowering &IL; MachineFunction *F; // The function we are compiling into MachineBasicBlock *BB; // The current MBB we are compiling int VarArgsFrameIndex; // FrameIndex for start of varargs area @@ -68,12 +69,17 @@ namespace { // MBBMap - Mapping between LLVM BB -> Machine BB std::map MBBMap; - ISel(TargetMachine &tm) : TM(tm), F(0), BB(0) {} + ISel(TargetMachine &tm, IntrinsicLowering &il) + : TM(tm), IL(il), F(0), BB(0) {} /// runOnFunction - Top level implementation of instruction selection for /// the entire function. /// bool runOnFunction(Function &Fn) { + // First pass over the function, lower any unknown intrinsic functions + // with the IntrinsicLowering class. + LowerUnknownIntrinsicFunctionCalls(Fn); + F = &MachineFunction::construct(&Fn, TM); // Create all of the machine basic blocks for the function... @@ -111,6 +117,11 @@ namespace { BB = MBBMap[&LLVM_BB]; } + /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the + /// function, lowering any calls to unknown intrinsic functions into the + /// equivalent LLVM code. + void LowerUnknownIntrinsicFunctionCalls(Function &F); + /// LoadArgumentsToVirtualRegs - Load all of the arguments to this function /// from the stack into virtual registers. /// @@ -1087,6 +1098,33 @@ void ISel::visitCallInst(CallInst &CI) { } +/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the +/// function, lowering any calls to unknown intrinsic functions into the +/// equivalent LLVM code. +void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) { + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) + if (CallInst *CI = dyn_cast(I++)) + if (Function *F = CI->getCalledFunction()) + switch (F->getIntrinsicID()) { + case Intrinsic::va_start: + case Intrinsic::va_copy: + case Intrinsic::va_end: + // We directly implement these intrinsics + break; + default: + // All other intrinsic calls we must lower. + Instruction *Before = CI->getPrev(); + IL.LowerIntrinsicCall(CI); + if (Before) { // Move iterator to instruction after call + I = Before; ++I; + } else { + I = BB->begin(); + } + } + +} + void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { unsigned TmpReg1, TmpReg2; switch (ID) { @@ -1103,17 +1141,7 @@ void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) { return; case Intrinsic::va_end: return; // Noop on X86 - case Intrinsic::longjmp: - case Intrinsic::siglongjmp: - BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("abort", true); - return; - - case Intrinsic::setjmp: - case Intrinsic::sigsetjmp: - // Setjmp always returns zero... - BuildMI(BB, X86::MOVir32, 1, getReg(CI)).addZImm(0); - return; - default: assert(0 && "Unknown intrinsic for X86!"); + default: assert(0 && "Error: unknown intrinsics should have been lowered!"); } } @@ -2167,8 +2195,7 @@ void ISel::visitFreeInst(FreeInst &I) { /// into a machine code representation is a very simple peep-hole fashion. The /// generated code sucks but the implementation is nice and simple. /// -FunctionPass *createX86SimpleInstructionSelector(TargetMachine &TM) { - return new ISel(TM); +FunctionPass *llvm::createX86SimpleInstructionSelector(TargetMachine &TM, + IntrinsicLowering &IL) { + return new ISel(TM, IL); } - -} // End llvm namespace diff --git a/lib/Target/X86/X86JITInfo.h b/lib/Target/X86/X86JITInfo.h index bce6e95a563..0ebb4c5208e 100644 --- a/lib/Target/X86/X86JITInfo.h +++ b/lib/Target/X86/X86JITInfo.h @@ -18,10 +18,13 @@ namespace llvm { class TargetMachine; + class IntrinsicLowering; + class X86JITInfo : public TargetJITInfo { TargetMachine &TM; + IntrinsicLowering &IL; public: - X86JITInfo(TargetMachine &tm) : TM(tm) {} + X86JITInfo(TargetMachine &tm, IntrinsicLowering &il) : TM(tm), IL(il) {} /// addPassesToJITCompile - Add passes to the specified pass manager to /// implement a fast dynamic compiler for this target. Return true if this diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 8440838fbfa..e4d1ecb9b14 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -13,6 +13,7 @@ #include "X86TargetMachine.h" #include "X86.h" +#include "llvm/IntrinsicLowering.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Target/TargetMachineImpls.h" @@ -29,23 +30,30 @@ namespace { cl::opt NoPatternISel("disable-pattern-isel", cl::init(true), cl::desc("Use the 'simple' X86 instruction selector")); cl::opt NoSSAPeephole("disable-ssa-peephole", cl::init(true), - cl::desc("Disable the ssa-based peephole optimizer (defaults to disabled)")); + cl::desc("Disable the ssa-based peephole optimizer " + "(defaults to disabled)")); } // allocateX86TargetMachine - Allocate and return a subclass of TargetMachine // that implements the X86 backend. // -TargetMachine *llvm::allocateX86TargetMachine(const Module &M) { - return new X86TargetMachine(M); +TargetMachine *llvm::allocateX86TargetMachine(const Module &M, + IntrinsicLowering *IL) { + return new X86TargetMachine(M, IL); } /// X86TargetMachine ctor - Create an ILP32 architecture model /// -X86TargetMachine::X86TargetMachine(const Module &M) +X86TargetMachine::X86TargetMachine(const Module &M, IntrinsicLowering *il) : TargetMachine("X86", true, 4, 4, 4, 4, 4), + IL(il ? il : new DefaultIntrinsicLowering()), FrameInfo(TargetFrameInfo::StackGrowsDown, 8/*16 for SSE*/, 4), - JITInfo(*this) { + JITInfo(*this, *IL) { +} + +X86TargetMachine::~X86TargetMachine() { + delete IL; } @@ -64,9 +72,9 @@ bool X86TargetMachine::addPassesToEmitAssembly(PassManager &PM, PM.add(createCFGSimplificationPass()); if (NoPatternISel) - PM.add(createX86SimpleInstructionSelector(*this)); + PM.add(createX86SimpleInstructionSelector(*this, *IL)); else - PM.add(createX86PatternInstructionSelector(*this)); + PM.add(createX86PatternInstructionSelector(*this, *IL)); // Run optional SSA-based machine code optimizations next... if (!NoSSAPeephole) @@ -119,9 +127,9 @@ void X86JITInfo::addPassesToJITCompile(FunctionPassManager &PM) { PM.add(createCFGSimplificationPass()); if (NoPatternISel) - PM.add(createX86SimpleInstructionSelector(TM)); + PM.add(createX86SimpleInstructionSelector(TM, IL)); else - PM.add(createX86PatternInstructionSelector(TM)); + PM.add(createX86PatternInstructionSelector(TM, IL)); // Run optional SSA-based machine code optimizations next... if (!NoSSAPeephole) diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h index fc043500a05..6cd8ac1ab3d 100644 --- a/lib/Target/X86/X86TargetMachine.h +++ b/lib/Target/X86/X86TargetMachine.h @@ -21,13 +21,16 @@ #include "X86JITInfo.h" namespace llvm { +class IntrinsicLowering; class X86TargetMachine : public TargetMachine { + IntrinsicLowering *IL; X86InstrInfo InstrInfo; TargetFrameInfo FrameInfo; X86JITInfo JITInfo; public: - X86TargetMachine(const Module &M); + X86TargetMachine(const Module &M, IntrinsicLowering *IL); + ~X86TargetMachine(); virtual const X86InstrInfo &getInstrInfo() const { return InstrInfo; } virtual const TargetFrameInfo &getFrameInfo() const { return FrameInfo; }