From a3355ffb3d30d19d226bbb75707991c60f236e37 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Mon, 3 Dec 2007 20:06:50 +0000 Subject: Rather than having special rules like "intrinsics cannot throw exceptions", just mark intrinsics with the nounwind attribute. Likewise, mark intrinsics as readnone/readonly and get rid of special aliasing logic (which didn't use anything more than this anyway). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44544 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Function.h | 10 +++++ include/llvm/Instructions.h | 30 ++++++++++++++ include/llvm/Intrinsics.h | 5 +++ include/llvm/Support/CallSite.h | 6 +++ lib/Analysis/AliasAnalysis.cpp | 8 ++-- lib/Analysis/BasicAliasAnalysis.cpp | 37 ------------------ lib/Analysis/IPA/CallGraph.cpp | 2 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 24 ++---------- lib/Target/CBackend/CBackend.cpp | 2 +- lib/Target/MSIL/MSILWriter.cpp | 2 +- lib/Transforms/IPO/DeadArgumentElimination.cpp | 2 +- lib/Transforms/Scalar/LowerGC.cpp | 2 +- lib/Transforms/Scalar/SimplifyCFG.cpp | 2 +- lib/Transforms/Utils/InlineFunction.cpp | 8 ++-- lib/VMCore/AutoUpgrade.cpp | 13 ++++++- lib/VMCore/Function.cpp | 33 ++++++++++++++-- lib/VMCore/Instruction.cpp | 19 ++------- lib/VMCore/Instructions.cpp | 13 ++++++- lib/VMCore/Mangler.cpp | 2 +- tools/bugpoint/Miscompilation.cpp | 2 +- utils/TableGen/IntrinsicEmitter.cpp | 54 +++++--------------------- utils/TableGen/IntrinsicEmitter.h | 6 +-- 22 files changed, 136 insertions(+), 146 deletions(-) diff --git a/include/llvm/Function.h b/include/llvm/Function.h index 627b47f9d9..20a43e285c 100644 --- a/include/llvm/Function.h +++ b/include/llvm/Function.h @@ -158,6 +158,16 @@ public: return ParamAttrs && ParamAttrs->paramHasAttr(i, attr); } + /// @brief Determine if the function does not access memory. + bool doesNotAccessMemory() const { + return paramHasAttr(0, ParamAttr::ReadNone); + } + + /// @brief Determine if the function does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); + } + /// @brief Determine if the function returns a structure. bool isStructReturn() const { return paramHasAttr(1, ParamAttr::StructRet); diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 34b22c7802..2d721bb414 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -927,6 +927,21 @@ public: /// @brief Determine whether the call or the callee has the given attribute. bool paramHasAttr(uint16_t i, ParameterAttributes attr) const; + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const { + return paramHasAttr(0, ParamAttr::ReadNone); + } + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); + } + + /// @brief Determine if the call cannot unwind. + bool isNoUnwind() const { + return paramHasAttr(0, ParamAttr::NoUnwind); + } + /// @brief Determine if the call returns a structure. bool isStructReturn() const { // Be friendly and also check the callee. @@ -1711,6 +1726,21 @@ public: /// @brief Determine whether the call or the callee has the given attribute. bool paramHasAttr(uint16_t i, ParameterAttributes attr) const; + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const { + return paramHasAttr(0, ParamAttr::ReadNone); + } + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); + } + + /// @brief Determine if the call cannot unwind. + bool isNoUnwind() const { + return paramHasAttr(0, ParamAttr::NoUnwind); + } + /// @brief Determine if the call returns a structure. bool isStructReturn() const { // Be friendly and also check the callee. diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h index 3a97b33358..47662501d6 100644 --- a/include/llvm/Intrinsics.h +++ b/include/llvm/Intrinsics.h @@ -22,6 +22,7 @@ class Type; class FunctionType; class Function; class Module; +class ParamAttrsList; /// Intrinsic Namespace - This namespace contains an enum with a value for /// every intrinsic/builtin function known by LLVM. These enum values are @@ -46,6 +47,10 @@ namespace Intrinsic { /// const FunctionType *getType(ID id, const Type **Tys = 0, unsigned numTys = 0); + /// Intrinsic::getParamAttrs(ID) - Return the attributes for an intrinsic. + /// + const ParamAttrsList *getParamAttrs(ID id); + /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function /// declaration for an intrinsic, and return it. Function *getDeclaration(Module *M, ID id, const Type **Tys = 0, diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index b613dffe97..5bb60a8a8a 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -67,6 +67,12 @@ public: /// paramHasAttr - whether the call or the callee has the given attribute. bool paramHasAttr(uint16_t i, ParameterAttributes attr) const; + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const; + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const; + /// getType - Return the type of the instruction that generated this call site /// const Type *getType() const { return I->getType(); } diff --git a/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp index 9e1ae2a0d2..12ea937fa9 100644 --- a/lib/Analysis/AliasAnalysis.cpp +++ b/lib/Analysis/AliasAnalysis.cpp @@ -116,13 +116,13 @@ AliasAnalysis::getModRefInfo(StoreInst *S, Value *P, unsigned Size) { AliasAnalysis::ModRefBehavior AliasAnalysis::getModRefBehavior(CallSite CS, std::vector *Info) { - if (CS.paramHasAttr(0, ParamAttr::ReadNone)) + if (CS.doesNotAccessMemory()) // Can't do better than this. return DoesNotAccessMemory; ModRefBehavior MRB = UnknownModRefBehavior; if (Function *F = CS.getCalledFunction()) MRB = getModRefBehavior(F, CS, Info); - if (MRB != DoesNotAccessMemory && CS.paramHasAttr(0, ParamAttr::ReadOnly)) + if (MRB != DoesNotAccessMemory && CS.onlyReadsMemory()) return OnlyReadsMemory; return MRB; } @@ -130,11 +130,11 @@ AliasAnalysis::getModRefBehavior(CallSite CS, AliasAnalysis::ModRefBehavior AliasAnalysis::getModRefBehavior(Function *F, std::vector *Info) { - if (F->paramHasAttr(0, ParamAttr::ReadNone)) + if (F->doesNotAccessMemory()) // Can't do better than this. return DoesNotAccessMemory; ModRefBehavior MRB = getModRefBehavior(F, CallSite(), Info); - if (MRB != DoesNotAccessMemory && F->paramHasAttr(0, ParamAttr::ReadOnly)) + if (MRB != DoesNotAccessMemory && F->onlyReadsMemory()) return OnlyReadsMemory; return MRB; } diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 5ec9afaec9..99d9499a52 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -25,8 +25,6 @@ #include "llvm/Pass.h" #include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/GetElementPtrTypeIterator.h" @@ -116,9 +114,6 @@ namespace { /// global) or not. bool pointsToConstantMemory(const Value *P); - virtual ModRefBehavior getModRefBehavior(Function *F, CallSite CS, - std::vector *Info); - private: // CheckGEPInstructions - Check two GEP instructions with known // must-aliasing base pointers. This checks to see if the index expressions @@ -810,37 +805,5 @@ BasicAliasAnalysis::CheckGEPInstructions( return MayAlias; } -static ManagedStatic NoMemoryIntrinsics; -static ManagedStatic OnlyReadsMemoryIntrinsics; - -AliasAnalysis::ModRefBehavior -BasicAliasAnalysis::getModRefBehavior(Function *F, CallSite CS, - std::vector *Info) { - if (!F->isDeclaration()) return UnknownModRefBehavior; - - static bool Initialized = false; - if (!Initialized) { - NoMemoryIntrinsics->resize(Intrinsic::num_intrinsics); - OnlyReadsMemoryIntrinsics->resize(Intrinsic::num_intrinsics); -#define GET_MODREF_BEHAVIOR -#include "llvm/Intrinsics.gen" -#undef GET_MODREF_BEHAVIOR - - Initialized = true; - } - - // If this is an intrinsic, we can use lookup tables - if (unsigned id = F->getIntrinsicID()) { - if (NoMemoryIntrinsics->test(id)) - return DoesNotAccessMemory; - if (OnlyReadsMemoryIntrinsics->test(id)) - return OnlyReadsMemory; - - return UnknownModRefBehavior; - } - - return UnknownModRefBehavior; -} - // Make sure that anything that uses AliasAnalysis pulls in this file... DEFINING_FILE_FOR(BasicAliasAnalysis) diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp index 5f9850c93d..e26ad7a7aa 100644 --- a/lib/Analysis/IPA/CallGraph.cpp +++ b/lib/Analysis/IPA/CallGraph.cpp @@ -136,7 +136,7 @@ private: // If this function is not defined in this translation unit, it could call // anything. - if (F->isDeclaration() && !F->getIntrinsicID()) + if (F->isDeclaration() && !F->isIntrinsic()) Node->addCalledFunction(CallSite(), CallsExternalNode); // Loop over all of the users of the function... looking for callers... diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index a350ea95f7..ed89878a0d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2417,31 +2417,13 @@ void SelectionDAGLowering::visitStore(StoreInst &I) { I.isVolatile(), I.getAlignment())); } -/// IntrinsicCannotAccessMemory - Return true if the specified intrinsic cannot -/// access memory and has no other side effects at all. -static bool IntrinsicCannotAccessMemory(unsigned IntrinsicID) { -#define GET_NO_MEMORY_INTRINSICS -#include "llvm/Intrinsics.gen" -#undef GET_NO_MEMORY_INTRINSICS - return false; -} - -// IntrinsicOnlyReadsMemory - Return true if the specified intrinsic doesn't -// have any side-effects or if it only reads memory. -static bool IntrinsicOnlyReadsMemory(unsigned IntrinsicID) { -#define GET_SIDE_EFFECT_INFO -#include "llvm/Intrinsics.gen" -#undef GET_SIDE_EFFECT_INFO - return false; -} - /// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC /// node. void SelectionDAGLowering::visitTargetIntrinsic(CallInst &I, unsigned Intrinsic) { - bool HasChain = !IntrinsicCannotAccessMemory(Intrinsic); - bool OnlyLoad = HasChain && IntrinsicOnlyReadsMemory(Intrinsic); - + bool HasChain = !I.doesNotAccessMemory(); + bool OnlyLoad = HasChain && I.onlyReadsMemory(); + // Build the operand list. SmallVector Ops; if (HasChain) { // If this intrinsic has side-effects, chainify it. diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 2d18468215..54a5f426cb 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -1551,7 +1551,7 @@ bool CWriter::doInitialization(Module &M) { for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { // Don't print declarations for intrinsic functions. - if (!I->getIntrinsicID() && I->getName() != "setjmp" && + if (!I->isIntrinsic() && I->getName() != "setjmp" && I->getName() != "longjmp" && I->getName() != "_setjmp") { if (I->hasExternalWeakLinkage()) Out << "extern "; diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp index dafdbe7b2e..87107d8908 100644 --- a/lib/Target/MSIL/MSILWriter.cpp +++ b/lib/Target/MSIL/MSILWriter.cpp @@ -1586,7 +1586,7 @@ void MSILWriter::printExternals() { // Functions. for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) { // Skip intrisics - if (I->getIntrinsicID()) continue; + if (I->isIntrinsic()) continue; if (I->isDeclaration()) { const Function* F = I; std::string Name = getConvModopt(F->getCallingConv())+getValueName(F); diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index a76a43a20b..446b9652e1 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -284,7 +284,7 @@ void DAE::SurveyFunction(Function &F) { Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? Live : Dead; if (!F.hasInternalLinkage() && - (!ShouldHackArguments() || F.getIntrinsicID())) + (!ShouldHackArguments() || F.isIntrinsic())) FunctionIntrinsicallyLive = true; else for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { diff --git a/lib/Transforms/Scalar/LowerGC.cpp b/lib/Transforms/Scalar/LowerGC.cpp index aff3f2cb30..9935a84cda 100644 --- a/lib/Transforms/Scalar/LowerGC.cpp +++ b/lib/Transforms/Scalar/LowerGC.cpp @@ -177,7 +177,7 @@ bool LowerGC::runOnFunction(Function &F) { for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) if (CallInst *CI = dyn_cast(II++)) { if (!CI->getCalledFunction() || - !CI->getCalledFunction()->getIntrinsicID()) + !CI->getCalledFunction()->isIntrinsic()) NormalCalls.push_back(CI); // Remember all normal function calls. if (Function *F = CI->getCalledFunction()) diff --git a/lib/Transforms/Scalar/SimplifyCFG.cpp b/lib/Transforms/Scalar/SimplifyCFG.cpp index 259f4d1626..eb1ed4e60d 100644 --- a/lib/Transforms/Scalar/SimplifyCFG.cpp +++ b/lib/Transforms/Scalar/SimplifyCFG.cpp @@ -135,7 +135,7 @@ static bool MarkAliveBlocks(BasicBlock *BB, // Turn invokes that call 'nounwind' functions into ordinary calls. if (InvokeInst *II = dyn_cast(BB->getTerminator())) - if (II->paramHasAttr(0, ParamAttr::NoUnwind)) { + if (II->isNoUnwind()) { ChangeToCall(II); Changed = true; } diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 2a6d9ae9a2..e9f6b28e98 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -69,13 +69,11 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock, if (!isa(I)) continue; CallInst *CI = cast(I); - // If this is an intrinsic function call or an inline asm, don't + // If this call cannot unwind or is an inline asm, don't // convert it to an invoke. - if ((CI->getCalledFunction() && - CI->getCalledFunction()->getIntrinsicID()) || - isa(CI->getCalledValue())) + if (CI->isNoUnwind() || isa(CI->getCalledValue())) continue; - + // Convert this function call into an invoke instruction. // First, split the basic block. BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc"); diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index 40c431c279..311941f0d7 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -20,7 +20,7 @@ using namespace llvm; -Function* llvm::UpgradeIntrinsicFunction(Function *F) { +static Function* UpgradeIntrinsicFunction1(Function *F) { assert(F && "Illegal to upgrade a non-existent Function."); // Get the Function's name. @@ -119,6 +119,17 @@ Function* llvm::UpgradeIntrinsicFunction(Function *F) { return 0; } +Function* llvm::UpgradeIntrinsicFunction(Function *F) { + Function *Upgraded = UpgradeIntrinsicFunction1(F); + + // Upgrade intrinsic attributes. This does not change the function. + if (Upgraded) + F = Upgraded; + if (unsigned id = F->getIntrinsicID(true)) + F->setParamAttrs(Intrinsic::getParamAttrs((Intrinsic::ID)id)); + return Upgraded; +} + // UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the // upgraded intrinsic. All argument and return casting must be provided in // order to seamlessly integrate with existing context. diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 37949559aa..04db3aa06c 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/LeakDetector.h" #include "llvm/Support/ManagedStatic.h" #include "SymbolTableListTraitsImpl.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; @@ -435,12 +436,36 @@ const FunctionType *Intrinsic::getType(ID id, const Type **Tys, return FunctionType::get(ResultTy, ArgTys, IsVarArg); } +const ParamAttrsList *Intrinsic::getParamAttrs(ID id) { + static const ParamAttrsList *IntrinsicAttributes[Intrinsic::num_intrinsics]; + + if (IntrinsicAttributes[id]) + return IntrinsicAttributes[id]; + + ParamAttrsVector Attrs; + uint16_t Attr = ParamAttr::None; + +#define GET_INTRINSIC_ATTRIBUTES +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_ATTRIBUTES + + // Intrinsics cannot throw exceptions. + Attr |= ParamAttr::NoUnwind; + + Attrs.push_back(ParamAttrsWithIndex::get(0, Attr)); + IntrinsicAttributes[id] = ParamAttrsList::get(Attrs); + return IntrinsicAttributes[id]; +} + Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys, unsigned numTys) { -// There can never be multiple globals with the same name of different types, -// because intrinsics must be a specific type. - return cast(M->getOrInsertFunction(getName(id, Tys, numTys), - getType(id, Tys, numTys))); + // There can never be multiple globals with the same name of different types, + // because intrinsics must be a specific type. + Function *F = + cast(M->getOrInsertFunction(getName(id, Tys, numTys), + getType(id, Tys, numTys))); + F->setParamAttrs(getParamAttrs(id)); + return F; } Value *IntrinsicInst::StripPointerCasts(Value *Ptr) { diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index a3687530de..9b208854ba 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -13,8 +13,8 @@ #include "llvm/Type.h" #include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" #include "llvm/Function.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/LeakDetector.h" using namespace llvm; @@ -197,31 +197,18 @@ bool Instruction::isSameOperationAs(Instruction *I) const { return true; } -// IntrinsicOnlyReadsMemory - Return true if the specified intrinsic doesn't -// have any side-effects or if it only reads memory. -static bool IntrinsicOnlyReadsMemory(unsigned IntrinsicID) { -#define GET_SIDE_EFFECT_INFO -#include "llvm/Intrinsics.gen" -#undef GET_SIDE_EFFECT_INFO - return false; -} - /// mayWriteToMemory - Return true if this instruction may modify memory. /// bool Instruction::mayWriteToMemory() const { switch (getOpcode()) { default: return false; case Instruction::Free: - case Instruction::Store: case Instruction::Invoke: + case Instruction::Store: case Instruction::VAArg: return true; case Instruction::Call: - if (const IntrinsicInst *II = dyn_cast(this)) { - // If the intrinsic doesn't write memory, it is safe. - return !IntrinsicOnlyReadsMemory(II->getIntrinsicID()); - } - return true; + return !cast(this)->onlyReadsMemory(); case Instruction::Load: return cast(this)->isVolatile(); } diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 7ad588c72e..0df0466112 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -53,7 +53,18 @@ bool CallSite::paramHasAttr(uint16_t i, ParameterAttributes attr) const { else return cast(I)->paramHasAttr(i, attr); } - +bool CallSite::doesNotAccessMemory() const { + if (CallInst *CI = dyn_cast(I)) + return CI->doesNotAccessMemory(); + else + return cast(I)->doesNotAccessMemory(); +} +bool CallSite::onlyReadsMemory() const { + if (CallInst *CI = dyn_cast(I)) + return CI->onlyReadsMemory(); + else + return cast(I)->onlyReadsMemory(); +} diff --git a/lib/VMCore/Mangler.cpp b/lib/VMCore/Mangler.cpp index 8b8ba598ef..8689c86d08 100644 --- a/lib/VMCore/Mangler.cpp +++ b/lib/VMCore/Mangler.cpp @@ -135,7 +135,7 @@ std::string Mangler::getValueName(const GlobalValue *GV, const char * Suffix) { // Name mangling occurs as follows: // - If V is an intrinsic function, do not change name at all // - Otherwise, mangling occurs if global collides with existing name. - if (isa(GV) && cast(GV)->getIntrinsicID()) { + if (isa(GV) && cast(GV)->isIntrinsic()) { Name = GV->getName(); // Is an intrinsic function } else if (!GV->hasName()) { // Must mangle the global into a unique ID. diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index c9780e2210..6bf42d4c51 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -685,7 +685,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, // Use the function we just added to get addresses of functions we need. for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc && - F->getIntrinsicID() == 0 /* ignore intrinsics */) { + !F->isIntrinsic() /* ignore intrinsics */) { Function *TestFn = Test->getFunction(F->getName()); // Don't forward functions which are external in the test module too. diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index b7c8093875..47569f3d41 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -42,14 +42,8 @@ void IntrinsicEmitter::run(std::ostream &OS) { // Emit the intrinsic declaration generator. EmitGenerator(Ints, OS); - // Emit mod/ref info for each function. - EmitModRefInfo(Ints, OS); - - // Emit table of non-memory accessing intrinsics. - EmitNoMemoryInfo(Ints, OS); - - // Emit side effect info for each intrinsic. - EmitSideEffectInfo(Ints, OS); + // Emit the intrinsic parameter attributes. + EmitAttributes(Ints, OS); // Emit a list of intrinsics with corresponding GCC builtins. EmitGCCBuiltinList(Ints, OS); @@ -297,30 +291,11 @@ void IntrinsicEmitter::EmitGenerator(const std::vector &Ints, OS << "#endif\n\n"; } -void IntrinsicEmitter::EmitModRefInfo(const std::vector &Ints, - std::ostream &OS) { - OS << "// BasicAliasAnalysis code.\n"; - OS << "#ifdef GET_MODREF_BEHAVIOR\n"; - for (unsigned i = 0, e = Ints.size(); i != e; ++i) { - switch (Ints[i].ModRef) { - default: break; - case CodeGenIntrinsic::NoMem: - OS << " NoMemoryIntrinsics->set(Intrinsic::" << Ints[i].EnumName << ");\n"; - break; - case CodeGenIntrinsic::ReadArgMem: - case CodeGenIntrinsic::ReadMem: - OS << " OnlyReadsMemoryIntrinsics->set(Intrinsic::" << Ints[i].EnumName << ");\n"; - break; - } - } - OS << "#endif\n\n"; -} - void IntrinsicEmitter:: -EmitNoMemoryInfo(const std::vector &Ints, std::ostream &OS) { - OS << "// SelectionDAGIsel code.\n"; - OS << "#ifdef GET_NO_MEMORY_INTRINSICS\n"; - OS << " switch (IntrinsicID) {\n"; +EmitAttributes(const std::vector &Ints, std::ostream &OS) { + OS << "// Add parameter attributes that are not common to all intrinsics.\n"; + OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; + OS << " switch (id) {\n"; OS << " default: break;\n"; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { switch (Ints[i].ModRef) { @@ -330,28 +305,19 @@ EmitNoMemoryInfo(const std::vector &Ints, std::ostream &OS) { break; } } - OS << " return true; // These intrinsics do not reference memory.\n"; - OS << " }\n"; - OS << "#endif\n\n"; -} - -void IntrinsicEmitter:: -EmitSideEffectInfo(const std::vector &Ints, std::ostream &OS){ - OS << "// Return true if doesn't access or only reads memory.\n"; - OS << "#ifdef GET_SIDE_EFFECT_INFO\n"; - OS << " switch (IntrinsicID) {\n"; - OS << " default: break;\n"; + OS << " Attr |= ParamAttr::ReadNone; // These do not access memory.\n"; + OS << " break;\n"; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { switch (Ints[i].ModRef) { default: break; - case CodeGenIntrinsic::NoMem: case CodeGenIntrinsic::ReadArgMem: case CodeGenIntrinsic::ReadMem: OS << " case Intrinsic::" << Ints[i].EnumName << ":\n"; break; } } - OS << " return true; // These intrinsics have no side effects.\n"; + OS << " Attr |= ParamAttr::ReadOnly; // These do not write memory.\n"; + OS << " break;\n"; OS << " }\n"; OS << "#endif\n\n"; } diff --git a/utils/TableGen/IntrinsicEmitter.h b/utils/TableGen/IntrinsicEmitter.h index fa483ce674..aece7a9bc4 100644 --- a/utils/TableGen/IntrinsicEmitter.h +++ b/utils/TableGen/IntrinsicEmitter.h @@ -37,12 +37,8 @@ namespace llvm { std::ostream &OS); void EmitGenerator(const std::vector &Ints, std::ostream &OS); - void EmitModRefInfo(const std::vector &Ints, + void EmitAttributes(const std::vector &Ints, std::ostream &OS); - void EmitNoMemoryInfo(const std::vector &Ints, - std::ostream &OS); - void EmitSideEffectInfo(const std::vector &Ints, - std::ostream &OS); void EmitGCCBuiltinList(const std::vector &Ints, std::ostream &OS); void EmitIntrinsicToGCCBuiltinMap(const std::vector &Ints, -- cgit v1.2.3