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
This commit is contained in:
Duncan Sands 2007-12-03 20:06:50 +00:00
parent 4cf4b69330
commit a3355ffb3d
22 changed files with 136 additions and 146 deletions

View File

@ -158,6 +158,16 @@ public:
return ParamAttrs && ParamAttrs->paramHasAttr(i, attr); 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. /// @brief Determine if the function returns a structure.
bool isStructReturn() const { bool isStructReturn() const {
return paramHasAttr(1, ParamAttr::StructRet); return paramHasAttr(1, ParamAttr::StructRet);

View File

@ -927,6 +927,21 @@ public:
/// @brief Determine whether the call or the callee has the given attribute. /// @brief Determine whether the call or the callee has the given attribute.
bool paramHasAttr(uint16_t i, ParameterAttributes attr) const; 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. /// @brief Determine if the call returns a structure.
bool isStructReturn() const { bool isStructReturn() const {
// Be friendly and also check the callee. // Be friendly and also check the callee.
@ -1711,6 +1726,21 @@ public:
/// @brief Determine whether the call or the callee has the given attribute. /// @brief Determine whether the call or the callee has the given attribute.
bool paramHasAttr(uint16_t i, ParameterAttributes attr) const; 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. /// @brief Determine if the call returns a structure.
bool isStructReturn() const { bool isStructReturn() const {
// Be friendly and also check the callee. // Be friendly and also check the callee.

View File

@ -22,6 +22,7 @@ class Type;
class FunctionType; class FunctionType;
class Function; class Function;
class Module; class Module;
class ParamAttrsList;
/// Intrinsic Namespace - This namespace contains an enum with a value for /// Intrinsic Namespace - This namespace contains an enum with a value for
/// every intrinsic/builtin function known by LLVM. These enum values are /// 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); 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 /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function
/// declaration for an intrinsic, and return it. /// declaration for an intrinsic, and return it.
Function *getDeclaration(Module *M, ID id, const Type **Tys = 0, Function *getDeclaration(Module *M, ID id, const Type **Tys = 0,

View File

@ -67,6 +67,12 @@ public:
/// paramHasAttr - whether the call or the callee has the given attribute. /// paramHasAttr - whether the call or the callee has the given attribute.
bool paramHasAttr(uint16_t i, ParameterAttributes attr) const; 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 /// getType - Return the type of the instruction that generated this call site
/// ///
const Type *getType() const { return I->getType(); } const Type *getType() const { return I->getType(); }

View File

@ -116,13 +116,13 @@ AliasAnalysis::getModRefInfo(StoreInst *S, Value *P, unsigned Size) {
AliasAnalysis::ModRefBehavior AliasAnalysis::ModRefBehavior
AliasAnalysis::getModRefBehavior(CallSite CS, AliasAnalysis::getModRefBehavior(CallSite CS,
std::vector<PointerAccessInfo> *Info) { std::vector<PointerAccessInfo> *Info) {
if (CS.paramHasAttr(0, ParamAttr::ReadNone)) if (CS.doesNotAccessMemory())
// Can't do better than this. // Can't do better than this.
return DoesNotAccessMemory; return DoesNotAccessMemory;
ModRefBehavior MRB = UnknownModRefBehavior; ModRefBehavior MRB = UnknownModRefBehavior;
if (Function *F = CS.getCalledFunction()) if (Function *F = CS.getCalledFunction())
MRB = getModRefBehavior(F, CS, Info); MRB = getModRefBehavior(F, CS, Info);
if (MRB != DoesNotAccessMemory && CS.paramHasAttr(0, ParamAttr::ReadOnly)) if (MRB != DoesNotAccessMemory && CS.onlyReadsMemory())
return OnlyReadsMemory; return OnlyReadsMemory;
return MRB; return MRB;
} }
@ -130,11 +130,11 @@ AliasAnalysis::getModRefBehavior(CallSite CS,
AliasAnalysis::ModRefBehavior AliasAnalysis::ModRefBehavior
AliasAnalysis::getModRefBehavior(Function *F, AliasAnalysis::getModRefBehavior(Function *F,
std::vector<PointerAccessInfo> *Info) { std::vector<PointerAccessInfo> *Info) {
if (F->paramHasAttr(0, ParamAttr::ReadNone)) if (F->doesNotAccessMemory())
// Can't do better than this. // Can't do better than this.
return DoesNotAccessMemory; return DoesNotAccessMemory;
ModRefBehavior MRB = getModRefBehavior(F, CallSite(), Info); ModRefBehavior MRB = getModRefBehavior(F, CallSite(), Info);
if (MRB != DoesNotAccessMemory && F->paramHasAttr(0, ParamAttr::ReadOnly)) if (MRB != DoesNotAccessMemory && F->onlyReadsMemory())
return OnlyReadsMemory; return OnlyReadsMemory;
return MRB; return MRB;
} }

View File

@ -25,8 +25,6 @@
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetData.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/GetElementPtrTypeIterator.h"
@ -116,9 +114,6 @@ namespace {
/// global) or not. /// global) or not.
bool pointsToConstantMemory(const Value *P); bool pointsToConstantMemory(const Value *P);
virtual ModRefBehavior getModRefBehavior(Function *F, CallSite CS,
std::vector<PointerAccessInfo> *Info);
private: private:
// CheckGEPInstructions - Check two GEP instructions with known // CheckGEPInstructions - Check two GEP instructions with known
// must-aliasing base pointers. This checks to see if the index expressions // must-aliasing base pointers. This checks to see if the index expressions
@ -810,37 +805,5 @@ BasicAliasAnalysis::CheckGEPInstructions(
return MayAlias; return MayAlias;
} }
static ManagedStatic<BitVector> NoMemoryIntrinsics;
static ManagedStatic<BitVector> OnlyReadsMemoryIntrinsics;
AliasAnalysis::ModRefBehavior
BasicAliasAnalysis::getModRefBehavior(Function *F, CallSite CS,
std::vector<PointerAccessInfo> *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... // Make sure that anything that uses AliasAnalysis pulls in this file...
DEFINING_FILE_FOR(BasicAliasAnalysis) DEFINING_FILE_FOR(BasicAliasAnalysis)

View File

@ -136,7 +136,7 @@ private:
// If this function is not defined in this translation unit, it could call // If this function is not defined in this translation unit, it could call
// anything. // anything.
if (F->isDeclaration() && !F->getIntrinsicID()) if (F->isDeclaration() && !F->isIntrinsic())
Node->addCalledFunction(CallSite(), CallsExternalNode); Node->addCalledFunction(CallSite(), CallsExternalNode);
// Loop over all of the users of the function... looking for callers... // Loop over all of the users of the function... looking for callers...

View File

@ -2417,31 +2417,13 @@ void SelectionDAGLowering::visitStore(StoreInst &I) {
I.isVolatile(), I.getAlignment())); 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 /// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC
/// node. /// node.
void SelectionDAGLowering::visitTargetIntrinsic(CallInst &I, void SelectionDAGLowering::visitTargetIntrinsic(CallInst &I,
unsigned Intrinsic) { unsigned Intrinsic) {
bool HasChain = !IntrinsicCannotAccessMemory(Intrinsic); bool HasChain = !I.doesNotAccessMemory();
bool OnlyLoad = HasChain && IntrinsicOnlyReadsMemory(Intrinsic); bool OnlyLoad = HasChain && I.onlyReadsMemory();
// Build the operand list. // Build the operand list.
SmallVector<SDOperand, 8> Ops; SmallVector<SDOperand, 8> Ops;
if (HasChain) { // If this intrinsic has side-effects, chainify it. if (HasChain) { // If this intrinsic has side-effects, chainify it.

View File

@ -1551,7 +1551,7 @@ bool CWriter::doInitialization(Module &M) {
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
// Don't print declarations for intrinsic functions. // 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") { I->getName() != "longjmp" && I->getName() != "_setjmp") {
if (I->hasExternalWeakLinkage()) if (I->hasExternalWeakLinkage())
Out << "extern "; Out << "extern ";

View File

@ -1586,7 +1586,7 @@ void MSILWriter::printExternals() {
// Functions. // Functions.
for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) { for (I=ModulePtr->begin(),E=ModulePtr->end(); I!=E; ++I) {
// Skip intrisics // Skip intrisics
if (I->getIntrinsicID()) continue; if (I->isIntrinsic()) continue;
if (I->isDeclaration()) { if (I->isDeclaration()) {
const Function* F = I; const Function* F = I;
std::string Name = getConvModopt(F->getCallingConv())+getValueName(F); std::string Name = getConvModopt(F->getCallingConv())+getValueName(F);

View File

@ -284,7 +284,7 @@ void DAE::SurveyFunction(Function &F) {
Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? Live : Dead; Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? Live : Dead;
if (!F.hasInternalLinkage() && if (!F.hasInternalLinkage() &&
(!ShouldHackArguments() || F.getIntrinsicID())) (!ShouldHackArguments() || F.isIntrinsic()))
FunctionIntrinsicallyLive = true; FunctionIntrinsicallyLive = true;
else else
for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) {

View File

@ -177,7 +177,7 @@ bool LowerGC::runOnFunction(Function &F) {
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;)
if (CallInst *CI = dyn_cast<CallInst>(II++)) { if (CallInst *CI = dyn_cast<CallInst>(II++)) {
if (!CI->getCalledFunction() || if (!CI->getCalledFunction() ||
!CI->getCalledFunction()->getIntrinsicID()) !CI->getCalledFunction()->isIntrinsic())
NormalCalls.push_back(CI); // Remember all normal function calls. NormalCalls.push_back(CI); // Remember all normal function calls.
if (Function *F = CI->getCalledFunction()) if (Function *F = CI->getCalledFunction())

View File

@ -135,7 +135,7 @@ static bool MarkAliveBlocks(BasicBlock *BB,
// Turn invokes that call 'nounwind' functions into ordinary calls. // Turn invokes that call 'nounwind' functions into ordinary calls.
if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
if (II->paramHasAttr(0, ParamAttr::NoUnwind)) { if (II->isNoUnwind()) {
ChangeToCall(II); ChangeToCall(II);
Changed = true; Changed = true;
} }

View File

@ -69,13 +69,11 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
if (!isa<CallInst>(I)) continue; if (!isa<CallInst>(I)) continue;
CallInst *CI = cast<CallInst>(I); CallInst *CI = cast<CallInst>(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. // convert it to an invoke.
if ((CI->getCalledFunction() && if (CI->isNoUnwind() || isa<InlineAsm>(CI->getCalledValue()))
CI->getCalledFunction()->getIntrinsicID()) ||
isa<InlineAsm>(CI->getCalledValue()))
continue; continue;
// Convert this function call into an invoke instruction. // Convert this function call into an invoke instruction.
// First, split the basic block. // First, split the basic block.
BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc"); BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc");

View File

@ -20,7 +20,7 @@
using namespace llvm; using namespace llvm;
Function* llvm::UpgradeIntrinsicFunction(Function *F) { static Function* UpgradeIntrinsicFunction1(Function *F) {
assert(F && "Illegal to upgrade a non-existent Function."); assert(F && "Illegal to upgrade a non-existent Function.");
// Get the Function's name. // Get the Function's name.
@ -119,6 +119,17 @@ Function* llvm::UpgradeIntrinsicFunction(Function *F) {
return 0; 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 // UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the
// upgraded intrinsic. All argument and return casting must be provided in // upgraded intrinsic. All argument and return casting must be provided in
// order to seamlessly integrate with existing context. // order to seamlessly integrate with existing context.

View File

@ -18,6 +18,7 @@
#include "llvm/Support/LeakDetector.h" #include "llvm/Support/LeakDetector.h"
#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/ManagedStatic.h"
#include "SymbolTableListTraitsImpl.h" #include "SymbolTableListTraitsImpl.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
using namespace llvm; using namespace llvm;
@ -435,12 +436,36 @@ const FunctionType *Intrinsic::getType(ID id, const Type **Tys,
return FunctionType::get(ResultTy, ArgTys, IsVarArg); 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, Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys,
unsigned numTys) { unsigned numTys) {
// There can never be multiple globals with the same name of different types, // There can never be multiple globals with the same name of different types,
// because intrinsics must be a specific type. // because intrinsics must be a specific type.
return cast<Function>(M->getOrInsertFunction(getName(id, Tys, numTys), Function *F =
getType(id, Tys, numTys))); cast<Function>(M->getOrInsertFunction(getName(id, Tys, numTys),
getType(id, Tys, numTys)));
F->setParamAttrs(getParamAttrs(id));
return F;
} }
Value *IntrinsicInst::StripPointerCasts(Value *Ptr) { Value *IntrinsicInst::StripPointerCasts(Value *Ptr) {

View File

@ -13,8 +13,8 @@
#include "llvm/Type.h" #include "llvm/Type.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Function.h" #include "llvm/Function.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/LeakDetector.h" #include "llvm/Support/LeakDetector.h"
using namespace llvm; using namespace llvm;
@ -197,31 +197,18 @@ bool Instruction::isSameOperationAs(Instruction *I) const {
return true; 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. /// mayWriteToMemory - Return true if this instruction may modify memory.
/// ///
bool Instruction::mayWriteToMemory() const { bool Instruction::mayWriteToMemory() const {
switch (getOpcode()) { switch (getOpcode()) {
default: return false; default: return false;
case Instruction::Free: case Instruction::Free:
case Instruction::Store:
case Instruction::Invoke: case Instruction::Invoke:
case Instruction::Store:
case Instruction::VAArg: case Instruction::VAArg:
return true; return true;
case Instruction::Call: case Instruction::Call:
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(this)) { return !cast<CallInst>(this)->onlyReadsMemory();
// If the intrinsic doesn't write memory, it is safe.
return !IntrinsicOnlyReadsMemory(II->getIntrinsicID());
}
return true;
case Instruction::Load: case Instruction::Load:
return cast<LoadInst>(this)->isVolatile(); return cast<LoadInst>(this)->isVolatile();
} }

View File

@ -53,7 +53,18 @@ bool CallSite::paramHasAttr(uint16_t i, ParameterAttributes attr) const {
else else
return cast<InvokeInst>(I)->paramHasAttr(i, attr); return cast<InvokeInst>(I)->paramHasAttr(i, attr);
} }
bool CallSite::doesNotAccessMemory() const {
if (CallInst *CI = dyn_cast<CallInst>(I))
return CI->doesNotAccessMemory();
else
return cast<InvokeInst>(I)->doesNotAccessMemory();
}
bool CallSite::onlyReadsMemory() const {
if (CallInst *CI = dyn_cast<CallInst>(I))
return CI->onlyReadsMemory();
else
return cast<InvokeInst>(I)->onlyReadsMemory();
}

View File

@ -135,7 +135,7 @@ std::string Mangler::getValueName(const GlobalValue *GV, const char * Suffix) {
// Name mangling occurs as follows: // Name mangling occurs as follows:
// - If V is an intrinsic function, do not change name at all // - If V is an intrinsic function, do not change name at all
// - Otherwise, mangling occurs if global collides with existing name. // - Otherwise, mangling occurs if global collides with existing name.
if (isa<Function>(GV) && cast<Function>(GV)->getIntrinsicID()) { if (isa<Function>(GV) && cast<Function>(GV)->isIntrinsic()) {
Name = GV->getName(); // Is an intrinsic function Name = GV->getName(); // Is an intrinsic function
} else if (!GV->hasName()) { } else if (!GV->hasName()) {
// Must mangle the global into a unique ID. // Must mangle the global into a unique ID.

View File

@ -685,7 +685,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
// Use the function we just added to get addresses of functions we need. // 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) { for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) {
if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc && if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc &&
F->getIntrinsicID() == 0 /* ignore intrinsics */) { !F->isIntrinsic() /* ignore intrinsics */) {
Function *TestFn = Test->getFunction(F->getName()); Function *TestFn = Test->getFunction(F->getName());
// Don't forward functions which are external in the test module too. // Don't forward functions which are external in the test module too.

View File

@ -42,14 +42,8 @@ void IntrinsicEmitter::run(std::ostream &OS) {
// Emit the intrinsic declaration generator. // Emit the intrinsic declaration generator.
EmitGenerator(Ints, OS); EmitGenerator(Ints, OS);
// Emit mod/ref info for each function. // Emit the intrinsic parameter attributes.
EmitModRefInfo(Ints, OS); EmitAttributes(Ints, OS);
// Emit table of non-memory accessing intrinsics.
EmitNoMemoryInfo(Ints, OS);
// Emit side effect info for each intrinsic.
EmitSideEffectInfo(Ints, OS);
// Emit a list of intrinsics with corresponding GCC builtins. // Emit a list of intrinsics with corresponding GCC builtins.
EmitGCCBuiltinList(Ints, OS); EmitGCCBuiltinList(Ints, OS);
@ -297,30 +291,11 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
OS << "#endif\n\n"; OS << "#endif\n\n";
} }
void IntrinsicEmitter::EmitModRefInfo(const std::vector<CodeGenIntrinsic> &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:: void IntrinsicEmitter::
EmitNoMemoryInfo(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) { EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
OS << "// SelectionDAGIsel code.\n"; OS << "// Add parameter attributes that are not common to all intrinsics.\n";
OS << "#ifdef GET_NO_MEMORY_INTRINSICS\n"; OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
OS << " switch (IntrinsicID) {\n"; OS << " switch (id) {\n";
OS << " default: break;\n"; OS << " default: break;\n";
for (unsigned i = 0, e = Ints.size(); i != e; ++i) { for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
switch (Ints[i].ModRef) { switch (Ints[i].ModRef) {
@ -330,28 +305,19 @@ EmitNoMemoryInfo(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
break; break;
} }
} }
OS << " return true; // These intrinsics do not reference memory.\n"; OS << " Attr |= ParamAttr::ReadNone; // These do not access memory.\n";
OS << " }\n"; OS << " break;\n";
OS << "#endif\n\n";
}
void IntrinsicEmitter::
EmitSideEffectInfo(const std::vector<CodeGenIntrinsic> &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";
for (unsigned i = 0, e = Ints.size(); i != e; ++i) { for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
switch (Ints[i].ModRef) { switch (Ints[i].ModRef) {
default: break; default: break;
case CodeGenIntrinsic::NoMem:
case CodeGenIntrinsic::ReadArgMem: case CodeGenIntrinsic::ReadArgMem:
case CodeGenIntrinsic::ReadMem: case CodeGenIntrinsic::ReadMem:
OS << " case Intrinsic::" << Ints[i].EnumName << ":\n"; OS << " case Intrinsic::" << Ints[i].EnumName << ":\n";
break; 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 << " }\n";
OS << "#endif\n\n"; OS << "#endif\n\n";
} }

View File

@ -37,12 +37,8 @@ namespace llvm {
std::ostream &OS); std::ostream &OS);
void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
std::ostream &OS); std::ostream &OS);
void EmitModRefInfo(const std::vector<CodeGenIntrinsic> &Ints, void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
std::ostream &OS); std::ostream &OS);
void EmitNoMemoryInfo(const std::vector<CodeGenIntrinsic> &Ints,
std::ostream &OS);
void EmitSideEffectInfo(const std::vector<CodeGenIntrinsic> &Ints,
std::ostream &OS);
void EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, void EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints,
std::ostream &OS); std::ostream &OS);
void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,