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
diff --git a/include/llvm/Function.h b/include/llvm/Function.h
index 627b47f..20a43e2 100644
--- a/include/llvm/Function.h
+++ b/include/llvm/Function.h
@@ -158,6 +158,16 @@
     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 34b22c7..2d721bb 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -927,6 +927,21 @@
   /// @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 @@
   /// @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 3a97b33..4766250 100644
--- a/include/llvm/Intrinsics.h
+++ b/include/llvm/Intrinsics.h
@@ -22,6 +22,7 @@
 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 @@
   ///
   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 b613dff..5bb60a8 100644
--- a/include/llvm/Support/CallSite.h
+++ b/include/llvm/Support/CallSite.h
@@ -67,6 +67,12 @@
   /// 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 9e1ae2a..12ea937 100644
--- a/lib/Analysis/AliasAnalysis.cpp
+++ b/lib/Analysis/AliasAnalysis.cpp
@@ -116,13 +116,13 @@
 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::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;
 }
diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp
index 5ec9afa..99d9499 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 @@
     /// 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 @@
   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)
diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp
index 5f9850c..e26ad7a 100644
--- a/lib/Analysis/IPA/CallGraph.cpp
+++ b/lib/Analysis/IPA/CallGraph.cpp
@@ -136,7 +136,7 @@
 
     // 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 a350ea9..ed89878 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2417,31 +2417,13 @@
                            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.
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 2d18468..54a5f42 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -1551,7 +1551,7 @@
   
   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 dafdbe7..87107d8 100644
--- a/lib/Target/MSIL/MSILWriter.cpp
+++ b/lib/Target/MSIL/MSILWriter.cpp
@@ -1586,7 +1586,7 @@
   // 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 a76a43a..446b965 100644
--- a/lib/Transforms/IPO/DeadArgumentElimination.cpp
+++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp
@@ -284,7 +284,7 @@
   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 aff3f2c..9935a84 100644
--- a/lib/Transforms/Scalar/LowerGC.cpp
+++ b/lib/Transforms/Scalar/LowerGC.cpp
@@ -177,7 +177,7 @@
     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())
diff --git a/lib/Transforms/Scalar/SimplifyCFG.cpp b/lib/Transforms/Scalar/SimplifyCFG.cpp
index 259f4d1..eb1ed4e 100644
--- a/lib/Transforms/Scalar/SimplifyCFG.cpp
+++ b/lib/Transforms/Scalar/SimplifyCFG.cpp
@@ -135,7 +135,7 @@
 
     // 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;
       }
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index 2a6d9ae..e9f6b28 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -69,13 +69,11 @@
           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");
diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp
index 40c431c..311941f 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 @@
   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 3794955..04db3aa 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 @@
   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) {
diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp
index a368753..9b20885 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 @@
   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();
   }
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 7ad588c..0df0466 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -53,7 +53,18 @@
   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();
+}
 
 
 
diff --git a/lib/VMCore/Mangler.cpp b/lib/VMCore/Mangler.cpp
index 8b8ba59..8689c86 100644
--- a/lib/VMCore/Mangler.cpp
+++ b/lib/VMCore/Mangler.cpp
@@ -135,7 +135,7 @@
   // 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.
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index c9780e2..6bf42d4 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -685,7 +685,7 @@
   // 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 b7c8093..47569f3 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -42,14 +42,8 @@
   // 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 @@
   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 @@
       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";
 }
diff --git a/utils/TableGen/IntrinsicEmitter.h b/utils/TableGen/IntrinsicEmitter.h
index fa483ce..aece7a9 100644
--- a/utils/TableGen/IntrinsicEmitter.h
+++ b/utils/TableGen/IntrinsicEmitter.h
@@ -37,12 +37,8 @@
                       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,