1; This test makes sure that rem instructions are properly eliminated. 2; 3; RUN: opt < %s -instcombine -S | FileCheck %s 4; END. 5 6define 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 13define 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 20define 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 28define <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 37define <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 46define 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 56define 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 65define 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 78define 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 85define 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 93define 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 101define 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 109define 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 120define 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 129define 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 137define 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 144define 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 157define 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 171define 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 185define 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 194define 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 209define 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 226define <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 235define i32 @test21(i1 %c0, i32* %val) { 236; CHECK-LABEL: @test21( 237entry: 238 br i1 %c0, label %if.then, label %if.end 239 240if.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 248if.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 261define i32 @pr27968_0(i1 %c0, i32* %val) { 262; CHECK-LABEL: @pr27968_0( 263entry: 264 br i1 %c0, label %if.then, label %if.end 265 266if.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 274if.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 278rem.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 286rem.is.unsafe: 287 ret i32 0 288} 289 290define i32 @pr27968_1(i1 %c0, i1 %always_false, i32* %val) { 291; CHECK-LABEL: @pr27968_1( 292entry: 293 br i1 %c0, label %if.then, label %if.end 294 295if.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 303if.end: 304 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 305 br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe 306 307rem.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 315rem.is.unsafe: 316 ret i32 0 317} 318 319define i32 @pr27968_2(i1 %c0, i32* %val) { 320; CHECK-LABEL: @pr27968_2( 321entry: 322 br i1 %c0, label %if.then, label %if.end 323 324if.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 332if.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 336rem.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 344rem.is.unsafe: 345 ret i32 0 346} 347 348define i32 @pr27968_3(i1 %c0, i1 %always_false, i32* %val) { 349; CHECK-LABEL: @pr27968_3( 350entry: 351 br i1 %c0, label %if.then, label %if.end 352 353if.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 362if.end: 363 %lhs = phi i32 [ %v, %if.then ], [ 5, %entry ] 364 br i1 %always_false, label %rem.is.safe, label %rem.is.unsafe 365 366rem.is.safe: 367 %rem = urem i32 %lhs, -2147483648 368 ret i32 %rem 369 370rem.is.unsafe: 371 ret i32 0 372} 373