xref: /llvm-project/llvm/test/Transforms/InstCombine/call-guard.ll (revision 095d49da76be09143582e07a807c86d3b4334dec)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3; RUN: opt < %s -passes=instcombine -S -debugify-each | FileCheck %s
4; RUN: opt < %s -passes=instcombine -S -debugify-each --try-experimental-debuginfo-iterators | FileCheck %s
5
6declare void @llvm.experimental.guard(i1, ...)
7
8define void @test_guard_adjacent_same_cond(i1 %A) {
9; CHECK-LABEL: @test_guard_adjacent_same_cond(
10; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[A:%.*]]) [ "deopt"() ]
11; CHECK-NEXT:    ret void
12;
13  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
14  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
15  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
16  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
17  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
18  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
19  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
20  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
21  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
22  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
23  ret void
24}
25
26define void @test_guard_adjacent_diff_cond(i1 %A, i1 %B, i1 %C) {
27; CHECK-LABEL: @test_guard_adjacent_diff_cond(
28; CHECK-NEXT:    [[TMP1:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
29; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[C:%.*]]
30; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 123) [ "deopt"() ]
31; CHECK-NEXT:    ret void
32;
33  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
34  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
35  call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ]
36  ret void
37}
38
39; This version tests for the common form where the conditions are
40; between the guards
41define void @test_guard_adjacent_diff_cond2(i32 %V1, i32 %V2) {
42; CHECK-LABEL: @test_guard_adjacent_diff_cond2(
43; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[V1:%.*]], [[V2:%.*]]
44; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
45; CHECK-NEXT:    [[AND:%.*]] = and i32 [[V1]], 255
46; CHECK-NEXT:    [[C:%.*]] = icmp samesign ult i32 [[AND]], 129
47; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[C]]
48; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 123) [ "deopt"() ]
49; CHECK-NEXT:    ret void
50;
51  %A = icmp slt i32 %V1, 0
52  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
53  %B = icmp slt i32 %V2, 0
54  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
55  %and = and i32 %V1, 255
56  %C = icmp sle i32 %and, 128
57  call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ]
58  ret void
59}
60
61; Might not be legal to hoist the load above the first guard since the
62; guard might control dereferenceability
63define void @negative_load(i32 %V1, ptr %P) {
64; CHECK-LABEL: @negative_load(
65; CHECK-NEXT:    [[A:%.*]] = icmp slt i32 [[V1:%.*]], 0
66; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[A]], i32 123) [ "deopt"() ]
67; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[P:%.*]], align 4
68; CHECK-NEXT:    [[B:%.*]] = icmp slt i32 [[V2]], 0
69; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[B]], i32 456) [ "deopt"() ]
70; CHECK-NEXT:    ret void
71;
72  %A = icmp slt i32 %V1, 0
73  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
74  %V2 = load i32, ptr %P
75  %B = icmp slt i32 %V2, 0
76  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
77  ret void
78}
79
80define void @deref_load(i32 %V1, ptr dereferenceable(4) align 4 %P) nofree nosync {
81; CHECK-LABEL: @deref_load(
82; CHECK-NEXT:    [[V2:%.*]] = load i32, ptr [[P:%.*]], align 4
83; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[V1:%.*]], [[V2]]
84; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
85; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 123) [ "deopt"() ]
86; CHECK-NEXT:    ret void
87;
88  %A = icmp slt i32 %V1, 0
89  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
90  %V2 = load i32, ptr %P
91  %B = icmp slt i32 %V2, 0
92  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
93  ret void
94}
95
96; The divide might fault above the guard
97define void @negative_div(i32 %V1, i32 %D) {
98; CHECK-LABEL: @negative_div(
99; CHECK-NEXT:    [[A:%.*]] = icmp slt i32 [[V1:%.*]], 0
100; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[A]], i32 123) [ "deopt"() ]
101; CHECK-NEXT:    [[V2:%.*]] = udiv i32 [[V1]], [[D:%.*]]
102; CHECK-NEXT:    [[B:%.*]] = icmp slt i32 [[V2]], 0
103; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[B]], i32 456) [ "deopt"() ]
104; CHECK-NEXT:    ret void
105;
106  %A = icmp slt i32 %V1, 0
107  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
108  %V2 = udiv i32 %V1, %D
109  %B = icmp slt i32 %V2, 0
110  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
111  ret void
112}
113
114; Highlight the limit of the window in a case which would otherwise be mergable
115define void @negative_window(i32 %V1, i32 %a, i32 %b, i32 %c, i32 %d) {
116; CHECK-LABEL: @negative_window(
117; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[V1:%.*]], 0
118; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[CMP1]], i32 123) [ "deopt"() ]
119; CHECK-NEXT:    [[V2:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
120; CHECK-NEXT:    [[V3:%.*]] = add i32 [[V2]], [[C:%.*]]
121; CHECK-NEXT:    [[V4:%.*]] = add i32 [[V3]], [[D:%.*]]
122; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[V4]], 0
123; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[CMP2]], i32 456) [ "deopt"() ]
124; CHECK-NEXT:    ret void
125;
126  %cmp1 = icmp slt i32 %V1, 0
127  call void(i1, ...) @llvm.experimental.guard( i1 %cmp1, i32 123 )[ "deopt"() ]
128  %V2 = add i32 %a, %b
129  %V3 = add i32 %V2, %c
130  %V4 = add i32 %V3, %d
131  %cmp2 = icmp slt i32 %V4, 0
132  call void(i1, ...) @llvm.experimental.guard( i1 %cmp2, i32 456 )[ "deopt"() ]
133  ret void
134}
135
136