1 ; This test makes sure that rem instructions are properly eliminated. 2 ; 3 ; RUN: opt < %s -instcombine -S | FileCheck %s 4 ; END. 5 6 define i32 @test1(i32 %A) { 7 ; CHECK-LABEL: @test1( 8 ; CHECK-NEXT: ret i32 0 9 %B = srem i32 %A, 1 ; ISA constant 0 10 ret i32 %B 11 } 12 13 define i32 @test2(i32 %A) { ; 0 % X = 0, we don't need to preserve traps 14 ; CHECK-LABEL: @test2( 15 ; CHECK-NEXT: ret i32 0 16 %B = srem i32 0, %A 17 ret i32 %B 18 } 19 20 define i32 @test3(i32 %A) { 21 ; CHECK-LABEL: @test3( 22 ; CHECK-NEXT: [[AND:%.*]] = and i32 %A, 7 23 ; CHECK-NEXT: ret i32 [[AND]] 24 %B = urem i32 %A, 8 25 ret i32 %B 26 } 27 28 define <2 x i32> @vec_power_of_2_constant_splat_divisor(<2 x i32> %A) { 29 ; CHECK-LABEL: @vec_power_of_2_constant_splat_divisor( 30 ; CHECK-NEXT: [[B:%.*]] = and <2 x i32> %A, <i32 7, i32 7> 31 ; CHECK-NEXT: ret <2 x i32> [[B]] 32 ; 33 %B = urem <2 x i32> %A, <i32 8, i32 8> 34 ret <2 x i32> %B 35 } 36 37 define <2 x i19> @weird_vec_power_of_2_constant_splat_divisor(<2 x i19> %A) { 38 ; CHECK-LABEL: @weird_vec_power_of_2_constant_splat_divisor( 39 ; CHECK-NEXT: [[B:%.*]] = and <2 x i19> %A, <i19 7, i19 7> 40 ; CHECK-NEXT: ret <2 x i19> [[B]] 41 ; 42 %B = urem <2 x i19> %A, <i19 8, i19 8> 43 ret <2 x i19> %B 44 } 45 46 define i1 @test3a(i32 %A) { 47 ; CHECK-LABEL: @test3a( 48 ; CHECK-NEXT: [[AND:%.*]] = and i32 %A, 7 49 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0 50 ; CHECK-NEXT: ret i1 [[CMP]] 51 %B = srem i32 %A, -8 52 %C = icmp ne i32 %B, 0 53 ret i1 %C 54 } 55 56 define i32 @test4(i32 %X, i1 %C) { 57 ; CHECK-LABEL: @test4( 58 ; CHECK-NEXT: [[SEL:%.*]] = select i1 %C, i32 0, i32 7 59 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SEL]], %X 60 %V = select i1 %C, i32 1, i32 8 61 %R = urem i32 %X, %V 62 ret i32 %R 63 } 64 65 define i32 @test5(i32 %X, i8 %B) { 66 ; CHECK-LABEL: @test5( 67 ; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 %B to i32 68 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 32, [[ZEXT]] 69 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], -1 70 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], %X 71 ; CHECK-NEXT: ret i32 [[AND]] 72 %shift.upgrd.1 = zext i8 %B to i32 73 %Amt = shl i32 32, %shift.upgrd.1 74 %V = urem i32 %X, %Amt 75 ret i32 %V 76 } 77 78 define i32 @test6(i32 %A) { 79 ; CHECK-LABEL: @test6( 80 ; CHECK-NEXT: ret i32 undef 81 %B = srem i32 %A, 0 ;; undef 82 ret i32 %B 83 } 84 85 define i32 @test7(i32 %A) { 86 ; CHECK-LABEL: @test7( 87 ; CHECK-NEXT: ret i32 0 88 %B = mul i32 %A, 8 89 %C = srem i32 %B, 4 90 ret i32 %C 91 } 92 93 define i32 @test8(i32 %A) { 94 ; CHECK-LABEL: @test8( 95 ; CHECK-NEXT: ret i32 0 96 %B = shl i32 %A, 4 97 %C = srem i32 %B, 8 98 ret i32 %C 99 } 100 101 define i32 @test9(i32 %A) { 102 ; CHECK-LABEL: @test9( 103 ; CHECK-NEXT: ret i32 0 104 %B = mul i32 %A, 64 105 %C = urem i32 %B, 32 106 ret i32 %C 107 } 108 109 define i32 @test10(i8 %c) { 110 ; CHECK-LABEL: @test10( 111 ; CHECK-NEXT: ret i32 0 112 %tmp.1 = zext i8 %c to i32 113 %tmp.2 = mul i32 %tmp.1, 4 114 %tmp.3 = sext i32 %tmp.2 to i64 115 %tmp.5 = urem i64 %tmp.3, 4 116 %tmp.6 = trunc i64 %tmp.5 to i32 117 ret i32 %tmp.6 118 } 119 120 define i32 @test11(i32 %i) { 121 ; CHECK-LABEL: @test11( 122 ; CHECK-NEXT: ret i32 0 123 %tmp.1 = and i32 %i, -2 124 %tmp.3 = mul i32 %tmp.1, 2 125 %tmp.5 = urem i32 %tmp.3, 4 126 ret i32 %tmp.5 127 } 128 129 define i32 @test12(i32 %i) { 130 ; CHECK-LABEL: @test12( 131 ; CHECK-NEXT: ret i32 0 132 %tmp.1 = and i32 %i, -4 133 %tmp.5 = srem i32 %tmp.1, 2 134 ret i32 %tmp.5 135 } 136 137 define i32 @test13(i32 %i) { 138 ; CHECK-LABEL: @test13( 139 ; CHECK-NEXT: ret i32 0 140 %x = srem i32 %i, %i 141 ret i32 %x 142 } 143 144 define i64 @test14(i64 %x, i32 %y) { 145 ; CHECK-LABEL: @test14( 146 ; CHECK-NEXT: [[SHL:%.*]] = shl i32 1, %y 147 ; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[SHL]] to i64 148 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[ZEXT]], -1 149 ; CHECK-NEXT: [[AND:%.*]] = and i64 [[ADD]], %x 150 ; CHECK-NEXT: ret i64 [[AND]] 151 %shl = shl i32 1, %y 152 %zext = zext i32 %shl to i64 153 %urem = urem i64 %x, %zext 154 ret i64 %urem 155 } 156 157 define i64 @test15(i32 %x, i32 %y) { 158 ; CHECK-LABEL: @test15( 159 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, %y 160 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SHL]], -1 161 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], %x 162 ; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[AND]] to i64 163 ; CHECK-NEXT: ret i64 [[ZEXT]] 164 %shl = shl i32 1, %y 165 %zext0 = zext i32 %shl to i64 166 %zext1 = zext i32 %x to i64 167 %urem = urem i64 %zext1, %zext0 168 ret i64 %urem 169 } 170 171 define i32 @test16(i32 %x, i32 %y) { 172 ; CHECK-LABEL: @test16( 173 ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 %y, 11 174 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHR]], 4 175 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], 3 176 ; CHECK-NEXT: [[REM:%.*]] = and i32 [[OR]], %x 177 ; CHECK-NEXT: ret i32 [[REM]] 178 %shr = lshr i32 %y, 11 179 %and = and i32 %shr, 4 180 %add = add i32 %and, 4 181 %rem = urem i32 %x, %add 182 ret i32 %rem 183 } 184 185 define i32 @test17(i32 %X) { 186 ; CHECK-LABEL: @test17( 187 ; CHECK-NEXT: icmp ne i32 %X, 1 188 ; CHECK-NEXT: zext i1 189 ; CHECK-NEXT: ret 190 %A = urem i32 1, %X 191 ret i32 %A 192 } 193 194 define i32 @test18(i16 %x, i32 %y) { 195 ; CHECK: @test18 196 ; CHECK-NEXT: [[AND:%.*]] = and i16 %x, 4 197 ; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[AND]] to i32 198 ; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[EXT]], 3 199 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHL]], 63 200 ; CHECK-NEXT: [[REM:%.*]] = and i32 [[XOR]], %y 201 ; CHECK-NEXT: ret i32 [[REM]] 202 %1 = and i16 %x, 4 203 %2 = icmp ne i16 %1, 0 204 %3 = select i1 %2, i32 32, i32 64 205 %4 = urem i32 %y, %3 206 ret i32 %4 207 } 208 209 define i32 @test19(i32 %x, i32 %y) { 210 ; CHECK: @test19 211 ; CHECK-NEXT: [[SHL1:%.*]] = shl i32 1, %x 212 ; CHECK-NEXT: [[SHL2:%.*]] = shl i32 1, %y 213 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHL1]], [[SHL2]] 214 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[AND]], [[SHL1]] 215 ; CHECK-NEXT: [[SUB:%.*]] = add i32 [[ADD]], -1 216 ; CHECK-NEXT: [[REM:%.*]] = and i32 [[SUB]], %y 217 ; CHECK-NEXT: ret i32 [[REM]] 218 %A = shl i32 1, %x 219 %B = shl i32 1, %y 220 %C = and i32 %A, %B 221 %D = add i32 %C, %A 222 %E = urem i32 %y, %D 223 ret i32 %E 224 } 225 226 define <2 x i64> @test20(<2 x i64> %X, <2 x i1> %C) { 227 ; CHECK-LABEL: @test20( 228 ; CHECK-NEXT: select <2 x i1> %C, <2 x i64> <i64 1, i64 2>, <2 x i64> zeroinitializer 229 ; CHECK-NEXT: ret <2 x i64> 230 %V = select <2 x i1> %C, <2 x i64> <i64 1, i64 2>, <2 x i64> <i64 8, i64 9> 231 %R = urem <2 x i64> %V, <i64 2, i64 3> 232 ret <2 x i64> %R 233 } 234 235 define i32 @test21(i1 %c0, i32* %val) { 236 ; CHECK-LABEL: @test21( 237 entry: 238 br i1 %c0, label %if.then, label %if.end 239 240 if.then: 241 ; CHECK: if.then: 242 ; CHECK-NEXT: %v = load volatile i32, i32* %val, align 4 243 ; CHECK-NEXT: %phitmp = srem i32 %v, 5 244 245 %v = load volatile i32, i32* %val 246 br label %if.end 247 248 if.end: 249 ; CHECK: if.end: 250 ; CHECK-NEXT: %lhs = phi i32 [ %phitmp, %if.then ], [ 0, %entry ] 251 ; CHECK-NEXT: ret i32 %lhs 252 253 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 254 %rem = srem i32 %lhs, 5 255 ret i32 %rem 256 } 257 258 @a = common global [5 x i16] zeroinitializer, align 2 259 @b = common global i16 0, align 2 260 261 define i32 @pr27968_0(i1 %c0, i32* %val) { 262 ; CHECK-LABEL: @pr27968_0( 263 entry: 264 br i1 %c0, label %if.then, label %if.end 265 266 if.then: 267 %v = load volatile i32, i32* %val 268 br label %if.end 269 270 ; CHECK: if.then: 271 ; CHECK-NOT: srem 272 ; CHECK: br label %if.end 273 274 if.end: 275 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 276 br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label %rem.is.safe, label %rem.is.unsafe 277 278 rem.is.safe: 279 ; CHECK: rem.is.safe: 280 ; CHECK-NEXT: %rem = srem i32 %lhs, zext (i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b) to i32) 281 ; CHECK-NEXT: ret i32 %rem 282 283 %rem = srem i32 %lhs, zext (i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b) to i32) 284 ret i32 %rem 285 286 rem.is.unsafe: 287 ret i32 0 288 } 289 290 define i32 @pr27968_1(i1 %c0, i1 %always_false, i32* %val) { 291 ; CHECK-LABEL: @pr27968_1( 292 entry: 293 br i1 %c0, label %if.then, label %if.end 294 295 if.then: 296 %v = load volatile i32, i32* %val 297 br label %if.end 298 299 ; CHECK: if.then: 300 ; CHECK-NOT: srem 301 ; CHECK: br label %if.end 302 303 if.end: 304 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 305 br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe 306 307 rem.is.safe: 308 %rem = srem i32 %lhs, -2147483648 309 ret i32 %rem 310 311 ; CHECK: rem.is.safe: 312 ; CHECK-NEXT: %rem = srem i32 %lhs, -2147483648 313 ; CHECK-NEXT: ret i32 %rem 314 315 rem.is.unsafe: 316 ret i32 0 317 } 318 319 define i32 @pr27968_2(i1 %c0, i32* %val) { 320 ; CHECK-LABEL: @pr27968_2( 321 entry: 322 br i1 %c0, label %if.then, label %if.end 323 324 if.then: 325 %v = load volatile i32, i32* %val 326 br label %if.end 327 328 ; CHECK: if.then: 329 ; CHECK-NOT: urem 330 ; CHECK: br label %if.end 331 332 if.end: 333 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 334 br i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b), label %rem.is.safe, label %rem.is.unsafe 335 336 rem.is.safe: 337 ; CHECK: rem.is.safe: 338 ; CHECK-NEXT: %rem = urem i32 %lhs, zext (i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b) to i32) 339 ; CHECK-NEXT: ret i32 %rem 340 341 %rem = urem i32 %lhs, zext (i1 icmp eq (i16* getelementptr inbounds ([5 x i16], [5 x i16]* @a, i64 0, i64 4), i16* @b) to i32) 342 ret i32 %rem 343 344 rem.is.unsafe: 345 ret i32 0 346 } 347 348 define i32 @pr27968_3(i1 %c0, i1 %always_false, i32* %val) { 349 ; CHECK-LABEL: @pr27968_3( 350 entry: 351 br i1 %c0, label %if.then, label %if.end 352 353 if.then: 354 %v = load volatile i32, i32* %val 355 br label %if.end 356 357 ; CHECK: if.then: 358 ; CHECK-NEXT: %v = load volatile i32, i32* %val, align 4 359 ; CHECK-NEXT: %phitmp = and i32 %v, 2147483647 360 ; CHECK-NEXT: br label %if.end 361 362 if.end: 363 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 364 br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe 365 366 rem.is.safe: 367 %rem = urem i32 %lhs, -2147483648 368 ret i32 %rem 369 370 rem.is.unsafe: 371 ret i32 0 372 } 373