aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Attributes.h26
-rw-r--r--include/llvm/Function.h24
-rw-r--r--include/llvm/Instructions.h46
-rw-r--r--lib/AsmParser/llvmAsmParser.y74
-rw-r--r--lib/AsmParser/llvmAsmParser.y.cvs74
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp49
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.h8
-rw-r--r--lib/Transforms/IPO/AddReadAttrs.cpp4
-rw-r--r--lib/Transforms/IPO/ArgumentPromotion.cpp18
-rw-r--r--lib/Transforms/IPO/DeadArgumentElimination.cpp23
-rw-r--r--lib/Transforms/IPO/PruneEH.cpp2
-rw-r--r--lib/Transforms/IPO/StructRetPromotion.cpp16
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp26
-rw-r--r--lib/VMCore/AsmWriter.cpp28
-rw-r--r--lib/VMCore/Attributes.cpp6
-rw-r--r--lib/VMCore/Function.cpp2
-rw-r--r--lib/VMCore/Verifier.cpp2
17 files changed, 325 insertions, 103 deletions
diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h
index 3adbf25115..bc7628011f 100644
--- a/include/llvm/Attributes.h
+++ b/include/llvm/Attributes.h
@@ -146,10 +146,23 @@ public:
//===--------------------------------------------------------------------===//
// Attribute List Accessors
//===--------------------------------------------------------------------===//
-
- /// getAttributes - The attributes for the specified index are
- /// returned. Attributes for the result are denoted with Idx = 0.
- Attributes getAttributes(unsigned Idx) const;
+ /// getParamAttributes - The attributes for the specified index are
+ /// returned.
+ Attributes getParamAttributes(unsigned Idx) const {
+ assert (Idx && Idx != ~0U && "Invalid parameter index!");
+ return getAttributes(Idx);
+ }
+
+ /// getRetAttributes - The attributes for the ret value are
+ /// returned.
+ Attributes getRetAttributes() const {
+ return getAttributes(0);
+ }
+
+ /// getFnAttributes - The function attributes are returned.
+ Attributes getFnAttributes() const {
+ return getAttributes(~0);
+ }
/// paramHasAttr - Return true if the specified parameter index has the
/// specified attribute set.
@@ -204,6 +217,11 @@ public:
private:
explicit AttrListPtr(AttributeListImpl *L);
+
+ /// getAttributes - The attributes for the specified index are
+ /// returned. Attributes for the result are denoted with Idx = 0.
+ Attributes getAttributes(unsigned Idx) const;
+
};
} // End llvm namespace
diff --git a/include/llvm/Function.h b/include/llvm/Function.h
index 82871bbff6..19ff2bf4da 100644
--- a/include/llvm/Function.h
+++ b/include/llvm/Function.h
@@ -187,38 +187,38 @@ public:
/// @brief Determine if the function does not access memory.
bool doesNotAccessMemory() const {
- return paramHasAttr(0, Attribute::ReadNone);
+ return paramHasAttr(~0, Attribute::ReadNone);
}
void setDoesNotAccessMemory(bool DoesNotAccessMemory = true) {
- if (DoesNotAccessMemory) addAttribute(0, Attribute::ReadNone);
- else removeAttribute(0, Attribute::ReadNone);
+ if (DoesNotAccessMemory) addAttribute(~0, Attribute::ReadNone);
+ else removeAttribute(~0, Attribute::ReadNone);
}
/// @brief Determine if the function does not access or only reads memory.
bool onlyReadsMemory() const {
- return doesNotAccessMemory() || paramHasAttr(0, Attribute::ReadOnly);
+ return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly);
}
void setOnlyReadsMemory(bool OnlyReadsMemory = true) {
- if (OnlyReadsMemory) addAttribute(0, Attribute::ReadOnly);
- else removeAttribute(0, Attribute::ReadOnly | Attribute::ReadNone);
+ if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly);
+ else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone);
}
/// @brief Determine if the function cannot return.
bool doesNotReturn() const {
- return paramHasAttr(0, Attribute::NoReturn);
+ return paramHasAttr(~0, Attribute::NoReturn);
}
void setDoesNotReturn(bool DoesNotReturn = true) {
- if (DoesNotReturn) addAttribute(0, Attribute::NoReturn);
- else removeAttribute(0, Attribute::NoReturn);
+ if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn);
+ else removeAttribute(~0, Attribute::NoReturn);
}
/// @brief Determine if the function cannot unwind.
bool doesNotThrow() const {
- return paramHasAttr(0, Attribute::NoUnwind);
+ return paramHasAttr(~0, Attribute::NoUnwind);
}
void setDoesNotThrow(bool DoesNotThrow = true) {
- if (DoesNotThrow) addAttribute(0, Attribute::NoUnwind);
- else removeAttribute(0, Attribute::NoUnwind);
+ if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind);
+ else removeAttribute(~0, Attribute::NoUnwind);
}
/// @brief Determine if the function returns a structure through first
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h
index a61457312e..2278757011 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -1097,38 +1097,38 @@ public:
/// @brief Determine if the call does not access memory.
bool doesNotAccessMemory() const {
- return paramHasAttr(0, Attribute::ReadNone);
+ return paramHasAttr(~0, Attribute::ReadNone);
}
void setDoesNotAccessMemory(bool NotAccessMemory = true) {
- if (NotAccessMemory) addAttribute(0, Attribute::ReadNone);
- else removeAttribute(0, Attribute::ReadNone);
+ if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone);
+ else removeAttribute(~0, Attribute::ReadNone);
}
/// @brief Determine if the call does not access or only reads memory.
bool onlyReadsMemory() const {
- return doesNotAccessMemory() || paramHasAttr(0, Attribute::ReadOnly);
+ return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly);
}
void setOnlyReadsMemory(bool OnlyReadsMemory = true) {
- if (OnlyReadsMemory) addAttribute(0, Attribute::ReadOnly);
- else removeAttribute(0, Attribute::ReadOnly | Attribute::ReadNone);
+ if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly);
+ else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone);
}
/// @brief Determine if the call cannot return.
bool doesNotReturn() const {
- return paramHasAttr(0, Attribute::NoReturn);
+ return paramHasAttr(~0, Attribute::NoReturn);
}
void setDoesNotReturn(bool DoesNotReturn = true) {
- if (DoesNotReturn) addAttribute(0, Attribute::NoReturn);
- else removeAttribute(0, Attribute::NoReturn);
+ if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn);
+ else removeAttribute(~0, Attribute::NoReturn);
}
/// @brief Determine if the call cannot unwind.
bool doesNotThrow() const {
- return paramHasAttr(0, Attribute::NoUnwind);
+ return paramHasAttr(~0, Attribute::NoUnwind);
}
void setDoesNotThrow(bool DoesNotThrow = true) {
- if (DoesNotThrow) addAttribute(0, Attribute::NoUnwind);
- else removeAttribute(0, Attribute::NoUnwind);
+ if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind);
+ else removeAttribute(~0, Attribute::NoUnwind);
}
/// @brief Determine if the call returns a structure through first
@@ -2459,35 +2459,35 @@ public:
return paramHasAttr(0, Attribute::ReadNone);
}
void setDoesNotAccessMemory(bool NotAccessMemory = true) {
- if (NotAccessMemory) addAttribute(0, Attribute::ReadNone);
- else removeAttribute(0, Attribute::ReadNone);
+ if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone);
+ else removeAttribute(~0, Attribute::ReadNone);
}
/// @brief Determine if the call does not access or only reads memory.
bool onlyReadsMemory() const {
- return doesNotAccessMemory() || paramHasAttr(0, Attribute::ReadOnly);
+ return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly);
}
void setOnlyReadsMemory(bool OnlyReadsMemory = true) {
- if (OnlyReadsMemory) addAttribute(0, Attribute::ReadOnly);
- else removeAttribute(0, Attribute::ReadOnly | Attribute::ReadNone);
+ if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly);
+ else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone);
}
/// @brief Determine if the call cannot return.
bool doesNotReturn() const {
- return paramHasAttr(0, Attribute::NoReturn);
+ return paramHasAttr(~0, Attribute::NoReturn);
}
void setDoesNotReturn(bool DoesNotReturn = true) {
- if (DoesNotReturn) addAttribute(0, Attribute::NoReturn);
- else removeAttribute(0, Attribute::NoReturn);
+ if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn);
+ else removeAttribute(~0, Attribute::NoReturn);
}
/// @brief Determine if the call cannot unwind.
bool doesNotThrow() const {
- return paramHasAttr(0, Attribute::NoUnwind);
+ return paramHasAttr(~0, Attribute::NoUnwind);
}
void setDoesNotThrow(bool DoesNotThrow = true) {
- if (DoesNotThrow) addAttribute(0, Attribute::NoUnwind);
- else removeAttribute(0, Attribute::NoUnwind);
+ if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind);
+ else removeAttribute(~0, Attribute::NoUnwind);
}
/// @brief Determine if the call returns a structure through first
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index 0ea2ee083d..fa62b4712b 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -2346,8 +2346,25 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
std::vector<const Type*> ParamTypeList;
SmallVector<AttributeWithIndex, 8> Attrs;
- if ($7 != Attribute::None)
- Attrs.push_back(AttributeWithIndex::get(0, $7));
+ //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function
+ //attributes.
+ Attributes RetAttrs = 0;
+ if ($7 != Attribute::None) {
+ if ($7 & Attribute::ZExt) {
+ RetAttrs = RetAttrs | Attribute::ZExt;
+ $7 = $7 ^ Attribute::ZExt;
+ }
+ if ($7 & Attribute::SExt) {
+ RetAttrs = RetAttrs | Attribute::SExt;
+ $7 = $7 ^ Attribute::SExt;
+ }
+ if ($7 & Attribute::InReg) {
+ RetAttrs = RetAttrs | Attribute::InReg;
+ $7 = $7 ^ Attribute::InReg;
+ }
+ if (RetAttrs != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(0, RetAttrs));
+ }
if ($5) { // If there are arguments...
unsigned index = 1;
for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I, ++index) {
@@ -2359,6 +2376,8 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
Attrs.push_back(AttributeWithIndex::get(index, I->Attrs));
}
}
+ if ($7 != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(~0, $7));
bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy;
if (isVarArg) ParamTypeList.pop_back();
@@ -2860,9 +2879,26 @@ BBTerminatorInst :
CHECK_FOR_ERROR
SmallVector<AttributeWithIndex, 8> Attrs;
- if ($8 != Attribute::None)
- Attrs.push_back(AttributeWithIndex::get(0, $8));
-
+ //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function
+ //attributes.
+ Attributes RetAttrs = 0;
+ if ($8 != Attribute::None) {
+ if ($8 & Attribute::ZExt) {
+ RetAttrs = RetAttrs | Attribute::ZExt;
+ $8 = $8 ^ Attribute::ZExt;
+ }
+ if ($8 & Attribute::SExt) {
+ RetAttrs = RetAttrs | Attribute::SExt;
+ $8 = $8 ^ Attribute::SExt;
+ }
+ if ($8 & Attribute::InReg) {
+ RetAttrs = RetAttrs | Attribute::InReg;
+ $8 = $8 ^ Attribute::InReg;
+ }
+ if (RetAttrs != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(0, RetAttrs));
+ }
+
// Check the arguments
ValueList Args;
if ($6->empty()) { // Has no arguments?
@@ -2897,7 +2933,8 @@ BBTerminatorInst :
} else if (I != E || ArgI != ArgE)
GEN_ERROR("Invalid number of parameters detected");
}
-
+ if ($8 != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(~0, $8));
AttrListPtr PAL;
if (!Attrs.empty())
PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
@@ -3258,8 +3295,27 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
// Set up the Attributes for the function
SmallVector<AttributeWithIndex, 8> Attrs;
- if ($8 != Attribute::None)
- Attrs.push_back(AttributeWithIndex::get(0, $8));
+ //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function
+ //attributes.
+ Attributes RetAttrs = 0;
+ Attributes TmpAttr = $8;
+ if ($8 != Attribute::None) {
+ if ($8 & Attribute::ZExt) {
+ RetAttrs = RetAttrs | Attribute::ZExt;
+ $8 = $8 ^ Attribute::ZExt;
+ }
+ if ($8 & Attribute::SExt) {
+ RetAttrs = RetAttrs | Attribute::SExt;
+ $8 = $8 ^ Attribute::SExt;
+ }
+ if ($8 & Attribute::InReg) {
+ RetAttrs = RetAttrs | Attribute::InReg;
+ $8 = $8 ^ Attribute::InReg;
+ }
+ if (RetAttrs != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(0, RetAttrs));
+ }
+
// Check the arguments
ValueList Args;
if ($6->empty()) { // Has no arguments?
@@ -3293,6 +3349,8 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
} else if (I != E || ArgI != ArgE)
GEN_ERROR("Invalid number of parameters detected");
}
+ if ($8 != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(~0, $8));
// Finish off the Attributes and check them
AttrListPtr PAL;
diff --git a/lib/AsmParser/llvmAsmParser.y.cvs b/lib/AsmParser/llvmAsmParser.y.cvs
index 0ea2ee083d..fa62b4712b 100644
--- a/lib/AsmParser/llvmAsmParser.y.cvs
+++ b/lib/AsmParser/llvmAsmParser.y.cvs
@@ -2346,8 +2346,25 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
std::vector<const Type*> ParamTypeList;
SmallVector<AttributeWithIndex, 8> Attrs;
- if ($7 != Attribute::None)
- Attrs.push_back(AttributeWithIndex::get(0, $7));
+ //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function
+ //attributes.
+ Attributes RetAttrs = 0;
+ if ($7 != Attribute::None) {
+ if ($7 & Attribute::ZExt) {
+ RetAttrs = RetAttrs | Attribute::ZExt;
+ $7 = $7 ^ Attribute::ZExt;
+ }
+ if ($7 & Attribute::SExt) {
+ RetAttrs = RetAttrs | Attribute::SExt;
+ $7 = $7 ^ Attribute::SExt;
+ }
+ if ($7 & Attribute::InReg) {
+ RetAttrs = RetAttrs | Attribute::InReg;
+ $7 = $7 ^ Attribute::InReg;
+ }
+ if (RetAttrs != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(0, RetAttrs));
+ }
if ($5) { // If there are arguments...
unsigned index = 1;
for (ArgListType::iterator I = $5->begin(); I != $5->end(); ++I, ++index) {
@@ -2359,6 +2376,8 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
Attrs.push_back(AttributeWithIndex::get(index, I->Attrs));
}
}
+ if ($7 != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(~0, $7));
bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy;
if (isVarArg) ParamTypeList.pop_back();
@@ -2860,9 +2879,26 @@ BBTerminatorInst :
CHECK_FOR_ERROR
SmallVector<AttributeWithIndex, 8> Attrs;
- if ($8 != Attribute::None)
- Attrs.push_back(AttributeWithIndex::get(0, $8));
-
+ //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function
+ //attributes.
+ Attributes RetAttrs = 0;
+ if ($8 != Attribute::None) {
+ if ($8 & Attribute::ZExt) {
+ RetAttrs = RetAttrs | Attribute::ZExt;
+ $8 = $8 ^ Attribute::ZExt;
+ }
+ if ($8 & Attribute::SExt) {
+ RetAttrs = RetAttrs | Attribute::SExt;
+ $8 = $8 ^ Attribute::SExt;
+ }
+ if ($8 & Attribute::InReg) {
+ RetAttrs = RetAttrs | Attribute::InReg;
+ $8 = $8 ^ Attribute::InReg;
+ }
+ if (RetAttrs != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(0, RetAttrs));
+ }
+
// Check the arguments
ValueList Args;
if ($6->empty()) { // Has no arguments?
@@ -2897,7 +2933,8 @@ BBTerminatorInst :
} else if (I != E || ArgI != ArgE)
GEN_ERROR("Invalid number of parameters detected");
}
-
+ if ($8 != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(~0, $8));
AttrListPtr PAL;
if (!Attrs.empty())
PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
@@ -3258,8 +3295,27 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
// Set up the Attributes for the function
SmallVector<AttributeWithIndex, 8> Attrs;
- if ($8 != Attribute::None)
- Attrs.push_back(AttributeWithIndex::get(0, $8));
+ //FIXME : In 3.0, stop accepting zext, sext and inreg as optional function
+ //attributes.
+ Attributes RetAttrs = 0;
+ Attributes TmpAttr = $8;
+ if ($8 != Attribute::None) {
+ if ($8 & Attribute::ZExt) {
+ RetAttrs = RetAttrs | Attribute::ZExt;
+ $8 = $8 ^ Attribute::ZExt;
+ }
+ if ($8 & Attribute::SExt) {
+ RetAttrs = RetAttrs | Attribute::SExt;
+ $8 = $8 ^ Attribute::SExt;
+ }
+ if ($8 & Attribute::InReg) {
+ RetAttrs = RetAttrs | Attribute::InReg;
+ $8 = $8 ^ Attribute::InReg;
+ }
+ if (RetAttrs != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(0, RetAttrs));
+ }
+
// Check the arguments
ValueList Args;
if ($6->empty()) { // Has no arguments?
@@ -3293,6 +3349,8 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
} else if (I != E || ArgI != ArgE)
GEN_ERROR("Invalid number of parameters detected");
}
+ if ($8 != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(~0, $8));
// Finish off the Attributes and check them
AttrListPtr PAL;
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 205650ddd0..23fbe1d35f 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -32,7 +32,7 @@ void BitcodeReader::FreeState() {
std::vector<PATypeHolder>().swap(TypeList);
ValueList.clear();
- std::vector<AttrListPtr>().swap(Attributes);
+ std::vector<AttrListPtr>().swap(MAttributes);
std::vector<BasicBlock*>().swap(FunctionBBs);
std::vector<Function*>().swap(FunctionsWithBodies);
DeferredFunctionInfo.clear();
@@ -317,7 +317,7 @@ bool BitcodeReader::ParseAttributeBlock() {
if (Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID))
return Error("Malformed block record");
- if (!Attributes.empty())
+ if (!MAttributes.empty())
return Error("Multiple PARAMATTR blocks found!");
SmallVector<uint64_t, 64> Record;
@@ -355,12 +355,53 @@ bool BitcodeReader::ParseAttributeBlock() {
if (Record.size() & 1)
return Error("Invalid ENTRY record");
+ // FIXME : Remove this backword compatibility one day.
+ // If Function attributes are using index 0 then transfer them
+ // to index ~0. Index 0 is strictly used for return value
+ // attributes.
+ Attributes RetAttribute = Attribute::None;
+ Attributes FnAttribute = Attribute::None;
for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
- if (Record[i+1] != Attribute::None)
+ if (Record[i] == 0)
+ RetAttribute = Record[i+1];
+ else if (Record[i] == ~0U)
+ FnAttribute = Record[i+1];
+ }
+ bool useUpdatedAttrs = false;
+ if (FnAttribute == Attribute::None && RetAttribute != Attribute::None) {
+ if (RetAttribute & Attribute::NoUnwind) {
+ FnAttribute = FnAttribute | Attribute::NoUnwind;
+ RetAttribute = RetAttribute ^ Attribute::NoUnwind;
+ useUpdatedAttrs = true;
+ }
+ if (RetAttribute & Attribute::NoReturn) {
+ FnAttribute = FnAttribute | Attribute::NoReturn;
+ RetAttribute = RetAttribute ^ Attribute::NoReturn;
+ useUpdatedAttrs = true;
+ }
+ if (RetAttribute & Attribute::ReadOnly) {
+ FnAttribute = FnAttribute | Attribute::ReadOnly;
+ RetAttribute = RetAttribute ^ Attribute::ReadOnly;
+ useUpdatedAttrs = true;
+ }
+ if (RetAttribute & Attribute::ReadNone) {
+ FnAttribute = FnAttribute | Attribute::ReadNone;
+ RetAttribute = RetAttribute ^ Attribute::ReadNone;
+ useUpdatedAttrs = true;
+ }
+ }
+
+ for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+ if (useUpdatedAttrs && Record[i] == 0
+ && RetAttribute != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(0, RetAttribute));
+ else if (Record[i+1] != Attribute::None)
Attrs.push_back(AttributeWithIndex::get(Record[i], Record[i+1]));
}
+ if (useUpdatedAttrs && FnAttribute != Attribute::None)
+ Attrs.push_back(AttributeWithIndex::get(~0, FnAttribute));
- Attributes.push_back(AttrListPtr::get(Attrs.begin(), Attrs.end()));
+ MAttributes.push_back(AttrListPtr::get(Attrs.begin(), Attrs.end()));
Attrs.clear();
break;
}
diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h
index e8ad1ddaca..0b72b34015 100644
--- a/lib/Bitcode/Reader/BitcodeReader.h
+++ b/lib/Bitcode/Reader/BitcodeReader.h
@@ -136,10 +136,10 @@ class BitcodeReader : public ModuleProvider {
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
- /// Attributes - The set of parameter attributes by index. Index zero in the
+ /// MAttributes - The set of attributes by index. Index zero in the
/// file is for null, and is thus not represented here. As such all indices
/// are off by one.
- std::vector<AttrListPtr> Attributes;
+ std::vector<AttrListPtr> MAttributes;
/// FunctionBBs - While parsing a function body, this is a list of the basic
/// blocks for the function.
@@ -204,8 +204,8 @@ private:
return FunctionBBs[ID];
}
AttrListPtr getAttributes(unsigned i) const {
- if (i-1 < Attributes.size())
- return Attributes[i-1];
+ if (i-1 < MAttributes.size())
+ return MAttributes[i-1];
return AttrListPtr();
}
diff --git a/lib/Transforms/IPO/AddReadAttrs.cpp b/lib/Transforms/IPO/AddReadAttrs.cpp
index 4e0677b0d8..897548bad5 100644
--- a/lib/Transforms/IPO/AddReadAttrs.cpp
+++ b/lib/Transforms/IPO/AddReadAttrs.cpp
@@ -105,10 +105,10 @@ bool AddReadAttrs::runOnSCC(const std::vector<CallGraphNode *> &SCC) {
MadeChange = true;
// Clear out any existing attributes.
- F->removeAttribute(0, Attribute::ReadOnly | Attribute::ReadNone);
+ F->removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone);
// Add in the new attribute.
- F->addAttribute(0, ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone);
+ F->addAttribute(~0, ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone);
if (ReadsMemory)
NumReadOnly++;
diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp
index fe6583e4da..d66e2c4620 100644
--- a/lib/Transforms/IPO/ArgumentPromotion.cpp
+++ b/lib/Transforms/IPO/ArgumentPromotion.cpp
@@ -508,7 +508,7 @@ Function *ArgPromotion::DoPromotion(Function *F,
const AttrListPtr &PAL = F->getAttributes();
// Add any return attributes.
- if (Attributes attrs = PAL.getAttributes(0))
+ if (Attributes attrs = PAL.getRetAttributes())
AttributesVec.push_back(AttributeWithIndex::get(0, attrs));
// First, determine the new argument list
@@ -525,7 +525,7 @@ Function *ArgPromotion::DoPromotion(Function *F,
} else if (!ArgsToPromote.count(I)) {
// Unchanged argument
Params.push_back(I->getType());
- if (Attributes attrs = PAL.getAttributes(ArgIndex))
+ if (Attributes attrs = PAL.getParamAttributes(ArgIndex))
AttributesVec.push_back(AttributeWithIndex::get(Params.size(), attrs));
} else if (I->use_empty()) {
// Dead argument (which are always marked as promotable)
@@ -578,6 +578,10 @@ Function *ArgPromotion::DoPromotion(Function *F,
}
}
+ // Add any function attributes.
+ if (Attributes attrs = PAL.getFnAttributes())
+ AttributesVec.push_back(AttributeWithIndex::get(~0, attrs));
+
const Type *RetTy = FTy->getReturnType();
// Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
@@ -621,7 +625,7 @@ Function *ArgPromotion::DoPromotion(Function *F,
const AttrListPtr &CallPAL = CS.getAttributes();
// Add any return attributes.
- if (Attributes attrs = CallPAL.getAttributes(0))
+ if (Attributes attrs = CallPAL.getRetAttributes())
AttributesVec.push_back(AttributeWithIndex::get(0, attrs));
// Loop over the operands, inserting GEP and loads in the caller as
@@ -633,7 +637,7 @@ Function *ArgPromotion::DoPromotion(Function *F,
if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) {
Args.push_back(*AI); // Unmodified argument
- if (Attributes Attrs = CallPAL.getAttributes(ArgIndex))
+ if (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex))
AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs));
} else if (ByValArgsToTransform.count(I)) {
@@ -688,10 +692,14 @@ Function *ArgPromotion::DoPromotion(Function *F,
// Push any varargs arguments on the list
for (; AI != CS.arg_end(); ++AI, ++ArgIndex) {
Args.push_back(*AI);
- if (Attributes Attrs = CallPAL.getAttributes(ArgIndex))
+ if (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex))
AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs));
}
+ // Add any function attributes.
+ if (Attributes attrs = CallPAL.getFnAttributes())
+ AttributesVec.push_back(AttributeWithIndex::get(~0, attrs));
+
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(),
diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp
index eef326b758..8f0c4c41fc 100644
--- a/lib/Transforms/IPO/DeadArgumentElimination.cpp
+++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp
@@ -229,6 +229,8 @@ bool DAE::DeleteDeadVarargs(Function &Fn) {
SmallVector<AttributeWithIndex, 8> AttributesVec;
for (unsigned i = 0; PAL.getSlot(i).Index <= NumArgs; ++i)
AttributesVec.push_back(PAL.getSlot(i));
+ if (Attributes FnAttrs = PAL.getFnAttributes())
+ AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs));
PAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end());
}
@@ -593,8 +595,8 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
const AttrListPtr &PAL = F->getAttributes();
// The existing function return attributes.
- Attributes RAttrs = PAL.getAttributes(0);
-
+ Attributes RAttrs = PAL.getRetAttributes();
+ Attributes FnAttrs = PAL.getFnAttributes();
// Find out the new return value.
@@ -678,7 +680,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
// Get the original parameter attributes (skipping the first one, that is
// for the return value.
- if (Attributes Attrs = PAL.getAttributes(i + 1))
+ if (Attributes Attrs = PAL.getParamAttributes(i + 1))
AttributesVec.push_back(AttributeWithIndex::get(Params.size(), Attrs));
} else {
++NumArgumentsEliminated;
@@ -687,6 +689,9 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
}
}
+ if (FnAttrs != Attribute::None)
+ AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs));
+
// Reconstruct the AttributesList based on the vector we constructed.
AttrListPtr NewPAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end());
@@ -730,7 +735,8 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
const AttrListPtr &CallPAL = CS.getAttributes();
// The call return attributes.
- Attributes RAttrs = CallPAL.getAttributes(0);
+ Attributes RAttrs = CallPAL.getRetAttributes();
+ Attributes FnAttrs = CallPAL.getFnAttributes();
// Adjust in case the function was changed to return void.
RAttrs &= ~Attribute::typeIncompatible(NF->getReturnType());
if (RAttrs)
@@ -746,7 +752,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
if (ArgAlive[i]) {
Args.push_back(*I);
// Get original parameter attributes, but skip return attributes.
- if (Attributes Attrs = CallPAL.getAttributes(i + 1))
+ if (Attributes Attrs = CallPAL.getParamAttributes(i + 1))
AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs));
}
@@ -756,13 +762,16 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) {
// Push any varargs arguments on the list. Don't forget their attributes.
for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) {
Args.push_back(*I);
- if (Attributes Attrs = CallPAL.getAttributes(i + 1))
+ if (Attributes Attrs = CallPAL.getParamAttributes(i + 1))
AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs));
}
+ if (FnAttrs != Attribute::None)
+ AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs));
+
// Reconstruct the AttributesList based on the vector we constructed.
AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(),
- AttributesVec.end());
+ AttributesVec.end());
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
diff --git a/lib/Transforms/IPO/PruneEH.cpp b/lib/Transforms/IPO/PruneEH.cpp
index 821e7d5da9..622184415c 100644
--- a/lib/Transforms/IPO/PruneEH.cpp
+++ b/lib/Transforms/IPO/PruneEH.cpp
@@ -133,7 +133,7 @@ bool PruneEH::runOnSCC(const std::vector<CallGraphNode *> &SCC) {
NewAttributes |= Attribute::NoReturn;
const AttrListPtr &PAL = SCC[i]->getFunction()->getAttributes();
- const AttrListPtr &NPAL = PAL.addAttr(0, NewAttributes);
+ const AttrListPtr &NPAL = PAL.addAttr(~0, NewAttributes);
if (PAL != NPAL) {
MadeChange = true;
SCC[i]->getFunction()->setAttributes(NPAL);
diff --git a/lib/Transforms/IPO/StructRetPromotion.cpp b/lib/Transforms/IPO/StructRetPromotion.cpp
index 07b9e504c7..96ef66c127 100644
--- a/lib/Transforms/IPO/StructRetPromotion.cpp
+++ b/lib/Transforms/IPO/StructRetPromotion.cpp
@@ -210,7 +210,7 @@ Function *SRETPromotion::cloneFunctionBody(Function *F,
const AttrListPtr &PAL = F->getAttributes();
// Add any return attributes.
- if (Attributes attrs = PAL.getAttributes(0))
+ if (Attributes attrs = PAL.getRetAttributes())
AttributesVec.push_back(AttributeWithIndex::get(0, attrs));
// Skip first argument.
@@ -221,12 +221,17 @@ Function *SRETPromotion::cloneFunctionBody(Function *F,
unsigned ParamIndex = 2;
while (I != E) {
Params.push_back(I->getType());
- if (Attributes Attrs = PAL.getAttributes(ParamIndex))
+ if (Attributes Attrs = PAL.getParamAttributes(ParamIndex))
AttributesVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs));
++I;
++ParamIndex;
}
+ // Add any fn attributes.
+ if (Attributes attrs = PAL.getFnAttributes())
+ AttributesVec.push_back(AttributeWithIndex::get(~0, attrs));
+
+
FunctionType *NFTy = FunctionType::get(STy, Params, FTy->isVarArg());
Function *NF = Function::Create(NFTy, F->getLinkage());
NF->takeName(F);
@@ -264,7 +269,7 @@ void SRETPromotion::updateCallSites(Function *F, Function *NF) {
const AttrListPtr &PAL = F->getAttributes();
// Add any return attributes.
- if (Attributes attrs = PAL.getAttributes(0))
+ if (Attributes attrs = PAL.getRetAttributes())
ArgAttrsVec.push_back(AttributeWithIndex::get(0, attrs));
// Copy arguments, however skip first one.
@@ -276,12 +281,15 @@ void SRETPromotion::updateCallSites(Function *F, Function *NF) {
unsigned ParamIndex = 2;
while (AI != AE) {
Args.push_back(*AI);
- if (Attributes Attrs = PAL.getAttributes(ParamIndex))
+ if (Attributes Attrs = PAL.getParamAttributes(ParamIndex))
ArgAttrsVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs));
++ParamIndex;
++AI;
}
+ // Add any function attributes.
+ if (Attributes attrs = PAL.getFnAttributes())
+ ArgAttrsVec.push_back(AttributeWithIndex::get(~0, attrs));
AttrListPtr NewPAL = AttrListPtr::get(ArgAttrsVec.begin(), ArgAttrsVec.end());
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 1decf2de02..9023db7d50 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/