1; RUN: opt < %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
2; RUN: opt < %s -instcombine -S -debugify-each | FileCheck %s
3; RUN: opt < %s -passes=instcombine -S -debugify-each | FileCheck %s
4
5declare void @llvm.experimental.guard(i1, ...)
6
7define void @test_guard_adjacent_same_cond(i1 %A) {
8; CHECK-LABEL: @test_guard_adjacent_same_cond(
9; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %A) [ "deopt"() ]
10; CHECK-NEXT:    ret void
11  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
12  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
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  ret void
22}
23
24define void @test_guard_adjacent_diff_cond(i1 %A, i1 %B, i1 %C) {
25; CHECK-LABEL: @test_guard_adjacent_diff_cond(
26; CHECK-NEXT:    %1 = and i1 %A, %B
27; CHECK-NEXT:    %2 = and i1 %1, %C
28; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %2, i32 123) [ "deopt"() ]
29; CHECK-NEXT:    ret void
30  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
31  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
32  call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ]
33  ret void
34}
35
36; This version tests for the common form where the conditions are
37; between the guards
38define void @test_guard_adjacent_diff_cond2(i32 %V1, i32 %V2) {
39; CHECK-LABEL: @test_guard_adjacent_diff_cond2(
40; CHECK-NEXT:    %1 = and i32 %V1, %V2
41; CHECK-NEXT:    %2 = icmp slt i32 %1, 0
42; CHECK-NEXT:    %and = and i32 %V1, 255
43; CHECK-NEXT:    %C = icmp ult i32 %and, 129
44; CHECK-NEXT:    %3 = and i1 %2, %C
45; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %3, i32 123) [ "deopt"() ]
46; CHECK-NEXT:    ret void
47  %A = icmp slt i32 %V1, 0
48  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
49  %B = icmp slt i32 %V2, 0
50  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
51  %and = and i32 %V1, 255
52  %C = icmp sle i32 %and, 128
53  call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ]
54  ret void
55}
56
57; Might not be legal to hoist the load above the first guard since the
58; guard might control dereferenceability
59define void @negative_load(i32 %V1, i32* %P) {
60; CHECK-LABEL: @negative_load
61; CHECK:    @llvm.experimental.guard
62; CHECK:    @llvm.experimental.guard
63  %A = icmp slt i32 %V1, 0
64  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
65  %V2 = load i32, i32* %P
66  %B = icmp slt i32 %V2, 0
67  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
68  ret void
69}
70
71define void @deref_load(i32 %V1, i32* dereferenceable(4) align 4 %P) {
72; CHECK-LABEL: @deref_load
73; CHECK-NEXT:  %V2 = load i32, i32* %P, align 4
74; CHECK-NEXT:  %1 = and i32 %V2, %V1
75; CHECK-NEXT:  %2 = icmp slt i32 %1, 0
76; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %2, i32 123) [ "deopt"() ]
77  %A = icmp slt i32 %V1, 0
78  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
79  %V2 = load i32, i32* %P
80  %B = icmp slt i32 %V2, 0
81  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
82  ret void
83}
84
85; The divide might fault above the guard
86define void @negative_div(i32 %V1, i32 %D) {
87; CHECK-LABEL: @negative_div
88; CHECK:    @llvm.experimental.guard
89; CHECK:    @llvm.experimental.guard
90  %A = icmp slt i32 %V1, 0
91  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
92  %V2 = udiv i32 %V1, %D
93  %B = icmp slt i32 %V2, 0
94  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
95  ret void
96}
97
98; Highlight the limit of the window in a case which would otherwise be mergable
99define void @negative_window(i32 %V1, i32 %a, i32 %b, i32 %c, i32 %d) {
100; CHECK-LABEL: @negative_window
101; CHECK:    @llvm.experimental.guard
102; CHECK:    @llvm.experimental.guard
103  %A = icmp slt i32 %V1, 0
104  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
105  %V2 = add i32 %a, %b
106  %V3 = add i32 %V2, %c
107  %V4 = add i32 %V3, %d
108  %B = icmp slt i32 %V4, 0
109  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
110  ret void
111}
112
113