1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 ; RUN: opt < %s -instcombine -S | FileCheck %s 3 4 ; https://bugs.llvm.org/show_bug.cgi?id=38123 5 6 ; Pattern: 7 ; x & C s>= x 8 ; Should be transformed into: 9 ; x s<= C 10 ; Iff: isPowerOf2(C + 1) 11 12 ; ============================================================================ ; 13 ; Basic positive tests 14 ; ============================================================================ ; 15 16 define i1 @p0(i8 %x) { 17 ; CHECK-LABEL: @p0( 18 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 4 19 ; CHECK-NEXT: ret i1 [[TMP1]] 20 ; 21 %tmp0 = and i8 %x, 3 22 %ret = icmp sge i8 %tmp0, %x 23 ret i1 %ret 24 } 25 26 ; ============================================================================ ; 27 ; Vector tests 28 ; ============================================================================ ; 29 30 define <2 x i1> @p1_vec_splat(<2 x i8> %x) { 31 ; CHECK-LABEL: @p1_vec_splat( 32 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i8> [[X:%.*]], <i8 4, i8 4> 33 ; CHECK-NEXT: ret <2 x i1> [[TMP1]] 34 ; 35 %tmp0 = and <2 x i8> %x, <i8 3, i8 3> 36 %ret = icmp sge <2 x i8> %tmp0, %x 37 ret <2 x i1> %ret 38 } 39 40 define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) { 41 ; CHECK-LABEL: @p2_vec_nonsplat( 42 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i8> [[X:%.*]], <i8 4, i8 16> 43 ; CHECK-NEXT: ret <2 x i1> [[TMP1]] 44 ; 45 %tmp0 = and <2 x i8> %x, <i8 3, i8 15> ; doesn't have to be splat. 46 %ret = icmp sge <2 x i8> %tmp0, %x 47 ret <2 x i1> %ret 48 } 49 50 define <3 x i1> @p3_vec_splat_undef(<3 x i8> %x) { 51 ; CHECK-LABEL: @p3_vec_splat_undef( 52 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <3 x i8> [[X:%.*]], <i8 4, i8 undef, i8 4> 53 ; CHECK-NEXT: ret <3 x i1> [[TMP1]] 54 ; 55 %tmp0 = and <3 x i8> %x, <i8 3, i8 undef, i8 3> 56 %ret = icmp sge <3 x i8> %tmp0, %x 57 ret <3 x i1> %ret 58 } 59 60 ; ============================================================================ ; 61 ; One-use tests. We don't care about multi-uses here. 62 ; ============================================================================ ; 63 64 declare void @use8(i8) 65 66 define i1 @oneuse0(i8 %x) { 67 ; CHECK-LABEL: @oneuse0( 68 ; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3 69 ; CHECK-NEXT: call void @use8(i8 [[TMP0]]) 70 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X]], 4 71 ; CHECK-NEXT: ret i1 [[TMP1]] 72 ; 73 %tmp0 = and i8 %x, 3 74 call void @use8(i8 %tmp0) 75 %ret = icmp sge i8 %tmp0, %x 76 ret i1 %ret 77 } 78 79 ; ============================================================================ ; 80 ; Negative tests 81 ; ============================================================================ ; 82 83 ; ============================================================================ ; 84 ; Commutativity tests. 85 ; ============================================================================ ; 86 87 declare i8 @gen8() 88 89 define i1 @c0() { 90 ; CHECK-LABEL: @c0( 91 ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() 92 ; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X]], 3 93 ; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[X]], [[TMP0]] 94 ; CHECK-NEXT: ret i1 [[RET]] 95 ; 96 %x = call i8 @gen8() 97 %tmp0 = and i8 %x, 3 98 %ret = icmp sge i8 %x, %tmp0 ; swapped order 99 ret i1 %ret 100 } 101 102 ; ============================================================================ ; 103 ; Commutativity tests with variable 104 ; ============================================================================ ; 105 106 ; Ok, this one should fold. We only testing commutativity of 'and'. 107 define i1 @cv0(i8 %y) { 108 ; CHECK-LABEL: @cv0( 109 ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() 110 ; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]] 111 ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]] 112 ; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[TMP1]], [[X]] 113 ; CHECK-NEXT: ret i1 [[RET]] 114 ; 115 %x = call i8 @gen8() 116 %tmp0 = lshr i8 -1, %y 117 %tmp1 = and i8 %x, %tmp0 ; swapped order 118 %ret = icmp sge i8 %tmp1, %x 119 ret i1 %ret 120 } 121 122 define i1 @cv1(i8 %y) { 123 ; CHECK-LABEL: @cv1( 124 ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() 125 ; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]] 126 ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X]] 127 ; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[X]], [[TMP1]] 128 ; CHECK-NEXT: ret i1 [[RET]] 129 ; 130 %x = call i8 @gen8() 131 %tmp0 = lshr i8 -1, %y 132 %tmp1 = and i8 %tmp0, %x 133 %ret = icmp sge i8 %x, %tmp1 ; swapped order 134 ret i1 %ret 135 } 136 137 define i1 @cv2(i8 %y) { 138 ; CHECK-LABEL: @cv2( 139 ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() 140 ; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]] 141 ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]] 142 ; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[X]], [[TMP1]] 143 ; CHECK-NEXT: ret i1 [[RET]] 144 ; 145 %x = call i8 @gen8() 146 %tmp0 = lshr i8 -1, %y 147 %tmp1 = and i8 %x, %tmp0 ; swapped order 148 %ret = icmp sge i8 %x, %tmp1 ; swapped order 149 ret i1 %ret 150 } 151 152 ; ============================================================================ ; 153 ; Normal negative tests 154 ; ============================================================================ ; 155 156 define i1 @n0(i8 %x) { 157 ; CHECK-LABEL: @n0( 158 ; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 4 159 ; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[TMP0]], [[X]] 160 ; CHECK-NEXT: ret i1 [[RET]] 161 ; 162 %tmp0 = and i8 %x, 4 ; power-of-two, but invalid. 163 %ret = icmp sge i8 %tmp0, %x 164 ret i1 %ret 165 } 166 167 define i1 @n1(i8 %x, i8 %y, i8 %notx) { 168 ; CHECK-LABEL: @n1( 169 ; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3 170 ; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[TMP0]], [[NOTX:%.*]] 171 ; CHECK-NEXT: ret i1 [[RET]] 172 ; 173 %tmp0 = and i8 %x, 3 174 %ret = icmp sge i8 %tmp0, %notx ; not %x 175 ret i1 %ret 176 } 177 178 define <2 x i1> @n2(<2 x i8> %x) { 179 ; CHECK-LABEL: @n2( 180 ; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 16> 181 ; CHECK-NEXT: [[RET:%.*]] = icmp sge <2 x i8> [[TMP0]], [[X]] 182 ; CHECK-NEXT: ret <2 x i1> [[RET]] 183 ; 184 %tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid. 185 %ret = icmp sge <2 x i8> %tmp0, %x 186 ret <2 x i1> %ret 187 } 188 189 ; ============================================================================ ; 190 ; Potential miscompiles. 191 ; ============================================================================ ; 192 193 define i1 @nv(i8 %x, i8 %y) { 194 ; CHECK-LABEL: @nv( 195 ; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]] 196 ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X:%.*]] 197 ; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[TMP1]], [[X]] 198 ; CHECK-NEXT: ret i1 [[RET]] 199 ; 200 %tmp0 = lshr i8 -1, %y 201 %tmp1 = and i8 %tmp0, %x 202 %ret = icmp sge i8 %tmp1, %x 203 ret i1 %ret 204 } 205 206 define <2 x i1> @n3_vec(<2 x i8> %x) { 207 ; CHECK-LABEL: @n3_vec( 208 ; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 -1> 209 ; CHECK-NEXT: [[RET:%.*]] = icmp sge <2 x i8> [[TMP0]], [[X]] 210 ; CHECK-NEXT: ret <2 x i1> [[RET]] 211 ; 212 %tmp0 = and <2 x i8> %x, <i8 3, i8 -1> 213 %ret = icmp sge <2 x i8> %tmp0, %x 214 ret <2 x i1> %ret 215 } 216 217 define <3 x i1> @n4_vec(<3 x i8> %x) { 218 ; CHECK-LABEL: @n4_vec( 219 ; CHECK-NEXT: [[TMP0:%.*]] = and <3 x i8> [[X:%.*]], <i8 3, i8 undef, i8 -1> 220 ; CHECK-NEXT: [[RET:%.*]] = icmp sge <3 x i8> [[TMP0]], [[X]] 221 ; CHECK-NEXT: ret <3 x i1> [[RET]] 222 ; 223 %tmp0 = and <3 x i8> %x, <i8 3, i8 undef, i8 -1> 224 %ret = icmp sge <3 x i8> %tmp0, %x 225 ret <3 x i1> %ret 226 } 227