3434#include " llvm/Analysis/VectorUtils.h"
3535#include " llvm/IR/Argument.h"
3636#include " llvm/IR/AttributeMask.h"
37+ #include " llvm/IR/Attributes.h"
3738#include " llvm/IR/BasicBlock.h"
3839#include " llvm/IR/CFG.h"
3940#include " llvm/IR/Constant.h"
5960#include " llvm/IR/MDBuilder.h"
6061#include " llvm/IR/Metadata.h"
6162#include " llvm/IR/Module.h"
63+ #include " llvm/IR/PatternMatch.h"
6264#include " llvm/IR/ProfDataUtils.h"
6365#include " llvm/IR/Type.h"
6466#include " llvm/IR/User.h"
@@ -1358,18 +1360,36 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
13581360 auto &Context = CalledFunction->getContext ();
13591361
13601362 // Collect valid attributes for all params.
1361- SmallVector<AttrBuilder> ValidParamAttrs ;
1363+ SmallVector<AttrBuilder> ValidObjParamAttrs, ValidExactParamAttrs ;
13621364 bool HasAttrToPropagate = false ;
13631365
1366+ // Attributes we can only propagate if the exact parameter is forwarded.
1367+ // We can propagate both poison generating and UB generating attributes
1368+ // without any extra checks. The only attribute that is tricky to propagate
1369+ // is `noundef` (skipped for now) as that can create new UB where previous
1370+ // behavior was just using a poison value.
1371+ static const Attribute::AttrKind ExactAttrsToPropagate[] = {
1372+ Attribute::Dereferenceable, Attribute::DereferenceableOrNull,
1373+ Attribute::NonNull, Attribute::Alignment, Attribute::Range};
1374+
13641375 for (unsigned I = 0 , E = CB.arg_size (); I < E; ++I) {
1365- ValidParamAttrs.emplace_back (AttrBuilder{CB.getContext ()});
1376+ ValidObjParamAttrs.emplace_back (AttrBuilder{CB.getContext ()});
1377+ ValidExactParamAttrs.emplace_back (AttrBuilder{CB.getContext ()});
13661378 // Access attributes can be propagated to any param with the same underlying
13671379 // object as the argument.
13681380 if (CB.paramHasAttr (I, Attribute::ReadNone))
1369- ValidParamAttrs .back ().addAttribute (Attribute::ReadNone);
1381+ ValidObjParamAttrs .back ().addAttribute (Attribute::ReadNone);
13701382 if (CB.paramHasAttr (I, Attribute::ReadOnly))
1371- ValidParamAttrs.back ().addAttribute (Attribute::ReadOnly);
1372- HasAttrToPropagate |= ValidParamAttrs.back ().hasAttributes ();
1383+ ValidObjParamAttrs.back ().addAttribute (Attribute::ReadOnly);
1384+
1385+ for (Attribute::AttrKind AK : ExactAttrsToPropagate) {
1386+ Attribute Attr = CB.getParamAttr (I, AK);
1387+ if (Attr.isValid ())
1388+ ValidExactParamAttrs.back ().addAttribute (Attr);
1389+ }
1390+
1391+ HasAttrToPropagate |= ValidObjParamAttrs.back ().hasAttributes ();
1392+ HasAttrToPropagate |= ValidExactParamAttrs.back ().hasAttributes ();
13731393 }
13741394
13751395 // Won't be able to propagate anything.
@@ -1391,22 +1411,60 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
13911411
13921412 AttributeList AL = NewInnerCB->getAttributes ();
13931413 for (unsigned I = 0 , E = InnerCB->arg_size (); I < E; ++I) {
1394- // Check if the underlying value for the parameter is an argument.
1395- const Value *UnderlyingV =
1396- getUnderlyingObject (InnerCB-> getArgOperand (I));
1397- const Argument *Arg = dyn_cast<Argument>(UnderlyingV);
1398- if (!Arg )
1414+ // It's unsound or requires special handling to propagate
1415+ // attributes to byval arguments. Even if CalledFunction
1416+ // doesn't e.g. write to the argument (readonly), the call to
1417+ // NewInnerCB may write to its by-value copy.
1418+ if (NewInnerCB-> paramHasAttr (I, Attribute::ByVal) )
13991419 continue ;
14001420
1401- if (NewInnerCB->paramHasAttr (I, Attribute::ByVal))
1402- // It's unsound to propagate memory attributes to byval arguments.
1403- // Even if CalledFunction doesn't e.g. write to the argument,
1404- // the call to NewInnerCB may write to its by-value copy.
1421+ // Don't bother propagating attrs to constants.
1422+ if (match (NewInnerCB->getArgOperand (I),
1423+ llvm::PatternMatch::m_ImmConstant ()))
14051424 continue ;
14061425
1407- unsigned ArgNo = Arg->getArgNo ();
1426+ // Check if the underlying value for the parameter is an argument.
1427+ const Argument *Arg = dyn_cast<Argument>(InnerCB->getArgOperand (I));
1428+ unsigned ArgNo;
1429+ if (Arg) {
1430+ ArgNo = Arg->getArgNo ();
1431+ // For dereferenceable, dereferenceable_or_null, align, etc...
1432+ // we don't want to propagate if the existing param has the same
1433+ // attribute with "better" constraints. So remove from the
1434+ // new AL if the region of the existing param is larger than
1435+ // what we can propagate.
1436+ AttrBuilder NewAB{
1437+ Context, AttributeSet::get (Context, ValidExactParamAttrs[ArgNo])};
1438+ if (AL.getParamDereferenceableBytes (I) >
1439+ NewAB.getDereferenceableBytes ())
1440+ NewAB.removeAttribute (Attribute::Dereferenceable);
1441+ if (AL.getParamDereferenceableOrNullBytes (I) >
1442+ NewAB.getDereferenceableOrNullBytes ())
1443+ NewAB.removeAttribute (Attribute::DereferenceableOrNull);
1444+ if (AL.getParamAlignment (I).valueOrOne () >
1445+ NewAB.getAlignment ().valueOrOne ())
1446+ NewAB.removeAttribute (Attribute::Alignment);
1447+ if (auto ExistingRange = AL.getParamRange (I)) {
1448+ if (auto NewRange = NewAB.getRange ()) {
1449+ ConstantRange CombinedRange =
1450+ ExistingRange->intersectWith (*NewRange);
1451+ NewAB.removeAttribute (Attribute::Range);
1452+ NewAB.addRangeAttr (CombinedRange);
1453+ }
1454+ }
1455+ AL = AL.addParamAttributes (Context, I, NewAB);
1456+ } else {
1457+ // Check if the underlying value for the parameter is an argument.
1458+ const Value *UnderlyingV =
1459+ getUnderlyingObject (InnerCB->getArgOperand (I));
1460+ Arg = dyn_cast<Argument>(UnderlyingV);
1461+ if (!Arg)
1462+ continue ;
1463+ ArgNo = Arg->getArgNo ();
1464+ }
1465+
14081466 // If so, propagate its access attributes.
1409- AL = AL.addParamAttributes (Context, I, ValidParamAttrs [ArgNo]);
1467+ AL = AL.addParamAttributes (Context, I, ValidObjParamAttrs [ArgNo]);
14101468 // We can have conflicting attributes from the inner callsite and
14111469 // to-be-inlined callsite. In that case, choose the most
14121470 // restrictive.
0 commit comments