Skip to content

Commit 5554451

Browse files
committed
[Attributor] Allow IR-attr deduction for non-IPO amendable functions
If the function is non-IPO amendable we do skip most attributes/AAs. However, if an AA has a isImpliedByIR that can deduce the attribute from other attributes, we can run those. For now, we manually enable them, if we have more later we can use some automation/flag.
1 parent 4dc5662 commit 5554451

File tree

15 files changed

+329
-169
lines changed

15 files changed

+329
-169
lines changed

llvm/include/llvm/Transforms/IPO/Attributor.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3522,6 +3522,15 @@ struct AAMustProgress
35223522
AAMustProgress> {
35233523
AAMustProgress(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
35243524

3525+
static bool isImpliedByIR(Attributor &A, const IRPosition &IRP,
3526+
Attribute::AttrKind ImpliedAttributeKind,
3527+
bool IgnoreSubsumingPositions = false) {
3528+
// Note: This is also run for non-IPO amendable functions.
3529+
assert(ImpliedAttributeKind == Attribute::MustProgress);
3530+
return A.hasAttr(IRP, {Attribute::MustProgress, Attribute::WillReturn},
3531+
IgnoreSubsumingPositions, Attribute::MustProgress);
3532+
}
3533+
35253534
/// Return true if we assume that the underlying value is nonnull.
35263535
bool isAssumedMustProgress() const { return getAssumed(); }
35273536

@@ -3640,6 +3649,8 @@ struct AAWillReturn
36403649
static bool isImpliedByIR(Attributor &A, const IRPosition &IRP,
36413650
Attribute::AttrKind ImpliedAttributeKind,
36423651
bool IgnoreSubsumingPositions = false) {
3652+
// Note: This is also run for non-IPO amendable functions.
3653+
assert(ImpliedAttributeKind == Attribute::WillReturn);
36433654
if (IRAttribute::isImpliedByIR(A, IRP, ImpliedAttributeKind,
36443655
IgnoreSubsumingPositions))
36453656
return true;
@@ -3816,6 +3827,17 @@ struct AANoFree
38163827
AANoFree> {
38173828
AANoFree(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {}
38183829

3830+
/// See IRAttribute::isImpliedByIR
3831+
static bool isImpliedByIR(Attributor &A, const IRPosition &IRP,
3832+
Attribute::AttrKind ImpliedAttributeKind,
3833+
bool IgnoreSubsumingPositions = false) {
3834+
// Note: This is also run for non-IPO amendable functions.
3835+
assert(ImpliedAttributeKind == Attribute::NoFree);
3836+
return A.hasAttr(
3837+
IRP, {Attribute::ReadNone, Attribute::ReadOnly, Attribute::NoFree},
3838+
IgnoreSubsumingPositions, Attribute::NoFree);
3839+
}
3840+
38193841
/// See AbstractAttribute::isValidIRPositionForInit
38203842
static bool isValidIRPositionForInit(Attributor &A, const IRPosition &IRP) {
38213843
if (!IRP.isFunctionScope() &&

llvm/lib/Transforms/IPO/Attributor.cpp

Lines changed: 52 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3270,26 +3270,26 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
32703270
if (EnableHeapToStack)
32713271
getOrCreateAAFor<AAHeapToStack>(FPos);
32723272

3273+
// Every function might be "must-progress".
3274+
checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs);
3275+
3276+
// Every function might be "no-free".
3277+
checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs);
3278+
3279+
// Every function might be "will-return".
3280+
checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs);
3281+
32733282
// Everything that is visible from the outside (=function, argument, return
32743283
// positions), cannot be changed if the function is not IPO amendable. We can
32753284
// however analyse the code inside.
32763285
if (IsIPOAmendable) {
32773286

3278-
// Every function might be "will-return".
3279-
checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs);
3280-
3281-
// Every function might be "must-progress".
3282-
checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs);
3283-
32843287
// Every function can be nounwind.
32853288
checkAndQueryIRAttr<Attribute::NoUnwind, AANoUnwind>(FPos, FnAttrs);
32863289

32873290
// Every function might be marked "nosync"
32883291
checkAndQueryIRAttr<Attribute::NoSync, AANoSync>(FPos, FnAttrs);
32893292

3290-
// Every function might be "no-free".
3291-
checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs);
3292-
32933293
// Every function might be "no-return".
32943294
checkAndQueryIRAttr<Attribute::NoReturn, AANoReturn>(FPos, FnAttrs);
32953295

@@ -3348,55 +3348,61 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
33483348
getOrCreateAAFor<AANoFPClass>(RetPos);
33493349
}
33503350
}
3351+
}
33513352

