1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
3 ; RUN: opt < %s -instcombine -S -debugify-each | FileCheck %s
4 ; RUN: opt < %s -passes=instcombine -S -debugify-each | FileCheck %s
6 declare void @llvm.experimental.guard(i1, ...)
8 define 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
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"() ]
26 define 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
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"() ]
39 ; This version tests for the common form where the conditions are
41 define 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 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
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"() ]
61 ; Might not be legal to hoist the load above the first guard since the
62 ; guard might control dereferenceability
63 define void @negative_load(i32 %V1, i32* %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, i32* [[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
72 %A = icmp slt i32 %V1, 0
73 call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
74 %V2 = load i32, i32* %P
75 %B = icmp slt i32 %V2, 0
76 call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
80 define void @deref_load(i32 %V1, i32* dereferenceable(4) align 4 %P) nofree nosync {
81 ; CHECK-LABEL: @deref_load(
82 ; CHECK-NEXT: [[V2:%.*]] = load i32, i32* [[P:%.*]], align 4
83 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[V2]], [[V1:%.*]]
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
88 %A = icmp slt i32 %V1, 0
89 call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
90 %V2 = load i32, i32* %P
91 %B = icmp slt i32 %V2, 0
92 call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
96 ; The divide might fault above the guard
97 define 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
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"() ]
114 ; Highlight the limit of the window in a case which would otherwise be mergable
115 define void @negative_window(i32 %V1, i32 %a, i32 %b, i32 %c, i32 %d) {
116 ; CHECK-LABEL: @negative_window(
117 ; CHECK-NEXT: [[A:%.*]] = icmp slt i32 [[V1:%.*]], 0
118 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[A]], 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: [[B:%.*]] = icmp slt i32 [[V4]], 0
123 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[B]], i32 456) [ "deopt"() ]
124 ; CHECK-NEXT: ret void
126 %A = icmp slt i32 %V1, 0
127 call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
129 %V3 = add i32 %V2, %c
130 %V4 = add i32 %V3, %d
131 %B = icmp slt i32 %V4, 0
132 call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]