687 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-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"5target triple = "thumbv7m-arm-none-eabi"6 7define void @h(ptr nocapture %p, i32 %x) local_unnamed_addr #0 {8; CHECK-LABEL: @h(9; CHECK-NEXT: entry:10; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], 011; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]12; CHECK: if.then:13; CHECK-NEXT: [[REM21:%.*]] = urem i32 [[X]], 1014; CHECK-NEXT: store i32 [[REM21]], ptr [[P:%.*]], align 415; CHECK-NEXT: br label [[IF_END]]16; CHECK: if.end:17; CHECK-NEXT: ret void18;19entry:20 21 %cmp = icmp sgt i32 %x, 022 br i1 %cmp, label %if.then, label %if.end23 24if.then:25 %rem2 = srem i32 %x, 1026 store i32 %rem2, ptr %p, align 427 br label %if.end28 29if.end:30 ret void31}32 33; looping case where loop has exactly one block34; at the point of srem, we know that %a is always greater than 0,35; because of the assume before it, so we can transform it to urem.36declare void @llvm.assume(i1)37define void @test4(i32 %n) {38; CHECK-LABEL: @test4(39; CHECK-NEXT: entry:40; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 041; CHECK-NEXT: br i1 [[CMP]], label [[LOOP:%.*]], label [[EXIT:%.*]]42; CHECK: loop:43; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[REM1:%.*]], [[LOOP]] ]44; CHECK-NEXT: [[COND:%.*]] = icmp samesign ugt i32 [[A]], 445; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])46; CHECK-NEXT: [[REM1]] = urem i32 [[A]], 1747; CHECK-NEXT: [[LOOPCOND:%.*]] = icmp samesign ugt i32 [[REM1]], 848; CHECK-NEXT: br i1 [[LOOPCOND]], label [[LOOP]], label [[EXIT]]49; CHECK: exit:50; CHECK-NEXT: ret void51;52entry:53 %cmp = icmp sgt i32 %n, 054 br i1 %cmp, label %loop, label %exit55 56loop:57 %a = phi i32 [ %n, %entry ], [ %rem, %loop ]58 %cond = icmp sgt i32 %a, 459 call void @llvm.assume(i1 %cond)60 %rem = srem i32 %a, 1761 %loopcond = icmp sgt i32 %rem, 862 br i1 %loopcond, label %loop, label %exit63 64exit:65 ret void66}67 68; Now, let's try various domain combinations for operands.69 70define i8 @test5_pos_pos(i8 %x, i8 %y) {71; CHECK-LABEL: @test5_pos_pos(72; CHECK-NEXT: [[C0:%.*]] = icmp sge i8 [[X:%.*]], 073; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])74; CHECK-NEXT: [[C1:%.*]] = icmp sge i8 [[Y:%.*]], 075; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])76; CHECK-NEXT: [[REM1:%.*]] = urem i8 [[X]], [[Y]]77; CHECK-NEXT: ret i8 [[REM1]]78;79 %c0 = icmp sge i8 %x, 080 call void @llvm.assume(i1 %c0)81 %c1 = icmp sge i8 %y, 082 call void @llvm.assume(i1 %c1)83 84 %rem = srem i8 %x, %y85 ret i8 %rem86}87define i8 @test6_pos_neg(i8 %x, i8 %y) {88; CHECK-LABEL: @test6_pos_neg(89; CHECK-NEXT: [[C0:%.*]] = icmp sge i8 [[X:%.*]], 090; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])91; CHECK-NEXT: [[C1:%.*]] = icmp sle i8 [[Y:%.*]], 092; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])93; CHECK-NEXT: [[Y_NONNEG:%.*]] = sub i8 0, [[Y]]94; CHECK-NEXT: [[REM1:%.*]] = urem i8 [[X]], [[Y_NONNEG]]95; CHECK-NEXT: ret i8 [[REM1]]96;97 %c0 = icmp sge i8 %x, 098 call void @llvm.assume(i1 %c0)99 %c1 = icmp sle i8 %y, 0100 call void @llvm.assume(i1 %c1)101 102 %rem = srem i8 %x, %y103 ret i8 %rem104}105define i8 @test7_neg_pos(i8 %x, i8 %y) {106; CHECK-LABEL: @test7_neg_pos(107; CHECK-NEXT: [[C0:%.*]] = icmp sle i8 [[X:%.*]], 0108; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])109; CHECK-NEXT: [[C1:%.*]] = icmp sge i8 [[Y:%.*]], 0110; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])111; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i8 0, [[X]]112; CHECK-NEXT: [[REM1:%.*]] = urem i8 [[X_NONNEG]], [[Y]]113; CHECK-NEXT: [[REM1_NEG:%.*]] = sub i8 0, [[REM1]]114; CHECK-NEXT: ret i8 [[REM1_NEG]]115;116 %c0 = icmp sle i8 %x, 0117 call void @llvm.assume(i1 %c0)118 %c1 = icmp sge i8 %y, 0119 call void @llvm.assume(i1 %c1)120 121 %rem = srem i8 %x, %y122 ret i8 %rem123}124define i8 @test8_neg_neg(i8 %x, i8 %y) {125; CHECK-LABEL: @test8_neg_neg(126; CHECK-NEXT: [[C0:%.*]] = icmp sle i8 [[X:%.*]], 0127; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])128; CHECK-NEXT: [[C1:%.*]] = icmp sle i8 [[Y:%.*]], 0129; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])130; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i8 0, [[X]]131; CHECK-NEXT: [[Y_NONNEG:%.*]] = sub i8 0, [[Y]]132; CHECK-NEXT: [[REM1:%.*]] = urem i8 [[X_NONNEG]], [[Y_NONNEG]]133; CHECK-NEXT: [[REM1_NEG:%.*]] = sub i8 0, [[REM1]]134; CHECK-NEXT: ret i8 [[REM1_NEG]]135;136 %c0 = icmp sle i8 %x, 0137 call void @llvm.assume(i1 %c0)138 %c1 = icmp sle i8 %y, 0139 call void @llvm.assume(i1 %c1)140 141 %rem = srem i8 %x, %y142 ret i8 %rem143}144 145; After making remainder unsigned, can we narrow it?146define i16 @test9_narrow(i16 %x, i16 %y) {147; CHECK-LABEL: @test9_narrow(148; CHECK-NEXT: [[C0:%.*]] = icmp ult i16 [[X:%.*]], 128149; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])150; CHECK-NEXT: [[C1:%.*]] = icmp ult i16 [[Y:%.*]], 128151; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])152; CHECK-NEXT: [[REM1_LHS_TRUNC:%.*]] = trunc i16 [[X]] to i8153; CHECK-NEXT: [[REM1_RHS_TRUNC:%.*]] = trunc i16 [[Y]] to i8154; CHECK-NEXT: [[REM12:%.*]] = urem i8 [[REM1_LHS_TRUNC]], [[REM1_RHS_TRUNC]]155; CHECK-NEXT: [[REM1_ZEXT:%.*]] = zext i8 [[REM12]] to i16156; CHECK-NEXT: ret i16 [[REM1_ZEXT]]157;158 %c0 = icmp ult i16 %x, 128159 call void @llvm.assume(i1 %c0)160 %c1 = icmp ult i16 %y, 128161 call void @llvm.assume(i1 %c1)162 163 %rem = srem i16 %x, %y164 ret i16 %rem165}166 167; Ok, but what about narrowing srem in general?168 169; If both operands are i15, it's uncontroversial - we can truncate to i16170define i64 @test11_i15_i15(i64 %x, i64 %y) {171; CHECK-LABEL: @test11_i15_i15(172; CHECK-NEXT: entry:173; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 16383174; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])175; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -16384176; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])177; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 16383178; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])179; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -16384180; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])181; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16182; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16183; CHECK-NEXT: [[DIV1:%.*]] = srem i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]184; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64185; CHECK-NEXT: ret i64 [[DIV_SEXT]]186;187entry:188 %c0 = icmp sle i64 %x, 16383189 call void @llvm.assume(i1 %c0)190 %c1 = icmp sge i64 %x, -16384191 call void @llvm.assume(i1 %c1)192 193 %c2 = icmp sle i64 %y, 16383194 call void @llvm.assume(i1 %c2)195 %c3 = icmp sge i64 %y, -16384196 call void @llvm.assume(i1 %c3)197 198 %div = srem i64 %x, %y199 ret i64 %div200}201 202; But if operands are i16, we can only truncate to i32, because we can't203; rule out UB of i16 INT_MIN s/ i16 -1204define i64 @test12_i16_i16(i64 %x, i64 %y) {205; CHECK-LABEL: @test12_i16_i16(206; CHECK-NEXT: entry:207; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767208; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])209; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768210; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])211; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767212; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])213; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768214; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])215; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32216; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32217; CHECK-NEXT: [[DIV1:%.*]] = srem i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]218; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64219; CHECK-NEXT: ret i64 [[DIV_SEXT]]220;221entry:222 %c0 = icmp sle i64 %x, 32767223 call void @llvm.assume(i1 %c0)224 %c1 = icmp sge i64 %x, -32768225 call void @llvm.assume(i1 %c1)226 227 %c2 = icmp sle i64 %y, 32767228 call void @llvm.assume(i1 %c2)229 %c3 = icmp sge i64 %y, -32768230 call void @llvm.assume(i1 %c3)231 232 %div = srem i64 %x, %y233 ret i64 %div234}235 236; But if divident is i16, and divisor is u15, then we know that i16 is UB-safe.237define i64 @test13_i16_u15(i64 %x, i64 %y) {238; CHECK-LABEL: @test13_i16_u15(239; CHECK-NEXT: entry:240; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767241; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])242; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -32768243; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])244; CHECK-NEXT: [[C2:%.*]] = icmp ule i64 [[Y:%.*]], 32767245; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])246; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16247; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16248; CHECK-NEXT: [[DIV1:%.*]] = srem i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]249; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64250; CHECK-NEXT: ret i64 [[DIV_SEXT]]251;252entry:253 %c0 = icmp sle i64 %x, 32767254 call void @llvm.assume(i1 %c0)255 %c1 = icmp sge i64 %x, -32768256 call void @llvm.assume(i1 %c1)257 258 %c2 = icmp ule i64 %y, 32767259 call void @llvm.assume(i1 %c2)260 261 %div = srem i64 %x, %y262 ret i64 %div263}264 265; And likewise, if we know that if the divident is never i16 INT_MIN,266; we can truncate to i16.267define i64 @test14_i16safe_i16(i64 %x, i64 %y) {268; CHECK-LABEL: @test14_i16safe_i16(269; CHECK-NEXT: entry:270; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767271; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])272; CHECK-NEXT: [[C1:%.*]] = icmp sgt i64 [[X]], -32768273; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])274; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 32767275; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])276; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -32768277; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])278; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16279; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16280; CHECK-NEXT: [[DIV1:%.*]] = srem i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]281; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64282; CHECK-NEXT: ret i64 [[DIV_SEXT]]283;284entry:285 %c0 = icmp sle i64 %x, 32767286 call void @llvm.assume(i1 %c0)287 %c1 = icmp sgt i64 %x, -32768288 call void @llvm.assume(i1 %c1)289 290 %c2 = icmp sle i64 %y, 32767291 call void @llvm.assume(i1 %c2)292 %c3 = icmp sge i64 %y, -32768293 call void @llvm.assume(i1 %c3)294 295 %div = srem i64 %x, %y296 ret i64 %div297}298 299; Of course, both of the conditions can happen at once.300define i64 @test15_i16safe_u15(i64 %x, i64 %y) {301; CHECK-LABEL: @test15_i16safe_u15(302; CHECK-NEXT: entry:303; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 32767304; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])305; CHECK-NEXT: [[C1:%.*]] = icmp sgt i64 [[X]], -32768306; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])307; CHECK-NEXT: [[C2:%.*]] = icmp ule i64 [[Y:%.*]], 32767308; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])309; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16310; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16311; CHECK-NEXT: [[DIV1:%.*]] = srem i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]312; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64313; CHECK-NEXT: ret i64 [[DIV_SEXT]]314;315entry:316 %c0 = icmp sle i64 %x, 32767317 call void @llvm.assume(i1 %c0)318 %c1 = icmp sgt i64 %x, -32768319 call void @llvm.assume(i1 %c1)320 321 %c2 = icmp ule i64 %y, 32767322 call void @llvm.assume(i1 %c2)323 324 %div = srem i64 %x, %y325 ret i64 %div326}327 328; We at most truncate to i8329define i64 @test16_i4_i4(i64 %x, i64 %y) {330; CHECK-LABEL: @test16_i4_i4(331; CHECK-NEXT: entry:332; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 3333; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])334; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -4335; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])336; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 3337; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])338; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -4339; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])340; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i8341; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i8342; CHECK-NEXT: [[DIV1:%.*]] = srem i8 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]343; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i8 [[DIV1]] to i64344; CHECK-NEXT: ret i64 [[DIV_SEXT]]345;346entry:347 %c0 = icmp sle i64 %x, 3348 call void @llvm.assume(i1 %c0)349 %c1 = icmp sge i64 %x, -4350 call void @llvm.assume(i1 %c1)351 352 %c2 = icmp sle i64 %y, 3353 call void @llvm.assume(i1 %c2)354 %c3 = icmp sge i64 %y, -4355 call void @llvm.assume(i1 %c3)356 357 %div = srem i64 %x, %y358 ret i64 %div359}360 361; And we round up to the powers of two362define i64 @test17_i9_i9(i64 %x, i64 %y) {363; CHECK-LABEL: @test17_i9_i9(364; CHECK-NEXT: entry:365; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 255366; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])367; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -256368; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])369; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 255370; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])371; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -256372; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])373; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i16374; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i16375; CHECK-NEXT: [[DIV1:%.*]] = srem i16 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]376; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i16 [[DIV1]] to i64377; CHECK-NEXT: ret i64 [[DIV_SEXT]]378;379entry:380 %c0 = icmp sle i64 %x, 255381 call void @llvm.assume(i1 %c0)382 %c1 = icmp sge i64 %x, -256383 call void @llvm.assume(i1 %c1)384 385 %c2 = icmp sle i64 %y, 255386 call void @llvm.assume(i1 %c2)387 %c3 = icmp sge i64 %y, -256388 call void @llvm.assume(i1 %c3)389 390 %div = srem i64 %x, %y391 ret i64 %div392}393 394; Don't widen the operation to the next power of two if it wasn't a power of two.395define i9 @test18_i9_i9(i9 %x, i9 %y) {396; CHECK-LABEL: @test18_i9_i9(397; CHECK-NEXT: entry:398; CHECK-NEXT: [[C0:%.*]] = icmp sle i9 [[X:%.*]], 255399; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])400; CHECK-NEXT: [[C1:%.*]] = icmp sge i9 [[X]], -256401; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])402; CHECK-NEXT: [[C2:%.*]] = icmp sle i9 [[Y:%.*]], 255403; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])404; CHECK-NEXT: [[C3:%.*]] = icmp sge i9 [[Y]], -256405; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])406; CHECK-NEXT: [[DIV:%.*]] = srem i9 [[X]], [[Y]]407; CHECK-NEXT: ret i9 [[DIV]]408;409entry:410 %c0 = icmp sle i9 %x, 255411 call void @llvm.assume(i1 %c0)412 %c1 = icmp sge i9 %x, -256413 call void @llvm.assume(i1 %c1)414 415 %c2 = icmp sle i9 %y, 255416 call void @llvm.assume(i1 %c2)417 %c3 = icmp sge i9 %y, -256418 call void @llvm.assume(i1 %c3)419 420 %div = srem i9 %x, %y421 ret i9 %div422}423define i10 @test19_i10_i10(i10 %x, i10 %y) {424; CHECK-LABEL: @test19_i10_i10(425; CHECK-NEXT: entry:426; CHECK-NEXT: [[C0:%.*]] = icmp sle i10 [[X:%.*]], 255427; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])428; CHECK-NEXT: [[C1:%.*]] = icmp sge i10 [[X]], -256429; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])430; CHECK-NEXT: [[C2:%.*]] = icmp sle i10 [[Y:%.*]], 255431; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])432; CHECK-NEXT: [[C3:%.*]] = icmp sge i10 [[Y]], -256433; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])434; CHECK-NEXT: [[DIV:%.*]] = srem i10 [[X]], [[Y]]435; CHECK-NEXT: ret i10 [[DIV]]436;437entry:438 %c0 = icmp sle i10 %x, 255439 call void @llvm.assume(i1 %c0)440 %c1 = icmp sge i10 %x, -256441 call void @llvm.assume(i1 %c1)442 443 %c2 = icmp sle i10 %y, 255444 call void @llvm.assume(i1 %c2)445 %c3 = icmp sge i10 %y, -256446 call void @llvm.assume(i1 %c3)447 448 %div = srem i10 %x, %y449 ret i10 %div450}451 452; Note that we need to take the maximal bitwidth, in which both of the operands are representable!453define i64 @test20_i16_i18(i64 %x, i64 %y) {454; CHECK-LABEL: @test20_i16_i18(455; CHECK-NEXT: entry:456; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 16383457; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])458; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -16384459; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])460; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 65535461; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])462; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -65536463; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])464; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32465; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32466; CHECK-NEXT: [[DIV1:%.*]] = srem i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]467; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64468; CHECK-NEXT: ret i64 [[DIV_SEXT]]469;470entry:471 %c0 = icmp sle i64 %x, 16383472 call void @llvm.assume(i1 %c0)473 %c1 = icmp sge i64 %x, -16384474 call void @llvm.assume(i1 %c1)475 476 %c2 = icmp sle i64 %y, 65535477 call void @llvm.assume(i1 %c2)478 %c3 = icmp sge i64 %y, -65536479 call void @llvm.assume(i1 %c3)480 481 %div = srem i64 %x, %y482 ret i64 %div483}484define i64 @test21_i18_i16(i64 %x, i64 %y) {485; CHECK-LABEL: @test21_i18_i16(486; CHECK-NEXT: entry:487; CHECK-NEXT: [[C0:%.*]] = icmp sle i64 [[X:%.*]], 65535488; CHECK-NEXT: call void @llvm.assume(i1 [[C0]])489; CHECK-NEXT: [[C1:%.*]] = icmp sge i64 [[X]], -65536490; CHECK-NEXT: call void @llvm.assume(i1 [[C1]])491; CHECK-NEXT: [[C2:%.*]] = icmp sle i64 [[Y:%.*]], 16383492; CHECK-NEXT: call void @llvm.assume(i1 [[C2]])493; CHECK-NEXT: [[C3:%.*]] = icmp sge i64 [[Y]], -16384494; CHECK-NEXT: call void @llvm.assume(i1 [[C3]])495; CHECK-NEXT: [[DIV_LHS_TRUNC:%.*]] = trunc i64 [[X]] to i32496; CHECK-NEXT: [[DIV_RHS_TRUNC:%.*]] = trunc i64 [[Y]] to i32497; CHECK-NEXT: [[DIV1:%.*]] = srem i32 [[DIV_LHS_TRUNC]], [[DIV_RHS_TRUNC]]498; CHECK-NEXT: [[DIV_SEXT:%.*]] = sext i32 [[DIV1]] to i64499; CHECK-NEXT: ret i64 [[DIV_SEXT]]500;501entry:502 %c0 = icmp sle i64 %x, 65535503 call void @llvm.assume(i1 %c0)504 %c1 = icmp sge i64 %x, -65536505 call void @llvm.assume(i1 %c1)506 507 %c2 = icmp sle i64 %y, 16383508 call void @llvm.assume(i1 %c2)509 %c3 = icmp sge i64 %y, -16384510 call void @llvm.assume(i1 %c3)511 512 %div = srem i64 %x, %y513 ret i64 %div514}515 516define dso_local i8 @abs_x_lt_abs_y_positive(i8 %x, i8 %y) {517; CHECK-LABEL: @abs_x_lt_abs_y_positive(518; CHECK-NEXT: entry:519; CHECK-NEXT: [[X_CMP:%.*]] = icmp slt i8 [[X:%.*]], 10520; CHECK-NEXT: [[X_CMP2:%.*]] = icmp sgt i8 [[X]], -10521; CHECK-NEXT: [[AND_X:%.*]] = and i1 [[X_CMP]], [[X_CMP2]]522; CHECK-NEXT: [[Y_CMP:%.*]] = icmp sge i8 [[Y:%.*]], 10523; CHECK-NEXT: [[AND_COND:%.*]] = and i1 [[AND_X]], [[Y_CMP]]524; CHECK-NEXT: br i1 [[AND_COND]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]525; CHECK: if.else:526; CHECK-NEXT: ret i8 [[X]]527; CHECK: if.then:528; CHECK-NEXT: ret i8 0529;530entry:531 %x.cmp = icmp slt i8 %x, 10532 %x.cmp2 = icmp sgt i8 %x, -10533 %and.x = and i1 %x.cmp, %x.cmp2534 %y.cmp = icmp sge i8 %y, 10535 %and.cond = and i1 %and.x, %y.cmp536 br i1 %and.cond, label %if.else, label %if.then537 538if.else: ; preds = %entry539 %rem = srem i8 %x, %y540 ret i8 %rem541 542if.then: ; preds = %entry, %if.then6, %if.end4543 ret i8 0544}545 546define dso_local i8 @abs_x_lt_abs_y_positive_unsigned_cmp(i8 %x, i8 %y) {547; CHECK-LABEL: @abs_x_lt_abs_y_positive_unsigned_cmp(548; CHECK-NEXT: entry:549; CHECK-NEXT: [[X_CMP:%.*]] = icmp slt i8 [[X:%.*]], 10550; CHECK-NEXT: [[X_CMP2:%.*]] = icmp sgt i8 [[X]], -10551; CHECK-NEXT: [[AND_X:%.*]] = and i1 [[X_CMP]], [[X_CMP2]]552; CHECK-NEXT: [[Y_CMP:%.*]] = icmp uge i8 [[Y:%.*]], 10553; CHECK-NEXT: [[Y_CMP2:%.*]] = icmp ule i8 [[Y]], 20554; CHECK-NEXT: [[AND_Y:%.*]] = and i1 [[Y_CMP]], [[Y_CMP2]]555; CHECK-NEXT: [[AND_COND:%.*]] = and i1 [[AND_X]], [[AND_Y]]556; CHECK-NEXT: br i1 [[AND_COND]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]557; CHECK: if.else:558; CHECK-NEXT: ret i8 [[X]]559; CHECK: if.then:560; CHECK-NEXT: ret i8 0561;562entry:563 %x.cmp = icmp slt i8 %x, 10564 %x.cmp2 = icmp sgt i8 %x, -10565 %and.x = and i1 %x.cmp, %x.cmp2566 %y.cmp = icmp uge i8 %y, 10567 %y.cmp2 = icmp ule i8 %y, 20568 %and.y = and i1 %y.cmp, %y.cmp2569 %and.cond = and i1 %and.x, %and.y570 br i1 %and.cond, label %if.else, label %if.then571 572if.else: ; preds = %entry573 %rem = srem i8 %x, %y574 ret i8 %rem575 576if.then: ; preds = %entry, %if.then6, %if.end4577 ret i8 0578}579 580define dso_local i8 @abs_x_lt_abs_y_negative(i8 %x, i8 %y) {581; CHECK-LABEL: @abs_x_lt_abs_y_negative(582; CHECK-NEXT: entry:583; CHECK-NEXT: [[X_CMP:%.*]] = icmp slt i8 [[X:%.*]], 10584; CHECK-NEXT: [[X_CMP2:%.*]] = icmp sgt i8 [[X]], -10585; CHECK-NEXT: [[AND_X:%.*]] = and i1 [[X_CMP]], [[X_CMP2]]586; CHECK-NEXT: [[Y_CMP:%.*]] = icmp sge i8 [[Y:%.*]], -20587; CHECK-NEXT: [[Y_CMP2:%.*]] = icmp sle i8 [[Y]], -11588; CHECK-NEXT: [[AND_Y:%.*]] = and i1 [[Y_CMP]], [[Y_CMP2]]589; CHECK-NEXT: [[AND_COND:%.*]] = and i1 [[AND_X]], [[AND_Y]]590; CHECK-NEXT: br i1 [[AND_COND]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]591; CHECK: if.else:592; CHECK-NEXT: ret i8 [[X]]593; CHECK: if.then:594; CHECK-NEXT: ret i8 0595;596entry:597 %x.cmp = icmp slt i8 %x, 10598 %x.cmp2 = icmp sgt i8 %x, -10599 %and.x = and i1 %x.cmp, %x.cmp2600 %y.cmp = icmp sge i8 %y, -20601 %y.cmp2 = icmp sle i8 %y, -11602 %and.y = and i1 %y.cmp, %y.cmp2603 %and.cond = and i1 %and.x, %and.y604 br i1 %and.cond, label %if.else, label %if.then605 606if.else: ; preds = %entry607 %rem = srem i8 %x, %y608 ret i8 %rem609 610if.then: ; preds = %entry, %if.then6, %if.end4611 ret i8 0612}613 614; Negative test: abs(x) less than or equal abs(y)615 616define dso_local i8 @abs_x_lte_abs_y(i8 %x, i8 %y) {617; CHECK-LABEL: @abs_x_lte_abs_y(618; CHECK-NEXT: entry:619; CHECK-NEXT: [[X_CMP:%.*]] = icmp slt i8 [[X:%.*]], 10620; CHECK-NEXT: [[X_CMP2:%.*]] = icmp sgt i8 [[X]], -10621; CHECK-NEXT: [[AND_X:%.*]] = and i1 [[X_CMP]], [[X_CMP2]]622; CHECK-NEXT: [[Y_CMP:%.*]] = icmp sge i8 [[Y:%.*]], -20623; CHECK-NEXT: [[Y_CMP2:%.*]] = icmp sle i8 [[Y]], -9624; CHECK-NEXT: [[AND_Y:%.*]] = and i1 [[Y_CMP]], [[Y_CMP2]]625; CHECK-NEXT: [[AND_COND:%.*]] = and i1 [[AND_X]], [[AND_Y]]626; CHECK-NEXT: br i1 [[AND_COND]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]627; CHECK: if.else:628; CHECK-NEXT: [[REM:%.*]] = srem i8 [[X]], [[Y]]629; CHECK-NEXT: ret i8 [[REM]]630; CHECK: if.then:631; CHECK-NEXT: ret i8 0632;633entry:634 %x.cmp = icmp slt i8 %x, 10635 %x.cmp2 = icmp sgt i8 %x, -10636 %and.x = and i1 %x.cmp, %x.cmp2637 %y.cmp = icmp sge i8 %y, -20638 %y.cmp2 = icmp sle i8 %y, -9639 %and.y = and i1 %y.cmp, %y.cmp2640 %and.cond = and i1 %and.x, %and.y641 br i1 %and.cond, label %if.else, label %if.then642 643if.else: ; preds = %entry644 %rem = srem i8 %x, %y645 ret i8 %rem646 647if.then: ; preds = %entry, %if.then6, %if.end4648 ret i8 0649}650 651; Negative test: abs(x) has unknown predication with abs(y)652 653define dso_local i8 @abs_x_unknown_abs_y(i8 %x, i8 %y) {654; CHECK-LABEL: @abs_x_unknown_abs_y(655; CHECK-NEXT: entry:656; CHECK-NEXT: [[X_CMP:%.*]] = icmp slt i8 [[X:%.*]], 10657; CHECK-NEXT: [[X_CMP2:%.*]] = icmp sgt i8 [[X]], -10658; CHECK-NEXT: [[AND_X:%.*]] = and i1 [[X_CMP]], [[X_CMP2]]659; CHECK-NEXT: [[Y_CMP:%.*]] = icmp sge i8 [[Y:%.*]], -20660; CHECK-NEXT: [[Y_CMP2:%.*]] = icmp sle i8 [[Y]], -9661; CHECK-NEXT: [[AND_Y:%.*]] = and i1 [[Y_CMP]], [[Y_CMP2]]662; CHECK-NEXT: [[AND_COND:%.*]] = and i1 [[AND_X]], [[AND_Y]]663; CHECK-NEXT: br i1 [[AND_COND]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]664; CHECK: if.else:665; CHECK-NEXT: [[REM:%.*]] = srem i8 [[X]], [[Y]]666; CHECK-NEXT: ret i8 [[REM]]667; CHECK: if.then:668; CHECK-NEXT: ret i8 0669;670entry:671 %x.cmp = icmp slt i8 %x, 10672 %x.cmp2 = icmp sgt i8 %x, -10673 %and.x = and i1 %x.cmp, %x.cmp2674 %y.cmp = icmp sge i8 %y, -20675 %y.cmp2 = icmp sle i8 %y, -9676 %and.y = and i1 %y.cmp, %y.cmp2677 %and.cond = and i1 %and.x, %and.y678 br i1 %and.cond, label %if.else, label %if.then679 680if.else: ; preds = %entry681 %rem = srem i8 %x, %y682 ret i8 %rem683 684if.then: ; preds = %entry, %if.then6, %if.end4685 ret i8 0686}687