@@ -1352,20 +1352,41 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
1352
1352
auto &Context = CalledFunction->getContext ();
1353
1353
1354
1354
// Collect valid attributes for all params.
1355
- SmallVector<AttrBuilder> ValidParamAttrs ;
1355
+ SmallVector<AttrBuilder> ValidObjParamAttrs, ValidExactParamAttrs ;
1356
1356
bool HasAttrToPropagate = false ;
1357
1357
1358
1358
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 ()});
1360
1361
// Access attributes can be propagated to any param with the same underlying
1361
1362
// object as the argument.
1362
1363
if (CB.paramHasAttr (I, Attribute::ReadNone))
1363
- ValidParamAttrs .back ().addAttribute (Attribute::ReadNone);
1364
+ ValidObjParamAttrs .back ().addAttribute (Attribute::ReadNone);
1364
1365
if (CB.paramHasAttr (I, Attribute::ReadOnly))
1365
- ValidParamAttrs .back ().addAttribute (Attribute::ReadOnly);
1366
+ ValidObjParamAttrs .back ().addAttribute (Attribute::ReadOnly);
1366
1367
if (CB.paramHasAttr (I, Attribute::WriteOnly))
1367
- ValidParamAttrs.back ().addAttribute (Attribute::WriteOnly);
1368
- HasAttrToPropagate |= ValidParamAttrs.back ().hasAttributes ();
1368
+ ValidObjParamAttrs.back ().addAttribute (Attribute::WriteOnly);
1369
+
1370
+ // Attributes we can only propagate if the exact parameter is forwarded.
1371
+
1372
+ // We can propagate both poison generating and UB generating attributes
1373
+ // without any extra checks. The only attribute that is tricky to propagate
1374
+ // is `noundef` (skipped for now) as that can create new UB where previous
1375
+ // behavior was just using a poison value.
1376
+ if (auto DerefBytes = CB.getParamDereferenceableBytes (I))
1377
+ ValidExactParamAttrs.back ().addDereferenceableAttr (DerefBytes);
1378
+ if (auto DerefOrNullBytes = CB.getParamDereferenceableOrNullBytes (I))
1379
+ ValidExactParamAttrs.back ().addDereferenceableOrNullAttr (
1380
+ DerefOrNullBytes);
1381
+ if (CB.paramHasAttr (I, Attribute::NoFree))
1382
+ ValidExactParamAttrs.back ().addAttribute (Attribute::NoFree);
1383
+ if (CB.paramHasAttr (I, Attribute::NonNull))
1384
+ ValidExactParamAttrs.back ().addAttribute (Attribute::NonNull);
1385
+ if (auto Align = CB.getParamAlign (I))
1386
+ ValidExactParamAttrs.back ().addAlignmentAttr (Align);
1387
+
1388
+ HasAttrToPropagate |= ValidObjParamAttrs.back ().hasAttributes ();
1389
+ HasAttrToPropagate |= ValidExactParamAttrs.back ().hasAttributes ();
1369
1390
}
1370
1391
1371
1392
// Won't be able to propagate anything.
@@ -1383,15 +1404,43 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
1383
1404
AttributeList AL = NewInnerCB->getAttributes ();
1384
1405
for (unsigned I = 0 , E = InnerCB->arg_size (); I < E; ++I) {
1385
1406
// Check if the underlying value for the parameter is an argument.
1386
- const Value *UnderlyingV =
1387
- getUnderlyingObject (InnerCB->getArgOperand (I));
1388
- const Argument *Arg = dyn_cast<Argument>(UnderlyingV);
1389
- if (!Arg)
1390
- continue ;
1407
+ const Argument *Arg = dyn_cast<Argument>(InnerCB->getArgOperand (I));
1408
+ unsigned ArgNo;
1409
+ if (Arg) {
1410
+ ArgNo = Arg->getArgNo ();
1411
+ // For dereferenceable, dereferenceable_or_null, align, etc...
1412
+ // we don't want to propagate if the existing param has the same
1413
+ // attribute with "better" constraints. So, only remove from the
1414
+ // existing AL if the region of the existing param is smaller than
1415
+ // what we can propagate. AttributeList's merge API honours the
1416
+ // already existing attribute value so we choose the "better"
1417
+ // attribute by removing if the existing one is worse.
1418
+ if (AL.getParamDereferenceableBytes (I) <
1419
+ ValidExactParamAttrs[ArgNo].getDereferenceableBytes ())
1420
+ AL =
1421
+ AL.removeParamAttribute (Context, I, Attribute::Dereferenceable);
1422
+ if (AL.getParamDereferenceableOrNullBytes (I) <
1423
+ ValidExactParamAttrs[ArgNo].getDereferenceableOrNullBytes ())
1424
+ AL =
1425
+ AL.removeParamAttribute (Context, I, Attribute::Dereferenceable);
1426
+ if (AL.getParamAlignment (I).valueOrOne () <
1427
+ ValidExactParamAttrs[ArgNo].getAlignment ().valueOrOne ())
1428
+ AL = AL.removeParamAttribute (Context, I, Attribute::Alignment);
1429
+
1430
+ AL = AL.addParamAttributes (Context, I, ValidExactParamAttrs[ArgNo]);
1431
+
1432
+ } else {
1433
+ // Check if the underlying value for the parameter is an argument.
1434
+ const Value *UnderlyingV =
1435
+ getUnderlyingObject (InnerCB->getArgOperand (I));
1436
+ Arg = dyn_cast<Argument>(UnderlyingV);
1437
+ if (!Arg)
1438
+ continue ;
1439
+ ArgNo = Arg->getArgNo ();
1440
+ }
1391
1441
1392
- unsigned ArgNo = Arg->getArgNo ();
1393
1442
// If so, propagate its access attributes.
1394
- AL = AL.addParamAttributes (Context, I, ValidParamAttrs [ArgNo]);
1443
+ AL = AL.addParamAttributes (Context, I, ValidObjParamAttrs [ArgNo]);
1395
1444
// We can have conflicting attributes from the inner callsite and
1396
1445
// to-be-inlined callsite. In that case, choose the most
1397
1446
// restrictive.
0 commit comments