diff --git a/llvm/test/Transforms/RewriteStatepointsForGC/base-pointers-4.ll b/llvm/test/Transforms/RewriteStatepointsForGC/base-pointers-4.ll index b9f67c1a37400..7fe70b22eb100 100644 --- a/llvm/test/Transforms/RewriteStatepointsForGC/base-pointers-4.ll +++ b/llvm/test/Transforms/RewriteStatepointsForGC/base-pointers-4.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -rewrite-statepoints-for-gc -spp-print-base-pointers -S 2>&1 | FileCheck %s ; RUN: opt < %s -passes=rewrite-statepoints-for-gc -spp-print-base-pointers -S 2>&1 | FileCheck %s @@ -10,17 +11,43 @@ declare i64 addrspace(1)* @generate_obj() declare void @consume_obj(i64 addrspace(1)*) define void @test(i32 %condition) gc "statepoint-example" { +; CHECK-LABEL: @test( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 2882400000, i32 0, i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) +; CHECK-NEXT: [[TMP0:%.*]] = call i64 addrspace(1)* @llvm.experimental.gc.result.p1i64(token [[STATEPOINT_TOKEN]]) +; CHECK-NEXT: switch i32 [[CONDITION:%.*]], label [[DEST_A:%.*]] [ +; CHECK-NEXT: i32 0, label [[DEST_B:%.*]] +; CHECK-NEXT: i32 1, label [[DEST_C:%.*]] +; CHECK-NEXT: ] +; CHECK: dest_a: +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: dest_b: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: dest_c: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: [[OBJ_TO_CONSUME_BASE:%.*]] = phi i64 addrspace(1)* [ [[TMP0]], [[DEST_A]] ], [ null, [[DEST_B]] ], [ null, [[DEST_C]] ], !is_base_value !0 +; CHECK-NEXT: [[OBJ_TO_CONSUME:%.*]] = phi i64 addrspace(1)* [ [[TMP0]], [[DEST_A]] ], [ null, [[DEST_B]] ], [ null, [[DEST_C]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN1:%.*]] = call token (i64, i32, void (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i64f(i64 2882400000, i32 0, void (i64 addrspace(1)*)* @consume_obj, i32 1, i32 0, i64 addrspace(1)* [[OBJ_TO_CONSUME]], i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i64 addrspace(1)* [[OBJ_TO_CONSUME_BASE]], i64 addrspace(1)* [[OBJ_TO_CONSUME]]) +; CHECK-NEXT: [[OBJ_TO_CONSUME_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN1]], i32 13, i32 13) +; CHECK-NEXT: [[OBJ_TO_CONSUME_BASE_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJ_TO_CONSUME_BASE_RELOCATED]] to i64 addrspace(1)* +; CHECK-NEXT: [[OBJ_TO_CONSUME_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN1]], i32 13, i32 14) +; CHECK-NEXT: [[OBJ_TO_CONSUME_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJ_TO_CONSUME_RELOCATED]] to i64 addrspace(1)* +; CHECK-NEXT: br label [[MERGE_SPLIT:%.*]] +; CHECK: merge.split: +; CHECK-NEXT: [[STATEPOINT_TOKEN2:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) +; CHECK-NEXT: br label [[LOOP]] +; entry: br label %loop loop: ; preds = %merge.split, %entry -; CHECK: loop: -; CHECK: [[TOKEN_0:%[^ ]+]] = call token (i64, i32, i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 2882400000, i32 0, i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i3 -; CHECK-NEXT: [[RESULT_0:%[^ ]+]] = call i64 addrspace(1)* @llvm.experimental.gc.result %0 = call i64 addrspace(1)* @generate_obj() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] switch i32 %condition, label %dest_a [ - i32 0, label %dest_b - i32 1, label %dest_c + i32 0, label %dest_b + i32 1, label %dest_c ] dest_a: ; preds = %loop @@ -33,8 +60,6 @@ dest_c: ; preds = %loop br label %merge merge: ; preds = %dest_c, %dest_b, %dest_a -; CHECK: merge: -; CHECK: %obj_to_consume = phi i64 addrspace(1)* [ [[RESULT_0]], %dest_a ], [ null, %dest_b ], [ null, %dest_c ] %obj_to_consume = phi i64 addrspace(1)* [ %0, %dest_a ], [ null, %dest_b ], [ null, %dest_c ] call void @consume_obj(i64 addrspace(1)* %obj_to_consume) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] br label %merge.split diff --git a/llvm/test/Transforms/RewriteStatepointsForGC/basic.ll b/llvm/test/Transforms/RewriteStatepointsForGC/basic.ll index c1c160b14274b..8e052a61a4dc3 100644 --- a/llvm/test/Transforms/RewriteStatepointsForGC/basic.ll +++ b/llvm/test/Transforms/RewriteStatepointsForGC/basic.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -rewrite-statepoints-for-gc < %s | FileCheck %s ; RUN: opt -S -passes=rewrite-statepoints-for-gc < %s | FileCheck %s @@ -6,69 +7,104 @@ declare i32 @h() define i32 addrspace(1)* @f0(i32 addrspace(1)* %arg) gc "statepoint-example" { ; CHECK-LABEL: @f0( - entry: -; CHECK: [[TOKEN_0:%[^ ]+]] = call token {{[^@]*}} @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* %arg) +; CHECK-NEXT: entry: +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* [[ARG:%.*]]) +; CHECK-NEXT: [[ARG_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 8, i32 8) +; CHECK-NEXT: [[ARG_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[ARG_RELOCATED]] to i32 addrspace(1)* +; CHECK-NEXT: ret i32 addrspace(1)* [[ARG_RELOCATED_CASTED]] +; + entry: call void @g() [ "deopt"(i32 100) ] -; CHECK: %arg.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[TOKEN_0]], i32 8, i32 8) ret i32 addrspace(1)* %arg } define i32 addrspace(1)* @f1(i32 addrspace(1)* %arg) gc "statepoint-example" personality i32 8 { ; CHECK-LABEL: @f1( - entry: -; CHECK: [[TOKEN_1:%[^ ]+]] = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* %arg) +; CHECK-NEXT: entry: +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* [[ARG:%.*]]) +; CHECK-NEXT: to label [[NORMAL_DEST:%.*]] unwind label [[UNWIND_DEST:%.*]] +; CHECK: normal_dest: +; CHECK-NEXT: [[ARG_RELOCATED1:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 8, i32 8) +; CHECK-NEXT: [[ARG_RELOCATED1_CASTED:%.*]] = bitcast i8 addrspace(1)* [[ARG_RELOCATED1]] to i32 addrspace(1)* +; CHECK-NEXT: ret i32 addrspace(1)* [[ARG_RELOCATED1_CASTED]] +; CHECK: unwind_dest: +; CHECK-NEXT: [[LPAD:%.*]] = landingpad token +; CHECK-NEXT: cleanup +; CHECK-NEXT: [[ARG_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[LPAD]], i32 8, i32 8) +; CHECK-NEXT: [[ARG_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[ARG_RELOCATED]] to i32 addrspace(1)* +; CHECK-NEXT: resume token undef +; + entry: invoke void @g() [ "deopt"(i32 100) ] to label %normal_dest unwind label %unwind_dest - normal_dest: -; CHECK: %arg.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[TOKEN_1]], i32 8, i32 8) + normal_dest: ret i32 addrspace(1)* %arg - unwind_dest: + unwind_dest: %lpad = landingpad token cleanup resume token undef } define i32 addrspace(1)* @f2(i32 addrspace(1)* %arg) gc "statepoint-example" { ; CHECK-LABEL: @f2( - entry: -; CHECK: [[TOKEN_2:%[^ ]+]] = call token (i64, i32, i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i64 2882400000, i32 0, i32 ()* @h, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* %arg) +; CHECK-NEXT: entry: +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i64 2882400000, i32 0, i32 ()* @h, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* [[ARG:%.*]]) +; CHECK-NEXT: [[VAL1:%.*]] = call i32 @llvm.experimental.gc.result.i32(token [[STATEPOINT_TOKEN]]) +; CHECK-NEXT: [[ARG_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 8, i32 8) +; CHECK-NEXT: [[ARG_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[ARG_RELOCATED]] to i32 addrspace(1)* +; CHECK-NEXT: store i32 [[VAL1]], i32 addrspace(1)* [[ARG_RELOCATED_CASTED]], align 4 +; CHECK-NEXT: ret i32 addrspace(1)* [[ARG_RELOCATED_CASTED]] +; + entry: %val = call i32 @h() [ "deopt"(i32 100) ] -; CHECK: [[RESULT_F2:%[^ ]+]] = call i32 @llvm.experimental.gc.result.i32(token [[TOKEN_2]]) -; CHECK: %arg.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[TOKEN_2]], i32 8, i32 8) -; CHECK: %arg.relocated.casted = bitcast i8 addrspace(1)* %arg.relocated to i32 addrspace(1)* store i32 %val, i32 addrspace(1)* %arg -; CHECK: store i32 [[RESULT_F2]], i32 addrspace(1)* %arg.relocated.casted ret i32 addrspace(1)* %arg } define i32 addrspace(1)* @f3(i32 addrspace(1)* %arg) gc "statepoint-example" personality i32 8 { ; CHECK-LABEL: @f3( - entry: -; CHECK: [[TOKEN_3:%[^ ]+]] = invoke token (i64, i32, i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i64 2882400000, i32 0, i32 ()* @h, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* %arg) +; CHECK-NEXT: entry: +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = invoke token (i64, i32, i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i64 2882400000, i32 0, i32 ()* @h, i32 0, i32 0, i32 0, i32 1, i32 100, i32 addrspace(1)* [[ARG:%.*]]) +; CHECK-NEXT: to label [[NORMAL_DEST:%.*]] unwind label [[UNWIND_DEST:%.*]] +; CHECK: normal_dest: +; CHECK-NEXT: [[VAL1:%.*]] = call i32 @llvm.experimental.gc.result.i32(token [[STATEPOINT_TOKEN]]) +; CHECK-NEXT: [[ARG_RELOCATED2:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 8, i32 8) +; CHECK-NEXT: [[ARG_RELOCATED2_CASTED:%.*]] = bitcast i8 addrspace(1)* [[ARG_RELOCATED2]] to i32 addrspace(1)* +; CHECK-NEXT: store i32 [[VAL1]], i32 addrspace(1)* [[ARG_RELOCATED2_CASTED]], align 4 +; CHECK-NEXT: ret i32 addrspace(1)* [[ARG_RELOCATED2_CASTED]] +; CHECK: unwind_dest: +; CHECK-NEXT: [[LPAD:%.*]] = landingpad token +; CHECK-NEXT: cleanup +; CHECK-NEXT: [[ARG_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[LPAD]], i32 8, i32 8) +; CHECK-NEXT: [[ARG_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[ARG_RELOCATED]] to i32 addrspace(1)* +; CHECK-NEXT: resume token undef +; + entry: %val = invoke i32 @h() [ "deopt"(i32 100) ] to label %normal_dest unwind label %unwind_dest - normal_dest: -; CHECK: [[RESULT_F3:%[^ ]+]] = call i32 @llvm.experimental.gc.result.i32(token [[TOKEN_3]]) -; CHECK: [[ARG_RELOCATED:%[^ ]+]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[TOKEN_3]], i32 8, i32 8) -; CHECK: [[ARG_RELOCATED_CASTED:%[^ ]+]] = bitcast i8 addrspace(1)* [[ARG_RELOCATED]] to i32 addrspace(1)* + normal_dest: store i32 %val, i32 addrspace(1)* %arg -; CHECK: store i32 [[RESULT_F3]], i32 addrspace(1)* [[ARG_RELOCATED_CASTED]] ret i32 addrspace(1)* %arg - unwind_dest: + unwind_dest: %lpad = landingpad token cleanup resume token undef } define i32 addrspace(1)* @f4(i32 addrspace(1)* %arg) gc "statepoint-example" { ; CHECK-LABEL: @f4( - entry: -; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 1, i32 2, i32 400, i8 90, +; CHECK-NEXT: entry: +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 1, i32 2, i32 400, i8 90, i32 0, i32 addrspace(1)* [[ARG:%.*]]) +; CHECK-NEXT: [[ARG_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 9, i32 9) +; CHECK-NEXT: [[ARG_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[ARG_RELOCATED]] to i32 addrspace(1)* +; CHECK-NEXT: ret i32 addrspace(1)* [[ARG_RELOCATED_CASTED]] +; + entry: call void @g() [ "gc-transition"(i32 400, i8 90) ] ret i32 addrspace(1)* %arg } diff --git a/llvm/test/Transforms/RewriteStatepointsForGC/deopt-lowering-attrs.ll b/llvm/test/Transforms/RewriteStatepointsForGC/deopt-lowering-attrs.ll index d0a331905088f..65e38d9d37587 100644 --- a/llvm/test/Transforms/RewriteStatepointsForGC/deopt-lowering-attrs.ll +++ b/llvm/test/Transforms/RewriteStatepointsForGC/deopt-lowering-attrs.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -rewrite-statepoints-for-gc -S < %s | FileCheck %s ; RUN: opt -passes=rewrite-statepoints-for-gc -S < %s | FileCheck %s ; Check that the "deopt-lowering" function attribute gets transcoded into @@ -12,9 +13,12 @@ declare void @baz() "deopt-lowering"="live-through" define void @test1() gc "statepoint-example" { ; CHECK-LABEL: @test1( -; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 1, i32 57) -; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 42) -; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @baz, i32 0, i32 0, i32 0, i32 1, i32 13) +; CHECK-NEXT: entry: +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 1, i32 57) +; CHECK-NEXT: [[STATEPOINT_TOKEN1:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 42) +; CHECK-NEXT: [[STATEPOINT_TOKEN2:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @baz, i32 0, i32 0, i32 0, i32 1, i32 13) +; CHECK-NEXT: ret void +; entry: call void @foo() [ "deopt"(i32 57) ] @@ -26,7 +30,10 @@ entry: ; add deopt-lowering attribute as part of callsite define void @test2() gc "statepoint-example" { ; CHECK-LABEL: @test2( -; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 2, i32 0, i32 1, i32 57) +; CHECK-NEXT: entry: +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 2, i32 0, i32 1, i32 57) #0 +; CHECK-NEXT: ret void +; entry: call void @foo() "deopt-lowering"="live-in" [ "deopt"(i32 57) ]