diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -174,7 +174,7 @@ 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)); diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -1144,7 +1144,7 @@ /// 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) || diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -168,6 +168,10 @@ /// 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; diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp --- a/llvm/lib/Analysis/IVDescriptors.cpp +++ b/llvm/lib/Analysis/IVDescriptors.cpp @@ -653,9 +653,9 @@ 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"); diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1145,7 +1145,7 @@ IsTailCall = false; if (IsTailCall && MF->getFunction() .getFnAttribute("disable-tail-calls") - .getValueAsString() == "true") + .getValueAsBool()) IsTailCall = false; CallLoweringInfo CLI; diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -53,7 +53,7 @@ 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 diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h --- a/llvm/lib/IR/AttributeImpl.h +++ b/llvm/lib/IR/AttributeImpl.h @@ -64,6 +64,7 @@ Attribute::AttrKind getKindAsEnum() const; uint64_t getValueAsInt() const; + bool getValueAsBool() const; StringRef getKindAsString() const; StringRef getValueAsString() const; diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -287,6 +287,13 @@ 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() && @@ -650,6 +657,11 @@ return static_cast(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(this)->getStringKind(); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1717,8 +1717,21 @@ 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())) { diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp @@ -809,7 +809,7 @@ static bool hasUnsafeFPMath(const Function &F) { Attribute Attr = F.getFnAttribute("unsafe-fp-math"); - return Attr.getValueAsString() == "true"; + return Attr.getValueAsBool(); } static std::pair getMul64(IRBuilder<> &Builder, diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp @@ -476,7 +476,7 @@ 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 { diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerKernelAttributes.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerKernelAttributes.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPULowerKernelAttributes.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerKernelAttributes.cpp @@ -67,7 +67,7 @@ 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; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp b/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp @@ -28,12 +28,10 @@ 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) diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp --- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -274,8 +274,7 @@ // 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) diff --git a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp --- a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -251,8 +251,7 @@ // 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]; diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp --- a/llvm/lib/Target/M68k/M68kISelLowering.cpp +++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -487,7 +487,7 @@ 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 diff --git a/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/llvm/lib/Target/Mips/MipsTargetMachine.cpp --- a/llvm/lib/Target/Mips/MipsTargetMachine.cpp +++ b/llvm/lib/Target/Mips/MipsTargetMachine.cpp @@ -176,9 +176,7 @@ // 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"; diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp @@ -4304,14 +4304,7 @@ // 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 diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -343,8 +343,7 @@ // 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) diff --git a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp --- a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp +++ b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp @@ -117,9 +117,7 @@ // 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"; diff --git a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp --- a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp +++ b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp @@ -179,9 +179,7 @@ // 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"; diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -56,7 +56,7 @@ 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"); diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -294,8 +294,7 @@ // 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) diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -5028,7 +5028,7 @@ 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; diff --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp --- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -799,7 +799,7 @@ 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; diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -5793,7 +5793,7 @@ // 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 diff --git a/llvm/test/Verifier/invalid-strbool-attr.ll b/llvm/test/Verifier/invalid-strbool-attr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/invalid-strbool-attr.ll @@ -0,0 +1,9 @@ +; 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" }