@@ -1352,18 +1352,40 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
13521352 auto &Context = CalledFunction->getContext ();
13531353
13541354 // Collect valid attributes for all params.
1355- SmallVector<AttrBuilder> ValidParamAttrs ;
1355+ SmallVector<AttrBuilder> ValidObjParamAttrs, ValidExactParamAttrs ;
13561356 bool HasAttrToPropagate = false ;
13571357
13581358 for (unsigned I = 0 , E = CB.arg_size (); I < E; ++I) {
1359- ValidParamAttrs.emplace_back (AttrBuilder{CB.getContext ()});
1359+ ValidObjParamAttrs.emplace_back (AttrBuilder{CB.getContext ()});
1360+ ValidExactParamAttrs.emplace_back (AttrBuilder{CB.getContext ()});
13601361 // Access attributes can be propagated to any param with the same underlying
13611362 // object as the argument.
13621363 if (CB.paramHasAttr (I, Attribute::ReadNone))
1363- ValidParamAttrs .back ().addAttribute (Attribute::ReadNone);
1364+ ValidObjParamAttrs .back ().addAttribute (Attribute::ReadNone);
13641365 if (CB.paramHasAttr (I, Attribute::ReadOnly))
1365- ValidParamAttrs.back ().addAttribute (Attribute::ReadOnly);
1366- HasAttrToPropagate |= ValidParamAttrs.back ().hasAttributes ();
1366+ ValidObjParamAttrs.back ().addAttribute (Attribute::ReadOnly);
1367+ HasAttrToPropagate |= ValidObjParamAttrs.back ().hasAttributes ();
1368+
1369+ // Attributes we can only propagate if the exact parameter is forwarded.
1370+
1371+ // We can propagate both poison generating and UB generating attributes
1372+ // without any extra checks. The only attribute that is tricky to propagate
1373+ // is `noundef` (skipped for now) as that can create new UB where previous
1374+ // behavior was just using a poison value.
1375+ if (auto DerefBytes = CB.getParamDereferenceableBytes (I))
1376+ ValidExactParamAttrs.back ().addDereferenceableAttr (DerefBytes);
1377+ if (auto DerefOrNullBytes = CB.getParamDereferenceableOrNullBytes (I))
1378+ ValidExactParamAttrs.back ().addDereferenceableOrNullAttr (
1379+ DerefOrNullBytes);
1380+ if (CB.paramHasAttr (I, Attribute::NoFree))
1381+ ValidExactParamAttrs.back ().addAttribute (Attribute::NoFree);
1382+ if (CB.paramHasAttr (I, Attribute::NonNull))
1383+ ValidExactParamAttrs.back ().addAttribute (Attribute::NonNull);
1384+ if (auto Align = CB.getParamAlign (I))
1385+ ValidExactParamAttrs.back ().addAlignmentAttr (Align);
1386+
1387+ HasAttrToPropagate |= ValidObjParamAttrs.back ().hasAttributes ();
1388+ HasAttrToPropagate |= ValidExactParamAttrs.back ().hasAttributes ();
13671389 }
13681390
13691391 // Won't be able to propagate anything.
@@ -1381,21 +1403,49 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
13811403 AttributeList AL = NewInnerCB->getAttributes ();
13821404 for (unsigned I = 0 , E = InnerCB->arg_size (); I < E; ++I) {
13831405 // Check if the underlying value for the parameter is an argument.
1384- const Value *UnderlyingV =
1385- getUnderlyingObject (InnerCB->getArgOperand (I));
1386- const Argument *Arg = dyn_cast<Argument>(UnderlyingV);
1387- if (!Arg)
1388- continue ;
1406+ const Argument *Arg = dyn_cast<Argument>(InnerCB->getArgOperand (I));
1407+ unsigned ArgNo;
1408+ if (Arg) {
1409+ ArgNo = Arg->getArgNo ();
1410+ // For dereferenceable, dereferenceable_or_null, align, etc...
1411+ // we don't want to propagate if the existing param has the same
1412+ // attribute with "better" constraints. So, only remove from the
1413+ // existing AL if the region of the existing param is smaller than
1414+ // what we can propagate. AttributeList's merge API honours the
1415+ // already existing attribute value so we choose the "better"
1416+ // attribute by removing if the existing one is worse.
1417+ if (AL.getParamDereferenceableBytes (I) <
1418+ ValidExactParamAttrs[ArgNo].getDereferenceableBytes ())
1419+ AL =
1420+ AL.removeParamAttribute (Context, I, Attribute::Dereferenceable);
1421+ if (AL.getParamDereferenceableOrNullBytes (I) <
1422+ ValidExactParamAttrs[ArgNo].getDereferenceableOrNullBytes ())
1423+ AL =
1424+ AL.removeParamAttribute (Context, I, Attribute::Dereferenceable);
1425+ if (AL.getParamAlignment (I).valueOrOne () <
1426+ ValidExactParamAttrs[ArgNo].getAlignment ().valueOrOne ())
1427+ AL = AL.removeParamAttribute (Context, I, Attribute::Alignment);
1428+
1429+ AL = AL.addParamAttributes (Context, I, ValidExactParamAttrs[ArgNo]);
1430+
1431+ } else {
1432+ // Check if the underlying value for the parameter is an argument.
1433+ const Value *UnderlyingV =
1434+ getUnderlyingObject (InnerCB->getArgOperand (I));
1435+ Arg = dyn_cast<Argument>(UnderlyingV);
1436+ if (!Arg)
1437+ continue ;
1438+ ArgNo = Arg->getArgNo ();
1439+ }
13891440
13901441 if (AL.hasParamAttr (I, Attribute::ByVal))
13911442 // It's unsound to propagate memory attributes to byval arguments.
13921443 // Even if CalledFunction doesn't e.g. write to the argument,
13931444 // the call to NewInnerCB may write to its by-value copy.
13941445 continue ;
13951446
1396- unsigned ArgNo = Arg->getArgNo ();
13971447 // If so, propagate its access attributes.
1398- AL = AL.addParamAttributes (Context, I, ValidParamAttrs [ArgNo]);
1448+ AL = AL.addParamAttributes (Context, I, ValidObjParamAttrs [ArgNo]);
13991449 // We can have conflicting attributes from the inner callsite and
14001450 // to-be-inlined callsite. In that case, choose the most
14011451 // restrictive.
0 commit comments