702 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s3 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]], 113; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]14; CHECK: for.body:15; CHECK-NEXT: [[DIV1]] = udiv i32 [[J_0]], 216; CHECK-NEXT: br label [[FOR_COND]]17; CHECK: for.end:18; CHECK-NEXT: ret void19;20entry:21 br label %for.cond22 23for.cond: ; preds = %for.body, %entry24 %j.0 = phi i32 [ %n, %entry ], [ %div, %for.body ]25 %cmp = icmp sgt i32 %j.0, 126 br i1 %cmp, label %for.body, label %for.end27 28for.body: ; preds = %for.cond29 %div = sdiv i32 %j.0, 230 br label %for.cond31 32for.end: ; preds = %for.cond33 ret void34}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]], -243; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]44; CHECK: for.body:45; CHECK-NEXT: [[DIV]] = sdiv i32 [[J_0]], 246; CHECK-NEXT: br label [[FOR_COND]]47; CHECK: for.end:48; CHECK-NEXT: ret void49;50entry:51 br label %for.cond52 53for.cond: ; preds = %for.body, %entry54 %j.0 = phi i32 [ %n, %entry ], [ %div, %for.body ]55 %cmp = icmp sgt i32 %j.0, -256 br i1 %cmp, label %for.body, label %for.end57 58for.body: ; preds = %for.cond59 %div = sdiv i32 %j.0, 260 br label %for.cond61 62for.end: ; preds = %for.cond63 ret void64}65 66define void @test2(i32 %n) {67; CHECK-LABEL: @test2(68; CHECK-NEXT: entry:69; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 170; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]]71; CHECK: bb:72; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[N]], 273; CHECK-NEXT: br label [[EXIT]]74; CHECK: exit:75; CHECK-NEXT: ret void76;77entry:78 %cmp = icmp sgt i32 %n, 179 br i1 %cmp, label %bb, label %exit80 81bb:82 %div = sdiv i32 %n, 283 br label %exit84 85exit:86 ret void87}88 89; looping case where loop has exactly one block90; 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:%.*]], 097; 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]], 4101; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND]]) [ "deopt"() ]102; CHECK-NEXT: [[DIV1]] = udiv i32 [[A]], 6103; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT]]104; CHECK: exit:105; CHECK-NEXT: ret void106;107entry:108 %cmp = icmp sgt i32 %n, 0109 br i1 %cmp, label %loop, label %exit110 111loop:112 %a = phi i32 [ %n, %entry ], [ %div, %loop ]113 %cond = icmp sgt i32 %a, 4114 call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]115 %div = sdiv i32 %a, 6116 br i1 %cond, label %loop, label %exit117 118exit:119 ret void120}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:%.*]], 0128; 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 samesign ugt i32 [[A]], 4132; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])133; CHECK-NEXT: [[DIV1]] = udiv i32 [[A]], 6134; CHECK-NEXT: [[LOOPCOND:%.*]] = icmp samesign ugt i32 [[DIV1]], 8135; CHECK-NEXT: br i1 [[LOOPCOND]], label [[LOOP]], label [[EXIT]]136; CHECK: exit:137; CHECK-NEXT: ret void138;139entry:140 %cmp = icmp sgt i32 %n, 0141 br i1 %cmp, label %loop, label %exit142 143loop:144 %a = phi i32 [ %n, %entry ], [ %div, %loop ]145 %cond = icmp sgt i32 %a, 4146 call void @llvm.assume(i1 %cond)147 %div = sdiv i32 %a, 6148 %loopcond = icmp sgt i32 %div, 8149 br i1 %loopcond, label %loop, label %exit150 151exit:152 ret void153}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:%.*]], 0160; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])161; CHECK-NEXT: [[C1:%.*]] = icmp sge i32 [[Y:%.*]], 0162; 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, 0167 call void @llvm.assume(i1 %c0)168 %c1 = icmp sge i32 %y, 0169 call void @llvm.assume(i1 %c1)170 171 %div = sdiv i32 %x, %y172 ret i32 %div173}174define i32 @test7_pos_neg(i32 %x, i32 %y) {175; CHECK-LABEL: @test7_pos_neg(176; CHECK-NEXT: [[C0:%.*]] = icmp sge i32 [[X:%.*]], 0177; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])178; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0179; 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, 0186 call void @llvm.assume(i1 %c0)187 %c1 = icmp sle i32 %y, 0188 call void @llvm.assume(i1 %c1)189 190 %div = sdiv i32 %x, %y191 ret i32 %div192}193define i32 @test8_neg_pos(i32 %x, i32 %y) {194; CHECK-LABEL: @test8_neg_pos(195; CHECK-NEXT: [[C0:%.*]] = icmp sle i32 [[X:%.*]], 0196; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])197; CHECK-NEXT: [[C1:%.*]] = icmp sge i32 [[Y:%.*]], 0198; 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, 0205 call void @llvm.assume(i1 %c0)206 %c1 = icmp sge i32 %y, 0207 call void @llvm.assume(i1 %c1)208 209 %div = sdiv i32 %x, %y210 ret i32 %div211}212define i32 @test9_neg_neg(i32 %x, i32 %y) {213; CHECK-LABEL: @test9_neg_neg(214; CHECK-NEXT: [[C0:%.*]] = icmp sle i32 [[X:%.*]], 0215; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])216; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0217; 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, 0224 call void @llvm.assume(i1 %c0)225 %c1 = icmp sle i32 %y, 0226 call void @llvm.assume(i1 %c1)227 228 %div = sdiv i32 %x, %y229 ret i32 %div230}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:%.*]], 128236; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])237; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[Y:%.*]], 128238; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])239; CHECK-NEXT: [[DIV1_LHS_TRUNC:%.*]] = trunc i32 [[X]] to i8240; CHECK-NEXT: [[DIV1_RHS_TRUNC:%.*]] = trunc i32 [[Y]] to i8241; CHECK-NEXT: [[DIV12:%.*]] = udiv i8 [[DIV1_LHS_TRUNC]], [[DIV1_RHS_TRUNC]]242; CHECK-NEXT: [[DIV1_ZEXT:%.*]] = zext i8 [[DIV12]] to i32243; CHECK-NEXT: ret i32 [[DIV1_ZEXT]]244;245 %c0 = icmp ult i32 %x, 128246 call void @llvm.assume(i1 %c0)247 %c1 = icmp ult i32 %y, 128248 call void @llvm.assume(i1 %c1)249 250 %div = sdiv i32 %x, %y251 ret i32 %div252}253 254; Ok, but what about narrowing sdiv in general?255 256; If both operands are i15, it's uncontroversial - we can truncate to i16257define 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:%.*]], 16383261; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])262; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -16384263; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])264; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 16383265; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])266; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -16384267; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])268; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16269; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16270; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]271; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64272; CHECK-NEXT: ret i64 [[DIV_SEXT]]273;274entry:275 %c0 = icmp sle i64 %x, 16383276 call void @llvm.assume(i1 %c0)277 %c1 = icmp sge i64 %x, -16384278 call void @llvm.assume(i1 %c1)279 280 %c2 = icmp sle i64 %y, 16383281 call void @llvm.assume(i1 %c2)282 %c3 = icmp sge i64 %y, -16384283 call void @llvm.assume(i1 %c3)284 285 %div = sdiv i64 %x, %y286 ret i64 %div287}288 289; But if operands are i16, we can only truncate to i32, because we can't290; rule out UB of i16 INT_MIN s/ i16 -1291define 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:%.*]], 32767295; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])296; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768297; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])298; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767299; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])300; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768301; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])302; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32303; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32304; CHECK-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]305; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64306; CHECK-NEXT: ret i64 [[DIV_SEXT]]307;308entry:309 %c0 = icmp sle i64 %x, 32767310 call void @llvm.assume(i1 %c0)311 %c1 = icmp sge i64 %x, -32768312 call void @llvm.assume(i1 %c1)313 314 %c2 = icmp sle i64 %y, 32767315 call void @llvm.assume(i1 %c2)316 %c3 = icmp sge i64 %y, -32768317 call void @llvm.assume(i1 %c3)318 319 %div = sdiv i64 %x, %y320 ret i64 %div321}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:%.*]], 32767328; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])329; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768330; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])331; CHECK-NEXT: [[C2:%.*]] = icmp ule i64 [[Y:%.*]], 32767332; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])333; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16334; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16335; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]336; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64337; CHECK-NEXT: ret i64 [[DIV_SEXT]]338;339entry:340 %c0 = icmp sle i64 %x, 32767341 call void @llvm.assume(i1 %c0)342 %c1 = icmp sge i64 %x, -32768343 call void @llvm.assume(i1 %c1)344 345 %c2 = icmp ule i64 %y, 32767346 call void @llvm.assume(i1 %c2)347 348 %div = sdiv i64 %x, %y349 ret i64 %div350}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:%.*]], 32767358; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])359; CHECK-NEXT: [[C1:%.*]] = icmp sgt i64 [[X]], -32768360; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])361; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767362; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])363; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768364; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])365; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16366; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16367; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]368; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64369; CHECK-NEXT: ret i64 [[DIV_SEXT]]370;371entry:372 %c0 = icmp sle i64 %x, 32767373 call void @llvm.assume(i1 %c0)374 %c1 = icmp sgt i64 %x, -32768375 call void @llvm.assume(i1 %c1)376 377 %c2 = icmp sle i64 %y, 32767378 call void @llvm.assume(i1 %c2)379 %c3 = icmp sge i64 %y, -32768380 call void @llvm.assume(i1 %c3)381 382 %div = sdiv i64 %x, %y383 ret i64 %div384}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:%.*]], 32767391; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])392; CHECK-NEXT: [[C1:%.*]] = icmp sgt i64 [[X]], -32768393; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])394; CHECK-NEXT: [[C2:%.*]] = icmp ule i64 [[Y:%.*]], 32767395; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])396; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16397; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16398; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]399; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64400; CHECK-NEXT: ret i64 [[DIV_SEXT]]401;402entry:403 %c0 = icmp sle i64 %x, 32767404 call void @llvm.assume(i1 %c0)405 %c1 = icmp sgt i64 %x, -32768406 call void @llvm.assume(i1 %c1)407 408 %c2 = icmp ule i64 %y, 32767409 call void @llvm.assume(i1 %c2)410 411 %div = sdiv i64 %x, %y412 ret i64 %div413}414 415; We at most truncate to i8416define 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:%.*]], 3420; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])421; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -4422; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])423; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 3424; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])425; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -4426; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])427; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i8428; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i8429; CHECK-NEXT: [[DIV1:%.*]] = sdiv i8 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]430; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i8 [[DIV1]] to i64431; CHECK-NEXT: ret i64 [[DIV_SEXT]]432;433entry:434 %c0 = icmp sle i64 %x, 3435 call void @llvm.assume(i1 %c0)436 %c1 = icmp sge i64 %x, -4437 call void @llvm.assume(i1 %c1)438 439 %c2 = icmp sle i64 %y, 3440 call void @llvm.assume(i1 %c2)441 %c3 = icmp sge i64 %y, -4442 call void @llvm.assume(i1 %c3)443 444 %div = sdiv i64 %x, %y445 ret i64 %div446}447 448; And we round up to the powers of two449define 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:%.*]], 255453; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])454; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -256455; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])456; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 255457; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])458; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -256459; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])460; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16461; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16462; CHECK-NEXT: [[DIV1:%.*]] = sdiv i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]463; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64464; CHECK-NEXT: ret i64 [[DIV_SEXT]]465;466entry:467 %c0 = icmp sle i64 %x, 255468 call void @llvm.assume(i1 %c0)469 %c1 = icmp sge i64 %x, -256470 call void @llvm.assume(i1 %c1)471 472 %c2 = icmp sle i64 %y, 255473 call void @llvm.assume(i1 %c2)474 %c3 = icmp sge i64 %y, -256475 call void @llvm.assume(i1 %c3)476 477 %div = sdiv i64 %x, %y478 ret i64 %div479}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:%.*]], 255486; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])487; CHECK-NEXT: [[C1:%.*]] = icmp sge i9 [[X]], -256488; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])489; CHECK-NEXT: [[C2:%.*]] = icmp sle i9 [[Y:%.*]], 255490; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])491; CHECK-NEXT: [[C3:%.*]] = icmp sge i9 [[Y]], -256492; 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, 255498 call void @llvm.assume(i1 %c0)499 %c1 = icmp sge i9 %x, -256500 call void @llvm.assume(i1 %c1)501 502 %c2 = icmp sle i9 %y, 255503 call void @llvm.assume(i1 %c2)504 %c3 = icmp sge i9 %y, -256505 call void @llvm.assume(i1 %c3)506 507 %div = sdiv i9 %x, %y508 ret i9 %div509}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:%.*]], 255514; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])515; CHECK-NEXT: [[C1:%.*]] = icmp sge i10 [[X]], -256516; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])517; CHECK-NEXT: [[C2:%.*]] = icmp sle i10 [[Y:%.*]], 255518; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])519; CHECK-NEXT: [[C3:%.*]] = icmp sge i10 [[Y]], -256520; 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, 255526 call void @llvm.assume(i1 %c0)527 %c1 = icmp sge i10 %x, -256528 call void @llvm.assume(i1 %c1)529 530 %c2 = icmp sle i10 %y, 255531 call void @llvm.assume(i1 %c2)532 %c3 = icmp sge i10 %y, -256533 call void @llvm.assume(i1 %c3)534 535 %div = sdiv i10 %x, %y536 ret i10 %div537}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:%.*]], 16383544; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])545; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -16384546; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])547; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 65535548; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])549; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -65536550; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])551; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32552; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32553; CHECK-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]554; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64555; CHECK-NEXT: ret i64 [[DIV_SEXT]]556;557entry:558 %c0 = icmp sle i64 %x, 16383559 call void @llvm.assume(i1 %c0)560 %c1 = icmp sge i64 %x, -16384561 call void @llvm.assume(i1 %c1)562 563 %c2 = icmp sle i64 %y, 65535564 call void @llvm.assume(i1 %c2)565 %c3 = icmp sge i64 %y, -65536566 call void @llvm.assume(i1 %c3)567 568 %div = sdiv i64 %x, %y569 ret i64 %div570}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:%.*]], 65535575; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])576; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -65536577; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])578; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 16383579; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])580; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -16384581; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])582; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32583; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32584; CHECK-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]585; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64586; CHECK-NEXT: ret i64 [[DIV_SEXT]]587;588entry:589 %c0 = icmp sle i64 %x, 65535590 call void @llvm.assume(i1 %c0)591 %c1 = icmp sge i64 %x, -65536592 call void @llvm.assume(i1 %c1)593 594 %c2 = icmp sle i64 %y, 16383595 call void @llvm.assume(i1 %c2)596 %c3 = icmp sge i64 %y, -16384597 call void @llvm.assume(i1 %c3)598 599 %div = sdiv i64 %x, %y600 ret i64 %div601}602 603; Ensure that we preserve exact-ness604define 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:%.*]], 32767608; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])609; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768610; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])611; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767612; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])613; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768614; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])615; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32616; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32617; CHECK-NEXT: [[DIV1:%.*]] = sdiv exact i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]618; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64619; CHECK-NEXT: ret i64 [[DIV_SEXT]]620;621entry:622 %c0 = icmp sle i64 %x, 32767623 call void @llvm.assume(i1 %c0)624 %c1 = icmp sge i64 %x, -32768625 call void @llvm.assume(i1 %c1)626 627 %c2 = icmp sle i64 %y, 32767628 call void @llvm.assume(i1 %c2)629 %c3 = icmp sge i64 %y, -32768630 call void @llvm.assume(i1 %c3)631 632 %div = sdiv exact i64 %x, %y633 ret i64 %div634}635 636define void @sdiv_zero(ptr %p, i32 %arg) {637; CHECK-LABEL: @sdiv_zero(638; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ARG:%.*]], 5639; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 11640; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])641; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4642; CHECK-NEXT: ret void643;644 %add = add i32 %arg, 5645 %cmp = icmp ult i32 %add, 11646 call void @llvm.assume(i1 %cmp)647 %div = sdiv i32 %arg, 6648 store i32 %div, ptr %p649 ret void650}651 652define void @sdiv_not_zero(ptr %p, i32 %arg) {653; CHECK-LABEL: @sdiv_not_zero(654; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ARG:%.*]], 5655; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 12656; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])657; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i32 [[ARG]] to i8658; CHECK-NEXT: [[DIV1:%.*]] = sdiv i8 [[DIV_LHS_TRUNC]], 6659; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i8 [[DIV1]] to i32660; CHECK-NEXT: store i32 [[DIV_SEXT]], ptr [[P:%.*]], align 4661; CHECK-NEXT: ret void662;663 %add = add i32 %arg, 5664 %cmp = icmp ult i32 %add, 12665 call void @llvm.assume(i1 %cmp)666 %div = sdiv i32 %arg, 6667 store i32 %div, ptr %p668 ret void669}670 671define void @sdiv_pos(ptr %p, i32 %arg) {672; CHECK-LABEL: @sdiv_pos(673; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ARG:%.*]], -12674; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 6675; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])676; CHECK-NEXT: store i32 2, ptr [[P:%.*]], align 4677; CHECK-NEXT: ret void678;679 %add = add i32 %arg, -12680 %cmp = icmp ult i32 %add, 6681 call void @llvm.assume(i1 %cmp)682 %div = sdiv i32 %arg, 6683 store i32 %div, ptr %p684 ret void685}686 687define void @sdiv_neg(ptr %p, i32 %arg) {688; CHECK-LABEL: @sdiv_neg(689; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ARG:%.*]], 17690; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 6691; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])692; CHECK-NEXT: store i32 -2, ptr [[P:%.*]], align 4693; CHECK-NEXT: ret void694;695 %add = add i32 %arg, 17696 %cmp = icmp ult i32 %add, 6697 call void @llvm.assume(i1 %cmp)698 %div = sdiv i32 %arg, 6699 store i32 %div, ptr %p700 ret void701}702