diff options
author | Matt Arsenault <Matthew.Arsenault@amd.com> | 2019-03-12 21:02:54 +0000 |
---|---|---|
committer | Matt Arsenault <Matthew.Arsenault@amd.com> | 2019-03-12 21:02:54 +0000 |
commit | caf1316f7100e1ba1e7e800eae6a5adf0d48bf90 (patch) | |
tree | 7b79b67ccf3ffe7fe9b56dee66444a586d7714d2 /llvm/lib/IR/Verifier.cpp | |
parent | 9df0754b8dbeeb597a22bb0418eb0ee04ce88b56 (diff) | |
download | bcm5719-llvm-caf1316f7100e1ba1e7e800eae6a5adf0d48bf90.tar.gz bcm5719-llvm-caf1316f7100e1ba1e7e800eae6a5adf0d48bf90.zip |
IR: Add immarg attribute
This indicates an intrinsic parameter is required to be a constant,
and should not be replaced with a non-constant value.
Add the attribute to all AMDGPU and generic intrinsics that comments
indicate it should apply to. I scanned other target intrinsics, but I
don't see any obvious comments indicating which arguments are intended
to be only immediates.
This breaks one questionable testcase for the autoupgrade. I'm unclear
on whether the autoupgrade is supposed to really handle declarations
which were never valid. The verifier fails because the attributes now
refer to a parameter past the end of the argument list.
llvm-svn: 355981
Diffstat (limited to 'llvm/lib/IR/Verifier.cpp')
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 117 |
1 files changed, 50 insertions, 67 deletions
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 55d3a323610..44095bf05e1 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -500,7 +500,7 @@ private: const Value *V); void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V); void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, - const Value *V); + const Value *V, bool IsIntrinsic); void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs); void visitConstantExprsRecursively(const Constant *EntryC); @@ -1562,6 +1562,11 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, verifyAttributeTypes(Attrs, /*IsFunction=*/false, V); + if (Attrs.hasAttribute(Attribute::ImmArg)) { + Assert(Attrs.getNumAttributes() == 1, + "Attribute 'immarg' is incompatible with other attributes", V); + } + // Check for mutually incompatible attributes. Only inreg is compatible with // sret. unsigned AttrCount = 0; @@ -1649,7 +1654,7 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, // Check parameter attributes against a function type. // The value V is printed in error messages. void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, - const Value *V) { + const Value *V, bool IsIntrinsic) { if (Attrs.isEmpty()) return; @@ -1686,6 +1691,11 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, Type *Ty = FT->getParamType(i); AttributeSet ArgAttrs = Attrs.getParamAttributes(i); + if (!IsIntrinsic) { + Assert(!ArgAttrs.hasAttribute(Attribute::ImmArg), + "immarg attribute only applies to intrinsics",V); + } + verifyParameterAttrs(ArgAttrs, Ty, V); if (ArgAttrs.hasAttribute(Attribute::Nest)) { @@ -1904,16 +1914,8 @@ void Verifier::verifyStatepoint(const CallBase &Call) { "reordering restrictions required by safepoint semantics", Call); - const Value *IDV = Call.getArgOperand(0); - Assert(isa<ConstantInt>(IDV), "gc.statepoint ID must be a constant integer", - Call); - - const Value *NumPatchBytesV = Call.getArgOperand(1); - Assert(isa<ConstantInt>(NumPatchBytesV), - "gc.statepoint number of patchable bytes must be a constant integer", - Call); const int64_t NumPatchBytes = - cast<ConstantInt>(NumPatchBytesV)->getSExtValue(); + cast<ConstantInt>(Call.getArgOperand(1))->getSExtValue(); assert(isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!"); Assert(NumPatchBytes >= 0, "gc.statepoint number of patchable bytes must be " @@ -1926,12 +1928,7 @@ void Verifier::verifyStatepoint(const CallBase &Call) { "gc.statepoint callee must be of function pointer type", Call, Target); FunctionType *TargetFuncType = cast<FunctionType>(PT->getElementType()); - const Value *NumCallArgsV = Call.getArgOperand(3); - Assert(isa<ConstantInt>(NumCallArgsV), - "gc.statepoint number of arguments to underlying call " - "must be constant integer", - Call); - const int NumCallArgs = cast<ConstantInt>(NumCallArgsV)->getZExtValue(); + const int NumCallArgs = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue(); Assert(NumCallArgs >= 0, "gc.statepoint number of arguments to underlying call " "must be positive", @@ -1950,10 +1947,8 @@ void Verifier::verifyStatepoint(const CallBase &Call) { Assert(NumCallArgs == NumParams, "gc.statepoint mismatch in number of call args", Call); - const Value *FlagsV = Call.getArgOperand(4); - Assert(isa<ConstantInt>(FlagsV), - "gc.statepoint flags must be constant integer", Call); - const uint64_t Flags = cast<ConstantInt>(FlagsV)->getZExtValue(); + const uint64_t Flags + = cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue(); Assert((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0, "unknown flag used in gc.statepoint flags argument", Call); @@ -2130,8 +2125,11 @@ void Verifier::visitFunction(const Function &F) { Assert(verifyAttributeCount(Attrs, FT->getNumParams()), "Attribute after last parameter!", &F); + bool isLLVMdotName = F.getName().size() >= 5 && + F.getName().substr(0, 5) == "llvm."; + // Check function attributes. - verifyFunctionAttrs(FT, Attrs, &F); + verifyFunctionAttrs(FT, Attrs, &F, isLLVMdotName); // On function declarations/definitions, we do not support the builtin // attribute. We do not check this in VerifyFunctionAttrs since that is @@ -2170,9 +2168,6 @@ void Verifier::visitFunction(const Function &F) { break; } - bool isLLVMdotName = F.getName().size() >= 5 && - F.getName().substr(0, 5) == "llvm."; - // Check that the argument values match the function type for this function... unsigned i = 0; for (const Argument &Arg : F.args()) { @@ -2800,17 +2795,21 @@ void Verifier::visitCallBase(CallBase &Call) { Assert(verifyAttributeCount(Attrs, Call.arg_size()), "Attribute after last parameter!", Call); + bool IsIntrinsic = Call.getCalledFunction() && + Call.getCalledFunction()->getName().startswith("llvm."); + + Function *Callee + = dyn_cast<Function>(Call.getCalledValue()->stripPointerCasts()); + if (Attrs.hasAttribute(AttributeList::FunctionIndex, Attribute::Speculatable)) { // Don't allow speculatable on call sites, unless the underlying function // declaration is also speculatable. - Function *Callee = - dyn_cast<Function>(Call.getCalledValue()->stripPointerCasts()); Assert(Callee && Callee->isSpeculatable(), "speculatable attribute may not apply to call sites", Call); } // Verify call attributes. - verifyFunctionAttrs(FTy, Attrs, &Call); + verifyFunctionAttrs(FTy, Attrs, &Call, IsIntrinsic); // Conservatively check the inalloca argument. // We have a bug if we can find that there is an underlying alloca without @@ -2825,7 +2824,7 @@ void Verifier::visitCallBase(CallBase &Call) { // For each argument of the callsite, if it has the swifterror argument, // make sure the underlying alloca/parameter it comes from has a swifterror as // well. - for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) { if (Call.paramHasAttr(i, Attribute::SwiftError)) { Value *SwiftErrorArg = Call.getArgOperand(i); if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) { @@ -2842,6 +2841,21 @@ void Verifier::visitCallBase(CallBase &Call) { Call); } + if (Attrs.hasParamAttribute(i, Attribute::ImmArg)) { + // Don't allow immarg on call sites, unless the underlying declaration + // also has the matching immarg. + Assert(Callee && Callee->hasParamAttribute(i, Attribute::ImmArg), + "immarg may not apply only to call sites", + Call.getArgOperand(i), Call); + } + + if (Call.paramHasAttr(i, Attribute::ImmArg)) { + Value *ArgVal = Call.getArgOperand(i); + Assert(isa<ConstantInt>(ArgVal) || isa<ConstantFP>(ArgVal), + "immarg operand has non-immediate parameter", ArgVal, Call); + } + } + if (FTy->isVarArg()) { // FIXME? is 'nest' even legal here? bool SawNest = false; @@ -2891,8 +2905,7 @@ void Verifier::visitCallBase(CallBase &Call) { } // Verify that there's no metadata unless it's a direct call to an intrinsic. - if (!Call.getCalledFunction() || - !Call.getCalledFunction()->getName().startswith("llvm.")) { + if (!IsIntrinsic) { for (Type *ParamTy : FTy->params()) { Assert(!ParamTy->isMetadataTy(), "Function has metadata parameter but isn't an intrinsic", Call); @@ -4181,13 +4194,6 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "an array"); break; } - case Intrinsic::ctlz: // llvm.ctlz - case Intrinsic::cttz: // llvm.cttz - Assert(isa<ConstantInt>(Call.getArgOperand(1)), - "is_zero_undef argument of bit counting intrinsics must be a " - "constant int", - Call); - break; case Intrinsic::experimental_constrained_fadd: case Intrinsic::experimental_constrained_fsub: case Intrinsic::experimental_constrained_fmul: @@ -4243,9 +4249,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "alignment of arg 1 of memory intrinsic must be 0 or a power of 2", Call); } - Assert(isa<ConstantInt>(Call.getArgOperand(3)), - "isvolatile argument of memory intrinsics must be a constant int", - Call); + break; } case Intrinsic::memcpy_element_unordered_atomic: @@ -4254,11 +4258,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { const auto *AMI = cast<AtomicMemIntrinsic>(&Call); ConstantInt *ElementSizeCI = - dyn_cast<ConstantInt>(AMI->getRawElementSizeInBytes()); - Assert(ElementSizeCI, - "element size of the element-wise unordered atomic memory " - "intrinsic must be a constant int", - Call); + cast<ConstantInt>(AMI->getRawElementSizeInBytes()); const APInt &ElementSizeVal = ElementSizeCI->getValue(); Assert(ElementSizeVal.isPowerOf2(), "element size of the element-wise atomic memory intrinsic " @@ -4313,28 +4313,14 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { Call); break; case Intrinsic::prefetch: - Assert(isa<ConstantInt>(Call.getArgOperand(1)) && - isa<ConstantInt>(Call.getArgOperand(2)) && - cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue() < 2 && - cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue() < 4, + Assert(cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue() < 2 && + cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue() < 4, "invalid arguments to llvm.prefetch", Call); break; case Intrinsic::stackprotector: Assert(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts()), "llvm.stackprotector parameter #2 must resolve to an alloca.", Call); break; - case Intrinsic::lifetime_start: - case Intrinsic::lifetime_end: - case Intrinsic::invariant_start: - Assert(isa<ConstantInt>(Call.getArgOperand(0)), - "size argument of memory use markers must be a constant integer", - Call); - break; - case Intrinsic::invariant_end: - Assert(isa<ConstantInt>(Call.getArgOperand(1)), - "llvm.invariant.end parameter #2 must be a constant integer", Call); - break; - case Intrinsic::localescape: { BasicBlock *BB = Call.getParent(); Assert(BB == &BB->getParent()->front(), @@ -4359,9 +4345,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "llvm.localrecover first " "argument must be function defined in this module", Call); - auto *IdxArg = dyn_cast<ConstantInt>(Call.getArgOperand(2)); - Assert(IdxArg, "idx argument of llvm.localrecover must be a constant int", - Call); + auto *IdxArg = cast<ConstantInt>(Call.getArgOperand(2)); auto &Entry = FrameEscapeInfo[Fn]; Entry.second = unsigned( std::max(uint64_t(Entry.second), IdxArg->getLimitedValue(~0U) + 1)); @@ -4606,8 +4590,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "second operand of [us]mul_fix must be an int type or vector " "of ints"); - auto *Op3 = dyn_cast<ConstantInt>(Call.getArgOperand(2)); - Assert(Op3, "third argument of [us]mul_fix must be a constant integer"); + auto *Op3 = cast<ConstantInt>(Call.getArgOperand(2)); Assert(Op3->getType()->getBitWidth() <= 32, "third argument of [us]mul_fix must fit within 32 bits"); |