1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -instcombine-max-iterations=1 -S | FileCheck %s
3; These tests check the optimizations specific to
4; pointers being relocated at a statepoint.
5
6
7declare void @func()
8
9define i1 @test_null(i1 %cond) gc "statepoint-example" {
10; CHECK-LABEL: @test_null(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
13; CHECK:       right:
14; CHECK-NEXT:    br label [[MERGE:%.*]]
15; CHECK:       left:
16; CHECK-NEXT:    [[SAFEPOINT_TOKEN:%.*]] = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* nonnull @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"() ]
17; CHECK-NEXT:    br label [[MERGE]]
18; CHECK:       merge:
19; CHECK-NEXT:    [[SAFEPOINT_TOKEN2:%.*]] = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* nonnull @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"() ]
20; CHECK-NEXT:    ret i1 true
21;
22entry:
23  br i1 %cond, label %left, label %right
24
25right:
26  br label %merge
27
28left:
29  %safepoint_token = tail 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* null)]
30  %pnew = call i32* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 0)
31  br label %merge
32
33merge:
34  %pnew_phi = phi i32* [null, %right], [%pnew, %left]
35  %safepoint_token2 = tail 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* %pnew_phi)]
36  %pnew2 = call i32* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2,  i32 0, i32 0)
37  %cmp = icmp eq i32* %pnew2, null
38  ret i1 %cmp
39}
40
41define i32* @test_undef(i1 %cond) gc "statepoint-example" {
42; CHECK-LABEL: @test_undef(
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
45; CHECK:       right:
46; CHECK-NEXT:    br label [[MERGE:%.*]]
47; CHECK:       left:
48; CHECK-NEXT:    [[SAFEPOINT_TOKEN:%.*]] = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* nonnull @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"() ]
49; CHECK-NEXT:    br label [[MERGE]]
50; CHECK:       merge:
51; CHECK-NEXT:    [[SAFEPOINT_TOKEN2:%.*]] = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* nonnull @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"() ]
52; CHECK-NEXT:    ret i32* undef
53;
54entry:
55  br i1 %cond, label %left, label %right
56
57right:
58  br label %merge
59
60left:
61  %safepoint_token = tail 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* undef)]
62  %pnew = call i32* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 0, i32 0)
63  br label %merge
64
65merge:
66  %pnew_phi = phi i32* [undef, %right], [%pnew, %left]
67  %safepoint_token2 = tail 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* %pnew_phi)]
68  %pnew2 = call i32* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2,  i32 0, i32 0)
69  ret i32* %pnew2
70}
71
72declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
73declare i32* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
74