Rather than having special rules like "intrinsics cannot
authorDuncan Sands <baldrick@free.fr>
Mon, 3 Dec 2007 20:06:50 +0000 (20:06 +0000)
committerDuncan Sands <baldrick@free.fr>
Mon, 3 Dec 2007 20:06:50 +0000 (20:06 +0000)
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

22 files changed:
include/llvm/Function.h
include/llvm/Instructions.h
include/llvm/Intrinsics.h
include/llvm/Support/CallSite.h
lib/Analysis/AliasAnalysis.cpp
lib/Analysis/BasicAliasAnalysis.cpp
lib/Analysis/IPA/CallGraph.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/CBackend/CBackend.cpp
lib/Target/MSIL/MSILWriter.cpp
lib/Transforms/IPO/DeadArgumentElimination.cpp
lib/Transforms/Scalar/LowerGC.cpp
lib/Transforms/Scalar/SimplifyCFG.cpp
lib/Transforms/Utils/InlineFunction.cpp
lib/VMCore/AutoUpgrade.cpp
lib/VMCore/Function.cpp
lib/VMCore/Instruction.cpp
lib/VMCore/Instructions.cpp
lib/VMCore/Mangler.cpp
tools/bugpoint/Miscompilation.cpp
utils/TableGen/IntrinsicEmitter.cpp
utils/TableGen/IntrinsicEmitter.h

index 627b47f9d9b2289f77ea7f1e653c6873dacc3abb..20a43e285cfff021f35792936927e1f0563df6e9 100644 (file)
@@ -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);
index 34b22c7802774f950adcf93b6897424a3bda41f4..2d721bb4147ac56bf2a775dce3c3e4a895e9666b 100644 (file)
@@ -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.
index 3a97b33358d87e17501a4bf2fba591392decd329..47662501d69d4a114ad5a5ce74d55c7471c0d594 100644 (file)
@@ -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, 
index b613dffe97a26dcd89a590638c5f9a981435e755..5bb60a8a8af95afcd2cbf3fdf2a9b012dd90b58a 100644 (file)
@@ -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(); }
index 9e1ae2a0d2016bf33ff953eb18e268ca4eba9e87..12ea937fa921a620411cd2262a9f5db2911ba93e 100644 (file)
@@ -116,13 +116,13 @@ AliasAnalysis::getModRefInfo(StoreInst *S, Value *P, unsigned Size) {
 AliasAnalysis::ModRefBehavior
 AliasAnalysis::getModRefBehavior(CallSite CS,
                                  std::vector<PointerAccessInfo> *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<PointerAccessInfo> *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;
 }
index 5ec9afaec98797d47b4d09a27b2073cdb3598b9a..99d9499a52611e2fa2a0ed1613a9c5466eda4993 100644 (file)
@@ -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<PointerAccessInfo> *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<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...
 DEFINING_FILE_FOR(BasicAliasAnalysis)
index 5f9850c93dcbff08dd43d71558e6eed0fec6971a..e26ad7a7aaff71cbe486fcfe10619a4508b86845 100644 (file)
@@ -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...
index a350ea95f7a95d303cf26cd975c4099bcfa0a27c..ed89878a0d89dbfbaa9a402b4ac84eeb72477433 100644 (file)
@@ -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<SDOperand, 8> Ops;
   if (HasChain) {  // If this intrinsic has side-effects, chainify it.
index 2d18468215ed1b7ccf958788359669732e85bb77..54a5f426cbf98f0da642c0392ddc876f69dacdc2 100644 (file)
@@ -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 ";
index dafdbe7b2e9feae810e2c41cf406cf0d29d6a755..87107d8908dbdb916270be6fbbc8eb62a6bc9791 100644 (file)
@@ -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);
index a76a43a20ba0cca0dd938b0a167b1e091909f092..446b9652e1cca82991e4b4807adb5db8672cb6aa 100644 (file)
@@ -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) {
index aff3f2cb301427c2314bbe6243f456baf3d06abb..9935a84cda8fcd85f13709ff14e527ee1dfd9fc7 100644 (file)
@@ -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<CallInst>(II++)) {
         if (!CI->getCalledFunction() ||
-            !CI->getCalledFunction()->getIntrinsicID())
+            !CI->getCalledFunction()->isIntrinsic())
           NormalCalls.push_back(CI);   // Remember all normal function calls.
 
         if (Function *F = CI->getCalledFunction())
