mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
Add initial support for the convergent attribute.
llvm-svn: 238264
This commit is contained in:
parent
2da00c394b
commit
1db6d7f8ed
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -597,6 +597,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(byval);
|
||||
KEYWORD(inalloca);
|
||||
KEYWORD(cold);
|
||||
KEYWORD(convergent);
|
||||
KEYWORD(dereferenceable);
|
||||
KEYWORD(dereferenceable_or_null);
|
||||
KEYWORD(inlinehint);
|
||||
|
@ -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;
|
||||
|
@ -105,6 +105,7 @@ namespace lltok {
|
||||
kw_byval,
|
||||
kw_inalloca,
|
||||
kw_cold,
|
||||
kw_convergent,
|
||||
kw_dereferenceable,
|
||||
kw_dereferenceable_or_null,
|
||||
kw_inlinehint,
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 }
|
||||
|
@ -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,
|
||||
|
@ -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")) {
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user