3352-
for (Argument &Arg : F.args()) {
3353-
IRPosition ArgPos = IRPosition::argument(Arg);
3354-
auto ArgNo = Arg.getArgNo();
3355-
AttributeSet ArgAttrs = Attrs.getParamAttrs(ArgNo);
3353+
for (Argument &Arg : F.args()) {
3354+
IRPosition ArgPos = IRPosition::argument(Arg);
3355+
auto ArgNo = Arg.getArgNo();
3356+
AttributeSet ArgAttrs = Attrs.getParamAttrs(ArgNo);
33563357

3357-
// Every argument might be simplified. We have to go through the
3358-
// Attributor interface though as outside AAs can register custom
3359-
// simplification callbacks.
3360-
bool UsedAssumedInformation = false;
3361-
getAssumedSimplified(ArgPos, /* AA */ nullptr, UsedAssumedInformation,
3362-
AA::Intraprocedural);
3358+
if (!IsIPOAmendable) {
3359+
if (Arg.getType()->isPointerTy())
3360+
// Every argument with pointer type might be marked nofree.
3361+
checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3362+
continue;
3363+
}
3364+
3365+
// Every argument might be simplified. We have to go through the
3366+
// Attributor interface though as outside AAs can register custom
3367+
// simplification callbacks.
3368+
bool UsedAssumedInformation = false;
3369+
getAssumedSimplified(ArgPos, /* AA */ nullptr, UsedAssumedInformation,
3370+
AA::Intraprocedural);
33633371

3364-
// Every argument might be dead.
3365-
getOrCreateAAFor<AAIsDead>(ArgPos);
3372+
// Every argument might be dead.
3373+
getOrCreateAAFor<AAIsDead>(ArgPos);
33663374

3367-
// Every argument might be marked noundef.
3368-
checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs);
3375+
// Every argument might be marked noundef.
3376+
checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs);
33693377

3370-
if (Arg.getType()->isPointerTy()) {
3371-
// Every argument with pointer type might be marked nonnull.
3372-
checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs);
3378+
if (Arg.getType()->isPointerTy()) {
3379+
// Every argument with pointer type might be marked nonnull.
3380+
checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs);
33733381

3374-
// Every argument with pointer type might be marked noalias.
3375-
checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs);
3382+
// Every argument with pointer type might be marked noalias.
3383+
checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs);
33763384

3377-
// Every argument with pointer type might be marked dereferenceable.
3378-
getOrCreateAAFor<AADereferenceable>(ArgPos);
3385+
// Every argument with pointer type might be marked dereferenceable.
3386+
getOrCreateAAFor<AADereferenceable>(ArgPos);
33793387

3380-
// Every argument with pointer type might be marked align.
3381-
getOrCreateAAFor<AAAlign>(ArgPos);
3388+
// Every argument with pointer type might be marked align.
3389+
getOrCreateAAFor<AAAlign>(ArgPos);
33823390

3383-
// Every argument with pointer type might be marked nocapture.
3384-
checkAndQueryIRAttr<Attribute::NoCapture, AANoCapture>(ArgPos,
3385-
ArgAttrs);
3391+
// Every argument with pointer type might be marked nocapture.
3392+
checkAndQueryIRAttr<Attribute::NoCapture, AANoCapture>(ArgPos, ArgAttrs);
33863393

3387-
// Every argument with pointer type might be marked
3388-
// "readnone/readonly/writeonly/..."
3389-
getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
3394+
// Every argument with pointer type might be marked
3395+
// "readnone/readonly/writeonly/..."
3396+
getOrCreateAAFor<AAMemoryBehavior>(ArgPos);
33903397

3391-
// Every argument with pointer type might be marked nofree.
3392-
checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
3398+
// Every argument with pointer type might be marked nofree.
3399+
checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
33933400

