Noah Goldstein e343af777e [SimplifyCFG][Attributes] Enabling sinking calls with differing number of attrsets
Prior impl would fail if the number of attribute sets on the two calls
wasn't the same which is unnecessary as long as we aren't throwing
away and must-preserve attrs.

Closes #110896
2024-10-02 15:15:07 -05:00

286 lines
10 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt < %s -passes='simplifycfg<sink-common-insts>' -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
declare ptr @foo0()
declare ptr @foo(ptr %p, i64 %x)
declare ptr @foo2(ptr %p, ptr %p2, i64 %x)
declare void @side.effect()
define ptr @test_sink_no_args_oneside(i1 %c) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_no_args_oneside
; CHECK-SAME: (i1 [[C:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[END:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[R2:%.*]] = call ptr @foo0()
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call ptr @foo0()
br label %end
else:
%r2 = call ptr @foo0() readonly
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
define ptr @test_sink_no_args_oneside_fail(i1 %c) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_no_args_oneside_fail
; CHECK-SAME: (i1 [[C:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: [[R:%.*]] = call ptr @foo0()
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: else:
; CHECK-NEXT: [[R2:%.*]] = call ptr @foo0() #[[ATTR0:[0-9]+]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
; CHECK-NEXT: ret ptr [[PR]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call ptr @foo0()
br label %end
else:
%r2 = call ptr @foo0() readonly alwaysinline
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
define ptr @test_sink_int_attrs(i1 %c, ptr %p, ptr %p2, i64 %x) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_int_attrs
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], ptr [[P2:%.*]], i64 [[X:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[END:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[R2:%.*]] = call ptr @foo2(ptr align 32 dereferenceable_or_null(100) [[P]], ptr align 32 dereferenceable(50) [[P2]], i64 range(i64 10, 100000) [[X]]) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call ptr @foo2(ptr align 64 dereferenceable_or_null(100) %p, ptr dereferenceable(50) align 64 %p2, i64 range(i64 10, 1000) %x) memory(read)
br label %end
else:
%r2 = call ptr @foo2(ptr align 32 dereferenceable_or_null(200) %p, ptr dereferenceable(100) align 32 %p2, i64 range(i64 10000, 100000) %x) memory(write)
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
define ptr @test_sink_int_attrs2(i1 %c, ptr %p, i64 %x) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_int_attrs2
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[END:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[R2:%.*]] = call ptr @foo(ptr dereferenceable(50) [[P]], i64 range(i64 10, 1000) [[X]]) #[[ATTR2:[0-9]+]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call ptr @foo(ptr dereferenceable(50) %p, i64 range(i64 10, 1000) %x) memory(read)
br label %end
else:
%r2 = call ptr @foo(ptr dereferenceable(100) align 32 dereferenceable_or_null(200) %p, i64 range(i64 11, 100) %x) memory(none)
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
define ptr @test_sink_bool_attrs2(i1 %c, ptr %p, i64 %x) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_bool_attrs2
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[END:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[R2:%.*]] = call noundef ptr @foo(ptr nonnull [[P]], i64 noundef [[X]]) #[[ATTR3:[0-9]+]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call noundef ptr @foo(ptr readnone nonnull noundef %p, i64 noundef %x) cold mustprogress nocallback nofree nosync willreturn
br label %end
else:
%r2 = call noundef nonnull ptr @foo(ptr readonly nonnull %p, i64 noundef %x) mustprogress nocallback nofree willreturn
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
define ptr @test_sink_bool_attrs3(i1 %c, ptr %p, i64 %x) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_bool_attrs3
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[END:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[R2:%.*]] = call nonnull ptr @foo(ptr [[P]], i64 noundef [[X]]) #[[ATTR4:[0-9]+]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call nonnull ptr @foo(ptr readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn alwaysinline
br label %end
else:
%r2 = call noundef nonnull ptr @foo(ptr writeonly nonnull %p, i64 noundef %x) nosync willreturn alwaysinline
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
define ptr @test_sink_bool_attrs_fail_non_droppable(i1 %c, ptr %p, i64 %x) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_bool_attrs_fail_non_droppable
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: [[R:%.*]] = call nonnull ptr @foo(ptr noundef readonly [[P]], i64 noundef [[X]]) #[[ATTR5:[0-9]+]]
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: else:
; CHECK-NEXT: [[R2:%.*]] = call noundef nonnull ptr @foo(ptr nonnull writeonly [[P]], i64 noundef [[X]]) #[[ATTR6:[0-9]+]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
; CHECK-NEXT: ret ptr [[PR]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call nonnull ptr @foo(ptr readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn alwaysinline
br label %end
else:
%r2 = call noundef nonnull ptr @foo(ptr writeonly nonnull %p, i64 noundef %x) nosync willreturn
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
define ptr @test_sink_bool_attrs_fail_non_droppable2(i1 %c, ptr %p, i64 %x) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_bool_attrs_fail_non_droppable2
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: [[R:%.*]] = call nonnull ptr @foo(ptr noundef readonly [[P]], i64 noundef [[X]]) #[[ATTR7:[0-9]+]]
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: else:
; CHECK-NEXT: [[R2:%.*]] = call noundef nonnull ptr @foo(ptr nonnull writeonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR6]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
; CHECK-NEXT: ret ptr [[PR]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call nonnull ptr @foo(ptr readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn
br label %end
else:
%r2 = call noundef nonnull ptr @foo(ptr byval(i64) writeonly nonnull %p, i64 noundef %x) nosync willreturn
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
define ptr @test_sink_bool_attrs_fail_non_droppable3(i1 %c, ptr %p, i64 %x) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_bool_attrs_fail_non_droppable3
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: [[R:%.*]] = call nonnull ptr @foo(ptr noundef readonly byval(i32) [[P]], i64 noundef [[X]]) #[[ATTR7]]
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: else:
; CHECK-NEXT: [[R2:%.*]] = call noundef nonnull ptr @foo(ptr nonnull writeonly byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR8:[0-9]+]]
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[PR:%.*]] = phi ptr [ [[R]], [[IF]] ], [ [[R2]], [[ELSE]] ]
; CHECK-NEXT: ret ptr [[PR]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call nonnull ptr @foo(ptr byval(i32) readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn
br label %end
else:
%r2 = call noundef nonnull ptr @foo(ptr byval(i64) writeonly nonnull %p, i64 noundef %x) nosync
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
define ptr @test_sink_bool_attrs4(i1 %c, ptr %p, i64 %x) {
; CHECK-LABEL: define {{[^@]+}}@test_sink_bool_attrs4
; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]], i64 [[X:%.*]]) {
; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[END:%.*]]
; CHECK: if:
; CHECK-NEXT: call void @side.effect()
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[R2:%.*]] = call nonnull ptr @foo(ptr byval(i64) [[P]], i64 noundef [[X]]) #[[ATTR8]]
; CHECK-NEXT: ret ptr [[R2]]
;
br i1 %c, label %if, label %else
if:
call void @side.effect()
%r = call nonnull ptr @foo(ptr byval(i64) readonly noundef %p, i64 noundef %x) cold nocallback nofree nosync willreturn
br label %end
else:
%r2 = call noundef nonnull ptr @foo(ptr byval(i64) writeonly nonnull %p, i64 noundef %x) nosync
br label %end
end:
%pr = phi ptr [ %r, %if], [%r2, %else]
ret ptr %pr
}
;.
; CHECK: attributes #[[ATTR0]] = { alwaysinline memory(read) }
; CHECK: attributes #[[ATTR1]] = { memory(readwrite) }
; CHECK: attributes #[[ATTR2]] = { memory(read) }
; CHECK: attributes #[[ATTR3]] = { mustprogress nocallback nofree willreturn }
; CHECK: attributes #[[ATTR4]] = { alwaysinline nosync willreturn }
; CHECK: attributes #[[ATTR5]] = { alwaysinline cold nocallback nofree nosync willreturn }
; CHECK: attributes #[[ATTR6]] = { nosync willreturn }
; CHECK: attributes #[[ATTR7]] = { cold nocallback nofree nosync willreturn }
; CHECK: attributes #[[ATTR8]] = { nosync }
;.