1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -correlated-propagation -S | FileCheck %s 3 4target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 5 6define void @test0(i32 %n) { 7; CHECK-LABEL: @test0( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br label [[FOR_COND:%.*]] 10; CHECK: for.cond: 11; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[DIV1:%.*]], [[FOR_BODY:%.*]] ] 12; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[J_0]], 1 13; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 14; CHECK: for.body: 15; CHECK-NEXT: [[DIV1]] = udiv i32 [[J_0]], 2 16; CHECK-NEXT: br label [[FOR_COND]] 17; CHECK: for.end: 18; CHECK-NEXT: ret void 19; 20entry: 21 br label %for.cond 22 23for.cond: ; preds = %for.body, %entry 24 %j.0 = phi i32 [ %n, %entry ], [ %div, %for.body ] 25 %cmp = icmp sgt i32 %j.0, 1 26 br i1 %cmp, label %for.body, label %for.end 27 28for.body: ; preds = %for.cond 29 %div = sdiv i32 %j.0, 2 30 br label %for.cond 31 32for.end: ; preds = %for.cond 33 ret void 34} 35 36define void @test1(i32 %n) { 37; CHECK-LABEL: @test1( 38; CHECK-NEXT: entry: 39; CHECK-NEXT: br label [[FOR_COND:%.*]] 40; CHECK: for.cond: 41; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[DIV:%.*]], [[FOR_BODY:%.*]] ] 42; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[J_0]], -2 43; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 44; CHECK: for.body: 45; CHECK-NEXT: [[DIV]] = sdiv i32 [[J_0]], 2 46; CHECK-NEXT: br label [[FOR_COND]] 47; CHECK: for.end: 48; CHECK-NEXT: ret void 49; 50entry: 51 br label %for.cond 52 53for.cond: ; preds = %for.body, %entry 54 %j.0 = phi i32 [ %n, %entry ], [ %div, %for.body ] 55 %cmp = icmp sgt i32 %j.0, -2 56 br i1 %cmp, label %for.body, label %for.end 57 58for.body: ; preds = %for.cond 59 %div = sdiv i32 %j.0, 2 60 br label %for.cond 61 62for.end: ; preds = %for.cond 63 ret void 64} 65 66define void @test2(i32 %n) { 67; CHECK-LABEL: @test2( 68; CHECK-NEXT: entry: 69; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 1 70; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] 71; CHECK: bb: 72; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[N]], 2 73; CHECK-NEXT: br label [[EXIT]] 74; CHECK: exit: 75; CHECK-NEXT: ret void 76; 77entry: 78 %cmp = icmp sgt i32 %n, 1 79 br i1 %cmp, label %bb, label %exit 80 81bb: 82 %div = sdiv i32 %n, 2 83 br label %exit 84 85exit: 86 ret void 87} 88 89; looping case where loop has exactly one block 90; at the point of sdiv, we know that %a is always greater than 0, 91; because of the guard before it, so we can transform it to udiv. 92declare void @llvm.experimental.guard(i1,...) 93define void @test4(i32 %n) { 94; CHECK-LABEL: @test4( 95; CHECK-NEXT: entry: 96; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 0 97; CHECK-NEXT: br i1 [[CMP]], label [[LOOP:%.*]], label [[EXIT:%.*]] 98; CHECK: loop: 99; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[DIV1:%.*]], [[LOOP]] ] 100; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[A]], 4 101; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND]]) [ "deopt"() ] 102; CHECK-NEXT: [[DIV1]] = udiv i32 [[A]], 6 103; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT]] 104; CHECK: exit: 105; CHECK-NEXT: ret void 106; 107entry: 108 %cmp = icmp sgt i32 %n, 0 109 br i1 %cmp, label %loop, label %exit 110 111loop: 112 %a = phi i32 [ %n, %entry ], [ %div, %loop ] 113 %cond = icmp sgt i32 %a, 4 114 call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ] 115 %div = sdiv i32 %a, 6 116 br i1 %cond, label %loop, label %exit 117 118exit: 119 ret void 120} 121 122; same test as above with assume instead of guard. 123declare void @llvm.assume(i1) 124define void @test5(i32 %n) { 125; CHECK-LABEL: @test5( 126; CHECK-NEXT: entry: 127; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 0 128; CHECK-NEXT: br i1 [[CMP]], label [[LOOP:%.*]], label [[EXIT:%.*]] 129; CHECK: loop: 130; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[DIV1:%.*]], [[LOOP]] ] 131; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[A]], 4 132; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) 133; CHECK-NEXT: [[DIV1]] = udiv i32 [[A]], 6 134; CHECK-NEXT: [[LOOPCOND:%.*]] = icmp sgt i32 [[DIV1]], 8 135; CHECK-NEXT: br i1 [[LOOPCOND]], label [[LOOP]], label [[EXIT]] 136; CHECK: exit: 137; CHECK-NEXT: ret void 138; 139entry: 140 %cmp = icmp sgt i32 %n, 0 141 br i1 %cmp, label %loop, label %exit 142 143loop: 144 %a = phi i32 [ %n, %entry ], [ %div, %loop ] 145 %cond = icmp sgt i32 %a, 4 146 call void @llvm.assume(i1 %cond) 147 %div = sdiv i32 %a, 6 148 %loopcond = icmp sgt i32 %div, 8 149 br i1 %loopcond, label %loop, label %exit 150 151exit: 152 ret void 153} 154 155; Now, let's try various domain combinations for operands. 156 157define i32 @test6_pos_pos(i32 %x, i32 %y) { 158; CHECK-LABEL: @test6_pos_pos( 159; CHECK-NEXT: [[C0:%.*]] = icmp sge i32 [[X:%.*]], 0 160; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 161; CHECK-NEXT: [[C1:%.*]] = icmp sge i32 [[Y:%.*]], 0 162; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 163; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X]], [[Y]] 164; CHECK-NEXT: ret i32 [[DIV1]] 165; 166 %c0 = icmp sge i32 %x, 0 167 call void @llvm.assume(i1 %c0) 168 %c1 = icmp sge i32 %y, 0 169 call void @llvm.assume(i1 %c1) 170 171 %div = sdiv i32 %x, %y 172 ret i32 %div 173} 174define i32 @test7_pos_neg(i32 %x, i32 %y) { 175; CHECK-LABEL: @test7_pos_neg( 176; CHECK-NEXT: [[C0:%.*]] = icmp sge i32 [[X:%.*]], 0 177; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 178; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0 179; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 180; CHECK-NEXT: [[Y_NONNEG:%.*]] = sub i32 0, [[Y]] 181; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X]], [[Y_NONNEG]] 182; CHECK-NEXT: [[DIV1_NEG:%.*]] = sub i32 0, [[DIV1]] 183; CHECK-NEXT: ret i32 [[DIV1_NEG]] 184; 185 %c0 = icmp sge i32 %x, 0 186 call void @llvm.assume(i1 %c0) 187 %c1 = icmp sle i32 %y, 0 188 call void @llvm.assume(i1 %c1) 189 190 %div = sdiv i32 %x, %y 191 ret i32 %div 192} 193define i32 @test8_neg_pos(i32 %x, i32 %y) { 194; CHECK-LABEL: @test8_neg_pos( 195; CHECK-NEXT: [[C0:%.*]] = icmp sle i32 [[X:%.*]], 0 196; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 197; CHECK-NEXT: [[C1:%.*]] = icmp sge i32 [[Y:%.*]], 0 198; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 199; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i32 0, [[X]] 200; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X_NONNEG]], [[Y]] 201; CHECK-NEXT: [[DIV1_NEG:%.*]] = sub i32 0, [[DIV1]] 202; CHECK-NEXT: ret i32 [[DIV1_NEG]] 203; 204 %c0 = icmp sle i32 %x, 0 205 call void @llvm.assume(i1 %c0) 206 %c1 = icmp sge i32 %y, 0 207 call void @llvm.assume(i1 %c1) 208 209 %div = sdiv i32 %x, %y 210 ret i32 %div 211} 212define i32 @test9_neg_neg(i32 %x, i32 %y) { 213; CHECK-LABEL: @test9_neg_neg( 214; CHECK-NEXT: [[C0:%.*]] = icmp sle i32 [[X:%.*]], 0 215; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 216; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0 217; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 218; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i32 0, [[X]] 219; CHECK-NEXT: [[Y_NONNEG:%.*]] = sub i32 0, [[Y]] 220; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X_NONNEG]], [[Y_NONNEG]] 221; CHECK-NEXT: ret i32 [[DIV1]] 222; 223 %c0 = icmp sle i32 %x, 0 224 call void @llvm.assume(i1 %c0) 225 %c1 = icmp sle i32 %y, 0 226 call void @llvm.assume(i1 %c1) 227 228 %div = sdiv i32 %x, %y 229 ret i32 %div 230} 231 232; After making division unsigned, can we narrow it? 233define i32 @test10_narrow(i32 %x, i32 %y) { 234; CHECK-LABEL: @test10_narrow( 235; CHECK-NEXT: [[C0:%.*]] = icmp ult i32 [[X:%.*]], 128 236; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 237; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[Y:%.*]], 128 238; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 239; CHECK-NEXT: [[DIV1_LHS_TRUNC:%.*]] = trunc i32 [[X]] to i8 240; CHECK-NEXT: [[DIV1_RHS_TRUNC:%.*]] = trunc i32 [[Y]] to i8 241; CHECK-NEXT: [[DIV12:%.*]] = udiv i8 [[DIV1_LHS_TRUNC]], [[DIV1_RHS_TRUNC]] 242; CHECK-NEXT: [[DIV1_ZEXT:%.*]] = zext i8 [[DIV12]] to i32 243; CHECK-NEXT: ret i32 [[DIV1_ZEXT]] 244; 245 %c0 = icmp ult i32 %x, 128 246 call void @llvm.assume(i1 %c0) 247 %c1 = icmp ult i32 %y, 128 248 call void @llvm.assume(i1 %c1) 249 250 %div = sdiv i32 %x, %y 251 ret i32 %div 252} 253 254; Ok, but what about narrowing sdiv in general? 255 256; If both operands are i15, it's uncontroversial - we can truncate to i16 257define i64 @test11_i15_i15(i64 %x, i64 %y) { 258; CHECK-LABEL: @test11_i15_i15( 259; CHECK-NEXT: entry: 260; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 16383 261; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 262; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -16384 263; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 264; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 16383 265; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 266; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -16384 267; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 268; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16 269; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16 270; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 271; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64 272; CHECK-NEXT: ret i64 [[DIV_SEXT]] 273; 274entry: 275 %c0 = icmp sle i64 %x, 16383 276 call void @llvm.assume(i1 %c0) 277 %c1 = icmp sge i64 %x, -16384 278 call void @llvm.assume(i1 %c1) 279 280 %c2 = icmp sle i64 %y, 16383 281 call void @llvm.assume(i1 %c2) 282 %c3 = icmp sge i64 %y, -16384 283 call void @llvm.assume(i1 %c3) 284 285 %div = sdiv i64 %x, %y 286 ret i64 %div 287} 288 289; But if operands are i16, we can only truncate to i32, because we can't 290; rule out UB of i16 INT_MIN s/ i16 -1 291define i64 @test12_i16_i16(i64 %x, i64 %y) { 292; CHECK-LABEL: @test12_i16_i16( 293; CHECK-NEXT: entry: 294; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767 295; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 296; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768 297; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 298; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767 299; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 300; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768 301; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 302; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32 303; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32 304; CHECK-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 305; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64 306; CHECK-NEXT: ret i64 [[DIV_SEXT]] 307; 308entry: 309 %c0 = icmp sle i64 %x, 32767 310 call void @llvm.assume(i1 %c0) 311 %c1 = icmp sge i64 %x, -32768 312 call void @llvm.assume(i1 %c1) 313 314 %c2 = icmp sle i64 %y, 32767 315 call void @llvm.assume(i1 %c2) 316 %c3 = icmp sge i64 %y, -32768 317 call void @llvm.assume(i1 %c3) 318 319 %div = sdiv i64 %x, %y 320 ret i64 %div 321} 322 323; But if divident is i16, and divisor is u15, then we know that i16 is UB-safe. 324define i64 @test13_i16_u15(i64 %x, i64 %y) { 325; CHECK-LABEL: @test13_i16_u15( 326; CHECK-NEXT: entry: 327; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767 328; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 329; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768 330; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 331; CHECK-NEXT: [[C2:%.*]] = icmp ule i64 [[Y:%.*]], 32767 332; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 333; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16 334; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16 335; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 336; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64 337; CHECK-NEXT: ret i64 [[DIV_SEXT]] 338; 339entry: 340 %c0 = icmp sle i64 %x, 32767 341 call void @llvm.assume(i1 %c0) 342 %c1 = icmp sge i64 %x, -32768 343 call void @llvm.assume(i1 %c1) 344 345 %c2 = icmp ule i64 %y, 32767 346 call void @llvm.assume(i1 %c2) 347 348 %div = sdiv i64 %x, %y 349 ret i64 %div 350} 351 352; And likewise, if we know that if the divident is never i16 INT_MIN, 353; we can truncate to i16. 354define i64 @test14_i16safe_i16(i64 %x, i64 %y) { 355; CHECK-LABEL: @test14_i16safe_i16( 356; CHECK-NEXT: entry: 357; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767 358; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 359; CHECK-NEXT: [[C1:%.*]] = icmp sgt i64 [[X]], -32768 360; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 361; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767 362; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 363; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768 364; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 365; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16 366; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16 367; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 368; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64 369; CHECK-NEXT: ret i64 [[DIV_SEXT]] 370; 371entry: 372 %c0 = icmp sle i64 %x, 32767 373 call void @llvm.assume(i1 %c0) 374 %c1 = icmp sgt i64 %x, -32768 375 call void @llvm.assume(i1 %c1) 376 377 %c2 = icmp sle i64 %y, 32767 378 call void @llvm.assume(i1 %c2) 379 %c3 = icmp sge i64 %y, -32768 380 call void @llvm.assume(i1 %c3) 381 382 %div = sdiv i64 %x, %y 383 ret i64 %div 384} 385 386; Of course, both of the conditions can happen at once. 387define i64 @test15_i16safe_u15(i64 %x, i64 %y) { 388; CHECK-LABEL: @test15_i16safe_u15( 389; CHECK-NEXT: entry: 390; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767 391; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 392; CHECK-NEXT: [[C1:%.*]] = icmp sgt i64 [[X]], -32768 393; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 394; CHECK-NEXT: [[C2:%.*]] = icmp ule i64 [[Y:%.*]], 32767 395; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 396; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16 397; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16 398; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 399; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64 400; CHECK-NEXT: ret i64 [[DIV_SEXT]] 401; 402entry: 403 %c0 = icmp sle i64 %x, 32767 404 call void @llvm.assume(i1 %c0) 405 %c1 = icmp sgt i64 %x, -32768 406 call void @llvm.assume(i1 %c1) 407 408 %c2 = icmp ule i64 %y, 32767 409 call void @llvm.assume(i1 %c2) 410 411 %div = sdiv i64 %x, %y 412 ret i64 %div 413} 414 415; We at most truncate to i8 416define i64 @test16_i4_i4(i64 %x, i64 %y) { 417; CHECK-LABEL: @test16_i4_i4( 418; CHECK-NEXT: entry: 419; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 3 420; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 421; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -4 422; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 423; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 3 424; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 425; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -4 426; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 427; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i8 428; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i8 429; CHECK-NEXT: [[DIV1:%.*]] = sdiv i8 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 430; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i8 [[DIV1]] to i64 431; CHECK-NEXT: ret i64 [[DIV_SEXT]] 432; 433entry: 434 %c0 = icmp sle i64 %x, 3 435 call void @llvm.assume(i1 %c0) 436 %c1 = icmp sge i64 %x, -4 437 call void @llvm.assume(i1 %c1) 438 439 %c2 = icmp sle i64 %y, 3 440 call void @llvm.assume(i1 %c2) 441 %c3 = icmp sge i64 %y, -4 442 call void @llvm.assume(i1 %c3) 443 444 %div = sdiv i64 %x, %y 445 ret i64 %div 446} 447 448; And we round up to the powers of two 449define i64 @test17_i9_i9(i64 %x, i64 %y) { 450; CHECK-LABEL: @test17_i9_i9( 451; CHECK-NEXT: entry: 452; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 255 453; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 454; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -256 455; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 456; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 255 457; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 458; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -256 459; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 460; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16 461; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16 462; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 463; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64 464; CHECK-NEXT: ret i64 [[DIV_SEXT]] 465; 466entry: 467 %c0 = icmp sle i64 %x, 255 468 call void @llvm.assume(i1 %c0) 469 %c1 = icmp sge i64 %x, -256 470 call void @llvm.assume(i1 %c1) 471 472 %c2 = icmp sle i64 %y, 255 473 call void @llvm.assume(i1 %c2) 474 %c3 = icmp sge i64 %y, -256 475 call void @llvm.assume(i1 %c3) 476 477 %div = sdiv i64 %x, %y 478 ret i64 %div 479} 480 481; Don't widen the operation to the next power of two if it wasn't a power of two. 482define i9 @test18_i9_i9(i9 %x, i9 %y) { 483; CHECK-LABEL: @test18_i9_i9( 484; CHECK-NEXT: entry: 485; CHECK-NEXT: [[C0:%.*]] = icmp sle i9 [[X:%.*]], 255 486; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 487; CHECK-NEXT: [[C1:%.*]] = icmp sge i9 [[X]], -256 488; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 489; CHECK-NEXT: [[C2:%.*]] = icmp sle i9 [[Y:%.*]], 255 490; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 491; CHECK-NEXT: [[C3:%.*]] = icmp sge i9 [[Y]], -256 492; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 493; CHECK-NEXT: [[DIV:%.*]] = sdiv i9 [[X]], [[Y]] 494; CHECK-NEXT: ret i9 [[DIV]] 495; 496entry: 497 %c0 = icmp sle i9 %x, 255 498 call void @llvm.assume(i1 %c0) 499 %c1 = icmp sge i9 %x, -256 500 call void @llvm.assume(i1 %c1) 501 502 %c2 = icmp sle i9 %y, 255 503 call void @llvm.assume(i1 %c2) 504 %c3 = icmp sge i9 %y, -256 505 call void @llvm.assume(i1 %c3) 506 507 %div = sdiv i9 %x, %y 508 ret i9 %div 509} 510define i10 @test19_i10_i10(i10 %x, i10 %y) { 511; CHECK-LABEL: @test19_i10_i10( 512; CHECK-NEXT: entry: 513; CHECK-NEXT: [[C0:%.*]] = icmp sle i10 [[X:%.*]], 255 514; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 515; CHECK-NEXT: [[C1:%.*]] = icmp sge i10 [[X]], -256 516; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 517; CHECK-NEXT: [[C2:%.*]] = icmp sle i10 [[Y:%.*]], 255 518; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 519; CHECK-NEXT: [[C3:%.*]] = icmp sge i10 [[Y]], -256 520; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 521; CHECK-NEXT: [[DIV:%.*]] = sdiv i10 [[X]], [[Y]] 522; CHECK-NEXT: ret i10 [[DIV]] 523; 524entry: 525 %c0 = icmp sle i10 %x, 255 526 call void @llvm.assume(i1 %c0) 527 %c1 = icmp sge i10 %x, -256 528 call void @llvm.assume(i1 %c1) 529 530 %c2 = icmp sle i10 %y, 255 531 call void @llvm.assume(i1 %c2) 532 %c3 = icmp sge i10 %y, -256 533 call void @llvm.assume(i1 %c3) 534 535 %div = sdiv i10 %x, %y 536 ret i10 %div 537} 538 539; Note that we need to take the maximal bitwidth, in which both of the operands are representable! 540define i64 @test20_i16_i18(i64 %x, i64 %y) { 541; CHECK-LABEL: @test20_i16_i18( 542; CHECK-NEXT: entry: 543; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 16383 544; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 545; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -16384 546; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 547; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 65535 548; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 549; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -65536 550; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 551; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32 552; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32 553; CHECK-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 554; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64 555; CHECK-NEXT: ret i64 [[DIV_SEXT]] 556; 557entry: 558 %c0 = icmp sle i64 %x, 16383 559 call void @llvm.assume(i1 %c0) 560 %c1 = icmp sge i64 %x, -16384 561 call void @llvm.assume(i1 %c1) 562 563 %c2 = icmp sle i64 %y, 65535 564 call void @llvm.assume(i1 %c2) 565 %c3 = icmp sge i64 %y, -65536 566 call void @llvm.assume(i1 %c3) 567 568 %div = sdiv i64 %x, %y 569 ret i64 %div 570} 571define i64 @test21_i18_i16(i64 %x, i64 %y) { 572; CHECK-LABEL: @test21_i18_i16( 573; CHECK-NEXT: entry: 574; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 65535 575; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 576; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -65536 577; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 578; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 16383 579; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 580; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -16384 581; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 582; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32 583; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32 584; CHECK-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 585; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64 586; CHECK-NEXT: ret i64 [[DIV_SEXT]] 587; 588entry: 589 %c0 = icmp sle i64 %x, 65535 590 call void @llvm.assume(i1 %c0) 591 %c1 = icmp sge i64 %x, -65536 592 call void @llvm.assume(i1 %c1) 593 594 %c2 = icmp sle i64 %y, 16383 595 call void @llvm.assume(i1 %c2) 596 %c3 = icmp sge i64 %y, -16384 597 call void @llvm.assume(i1 %c3) 598 599 %div = sdiv i64 %x, %y 600 ret i64 %div 601} 602 603; Ensure that we preserve exact-ness 604define i64 @test22_i16_i16(i64 %x, i64 %y) { 605; CHECK-LABEL: @test22_i16_i16( 606; CHECK-NEXT: entry: 607; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767 608; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) 609; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768 610; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) 611; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767 612; CHECK-NEXT: call void @llvm.assume(i1 [[C2]]) 613; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768 614; CHECK-NEXT: call void @llvm.assume(i1 [[C3]]) 615; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32 616; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32 617; CHECK-NEXT: [[DIV1:%.*]] = sdiv exact i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]] 618; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64 619; CHECK-NEXT: ret i64 [[DIV_SEXT]] 620; 621entry: 622 %c0 = icmp sle i64 %x, 32767 623 call void @llvm.assume(i1 %c0) 624 %c1 = icmp sge i64 %x, -32768 625 call void @llvm.assume(i1 %c1) 626 627 %c2 = icmp sle i64 %y, 32767 628 call void @llvm.assume(i1 %c2) 629 %c3 = icmp sge i64 %y, -32768 630 call void @llvm.assume(i1 %c3) 631 632 %div = sdiv exact i64 %x, %y 633 ret i64 %div 634} 635