3394-
// Every argument with pointer type might be privatizable (or
3395-
// promotable)
3396-
getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
3397-
} else if (AttributeFuncs::isNoFPClassCompatibleType(Arg.getType())) {
3398-
getOrCreateAAFor<AANoFPClass>(ArgPos);
3399-
}
3401+
// Every argument with pointer type might be privatizable (or
3402+
// promotable)
3403+
getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
3404+
} else if (AttributeFuncs::isNoFPClassCompatibleType(Arg.getType())) {
3405+
getOrCreateAAFor<AANoFPClass>(ArgPos);
34003406
}
34013407
}
34023408

llvm/test/Transforms/Attributor/ArgumentPromotion/array.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ define internal void @callee(ptr noalias %arg) {
3939
; CHECK-NEXT: store i32 [[TMP1]], ptr [[ARG_PRIV_0_1]], align 4
4040
; CHECK-NEXT: [[ARG_PRIV_0_2:%.*]] = getelementptr [3 x i32], ptr [[ARG_PRIV]], i64 0, i64 2
4141
; CHECK-NEXT: store i32 [[TMP2]], ptr [[ARG_PRIV_0_2]], align 4
42-
; CHECK-NEXT: call void @use(ptr noalias nocapture noundef nonnull readonly align 4 dereferenceable(12) [[ARG_PRIV]])
42+
; CHECK-NEXT: call void @use(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(12) [[ARG_PRIV]])
4343
; CHECK-NEXT: ret void
4444
;
4545
entry:

llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ define internal i32 @test2(ptr %p, i32 %p2) {
6868
; CGSCC-NEXT: [[A:%.*]] = load i32, ptr [[A_GEP]], align 4
6969
; CGSCC-NEXT: [[B:%.*]] = load i32, ptr [[B_GEP]], align 4
7070
; CGSCC-NEXT: [[V:%.*]] = add i32 [[A]], [[B]]
71-
; CGSCC-NEXT: [[CA:%.*]] = musttail call noundef i32 @foo(ptr undef, i32 [[V]]) #[[ATTR6:[0-9]+]]
71+
; CGSCC-NEXT: [[CA:%.*]] = musttail call noundef i32 @foo(ptr nofree undef, i32 [[V]]) #[[ATTR6:[0-9]+]]
7272
; CGSCC-NEXT: ret i32 [[CA]]
7373
;
7474
%a.gep = getelementptr %T, ptr %p, i64 0, i32 3
@@ -138,7 +138,7 @@ define internal i32 @test2b(ptr %p, i32 %p2) {
138138
; CGSCC-NEXT: [[A:%.*]] = load i32, ptr [[A_GEP]], align 4
139139
; CGSCC-NEXT: [[B:%.*]] = load i32, ptr [[B_GEP]], align 4
140140
; CGSCC-NEXT: [[V:%.*]] = add i32 [[A]], [[B]]
141-
; CGSCC-NEXT: [[CA:%.*]] = musttail call noundef i32 @bar(ptr nonnull undef, i32 [[V]]) #[[ATTR7:[0-9]+]]
141+
; CGSCC-NEXT: [[CA:%.*]] = musttail call noundef i32 @bar(ptr nofree nonnull undef, i32 [[V]]) #[[ATTR7:[0-9]+]]
142142
; CGSCC-NEXT: ret i32 [[CA]]
143143
;
144144
%a.gep = getelementptr %T, ptr %p, i64 0, i32 3

llvm/test/Transforms/Attributor/ArgumentPromotion/variadic.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ define i32 @main(i32 %argc, ptr nocapture readnone %argv) #0 {
2222
; CHECK-LABEL: define {{[^@]+}}@main
2323
; CHECK-SAME: (i32 [[ARGC:%.*]], ptr nocapture nofree readnone [[ARGV:%.*]]) {
2424
; CHECK-NEXT: entry:
25-
; CHECK-NEXT: tail call void (ptr, ptr, ptr, ptr, ptr, ...) @callee_t0f(ptr undef, ptr undef, ptr undef, ptr undef, ptr undef, ptr noalias noundef nonnull byval([[STRUCT_TT0:%.*]]) align 8 dereferenceable(16) @t45)
25+
; CHECK-NEXT: tail call void (ptr, ptr, ptr, ptr, ptr, ...) @callee_t0f(ptr nofree undef, ptr nofree undef, ptr nofree undef, ptr nofree undef, ptr nofree undef, ptr noalias noundef nonnull byval([[STRUCT_TT0:%.*]]) align 8 dereferenceable(16) @t45)
2626
; CHECK-NEXT: ret i32 0
2727
;
2828
entry:

llvm/test/Transforms/Attributor/align.ll

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -335,18 +335,18 @@ define void @test8_helper() {
335335
; TUNIT-NEXT: [[PTR0:%.*]] = tail call ptr @unknown()
336336
; TUNIT-NEXT: [[PTR1:%.*]] = tail call align 4 ptr @unknown()
337337
; TUNIT-NEXT: [[PTR2:%.*]] = tail call align 8 ptr @unknown()
338-
; TUNIT-NEXT: tail call void @test8(ptr noalias nocapture readnone align 4 [[PTR1]], ptr noalias nocapture readnone align 4 [[PTR1]], ptr noalias nocapture readnone [[PTR0]]) #[[ATTR2:[0-9]+]]
339-
; TUNIT-NEXT: tail call void @test8(ptr noalias nocapture readnone align 8 [[PTR2]], ptr noalias nocapture readnone align 4 [[PTR1]], ptr noalias nocapture readnone align 4 [[PTR1]]) #[[ATTR2]]
340-
; TUNIT-NEXT: tail call void @test8(ptr noalias nocapture readnone align 8 [[PTR2]], ptr noalias nocapture readnone align 4 [[PTR1]], ptr noalias nocapture readnone align 4 [[PTR1]]) #[[ATTR2]]
338+
; TUNIT-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone [[PTR0]]) #[[ATTR2:[0-9]+]]
339+
; TUNIT-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 8 [[PTR2]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]]) #[[ATTR2]]
340+
; TUNIT-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 8 [[PTR2]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]]) #[[ATTR2]]
341341
; TUNIT-NEXT: ret void
342342
;
343343
; CGSCC-LABEL: define {{[^@]+}}@test8_helper() {
344344
; CGSCC-NEXT: [[PTR0:%.*]] = tail call ptr @unknown()
345345
; CGSCC-NEXT: [[PTR1:%.*]] = tail call align 4 ptr @unknown()
346346
; CGSCC-NEXT: [[PTR2:%.*]] = tail call align 8 ptr @unknown()
347-
; CGSCC-NEXT: tail call void @test8(ptr noalias nocapture readnone align 4 [[PTR1]], ptr noalias nocapture readnone align 4 [[PTR1]], ptr noalias nocapture readnone [[PTR0]]) #[[ATTR3:[0-9]+]]
348-
; CGSCC-NEXT: tail call void @test8(ptr noalias nocapture readnone align 8 [[PTR2]], ptr noalias nocapture readnone align 4 [[PTR1]], ptr noalias nocapture readnone align 4 [[PTR1]]) #[[ATTR3]]
349-
; CGSCC-NEXT: tail call void @test8(ptr noalias nocapture readnone align 8 [[PTR2]], ptr noalias nocapture readnone align 4 [[PTR1]], ptr noalias nocapture readnone align 4 [[PTR1]]) #[[ATTR3]]
347+
; CGSCC-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone [[PTR0]]) #[[ATTR3:[0-9]+]]
348+
; CGSCC-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 8 [[PTR2]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]]) #[[ATTR3]]
349+
; CGSCC-NEXT: tail call void @test8(ptr noalias nocapture nofree readnone align 8 [[PTR2]], ptr noalias nocapture nofree readnone align 4 [[PTR1]], ptr noalias nocapture nofree readnone align 4 [[PTR1]]) #[[ATTR3]]
350350
; CGSCC-NEXT: ret void
351351
;
352352
%ptr0 = tail call ptr @unknown()
@@ -363,18 +363,18 @@ declare void @user_i32_ptr(ptr nocapture readnone) nounwind
363363
define internal void @test8(ptr %a, ptr %b, ptr %c) {
364364
; TUNIT: Function Attrs: nounwind
365365
; TUNIT-LABEL: define {{[^@]+}}@test8
366-
; TUNIT-SAME: (ptr noalias nocapture readnone align 4 [[A:%.*]], ptr noalias nocapture readnone align 4 [[B:%.*]], ptr noalias nocapture readnone [[C:%.*]]) #[[ATTR2]] {
367-
; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture readnone align 4 [[A]]) #[[ATTR2]]
368-
; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture readnone align 4 [[B]]) #[[ATTR2]]
369-
; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture readnone [[C]]) #[[ATTR2]]
366+
; TUNIT-SAME: (ptr noalias nocapture nofree readnone align 4 [[A:%.*]], ptr noalias nocapture nofree readnone align 4 [[B:%.*]], ptr noalias nocapture nofree readnone [[C:%.*]]) #[[ATTR2]] {
367+
; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone align 4 [[A]]) #[[ATTR2]]
368+
; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone align 4 [[B]]) #[[ATTR2]]
369+
; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone [[C]]) #[[ATTR2]]
370370
; TUNIT-NEXT: ret void
371371
;
372372
; CGSCC: Function Attrs: nounwind
373373
; CGSCC-LABEL: define {{[^@]+}}@test8
374-
; CGSCC-SAME: (ptr noalias nocapture readnone align 4 [[A:%.*]], ptr noalias nocapture readnone align 4 [[B:%.*]], ptr noalias nocapture readnone [[C:%.*]]) #[[ATTR3]] {
375-
; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture readnone align 4 [[A]]) #[[ATTR3]]
376-
; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture readnone align 4 [[B]]) #[[ATTR3]]
377-
; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture readnone [[C]]) #[[ATTR3]]
374+
; CGSCC-SAME: (ptr noalias nocapture nofree readnone align 4 [[A:%.*]], ptr noalias nocapture nofree readnone align 4 [[B:%.*]], ptr noalias nocapture nofree readnone [[C:%.*]]) #[[ATTR3]] {
375+
; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone align 4 [[A]]) #[[ATTR3]]
376+
; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone align 4 [[B]]) #[[ATTR3]]
377+
; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree readnone [[C]]) #[[ATTR3]]
378378
; CGSCC-NEXT: ret void
379379
;
380380
call void @user_i32_ptr(ptr %a)
@@ -961,34 +961,34 @@ exit:
961961
define ptr @checkAndAdvance(ptr align(16) %p) {
962962
; TUNIT: Function Attrs: nounwind
963963
; TUNIT-LABEL: define {{[^@]+}}@checkAndAdvance
964-
; TUNIT-SAME: (ptr noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR2]] {
964+
; TUNIT-SAME: (ptr nofree noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR2]] {
965965
; TUNIT-NEXT: entry:
966966
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 16
967967
; TUNIT-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
968968
; TUNIT-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
969969
; TUNIT: if.then:
970970
; TUNIT-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 4
971-
; TUNIT-NEXT: [[CALL:%.*]] = call ptr @checkAndAdvance(ptr noundef nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR2]]
971+
; TUNIT-NEXT: [[CALL:%.*]] = call ptr @checkAndAdvance(ptr nofree noundef nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR2]]
972972
; TUNIT-NEXT: br label [[RETURN]]
973973
; TUNIT: return:
974974
; TUNIT-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[ADD_PTR]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ]
975-
; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture nonnull readnone align 16 [[RETVAL_0]]) #[[ATTR2]]
975+
; TUNIT-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree nonnull readnone align 16 [[RETVAL_0]]) #[[ATTR2]]
976976
; TUNIT-NEXT: ret ptr [[RETVAL_0]]
977977
;
978978
; CGSCC: Function Attrs: nounwind
979979
; CGSCC-LABEL: define {{[^@]+}}@checkAndAdvance
980-
; CGSCC-SAME: (ptr noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3]] {
980+
; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR3]] {
981981
; CGSCC-NEXT: entry:
982982
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 16
983983
; CGSCC-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
984984
; CGSCC-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
985985
; CGSCC: if.then:
986986
; CGSCC-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 4
987-
; CGSCC-NEXT: [[CALL:%.*]] = call ptr @checkAndAdvance(ptr noundef nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR3]]
987+
; CGSCC-NEXT: [[CALL:%.*]] = call ptr @checkAndAdvance(ptr nofree noundef nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) #[[ATTR3]]
988988
; CGSCC-NEXT: br label [[RETURN]]
989989
; CGSCC: return:
990990
; CGSCC-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[ADD_PTR]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ]
991-
; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture nonnull readnone align 16 [[RETVAL_0]]) #[[ATTR3]]
991+
; CGSCC-NEXT: call void @user_i32_ptr(ptr noalias nocapture nofree nonnull readnone align 16 [[RETVAL_0]]) #[[ATTR3]]
992992
; CGSCC-NEXT: ret ptr [[RETVAL_0]]
993993
;
994994
entry:

0 commit comments

Comments
 (0)