| ; 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 } |
| ;. |