1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -basic-aa -gvn -S < %s | FileCheck %s 3 4declare void @func() 5declare i32 @"personality_function"() 6 7define i1 @test_trivial(i32 addrspace(1)* %in) gc "statepoint-example" { 8; CHECK-LABEL: @test_trivial( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[IN:%.*]]) ] 11; CHECK-NEXT: [[A:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) 12; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 addrspace(1)* [[A]], null 13; CHECK-NEXT: ret i1 [[CMP1]] 14; 15entry: 16 %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %in)] 17 %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 18 %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 19 %cmp1 = icmp eq i32 addrspace(1)* %a, null 20 %cmp2 = icmp eq i32 addrspace(1)* %b, null 21 %cmp = and i1 %cmp1, %cmp2 22 ret i1 %cmp 23} 24 25@G = external global i32 26 27define i1 @test_readnone(i32 addrspace(1)* %in) gc "statepoint-example" { 28; CHECK-LABEL: @test_readnone( 29; CHECK-NEXT: entry: 30; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[IN:%.*]]) ] 31; CHECK-NEXT: [[A:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) 32; CHECK-NEXT: store i32 0, i32* @G, align 4 33; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 addrspace(1)* [[A]], null 34; CHECK-NEXT: ret i1 [[CMP1]] 35; 36entry: 37 %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %in)] 38 %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 39 store i32 0, i32* @G 40 %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 41 %cmp1 = icmp eq i32 addrspace(1)* %a, null 42 %cmp2 = icmp eq i32 addrspace(1)* %b, null 43 %cmp = and i1 %cmp1, %cmp2 44 ret i1 %cmp 45} 46 47define i1 @test_call(i32 addrspace(1)* %in) gc "statepoint-example" { 48; CHECK-LABEL: @test_call( 49; CHECK-NEXT: entry: 50; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[IN:%.*]], i32 addrspace(1)* [[IN]]) ] 51; CHECK-NEXT: [[BASE:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) 52; CHECK-NEXT: [[SAFEPOINT_TOKEN2:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[BASE]], i32 addrspace(1)* [[BASE]]) ] 53; CHECK-NEXT: [[BASE_RELOC:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN2]], i32 0, i32 0) 54; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 addrspace(1)* [[BASE_RELOC]], null 55; CHECK-NEXT: ret i1 [[CMP1]] 56; 57entry: 58 %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %in, i32 addrspace(1)* %in)] 59 %base = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 60 %derived = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 1) 61 %safepoint_token2 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %base, i32 addrspace(1)* %derived)] 62 br label %next 63 64next: 65 %base_reloc = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 0, i32 0) 66 %derived_reloc = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 0, i32 1) 67 %cmp1 = icmp eq i32 addrspace(1)* %base_reloc, null 68 %cmp2 = icmp eq i32 addrspace(1)* %derived_reloc, null 69 %cmp = and i1 %cmp1, %cmp2 70 ret i1 %cmp 71} 72 73; Negative test: Check that relocates from different statepoints are not CSE'd 74define i1 @test_two_calls(i32 addrspace(1)* %in1, i32 addrspace(1)* %in2) gc "statepoint-example" { 75; CHECK-LABEL: @test_two_calls( 76; CHECK-NEXT: entry: 77; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[IN1:%.*]], i32 addrspace(1)* [[IN2:%.*]]) ] 78; CHECK-NEXT: [[IN1_RELOC1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) 79; CHECK-NEXT: [[IN2_RELOC1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 1, i32 1) 80; CHECK-NEXT: [[SAFEPOINT_TOKEN2:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[IN1_RELOC1]], i32 addrspace(1)* [[IN2_RELOC1]]) ] 81; CHECK-NEXT: [[IN1_RELOC2:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN2]], i32 0, i32 1) 82; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 addrspace(1)* [[IN1_RELOC2]], null 83; CHECK-NEXT: ret i1 [[CMP1]] 84; 85entry: 86 %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %in1, i32 addrspace(1)* %in2)] 87 %in1.reloc1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 88 %in2.reloc1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 1, i32 1) 89 %safepoint_token2 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %in1.reloc1, i32 addrspace(1)* %in2.reloc1)] 90 %in1.reloc2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 0, i32 1) 91 %in2.reloc2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 0, i32 1) 92 %cmp1 = icmp eq i32 addrspace(1)* %in1.reloc2, null 93 %cmp2 = icmp eq i32 addrspace(1)* %in2.reloc2, null 94 %cmp = and i1 %cmp1, %cmp2 95 ret i1 %cmp 96} 97 98; Negative test: Check that relocates from normal and exceptional pathes are not be CSE'd 99define i32 addrspace(1)* @test_invoke(i32 addrspace(1)* %in) gc "statepoint-example" personality i32 ()* @"personality_function" { 100; CHECK-LABEL: @test_invoke( 101; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[IN:%.*]]) ] 102; CHECK-NEXT: to label [[INVOKE_NORMAL_DEST:%.*]] unwind label [[EXCEPTIONAL_RETURN:%.*]] 103; CHECK: invoke_normal_dest: 104; CHECK-NEXT: [[OUT:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) 105; CHECK-NEXT: ret i32 addrspace(1)* [[OUT]] 106; CHECK: exceptional_return: 107; CHECK-NEXT: [[LANDING_PAD:%.*]] = landingpad token 108; CHECK-NEXT: cleanup 109; CHECK-NEXT: [[OUT1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[LANDING_PAD]], i32 0, i32 0) 110; CHECK-NEXT: ret i32 addrspace(1)* [[OUT1]] 111; 112 %safepoint_token = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %in)] 113 to label %invoke_normal_dest unwind label %exceptional_return 114 115invoke_normal_dest: 116 %out = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 117 ret i32 addrspace(1)* %out 118 119exceptional_return: 120 %landing_pad = landingpad token 121 cleanup 122 %out1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %landing_pad, i32 0, i32 0) 123 ret i32 addrspace(1)* %out1 124} 125 126; negative test - neither dominates the other 127define i1 @test_non_dominating(i1 %c, i32 addrspace(1)* %in) gc "statepoint-example" { 128; 129; CHECK-LABEL: @test_non_dominating( 130; CHECK-NEXT: entry: 131; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[IN:%.*]]) ] 132; CHECK-NEXT: br i1 [[C:%.*]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]] 133; CHECK: taken: 134; CHECK-NEXT: [[A:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) 135; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 addrspace(1)* [[A]], null 136; CHECK-NEXT: ret i1 [[CMP]] 137; CHECK: untaken: 138; CHECK-NEXT: [[B:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) 139; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 addrspace(1)* [[B]], null 140; CHECK-NEXT: ret i1 [[CMP2]] 141; 142entry: 143 %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %in)] 144 br i1 %c, label %taken, label %untaken 145taken: 146 %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 147 %cmp = icmp eq i32 addrspace(1)* %a, null 148 ret i1 %cmp 149untaken: 150 %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 151 %cmp2 = icmp eq i32 addrspace(1)* %b, null 152 ret i1 %cmp2 153} 154 155declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) 156declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) 157