Index: llvm/include/llvm/IR/Attributes.h =================================================================== --- llvm/include/llvm/IR/Attributes.h +++ llvm/include/llvm/IR/Attributes.h @@ -114,6 +114,8 @@ /// Return true if and only if the attribute has an Argument. static bool doesAttrKindHaveArgument(Attribute::AttrKind AttrKind); + static bool isExistingAttribute(StringRef Name); + //===--------------------------------------------------------------------===// // Attribute Accessors //===--------------------------------------------------------------------===// Index: llvm/lib/IR/Attributes.cpp =================================================================== --- llvm/lib/IR/Attributes.cpp +++ llvm/lib/IR/Attributes.cpp @@ -207,6 +207,15 @@ AttrKind == Attribute::DereferenceableOrNull; } +bool Attribute::isExistingAttribute(StringRef Name) { + return StringSwitch(Name) +#define GET_ATTR_NAMES +#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true) +#include "llvm/IR/Attributes.inc" + .Default(false); +} + + //===----------------------------------------------------------------------===// // Attribute Accessor Methods //===----------------------------------------------------------------------===// Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -4322,6 +4322,29 @@ switch (ID) { default: break; + case Intrinsic::assume: { + for (auto& Elem : Call.bundle_op_infos()) { + Assert(Attribute::isExistingAttribute(Elem.Tag->getKey()), + "tags must be valid attribute names"); + Assert(Elem.End - Elem.Begin <= 2, "to many arguments"); + Attribute::AttrKind Kind = + Attribute::getAttrKindFromName(Elem.Tag->getKey()); + if (Kind == Attribute::None) + break; + if (Attribute::doesAttrKindHaveArgument(Kind)) { + Assert(Elem.End - Elem.Begin == 2, + "this attribute should have 2 arguments"); + Assert(isa(Call.getOperand(Elem.Begin + 1)), + "the second argument should be a constant integral value"); + } else if (isFuncOnlyAttr(Kind)) { + Assert((Elem.End - Elem.Begin) == 0, "this attribute has not argument"); + } else if (!isFuncOrArgAttr(Kind)) { + Assert((Elem.End - Elem.Begin) == 1, + "this attribute should have one argument"); + } + } + break; + } case Intrinsic::coro_id: { auto *InfoArg = Call.getArgOperand(3)->stripPointerCasts(); if (isa(InfoArg)) Index: llvm/lib/Transforms/Utils/KnowledgeRetention.cpp =================================================================== --- llvm/lib/Transforms/Utils/KnowledgeRetention.cpp +++ llvm/lib/Transforms/Utils/KnowledgeRetention.cpp @@ -178,25 +178,14 @@ return (Assume.op_begin() + BOI.Begin + Idx)->get(); } -#ifndef NDEBUG - -static bool isExistingAttribute(StringRef Name) { - return StringSwitch(Name) -#define GET_ATTR_NAMES -#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) .Case(#DISPLAY_NAME, true) -#include "llvm/IR/Attributes.inc" - .Default(false); -} - -#endif - bool llvm::hasAttributeInAssume(CallInst &AssumeCI, Value *IsOn, StringRef AttrName, uint64_t *ArgVal, AssumeQuery AQR) { IntrinsicInst &Assume = cast(AssumeCI); assert(Assume.getIntrinsicID() == Intrinsic::assume && "this function is intended to be used on llvm.assume"); - assert(isExistingAttribute(AttrName) && "this attribute doesn't exist"); + assert(Attribute::isExistingAttribute(AttrName) && + "this attribute doesn't exist"); assert((ArgVal == nullptr || Attribute::doesAttrKindHaveArgument( Attribute::getAttrKindFromName(AttrName))) && "requested value for an attribute that has no argument"); @@ -213,16 +202,12 @@ Lookup = llvm::lower_bound(Assume.bundle_op_infos(), AttrName, [](const CallBase::BundleOpInfo &BOI, StringRef RHS) { - assert(isExistingAttribute(BOI.Tag->getKey()) && - "this attribute doesn't exist"); return BOI.Tag->getKey() < RHS; }); else Lookup = std::prev( llvm::upper_bound(Assume.bundle_op_infos(), AttrName, [](StringRef LHS, const CallBase::BundleOpInfo &BOI) { - assert(isExistingAttribute(BOI.Tag->getKey()) && - "this attribute doesn't exist"); return LHS < BOI.Tag->getKey(); })); Index: llvm/test/Transforms/Util/assume-builder.ll =================================================================== --- llvm/test/Transforms/Util/assume-builder.ll +++ llvm/test/Transforms/Util/assume-builder.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -passes='assume-builder' -S %s | FileCheck %s --check-prefixes=BASIC -; RUN: opt -passes='assume-builder' --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL +; RUN: opt -passes='assume-builder,verify' -S %s | FileCheck %s --check-prefixes=BASIC +; RUN: opt -passes='assume-builder,verify' --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL declare void @func(i32*, i32*) declare void @func_cold(i32*) cold