[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / icmp-div-constant.ll
blob8028dd636c1afcb05ddc935ad0a8399670669cf1
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 define i1 @is_rem2_neg_i8(i8 %x) {
5 ; CHECK-LABEL: @is_rem2_neg_i8(
6 ; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], -127
7 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP1]], -127
8 ; CHECK-NEXT:    ret i1 [[R]]
10   %s = srem i8 %x, 2
11   %r = icmp slt i8 %s, 0
12   ret i1 %r
15 define <2 x i1> @is_rem2_pos_v2i8(<2 x i8> %x) {
16 ; CHECK-LABEL: @is_rem2_pos_v2i8(
17 ; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -127, i8 -127>
18 ; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i8> [[TMP1]], <i8 1, i8 1>
19 ; CHECK-NEXT:    ret <2 x i1> [[R]]
21   %s = srem <2 x i8> %x, <i8 2, i8 2>
22   %r = icmp sgt <2 x i8> %s, zeroinitializer
23   ret <2 x i1> %r
26 ; i8 -97 == 159 == 0b10011111
28 define i1 @is_rem32_pos_i8(i8 %x) {
29 ; CHECK-LABEL: @is_rem32_pos_i8(
30 ; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], -97
31 ; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[TMP1]], 0
32 ; CHECK-NEXT:    ret i1 [[R]]
34   %s = srem i8 %x, 32
35   %r = icmp sgt i8 %s, 0
36   ret i1 %r
39 ; i16 -32765 == 32771 == 0b1000000000000011
41 define i1 @is_rem4_neg_i16(i16 %x) {
42 ; CHECK-LABEL: @is_rem4_neg_i16(
43 ; CHECK-NEXT:    [[TMP1:%.*]] = and i16 [[X:%.*]], -32765
44 ; CHECK-NEXT:    [[R:%.*]] = icmp ugt i16 [[TMP1]], -32768
45 ; CHECK-NEXT:    ret i1 [[R]]
47   %s = srem i16 %x, 4
48   %r = icmp slt i16 %s, 0
49   ret i1 %r
52 declare void @use(i32)
54 ; TODO: This is still worth folding because srem is difficult?
56 define i1 @is_rem32_neg_i32_extra_use(i32 %x) {
57 ; CHECK-LABEL: @is_rem32_neg_i32_extra_use(
58 ; CHECK-NEXT:    [[S:%.*]] = srem i32 [[X:%.*]], 32
59 ; CHECK-NEXT:    call void @use(i32 [[S]])
60 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[S]], 0
61 ; CHECK-NEXT:    ret i1 [[R]]
63   %s = srem i32 %x, 32
64   call void @use(i32 %s)
65   %r = icmp slt i32 %s, 0
66   ret i1 %r
69 ; Negative test - wrong compare constant
71 define i1 @is_rem8_nonneg_i16(i16 %x) {
72 ; CHECK-LABEL: @is_rem8_nonneg_i16(
73 ; CHECK-NEXT:    [[S:%.*]] = srem i16 [[X:%.*]], 8
74 ; CHECK-NEXT:    [[R:%.*]] = icmp sgt i16 [[S]], -1
75 ; CHECK-NEXT:    ret i1 [[R]]
77   %s = srem i16 %x, 8
78   %r = icmp sgt i16 %s, -1
79   ret i1 %r
82 ; Negative test - wrong remainder constant
84 define i1 @is_rem3_neg_i8(i8 %x) {
85 ; CHECK-LABEL: @is_rem3_neg_i8(
86 ; CHECK-NEXT:    [[S:%.*]] = srem i8 [[X:%.*]], 3
87 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[S]], 0
88 ; CHECK-NEXT:    ret i1 [[R]]
90   %s = srem i8 %x, 3
91   %r = icmp slt i8 %s, 0
92   ret i1 %r
95 ; Negative test - wrong compare constant
97 define i1 @is_rem16_something_i8(i8 %x) {
98 ; CHECK-LABEL: @is_rem16_something_i8(
99 ; CHECK-NEXT:    [[S:%.*]] = srem i8 [[X:%.*]], 16
100 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[S]], 7
101 ; CHECK-NEXT:    ret i1 [[R]]
103   %s = srem i8 %x, 16
104   %r = icmp slt i8 %s, 7
105   ret i1 %r
108 ; PR30281 - https://llvm.org/bugs/show_bug.cgi?id=30281
110 ; All of these tests contain foldable division-by-constant instructions, but we
111 ; can't assert that those folds have occurred before we process the later icmp.
113 define i32 @icmp_div(i16 %a, i16 %c) {
114 ; CHECK-LABEL: @icmp_div(
115 ; CHECK-NEXT:  entry:
116 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0
117 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]]
118 ; CHECK:       then:
119 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[C:%.*]], 0
120 ; CHECK-NEXT:    [[PHITMP1:%.*]] = sext i1 [[CMP]] to i32
121 ; CHECK-NEXT:    br label [[EXIT]]
122 ; CHECK:       exit:
123 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[PHITMP1]], [[THEN]] ]
124 ; CHECK-NEXT:    ret i32 [[PHI]]
126 entry:
127   %tobool = icmp eq i16 %a, 0
128   br i1 %tobool, label %then, label %exit
130 then:
131   %div = sdiv i16 %c, -1
132   %cmp = icmp ne i16 %div, 0
133   br label %exit
135 exit:
136   %phi = phi i1 [ false, %entry ], [ %cmp, %then ]
137   %zext = zext i1 %phi to i32
138   %add = add nsw i32 %zext, -1
139   ret i32 %add
142 define i32 @icmp_div2(i16 %a, i16 %c) {
143 ; CHECK-LABEL: @icmp_div2(
144 ; CHECK-NEXT:  entry:
145 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0
146 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]]
147 ; CHECK:       then:
148 ; CHECK-NEXT:    br label [[EXIT]]
149 ; CHECK:       exit:
150 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 0, [[THEN]] ]
151 ; CHECK-NEXT:    ret i32 [[PHI]]
153 entry:
154   %tobool = icmp eq i16 %a, 0
155   br i1 %tobool, label %then, label %exit
157 then:
158   %div = sdiv i16 %c, 0
159   %cmp = icmp ne i16 %div, 0
160   br label %exit
162 exit:
163   %phi = phi i1 [ false, %entry ], [ %cmp, %then ]
164   %zext = zext i1 %phi to i32
165   %add = add nsw i32 %zext, -1
166   ret i32 %add
169 define i32 @icmp_div3(i16 %a, i16 %c) {
170 ; CHECK-LABEL: @icmp_div3(
171 ; CHECK-NEXT:  entry:
172 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0
173 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]]
174 ; CHECK:       then:
175 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i16 [[C:%.*]], 0
176 ; CHECK-NEXT:    [[PHITMP1:%.*]] = sext i1 [[CMP]] to i32
177 ; CHECK-NEXT:    br label [[EXIT]]
178 ; CHECK:       exit:
179 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[PHITMP1]], [[THEN]] ]
180 ; CHECK-NEXT:    ret i32 [[PHI]]
182 entry:
183   %tobool = icmp eq i16 %a, 0
184   br i1 %tobool, label %then, label %exit
186 then:
187   %div = sdiv i16 %c, 1
188   %cmp = icmp ne i16 %div, 0
189   br label %exit
191 exit:
192   %phi = phi i1 [ false, %entry ], [ %cmp, %then ]
193   %zext = zext i1 %phi to i32
194   %add = add nsw i32 %zext, -1
195   ret i32 %add