index 259f4d162668dfee8aa4ea32f8347c99da663816..eb1ed4e60d3420c41426795f464c35c581ab218e 100644 (file)
@@ -135,7 +135,7 @@ static bool MarkAliveBlocks(BasicBlock *BB,
 
     // Turn invokes that call 'nounwind' functions into ordinary calls.
     if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
-      if (II->paramHasAttr(0, ParamAttr::NoUnwind)) {
+      if (II->isNoUnwind()) {
         ChangeToCall(II);
         Changed = true;
       }
index 2a6d9ae9a2f1de2130d93c63f0c24f41aaddcf40..e9f6b28e98b5259853d784452e9e069aba702c43 100644 (file)
@@ -69,13 +69,11 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
           if (!isa<CallInst>(I)) continue;
           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.
-          if ((CI->getCalledFunction() &&
-               CI->getCalledFunction()->getIntrinsicID()) ||
-              isa<InlineAsm>(CI->getCalledValue()))
+          if (CI->isNoUnwind() || isa<InlineAsm>(CI->getCalledValue()))
             continue;
-          
+
           // Convert this function call into an invoke instruction.
           // First, split the basic block.
           BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc");
index 40c431c27944d2bf845173e91d90304d66a3d34a..311941f0d7c808db783415767ca2a6a4cf2b3414 100644 (file)
@@ -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.
index 37949559aafa6ecd2471cf59c94d7ae6a9d5572a..04db3aa06c31fadba07a20f1939663fd7d7e488a 100644 (file)
@@ -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<Function>(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<Function>(M->getOrInsertFunction(getName(id, Tys, numTys),
+                                          getType(id, Tys, numTys)));
+  F->setParamAttrs(getParamAttrs(id));
+  return F;
 }
 
 Value *IntrinsicInst::StripPointerCasts(Value *Ptr) {
index a3687530de9b69a69e251fda3da08f145f39f4ad..9b208854ba12e0d0feb20b709a58647cf60a3d70 100644 (file)
@@ -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<IntrinsicInst>(this)) {
-      // If the intrinsic doesn't write memory, it is safe.
-      return !IntrinsicOnlyReadsMemory(II->getIntrinsicID());
-    }
-    return true;
+    return !cast<CallInst>(this)->onlyReadsMemory();
   case Instruction::Load:
     return cast<LoadInst>(this)->isVolatile();
   }
index 7ad588c72ea882a7b3b4e4325cc5612e36794b09..0df0466112bc797aeeacb2ef1fcad8486687d905 100644 (file)
@@ -53,7 +53,18 @@ bool CallSite::paramHasAttr(uint16_t i, ParameterAttributes attr) const {
   else
     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();
+}
 
 
 
index 8b8ba598ef8131d04063c8e2b36c71c027fbe5f4..8689c86d0832c6ab557c0c9c3accb3aa82eb4c13 100644 (file)
@@ -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<Function>(GV) && cast<Function>(GV)->getIntrinsicID()) {
+  if (isa<Function>(GV) && cast<Function>(GV)->isIntrinsic()) {
     Name = GV->getName(); // Is an intrinsic function
   } else if (!GV->hasName()) {
     // Must mangle the global into a unique ID.
index c9780e22103df19ee42a6680a8d17990e67b813d..6bf42d4c519476d3432bf12b09250e64f6ab91e4 100644 (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.
   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.
index b7c8093875ce4db053a9f125a018567676d9ebdd..47569f3d412ba5b69e511be092c9f34a14d9567d 100644 (file)
@@ -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<CodeGenIntrinsic> &Ints,
   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::
-EmitNoMemoryInfo(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
-  OS << "// SelectionDAGIsel code.\n";
-  OS << "#ifdef GET_NO_MEMORY_INTRINSICS\n";
-  OS << "  switch (IntrinsicID) {\n";
+EmitAttributes(const std::vector<CodeGenIntrinsic> &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<CodeGenIntrinsic> &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<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";
+  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";
 }
index fa483ce67455f88230517d595a70154edbf7b567..aece7a9bc4a8a0dd713e9c604755fc91f70bdd9b 100644 (file)
@@ -37,12 +37,8 @@ namespace llvm {
                       std::ostream &OS);
     void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, 
                        std::ostream &OS);
-    void EmitModRefInfo(const std::vector<CodeGenIntrinsic> &Ints, 
+    void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
                         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, 
                             std::ostream &OS);
     void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,