Skip to content

Commit c85611e

Browse files
authored
[SimplifyLibCall][Attribute] Fix bug where we may keep range attr with incompatible type (#112649)
In a variety of places we change the bitwidth of a parameter but don't update the attributes. The issue in this case is from the `range` attribute when inlining `__memset_chk`. `optimizeMemSetChk` will replace an `i32` with an `i8`, and if the `i32` had a `range` attr assosiated it will cause an error. Fixes #112633
1 parent ab208de commit c85611e

File tree

18 files changed

+88
-34
lines changed

18 files changed

+88
-34
lines changed

llvm/include/llvm/IR/Argument.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ class Argument final : public Value {
182182

183183
Attribute getAttribute(Attribute::AttrKind Kind) const;
184184

185+
AttributeSet getAttributes() const;
186+
185187
/// Method for support type inquiry through isa, cast, and dyn_cast.
186188
static bool classof(const Value *V) {
187189
return V->getValueID() == ArgumentVal;

llvm/include/llvm/IR/Attributes.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,11 +1288,17 @@ enum AttributeSafetyKind : uint8_t {
12881288
/// follows the same type rules as FPMathOperator.
12891289
bool isNoFPClassCompatibleType(Type *Ty);
12901290

1291-
/// Which attributes cannot be applied to a type. The argument \p ASK indicates,
1292-
/// if only attributes that are known to be safely droppable are contained in
1293-
/// the mask; only attributes that might be unsafe to drop (e.g., ABI-related
1294-
/// attributes) are in the mask; or both.
1295-
AttributeMask typeIncompatible(Type *Ty, AttributeSafetyKind ASK = ASK_ALL);
1291+
/// Which attributes cannot be applied to a type. The argument \p AS
1292+
/// is used as a hint for the attributes whose compatibility is being
1293+
/// checked against \p Ty. This does not mean the return will be a
1294+
/// subset of \p AS, just that attributes that have specific dynamic
1295+
/// type compatibilities (i.e `range`) will be checked against what is
1296+
/// contained in \p AS. The argument \p ASK indicates, if only
1297+
/// attributes that are known to be safely droppable are contained in
1298+
/// the mask; only attributes that might be unsafe to drop (e.g.,
1299+
/// ABI-related attributes) are in the mask; or both.
1300+
AttributeMask typeIncompatible(Type *Ty, AttributeSet AS,
1301+
AttributeSafetyKind ASK = ASK_ALL);
12961302

12971303
/// Get param/return attributes which imply immediate undefined behavior if an
12981304
/// invalid value is passed. For example, this includes noundef (where undef

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,14 +1453,22 @@ class CallBase : public Instruction {
14531453
/// looking through to the attributes on the called function when necessary).
14541454
///@{
14551455

1456-
/// Return the parameter attributes for this call.
1457-
///
1456+
/// Return the attributes for this call.
14581457
AttributeList getAttributes() const { return Attrs; }
14591458

1460-
/// Set the parameter attributes for this call.
1461-
///
1459+
/// Set the attributes for this call.
14621460
void setAttributes(AttributeList A) { Attrs = A; }
14631461

1462+
/// Return the return attributes for this call.
1463+
AttributeSet getRetAttributes() const {
1464+
return getAttributes().getRetAttrs();
1465+
}
1466+
1467+
/// Return the param attributes for this call.
1468+
AttributeSet getParamAttributes(unsigned ArgNo) const {
1469+
return getAttributes().getParamAttrs(ArgNo);
1470+
}
1471+
14641472
/// Try to intersect the attributes from 'this' CallBase and the
14651473
/// 'Other' CallBase. Sets the intersected attributes to 'this' and
14661474
/// return true if successful. Doesn't modify 'this' and returns

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7040,11 +7040,12 @@ Error BitcodeReader::materialize(GlobalValue *GV) {
70407040
// Remove incompatible attributes on function calls.
70417041
if (auto *CI = dyn_cast<CallBase>(&I)) {
70427042
CI->removeRetAttrs(AttributeFuncs::typeIncompatible(
7043-
CI->getFunctionType()->getReturnType()));
7043+
CI->getFunctionType()->getReturnType(), CI->getRetAttributes()));
70447044

70457045
for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ++ArgNo)
70467046
CI->removeParamAttrs(ArgNo, AttributeFuncs::typeIncompatible(
7047-
CI->getArgOperand(ArgNo)->getType()));
7047+
CI->getArgOperand(ArgNo)->getType(),
7048+
CI->getParamAttributes(ArgNo)));
70487049
}
70497050
}
70507051

llvm/lib/IR/Attributes.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2300,7 +2300,7 @@ bool AttributeFuncs::isNoFPClassCompatibleType(Type *Ty) {
23002300
}
23012301

