Such attributes can either be unset, or set to "true" or "false" (as string).
throughout the codebase, this led to inelegant checks ranging from
if (Fn->getFnAttribute("no-jump-tables").getValueAsString() == "true")
to
if (Fn->hasAttribute("no-jump-tables") && Fn->getFnAttribute("no-jump-tables").getValueAsString() == "true")
Introduce a getValueAsBool that normalize the check, with the following
behavior:
no attributes or attribute set to "false" => return false
attribute set to "true" => return true
Differential Revision: https://reviews.llvm.org/D99299
auto mergeFnAttrValue = [&](StringRef Name, bool Value) {
auto OldValue =
- CGF.CurFn->getFnAttribute(Name).getValueAsString() == "true";
+ CGF.CurFn->getFnAttribute(Name).getValueAsBool();
auto NewValue = OldValue & Value;
if (OldValue != NewValue)
CGF.CurFn->addFnAttr(Name, llvm::toStringRef(NewValue));
/// Return true if lowering to a jump table is allowed.
virtual bool areJTsAllowed(const Function *Fn) const {
- if (Fn->getFnAttribute("no-jump-tables").getValueAsString() == "true")
+ if (Fn->getFnAttribute("no-jump-tables").getValueAsBool())
return false;
return isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) ||
/// attribute be an integer attribute.
uint64_t getValueAsInt() const;
+ /// Return the attribute's value as a boolean. This requires that the
+ /// attribute be a string attribute.
+ bool getValueAsBool() const;
+
/// Return the attribute's kind as a string. This requires the
/// attribute to be a string attribute.
StringRef getKindAsString() const;
Function &F = *Header->getParent();
FastMathFlags FMF;
FMF.setNoNaNs(
- F.getFnAttribute("no-nans-fp-math").getValueAsString() == "true");
+ F.getFnAttribute("no-nans-fp-math").getValueAsBool());
FMF.setNoSignedZeros(
- F.getFnAttribute("no-signed-zeros-fp-math").getValueAsString() == "true");
+ F.getFnAttribute("no-signed-zeros-fp-math").getValueAsBool());
if (AddReductionVar(Phi, RecurKind::Add, TheLoop, FMF, RedDes, DB, AC, DT)) {
LLVM_DEBUG(dbgs() << "Found an ADD reduction PHI." << *Phi << "\n");
IsTailCall = false;
if (IsTailCall && MF->getFunction()
.getFnAttribute("disable-tail-calls")
- .getValueAsString() == "true")
+ .getValueAsBool())
IsTailCall = false;
CallLoweringInfo CLI;
const Function &F = DAG.getMachineFunction().getFunction();
// First, check if tail calls have been disabled in this function.
- if (F.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
+ if (F.getFnAttribute("disable-tail-calls").getValueAsBool())
return false;
// Conservatively require the attributes of the call to match those of
Attribute::AttrKind getKindAsEnum() const;
uint64_t getValueAsInt() const;
+ bool getValueAsBool() const;
StringRef getKindAsString() const;
StringRef getValueAsString() const;
return pImpl->getValueAsInt();
}
+bool Attribute::getValueAsBool() const {
+ if (!pImpl) return false;
+ assert(isStringAttribute() &&
+ "Expected the attribute to be a string attribute!");
+ return pImpl->getValueAsBool();
+}
+
StringRef Attribute::getKindAsString() const {
if (!pImpl) return {};
assert(isStringAttribute() &&
return static_cast<const IntAttributeImpl *>(this)->getValue();
}
+bool AttributeImpl::getValueAsBool() const {
+ assert(getValueAsString().empty() || getValueAsString() == "false" || getValueAsString() == "true");
+ return getValueAsString() == "true";
+}
+
StringRef AttributeImpl::getKindAsString() const {
assert(isStringAttribute());
return static_cast<const StringAttributeImpl *>(this)->getStringKind();
void Verifier::verifyAttributeTypes(AttributeSet Attrs, bool IsFunction,
const Value *V) {
for (Attribute A : Attrs) {
- if (A.isStringAttribute())
+
+ if (A.isStringAttribute()) {
+#define GET_ATTR_NAMES
+#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME)
+#define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \
+ if (A.getKindAsString() == #DISPLAY_NAME) { \
+ auto V = A.getValueAsString(); \
+ if (!(V.empty() || V == "true" || V == "false")) \
+ CheckFailed("invalid value for '" #DISPLAY_NAME "' attribute: " + V + \
+ ""); \
+ }
+
+#include "llvm/IR/Attributes.inc"
continue;
+ }
if (A.isIntAttribute() !=
Attribute::doesAttrKindHaveArgument(A.getKindAsEnum())) {
static bool hasUnsafeFPMath(const Function &F) {
Attribute Attr = F.getFnAttribute("unsafe-fp-math");
- return Attr.getValueAsString() == "true";
+ return Attr.getValueAsBool();
}
static std::pair<Value*, Value*> getMul64(IRBuilder<> &Builder,
return true;
const Function *F = CI->getParent()->getParent();
Attribute Attr = F->getFnAttribute("unsafe-fp-math");
- return Attr.getValueAsString() == "true";
+ return Attr.getValueAsBool();
}
bool AMDGPULibCalls::useNativeFunc(const StringRef F) const {
const bool HasReqdWorkGroupSize = MD && MD->getNumOperands() == 3;
const bool HasUniformWorkGroupSize =
- F->getFnAttribute("uniform-work-group-size").getValueAsString() == "true";
+ F->getFnAttribute("uniform-work-group-size").getValueAsBool();
if (!HasReqdWorkGroupSize && !HasUniformWorkGroupSize)
return false;
const Function &F = MF.getFunction();
Attribute MemBoundAttr = F.getFnAttribute("amdgpu-memory-bound");
- MemoryBound = MemBoundAttr.isStringAttribute() &&
- MemBoundAttr.getValueAsString() == "true";
+ MemoryBound = MemBoundAttr.getValueAsBool();
Attribute WaveLimitAttr = F.getFnAttribute("amdgpu-wave-limiter");
- WaveLimiter = WaveLimitAttr.isStringAttribute() &&
- WaveLimitAttr.getValueAsString() == "true";
+ WaveLimiter = WaveLimitAttr.getValueAsBool();
CallingConv::ID CC = F.getCallingConv();
if (CC == CallingConv::AMDGPU_KERNEL || CC == CallingConv::SPIR_KERNEL)
// function before we can generate a subtarget. We also need to use
// it as a key for the subtarget since that can be the only difference
// between two functions.
- bool SoftFloat =
- F.getFnAttribute("use-soft-float").getValueAsString() == "true";
+ bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
// If the soft float attribute is set on the function turn on the soft float
// subtarget feature.
if (SoftFloat)
// Creating a separate target feature is not strictly necessary, it only
// exists to make "unsafe-fp-math" force creating a new subtarget.
- if (FnAttrs.hasFnAttribute("unsafe-fp-math") &&
- F.getFnAttribute("unsafe-fp-math").getValueAsString() == "true")
+ if (F.getFnAttribute("unsafe-fp-math").getValueAsBool())
FS = FS.empty() ? "+unsafe-fp" : "+unsafe-fp," + FS;
auto &I = SubtargetMap[CPU + FS];
report_fatal_error("M68k interrupts may not be called directly");
auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls");
- if (Attr.getValueAsString() == "true")
+ if (Attr.getValueAsBool())
IsTailCall = false;
// FIXME Add tailcalls support
// FIXME: This is related to the code below to reset the target options,
// we need to know whether or not the soft float flag is set on the
// function, so we can enable it as a subtarget feature.
- bool softFloat =
- F.hasFnAttribute("use-soft-float") &&
- F.getFnAttribute("use-soft-float").getValueAsString() == "true";
+ bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
if (hasMips16Attr)
FS += FS.empty() ? "+mips16" : ",+mips16";
// Allow unsafe math if unsafe-fp-math attribute explicitly says so.
const Function &F = MF.getFunction();
- if (F.hasFnAttribute("unsafe-fp-math")) {
- Attribute Attr = F.getFnAttribute("unsafe-fp-math");
- StringRef Val = Attr.getValueAsString();
- if (Val == "true")
- return true;
- }
-
- return false;
+ return F.getFnAttribute("unsafe-fp-math").getValueAsBool();
}
/// PerformADDCombineWithOperands - Try DAG combinations for an ADD with
// function before we can generate a subtarget. We also need to use
// it as a key for the subtarget since that can be the only difference
// between two functions.
- bool SoftFloat =
- F.getFnAttribute("use-soft-float").getValueAsString() == "true";
+ bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
// If the soft float attribute is set on the function turn on the soft float
// subtarget feature.
if (SoftFloat)
// FIXME: This is related to the code below to reset the target options,
// we need to know whether or not the soft float flag is set on the
// function, so we can enable it as a subtarget feature.
- bool softFloat =
- F.hasFnAttribute("use-soft-float") &&
- F.getFnAttribute("use-soft-float").getValueAsString() == "true";
+ bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
if (softFloat)
FS += FS.empty() ? "+soft-float" : ",+soft-float";
// FIXME: This is related to the code below to reset the target options,
// we need to know whether or not the soft float flag is set on the
// function, so we can enable it as a subtarget feature.
- bool softFloat =
- F.hasFnAttribute("use-soft-float") &&
- F.getFnAttribute("use-soft-float").getValueAsString() == "true";
+ bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
if (softFloat)
FS += FS.empty() ? "+soft-float" : ",+soft-float";
void TargetMachine::resetTargetOptions(const Function &F) const {
#define RESET_OPTION(X, Y) \
do { \
- Options.X = (F.getFnAttribute(Y).getValueAsString() == "true"); \
+ Options.X = F.getFnAttribute(Y).getValueAsBool(); \
} while (0)
RESET_OPTION(UnsafeFPMath, "unsafe-fp-math");
// function before we can generate a subtarget. We also need to use
// it as a key for the subtarget since that can be the only difference
// between two functions.
- bool SoftFloat =
- F.getFnAttribute("use-soft-float").getValueAsString() == "true";
+ bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
// If the soft float attribute is set on the function turn on the soft float
// subtarget feature.
if (SoftFloat)
void visitCallBase(CallBase &CB, IRBuilder<> &IRB) override {
bool IsSoftFloatABI = CB.getCalledFunction()
->getFnAttribute("use-soft-float")
- .getValueAsString() == "true";
+ .getValueAsBool();
unsigned GpOffset = SystemZGpOffset;
unsigned FpOffset = SystemZFpOffset;
unsigned VrIndex = 0;
AliasAnalysis *AA,
OptimizationRemarkEmitter *ORE,
DomTreeUpdater &DTU) {
- if (F.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
+ if (F.getFnAttribute("disable-tail-calls").getValueAsBool())
return false;
bool MadeChange = false;
// Only build lookup table when we have a target that supports it or the
// attribute is not set.
if (!TTI.shouldBuildLookupTables() ||
- (Fn->getFnAttribute("no-jump-tables").getValueAsString() == "true"))
+ (Fn->getFnAttribute("no-jump-tables").getValueAsBool()))
return false;
// FIXME: If the switch is too sparse for a lookup table, perhaps we could
--- /dev/null
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+
+; CHECK: invalid value for 'no-jump-tables' attribute: yes
+
+define void @func() #0 {
+ ret void
+}
+
+attributes #0 = { "no-jump-tables"="yes" }