34
34
#include " llvm/Analysis/VectorUtils.h"
35
35
#include " llvm/IR/Argument.h"
36
36
#include " llvm/IR/AttributeMask.h"
37
+ #include " llvm/IR/Attributes.h"
37
38
#include " llvm/IR/BasicBlock.h"
38
39
#include " llvm/IR/CFG.h"
39
40
#include " llvm/IR/Constant.h"
59
60
#include " llvm/IR/MDBuilder.h"
60
61
#include " llvm/IR/Metadata.h"
61
62
#include " llvm/IR/Module.h"
63
+ #include " llvm/IR/PatternMatch.h"
62
64
#include " llvm/IR/ProfDataUtils.h"
63
65
#include " llvm/IR/Type.h"
64
66
#include " llvm/IR/User.h"
@@ -1358,18 +1360,36 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
1358
1360
auto &Context = CalledFunction->getContext ();
1359
1361
1360
1362
// Collect valid attributes for all params.
1361
- SmallVector<AttrBuilder> ValidParamAttrs ;
1363
+ SmallVector<AttrBuilder> ValidObjParamAttrs, ValidExactParamAttrs ;
1362
1364
bool HasAttrToPropagate = false ;
1363
1365
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
+
1364
1375
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 ()});
1366
1378
// Access attributes can be propagated to any param with the same underlying
1367
1379
// object as the argument.
1368
1380
if (CB.paramHasAttr (I, Attribute::ReadNone))
1369
- ValidParamAttrs .back ().addAttribute (Attribute::ReadNone);
1381
+ ValidObjParamAttrs .back ().addAttribute (Attribute::ReadNone);
1370
1382
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 ();
1373
1393
}
1374
1394
1375
1395
// Won't be able to propagate anything.
@@ -1391,22 +1411,60 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
1391
1411
1392
1412
AttributeList AL = NewInnerCB->getAttributes ();
1393
1413
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) )
1399
1419
continue ;
1400
1420
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 ()))
1405
1424
continue ;
1406
1425
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
+
1408
1466
// If so, propagate its access attributes.
1409
- AL = AL.addParamAttributes (Context, I, ValidParamAttrs [ArgNo]);
1467
+ AL = AL.addParamAttributes (Context, I, ValidObjParamAttrs [ArgNo]);
1410
1468
// We can have conflicting attributes from the inner callsite and
1411
1469
// to-be-inlined callsite. In that case, choose the most
1412
1470
// restrictive.
0 commit comments