Add initial support for the convergent attribute.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238264 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2015-05-26 23:48:40 +00:00
parent 1c74d4768a
commit 13146c7e3b
16 changed files with 61 additions and 5 deletions

View File

@ -1196,6 +1196,13 @@ example:
computing edge weights, basic blocks post-dominated by a cold
function call are also considered to be cold; and, thus, given low
weight.
``convergent``
This attribute indicates that the callee is dependent on a convergent
thread execution pattern under certain parallel execution models.
Transformations that are execution model agnostic may only move or
tranform this call if the final location is control equivalent to its
original position in the program, where control equivalence is defined as
A dominates B and B post-dominates A, or vice versa.
``inlinehint``
This attribute indicates that the source code contained a hint that
inlining this function is desirable (such as the "inline" keyword in

View File

@ -402,7 +402,8 @@ namespace bitc {
ATTR_KIND_NON_NULL = 39,
ATTR_KIND_JUMP_TABLE = 40,
ATTR_KIND_DEREFERENCEABLE = 41,
ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42
ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42,
ATTR_KIND_CONVERGENT = 43
};
enum ComdatSelectionKindCodes {

View File

@ -73,6 +73,7 @@ public:
ByVal, ///< Pass structure by value
InAlloca, ///< Pass structure in an alloca
Cold, ///< Marks function as being in a cold path.
Convergent, ///< Can only be moved to control-equivalent blocks
InlineHint, ///< Source said inlining was desirable
InReg, ///< Force argument to be passed in register
JumpTable, ///< Build jump-instruction tables and replace refs.

View File

@ -308,6 +308,16 @@ public:
addFnAttr(Attribute::NoDuplicate);
}
/// @brief Determine if the call is convergent.
bool isConvergent() const {
return AttributeSets.hasAttribute(AttributeSet::FunctionIndex,
Attribute::Convergent);
}
void setConvergent() {
addFnAttr(Attribute::Convergent);
}
/// @brief True if the ABI mandates (or the user requested) that this
/// function be in a unwind table.
bool hasUWTable() const {

View File

@ -73,6 +73,11 @@ def IntrNoReturn : IntrinsicProperty;
// Parallels the noduplicate attribute on LLVM IR functions.
def IntrNoDuplicate : IntrinsicProperty;
// IntrConvergent - Calls to this intrinsic are convergent and may only be
// moved to control equivalent blocks.
// Parallels the convergent attribute on LLVM IR functions.
def IntrConvergent : IntrinsicProperty;
//===----------------------------------------------------------------------===//
// Types used by intrinsics.
//===----------------------------------------------------------------------===//

View File

@ -597,6 +597,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(byval);
KEYWORD(inalloca);
KEYWORD(cold);
KEYWORD(convergent);
KEYWORD(dereferenceable);
KEYWORD(dereferenceable_or_null);
KEYWORD(inlinehint);

View File

@ -937,6 +937,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break;
case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break;
case lltok::kw_cold: B.addAttribute(Attribute::Cold); break;
case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break;
case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break;
case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break;
case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break;

View File

@ -105,6 +105,7 @@ namespace lltok {
kw_byval,
kw_inalloca,
kw_cold,
kw_convergent,
kw_dereferenceable,
kw_dereferenceable_or_null,
kw_inlinehint,

View File

@ -1095,6 +1095,8 @@ static Attribute::AttrKind GetAttrFromCode(uint64_t Code) {
return Attribute::InAlloca;
case bitc::ATTR_KIND_COLD:
return Attribute::Cold;
case bitc::ATTR_KIND_CONVERGENT:
return Attribute::Convergent;
case bitc::ATTR_KIND_INLINE_HINT:
return Attribute::InlineHint;
case bitc::ATTR_KIND_IN_REG:

View File

@ -166,6 +166,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
return bitc::ATTR_KIND_BUILTIN;
case Attribute::ByVal:
return bitc::ATTR_KIND_BY_VAL;
case Attribute::Convergent:
return bitc::ATTR_KIND_CONVERGENT;
case Attribute::InAlloca:
return bitc::ATTR_KIND_IN_ALLOCA;
case Attribute::Cold:

View File

@ -194,6 +194,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "builtin";
if (hasAttribute(Attribute::ByVal))
return "byval";
if (hasAttribute(Attribute::Convergent))
return "convergent";
if (hasAttribute(Attribute::InAlloca))
return "inalloca";
if (hasAttribute(Attribute::InlineHint))
@ -434,6 +436,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
case Attribute::InAlloca: return 1ULL << 43;
case Attribute::NonNull: return 1ULL << 44;
case Attribute::JumpTable: return 1ULL << 45;
case Attribute::Convergent: return 1ULL << 46;
case Attribute::Dereferenceable:
llvm_unreachable("dereferenceable attribute not supported in raw format");
break;

View File

@ -1268,7 +1268,8 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
I->getKindAsEnum() == Attribute::NoBuiltin ||
I->getKindAsEnum() == Attribute::Cold ||
I->getKindAsEnum() == Attribute::OptimizeNone ||
I->getKindAsEnum() == Attribute::JumpTable) {
I->getKindAsEnum() == Attribute::JumpTable ||
I->getKindAsEnum() == Attribute::Convergent) {
if (!isFunction) {
CheckFailed("Attribute '" + I->getAsString() +
"' only applies to functions!", V);

View File

@ -204,7 +204,7 @@ define void @f34()
; CHECK: define void @f34()
{
call void @nobuiltin() nobuiltin
; CHECK: call void @nobuiltin() #25
; CHECK: call void @nobuiltin() #26
ret void;
}
@ -251,6 +251,11 @@ define dereferenceable_or_null(8) i8* @f42(i8* dereferenceable_or_null(8) %foo)
ret i8* %foo
}
; CHECK: define void @f43() #25
define void @f43() convergent {
ret void
}
; CHECK: attributes #0 = { noreturn }
; CHECK: attributes #1 = { nounwind }
; CHECK: attributes #2 = { readnone }
@ -276,4 +281,5 @@ define dereferenceable_or_null(8) i8* @f42(i8* dereferenceable_or_null(8) %foo)
; CHECK: attributes #22 = { minsize }
; CHECK: attributes #23 = { noinline optnone }
; CHECK: attributes #24 = { jumptable }
; CHECK: attributes #25 = { nobuiltin }
; CHECK: attributes #25 = { convergent }
; CHECK: attributes #26 = { nobuiltin }

View File

@ -80,6 +80,9 @@ namespace llvm {
/// isNoReturn - True if the intrinsic is no-return.
bool isNoReturn;
/// isConvergent - True if the intrinsic is marked as convergent.
bool isConvergent;
enum ArgAttribute {
NoCapture,
ReadOnly,

View File

@ -444,6 +444,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
canThrow = false;
isNoReturn = false;
isNoDuplicate = false;
isConvergent = false;
if (DefName.size() <= 4 ||
std::string(DefName.begin(), DefName.begin() + 4) != "int_")
@ -574,6 +575,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
canThrow = true;
else if (Property->getName() == "IntrNoDuplicate")
isNoDuplicate = true;
else if (Property->getName() == "IntrConvergent")
isConvergent = true;
else if (Property->getName() == "IntrNoReturn")
isNoReturn = true;
else if (Property->isSubClassOf("NoCapture")) {

View File

@ -537,6 +537,9 @@ struct AttributeComparator {
if (L->isNoReturn != R->isNoReturn)
return R->isNoReturn;
if (L->isConvergent != R->isConvergent)
return R->isConvergent;
// Try to order by readonly/readnone attribute.
ModRefKind LK = getModRefKind(*L);
ModRefKind RK = getModRefKind(*R);
@ -649,7 +652,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
ModRefKind modRef = getModRefKind(intrinsic);
if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn ||
intrinsic.isNoDuplicate) {
intrinsic.isNoDuplicate || intrinsic.isConvergent) {
OS << " const Attribute::AttrKind Atts[] = {";
bool addComma = false;
if (!intrinsic.canThrow) {
@ -668,6 +671,12 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << "Attribute::NoDuplicate";
addComma = true;
}
if (intrinsic.isConvergent) {
if (addComma)
OS << ",";
OS << "Attribute::Convergent";
addComma = true;
}
switch (modRef) {
case MRK_none: break;