23022302
/// Which attributes cannot be applied to a type.
2303-
AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
2303+
AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, AttributeSet AS,
23042304
AttributeSafetyKind ASK) {
23052305
AttributeMask Incompatible;
23062306

@@ -2316,6 +2316,11 @@ AttributeMask AttributeFuncs::typeIncompatible(Type *Ty,
23162316
// Attributes that only apply to integers or vector of integers.
23172317
if (ASK & ASK_SAFE_TO_DROP)
23182318
Incompatible.addAttribute(Attribute::Range);
2319+
} else {
2320+
Attribute RangeAttr = AS.getAttribute(Attribute::Range);
2321+
if (RangeAttr.isValid() &&
2322+
RangeAttr.getRange().getBitWidth() != Ty->getScalarSizeInBits())
2323+
Incompatible.addAttribute(Attribute::Range);
23192324
}
23202325

23212326
if (!Ty->isPointerTy()) {

llvm/lib/IR/AutoUpgrade.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5378,9 +5378,11 @@ void llvm::UpgradeFunctionAttributes(Function &F) {
53785378
}
53795379

53805380
// Remove all incompatibile attributes from function.
5381-
F.removeRetAttrs(AttributeFuncs::typeIncompatible(F.getReturnType()));
5381+
F.removeRetAttrs(AttributeFuncs::typeIncompatible(
5382+
F.getReturnType(), F.getAttributes().getRetAttrs()));
53825383
for (auto &Arg : F.args())
5383-
Arg.removeAttrs(AttributeFuncs::typeIncompatible(Arg.getType()));
5384+
Arg.removeAttrs(
5385+
AttributeFuncs::typeIncompatible(Arg.getType(), Arg.getAttributes()));
53845386

53855387
// Older versions of LLVM treated an "implicit-section-name" attribute
53865388
// similarly to directly setting the section on a Function.

llvm/lib/IR/Function.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@ Attribute Argument::getAttribute(Attribute::AttrKind Kind) const {
359359
return getParent()->getParamAttribute(getArgNo(), Kind);
360360
}
361361

362+
AttributeSet Argument::getAttributes() const {
363+
return getParent()->getAttributes().getParamAttrs(getArgNo());
364+
}
365+
362366
//===----------------------------------------------------------------------===//
363367
// Helper Methods in Function
364368
//===----------------------------------------------------------------------===//

llvm/lib/IR/Verifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2012,7 +2012,7 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
20122012
Attrs.hasAttribute(Attribute::ReadOnly)),
20132013
"Attributes writable and readonly are incompatible!", V);
20142014

2015-
AttributeMask IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty);
2015+
AttributeMask IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty, Attrs);
20162016
for (Attribute Attr : Attrs) {
20172017
if (!Attr.isStringAttribute() &&
20182018
IncompatibleAttrs.contains(Attr.getKindAsEnum())) {

llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,8 @@ bool AMDGPULibCalls::fold(CallInst *CI) {
788788
B.CreateFPToSI(FPOp->getOperand(1), PownType->getParamType(1));
789789
// Have to drop any nofpclass attributes on the original call site.
790790
Call->removeParamAttrs(
791-
1, AttributeFuncs::typeIncompatible(CastedArg->getType()));
791+
1, AttributeFuncs::typeIncompatible(CastedArg->getType(),
792+
Call->getParamAttributes(1)));
792793
Call->setCalledFunction(PownFunc);
793794
Call->setArgOperand(1, CastedArg);
794795
return fold_pow(FPOp, B, PownInfo) || true;

llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -857,9 +857,10 @@ bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(Function *F) {
857857
// here. Currently, this should not be possible, but special handling might be
858858
// required when new return value attributes are added.
859859
if (NRetTy->isVoidTy())
860-
RAttrs.remove(AttributeFuncs::typeIncompatible(NRetTy));
860+
RAttrs.remove(AttributeFuncs::typeIncompatible(NRetTy, PAL.getRetAttrs()));
861861
else
862-
assert(!RAttrs.overlaps(AttributeFuncs::typeIncompatible(NRetTy)) &&
862+
assert(!RAttrs.overlaps(
863+
AttributeFuncs::typeIncompatible(NRetTy, PAL.getRetAttrs())) &&
863864
"Return attributes no longer compatible?");
864865

865866
AttributeSet RetAttrs = AttributeSet::get(F->getContext(), RAttrs);
@@ -903,7 +904,8 @@ bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(Function *F) {
903904
// Adjust the call return attributes in case the function was changed to
904905
// return void.
905906
AttrBuilder RAttrs(F->getContext(), CallPAL.getRetAttrs());
906-
RAttrs.remove(AttributeFuncs::typeIncompatible(NRetTy));
907+
RAttrs.remove(
908+
AttributeFuncs::typeIncompatible(NRetTy, CallPAL.getRetAttrs()));
907909
AttributeSet RetAttrs = AttributeSet::get(F->getContext(), RAttrs);
908910

909911
// Declare these outside of the loops, so we can reuse them for the second

0 commit comments

Comments
 (0)