10f37ba7bSWilliam Huang; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2ec9ccb16SBjorn Pettersson; RUN: opt -S -passes=instcombine < %s | FileCheck %s 30f37ba7bSWilliam Huang 40f37ba7bSWilliam Huang; Check if a value can be deduced as a power of 2, allowing urem optimization. 50f37ba7bSWilliam Huang; i.e. A urem B = A & (B - 1) if B is a power of 2. 60f37ba7bSWilliam Huang 70f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_phi(i64 %size, i1 %cmp, i1 %cmp1) { 80f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_phi( 90f37ba7bSWilliam Huang; CHECK-NEXT: entry: 100f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[CMP:%.*]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] 110f37ba7bSWilliam Huang; CHECK: cond.true: 120f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[CMP1:%.*]], label [[COND_TRUE_TRUE:%.*]], label [[COND_TRUE_FALSE:%.*]] 130f37ba7bSWilliam Huang; CHECK: cond.true.true: 140f37ba7bSWilliam Huang; CHECK-NEXT: br label [[COND_TRUE_END:%.*]] 150f37ba7bSWilliam Huang; CHECK: cond.true.false: 160f37ba7bSWilliam Huang; CHECK-NEXT: br label [[COND_TRUE_END]] 170f37ba7bSWilliam Huang; CHECK: cond.true.end: 18d53b3df5SDhruv Chawla; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 1, [[COND_TRUE_TRUE]] ], [ 3, [[COND_TRUE_FALSE]] ] 190f37ba7bSWilliam Huang; CHECK-NEXT: br label [[COND_END]] 200f37ba7bSWilliam Huang; CHECK: cond.end: 21d53b3df5SDhruv Chawla; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ 4095, [[ENTRY:%.*]] ], [ [[PHI]], [[COND_TRUE_END]] ] 22*a1058776SNikita Popov; CHECK-NEXT: [[UREM:%.*]] = and i64 [[SIZE:%.*]], [[PHI1]] 230f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[UREM]] 240f37ba7bSWilliam Huang; 250f37ba7bSWilliam Huangentry: 260f37ba7bSWilliam Huang br i1 %cmp, label %cond.true, label %cond.end 270f37ba7bSWilliam Huang 280f37ba7bSWilliam Huangcond.true: 290f37ba7bSWilliam Huang br i1 %cmp1, label %cond.true.true, label %cond.true.false 300f37ba7bSWilliam Huang 310f37ba7bSWilliam Huangcond.true.true: 320f37ba7bSWilliam Huang br label %cond.true.end 330f37ba7bSWilliam Huang 340f37ba7bSWilliam Huangcond.true.false: 350f37ba7bSWilliam Huang br label %cond.true.end 360f37ba7bSWilliam Huang 370f37ba7bSWilliam Huangcond.true.end: 380f37ba7bSWilliam Huang %phi = phi i64 [ 2, %cond.true.true ], [ 4, %cond.true.false ] 390f37ba7bSWilliam Huang br label %cond.end 400f37ba7bSWilliam Huang 410f37ba7bSWilliam Huangcond.end: 420f37ba7bSWilliam Huang %phi1 = phi i64 [ 4096, %entry ], [ %phi, %cond.true.end ] 430f37ba7bSWilliam Huang %urem = urem i64 %size, %phi1 440f37ba7bSWilliam Huang ret i64 %urem 450f37ba7bSWilliam Huang} 460f37ba7bSWilliam Huang 470f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_nested_expr(i64 %size, i1 %cmp, i1 %cmp1, i64 %0) { 480f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_nested_expr( 490f37ba7bSWilliam Huang; CHECK-NEXT: entry: 500f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[CMP:%.*]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 510f37ba7bSWilliam Huang; CHECK: cond.true: 520f37ba7bSWilliam Huang; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i64 1, [[TMP0:%.*]] 530f37ba7bSWilliam Huang; CHECK-NEXT: br label [[COND_END:%.*]] 540f37ba7bSWilliam Huang; CHECK: cond.false: 550f37ba7bSWilliam Huang; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP1:%.*]], i64 2, i64 8 560f37ba7bSWilliam Huang; CHECK-NEXT: br label [[COND_END]] 570f37ba7bSWilliam Huang; CHECK: cond.end: 580f37ba7bSWilliam Huang; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[SELECT]], [[COND_FALSE]] ], [ [[TMP1]], [[COND_TRUE]] ], [ [[PHI]], [[COND_END]] ] 5935b0955aSWilliam Huang; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[PHI]], -1 60*a1058776SNikita Popov; CHECK-NEXT: [[UREM:%.*]] = and i64 [[SIZE:%.*]], [[TMP2]] 610f37ba7bSWilliam Huang; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[UREM]], 10 620f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[CMP2]], label [[COND_END]], label [[END:%.*]] 630f37ba7bSWilliam Huang; CHECK: end: 640f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[UREM]] 650f37ba7bSWilliam Huang; 660f37ba7bSWilliam Huangentry: 670f37ba7bSWilliam Huang br i1 %cmp, label %cond.true, label %cond.false 680f37ba7bSWilliam Huang 690f37ba7bSWilliam Huangcond.true: 700f37ba7bSWilliam Huang %1 = shl nuw i64 1, %0 710f37ba7bSWilliam Huang br label %cond.end 720f37ba7bSWilliam Huang 730f37ba7bSWilliam Huangcond.false: 740f37ba7bSWilliam Huang %select = select i1 %cmp1, i64 2, i64 8 750f37ba7bSWilliam Huang br label %cond.end 760f37ba7bSWilliam Huang 770f37ba7bSWilliam Huangcond.end: 780f37ba7bSWilliam Huang %phi = phi i64 [ %select, %cond.false ], [ %1, %cond.true ], [ %phi, %cond.end ] 790f37ba7bSWilliam Huang %2 = phi i64 [ %size, %cond.false ], [ %size, %cond.true ], [ %0, %cond.end ] 800f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 810f37ba7bSWilliam Huang %cmp2 = icmp ult i64 %urem, 10 820f37ba7bSWilliam Huang br i1 %cmp2, label %cond.end, label %end 830f37ba7bSWilliam Huang 840f37ba7bSWilliam Huangend: 850f37ba7bSWilliam Huang ret i64 %urem 860f37ba7bSWilliam Huang} 870f37ba7bSWilliam Huang 880f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_negative(i64 %size, i1 %cmp, i64 %0) { 890f37ba7bSWilliam Huang; urem is not replaced if not all operands are power of 2. 900f37ba7bSWilliam Huang; 910f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_negative( 920f37ba7bSWilliam Huang; CHECK-NEXT: entry: 930f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[CMP:%.*]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] 940f37ba7bSWilliam Huang; CHECK: cond.true: 950f37ba7bSWilliam Huang; CHECK-NEXT: br label [[COND_END]] 960f37ba7bSWilliam Huang; CHECK: cond.end: 970f37ba7bSWilliam Huang; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 4, [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[COND_TRUE]] ] 980f37ba7bSWilliam Huang; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[SIZE:%.*]], [[PHI]] 990f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[UREM]] 1000f37ba7bSWilliam Huang; 1010f37ba7bSWilliam Huangentry: 1020f37ba7bSWilliam Huang br i1 %cmp, label %cond.true, label %cond.end 1030f37ba7bSWilliam Huang 1040f37ba7bSWilliam Huangcond.true: 1050f37ba7bSWilliam Huang br label %cond.end 1060f37ba7bSWilliam Huang 1070f37ba7bSWilliam Huangcond.end: 1080f37ba7bSWilliam Huang %phi = phi i64 [ 4, %entry ], [ %0, %cond.true ] 1090f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 1100f37ba7bSWilliam Huang ret i64 %urem 1110f37ba7bSWilliam Huang} 1120f37ba7bSWilliam Huang 1130f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_loop_mul(i64 %size, i64 %a) { 1140f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_loop_mul( 1150f37ba7bSWilliam Huang; CHECK-NEXT: entry: 1160f37ba7bSWilliam Huang; CHECK-NEXT: [[START:%.*]] = shl nuw i64 1, [[A:%.*]] 1170f37ba7bSWilliam Huang; CHECK-NEXT: br label [[FOR_BODY:%.*]] 1180f37ba7bSWilliam Huang; CHECK: for.body: 1190f37ba7bSWilliam Huang; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR_BODY]] ] 1200f37ba7bSWilliam Huang; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 121ba26e45cSWilliam Huang; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[PHI]], -1 122*a1058776SNikita Popov; CHECK-NEXT: [[UREM:%.*]] = and i64 [[SIZE:%.*]], [[TMP0]] 1230f37ba7bSWilliam Huang; CHECK-NEXT: [[ADD]] = add nuw i64 [[SUM]], [[UREM]] 1240f37ba7bSWilliam Huang; CHECK-NEXT: [[I]] = shl nuw i64 [[PHI]], 2 1250f37ba7bSWilliam Huang; CHECK-NEXT: [[ICMP:%.*]] = icmp ult i64 [[PHI]], 25000000 1260f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[ICMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 1270f37ba7bSWilliam Huang; CHECK: for.end: 1280f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[SUM]] 1290f37ba7bSWilliam Huang; 1300f37ba7bSWilliam Huangentry: 1310f37ba7bSWilliam Huang %start = shl nuw i64 1, %a 1320f37ba7bSWilliam Huang br label %for.body 1330f37ba7bSWilliam Huang 1340f37ba7bSWilliam Huangfor.body: 1350f37ba7bSWilliam Huang %phi = phi i64 [ %start, %entry ], [ %i, %for.body ] 1360f37ba7bSWilliam Huang %sum = phi i64 [ 0, %entry ], [ %add, %for.body ] 1370f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 1380f37ba7bSWilliam Huang %add = add nuw i64 %sum, %urem 1390f37ba7bSWilliam Huang %i = mul nuw i64 %phi, 4 1400f37ba7bSWilliam Huang %icmp = icmp ult i64 %i, 100000000 1410f37ba7bSWilliam Huang br i1 %icmp, label %for.body, label %for.end 1420f37ba7bSWilliam Huang 1430f37ba7bSWilliam Huangfor.end: 1440f37ba7bSWilliam Huang %r = phi i64 [ %sum, %for.body ] 1450f37ba7bSWilliam Huang ret i64 %r 1460f37ba7bSWilliam Huang} 1470f37ba7bSWilliam Huang 1480f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_loop_mul_negative(i64 %size, i64 %a) { 1490f37ba7bSWilliam Huang; Cannot deduce induction variable is a power of 2 if it is multiplied by 3. 1500f37ba7bSWilliam Huang; 1510f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_loop_mul_negative( 1520f37ba7bSWilliam Huang; CHECK-NEXT: entry: 1530f37ba7bSWilliam Huang; CHECK-NEXT: [[START:%.*]] = shl nuw i64 1, [[A:%.*]] 1540f37ba7bSWilliam Huang; CHECK-NEXT: br label [[FOR_BODY:%.*]] 1550f37ba7bSWilliam Huang; CHECK: for.body: 1560f37ba7bSWilliam Huang; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR_BODY]] ] 1570f37ba7bSWilliam Huang; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 1580f37ba7bSWilliam Huang; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[SIZE:%.*]], [[PHI]] 1590f37ba7bSWilliam Huang; CHECK-NEXT: [[ADD]] = add nuw i64 [[SUM]], [[UREM]] 1600f37ba7bSWilliam Huang; CHECK-NEXT: [[I]] = mul nuw i64 [[PHI]], 3 1612ebfda24SAlexander Shaposhnikov; CHECK-NEXT: [[ICMP:%.*]] = icmp ult i64 [[PHI]], 33333334 1620f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[ICMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 1630f37ba7bSWilliam Huang; CHECK: for.end: 1640f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[SUM]] 1650f37ba7bSWilliam Huang; 1660f37ba7bSWilliam Huangentry: 1670f37ba7bSWilliam Huang %start = shl nuw i64 1, %a 1680f37ba7bSWilliam Huang br label %for.body 1690f37ba7bSWilliam Huang 1700f37ba7bSWilliam Huangfor.body: 1710f37ba7bSWilliam Huang %phi = phi i64 [ %start, %entry ], [ %i, %for.body ] 1720f37ba7bSWilliam Huang %sum = phi i64 [ 0, %entry ], [ %add, %for.body ] 1730f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 1740f37ba7bSWilliam Huang %add = add nuw i64 %sum, %urem 1750f37ba7bSWilliam Huang %i = mul nuw i64 %phi, 3 1760f37ba7bSWilliam Huang %icmp = icmp ult i64 %i, 100000000 1770f37ba7bSWilliam Huang br i1 %icmp, label %for.body, label %for.end 1780f37ba7bSWilliam Huang 1790f37ba7bSWilliam Huangfor.end: 1800f37ba7bSWilliam Huang %r = phi i64 [ %sum, %for.body ] 1810f37ba7bSWilliam Huang ret i64 %r 1820f37ba7bSWilliam Huang} 1830f37ba7bSWilliam Huang 1840f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_loop_shl(i64 %size, i64 %a) { 1850f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_loop_shl( 1860f37ba7bSWilliam Huang; CHECK-NEXT: entry: 1870f37ba7bSWilliam Huang; CHECK-NEXT: [[START:%.*]] = shl nuw i64 1, [[A:%.*]] 1880f37ba7bSWilliam Huang; CHECK-NEXT: br label [[FOR_BODY:%.*]] 1890f37ba7bSWilliam Huang; CHECK: for.body: 1900f37ba7bSWilliam Huang; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR_BODY]] ] 1910f37ba7bSWilliam Huang; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 192ba26e45cSWilliam Huang; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[PHI]], -1 193*a1058776SNikita Popov; CHECK-NEXT: [[UREM:%.*]] = and i64 [[SIZE:%.*]], [[TMP0]] 1940f37ba7bSWilliam Huang; CHECK-NEXT: [[ADD]] = add nuw i64 [[SUM]], [[UREM]] 1950f37ba7bSWilliam Huang; CHECK-NEXT: [[I]] = shl nuw i64 [[PHI]], 1 1960f37ba7bSWilliam Huang; CHECK-NEXT: [[ICMP:%.*]] = icmp ult i64 [[PHI]], 50000000 1970f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[ICMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 1980f37ba7bSWilliam Huang; CHECK: for.end: 1990f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[SUM]] 2000f37ba7bSWilliam Huang; 2010f37ba7bSWilliam Huangentry: 2020f37ba7bSWilliam Huang %start = shl nuw i64 1, %a 2030f37ba7bSWilliam Huang br label %for.body 2040f37ba7bSWilliam Huang 2050f37ba7bSWilliam Huangfor.body: 2060f37ba7bSWilliam Huang %phi = phi i64 [ %start, %entry ], [ %i, %for.body ] 2070f37ba7bSWilliam Huang %sum = phi i64 [ 0, %entry ], [ %add, %for.body ] 2080f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 2090f37ba7bSWilliam Huang %add = add nuw i64 %sum, %urem 2100f37ba7bSWilliam Huang %i = shl nuw i64 %phi, 1 2110f37ba7bSWilliam Huang %icmp = icmp ult i64 %i, 100000000 2120f37ba7bSWilliam Huang br i1 %icmp, label %for.body, label %for.end 2130f37ba7bSWilliam Huang 2140f37ba7bSWilliam Huangfor.end: 2150f37ba7bSWilliam Huang %r = phi i64 [ %sum, %for.body ] 2160f37ba7bSWilliam Huang ret i64 %r 2170f37ba7bSWilliam Huang} 2180f37ba7bSWilliam Huang 2190f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_loop_lshr(i64 %size, i64 %a) { 2200f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_loop_lshr( 2210f37ba7bSWilliam Huang; CHECK-NEXT: entry: 2220f37ba7bSWilliam Huang; CHECK-NEXT: [[START:%.*]] = shl nuw i64 1, [[A:%.*]] 2230f37ba7bSWilliam Huang; CHECK-NEXT: br label [[FOR_BODY:%.*]] 2240f37ba7bSWilliam Huang; CHECK: for.body: 2250f37ba7bSWilliam Huang; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR_BODY]] ] 2260f37ba7bSWilliam Huang; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 227ba26e45cSWilliam Huang; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[PHI]], -1 228*a1058776SNikita Popov; CHECK-NEXT: [[UREM:%.*]] = and i64 [[SIZE:%.*]], [[TMP0]] 2290f37ba7bSWilliam Huang; CHECK-NEXT: [[ADD]] = add nuw i64 [[SUM]], [[UREM]] 2300f37ba7bSWilliam Huang; CHECK-NEXT: [[I]] = lshr i64 [[PHI]], 1 2310f37ba7bSWilliam Huang; CHECK-NEXT: [[ICMP_NOT:%.*]] = icmp ult i64 [[PHI]], 2 2320f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[ICMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 2330f37ba7bSWilliam Huang; CHECK: for.end: 2340f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[SUM]] 2350f37ba7bSWilliam Huang; 2360f37ba7bSWilliam Huangentry: 2370f37ba7bSWilliam Huang %start = shl nuw i64 1, %a 2380f37ba7bSWilliam Huang br label %for.body 2390f37ba7bSWilliam Huang 2400f37ba7bSWilliam Huangfor.body: 2410f37ba7bSWilliam Huang %phi = phi i64 [ %start, %entry ], [ %i, %for.body ] 2420f37ba7bSWilliam Huang %sum = phi i64 [ 0, %entry ], [ %add, %for.body ] 2430f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 2440f37ba7bSWilliam Huang %add = add nuw i64 %sum, %urem 2450f37ba7bSWilliam Huang %i = lshr i64 %phi, 1 2460f37ba7bSWilliam Huang %icmp = icmp ugt i64 %i, 0 2470f37ba7bSWilliam Huang br i1 %icmp, label %for.body, label %for.end 2480f37ba7bSWilliam Huang 2490f37ba7bSWilliam Huangfor.end: 2500f37ba7bSWilliam Huang %r = phi i64 [ %sum, %for.body ] 2510f37ba7bSWilliam Huang ret i64 %r 2520f37ba7bSWilliam Huang} 2530f37ba7bSWilliam Huang 2540f37ba7bSWilliam Huang 2550f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_loop_ashr(i64 %size, i64 %a) { 2560f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_loop_ashr( 2570f37ba7bSWilliam Huang; CHECK-NEXT: entry: 2580f37ba7bSWilliam Huang; CHECK-NEXT: br label [[FOR_BODY:%.*]] 2590f37ba7bSWilliam Huang; CHECK: for.body: 2600f37ba7bSWilliam Huang; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 4096, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR_BODY]] ] 2610f37ba7bSWilliam Huang; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 262ba26e45cSWilliam Huang; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[PHI]], -1 263*a1058776SNikita Popov; CHECK-NEXT: [[UREM:%.*]] = and i64 [[SIZE:%.*]], [[TMP0]] 264ba26e45cSWilliam Huang; CHECK-NEXT: [[ADD]] = add nsw i64 [[SUM]], [[UREM]] 2650f37ba7bSWilliam Huang; CHECK-NEXT: [[I]] = lshr i64 [[PHI]], [[A:%.*]] 2660f37ba7bSWilliam Huang; CHECK-NEXT: [[ICMP_NOT:%.*]] = icmp eq i64 [[I]], 0 2670f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[ICMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 2680f37ba7bSWilliam Huang; CHECK: for.end: 2690f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[SUM]] 2700f37ba7bSWilliam Huang; 2710f37ba7bSWilliam Huangentry: 2720f37ba7bSWilliam Huang br label %for.body 2730f37ba7bSWilliam Huang 2740f37ba7bSWilliam Huangfor.body: 2750f37ba7bSWilliam Huang %phi = phi i64 [ 4096, %entry ], [ %i, %for.body ] 2760f37ba7bSWilliam Huang %sum = phi i64 [ 0, %entry ], [ %add, %for.body ] 2770f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 2780f37ba7bSWilliam Huang %add = add nsw i64 %sum, %urem 2790f37ba7bSWilliam Huang %i = ashr i64 %phi, %a 2800f37ba7bSWilliam Huang %icmp = icmp ugt i64 %i, 0 2810f37ba7bSWilliam Huang br i1 %icmp, label %for.body, label %for.end 2820f37ba7bSWilliam Huang 2830f37ba7bSWilliam Huangfor.end: 2840f37ba7bSWilliam Huang %r = phi i64 [ %sum, %for.body ] 2850f37ba7bSWilliam Huang ret i64 %r 2860f37ba7bSWilliam Huang} 2870f37ba7bSWilliam Huang 2880f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_loop_ashr_negative(i64 %size, i64 %a) { 2890f37ba7bSWilliam Huang; Cannot deduce induction variable is a power of 2 for ashr if its starting 2900f37ba7bSWilliam Huang; value is equal to sign bit 2910f37ba7bSWilliam Huang; 2920f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_loop_ashr_negative( 2930f37ba7bSWilliam Huang; CHECK-NEXT: entry: 2940f37ba7bSWilliam Huang; CHECK-NEXT: br label [[FOR_BODY:%.*]] 2950f37ba7bSWilliam Huang; CHECK: for.body: 296dfb36939SNikita Popov; CHECK-NEXT: br i1 true, label [[FOR_BODY]], label [[FOR_END:%.*]] 2970f37ba7bSWilliam Huang; CHECK: for.end: 298dfb36939SNikita Popov; CHECK-NEXT: ret i64 poison 2990f37ba7bSWilliam Huang; 3000f37ba7bSWilliam Huangentry: 3010f37ba7bSWilliam Huang br label %for.body 3020f37ba7bSWilliam Huang 3030f37ba7bSWilliam Huangfor.body: 3040f37ba7bSWilliam Huang %phi = phi i64 [ u0x8000000000000000, %entry ], [ %i, %for.body ] 3050f37ba7bSWilliam Huang %sum = phi i64 [ 0, %entry ], [ %add, %for.body ] 3060f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 3070f37ba7bSWilliam Huang %add = add nsw i64 %sum, %urem 3080f37ba7bSWilliam Huang %i = ashr i64 %phi, %a 309a1dec5daSNikita Popov %icmp = icmp ugt i64 %i, 1 3100f37ba7bSWilliam Huang br i1 %icmp, label %for.body, label %for.end 3110f37ba7bSWilliam Huang 3120f37ba7bSWilliam Huangfor.end: 3130f37ba7bSWilliam Huang %r = phi i64 [ %sum, %for.body ] 3140f37ba7bSWilliam Huang ret i64 %r 3150f37ba7bSWilliam Huang} 3160f37ba7bSWilliam Huang 3170f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_loop_ashr_negative_2(i64 %size, i64 %a) { 3180f37ba7bSWilliam Huang; Cannot deduce induction variable is a power of 2 for ashr if its starting 3190f37ba7bSWilliam Huang; value may equal to sign bit. 3200f37ba7bSWilliam Huang; 3210f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_loop_ashr_negative_2( 3220f37ba7bSWilliam Huang; CHECK-NEXT: entry: 3230f37ba7bSWilliam Huang; CHECK-NEXT: [[START:%.*]] = shl nuw i64 1, [[A:%.*]] 3240f37ba7bSWilliam Huang; CHECK-NEXT: br label [[FOR_BODY:%.*]] 3250f37ba7bSWilliam Huang; CHECK: for.body: 3260f37ba7bSWilliam Huang; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR_BODY]] ] 3270f37ba7bSWilliam Huang; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 3280f37ba7bSWilliam Huang; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[SIZE:%.*]], [[PHI]] 3290f37ba7bSWilliam Huang; CHECK-NEXT: [[ADD]] = add nsw i64 [[SUM]], [[UREM]] 3300f37ba7bSWilliam Huang; CHECK-NEXT: [[I]] = ashr i64 [[PHI]], 2 3310f37ba7bSWilliam Huang; CHECK-NEXT: [[ICMP_NOT:%.*]] = icmp ult i64 [[PHI]], 4 3320f37ba7bSWilliam Huang; CHECK-NEXT: br i1 [[ICMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 3330f37ba7bSWilliam Huang; CHECK: for.end: 3340f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[SUM]] 3350f37ba7bSWilliam Huang; 3360f37ba7bSWilliam Huangentry: 3370f37ba7bSWilliam Huang %start = shl nuw i64 1, %a 3380f37ba7bSWilliam Huang br label %for.body 3390f37ba7bSWilliam Huang 3400f37ba7bSWilliam Huangfor.body: 3410f37ba7bSWilliam Huang %phi = phi i64 [ %start, %entry ], [ %i, %for.body ] 3420f37ba7bSWilliam Huang %sum = phi i64 [ 0, %entry ], [ %add, %for.body ] 3430f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 3440f37ba7bSWilliam Huang %add = add nsw i64 %sum, %urem 3450f37ba7bSWilliam Huang %i = ashr i64 %phi, 2 3460f37ba7bSWilliam Huang %icmp = icmp ugt i64 %i, 0 3470f37ba7bSWilliam Huang br i1 %icmp, label %for.body, label %for.end 3480f37ba7bSWilliam Huang 3490f37ba7bSWilliam Huangfor.end: 3500f37ba7bSWilliam Huang %r = phi i64 [ %sum, %for.body ] 3510f37ba7bSWilliam Huang ret i64 %r 3520f37ba7bSWilliam Huang} 3530f37ba7bSWilliam Huang 3540f37ba7bSWilliam Huangdefine i64 @known_power_of_two_urem_loop_negative(i64 %size, i64 %a) { 3550f37ba7bSWilliam Huang; Cannot deduce induction variable is a power of 2 if the recurrence is not one 3560f37ba7bSWilliam Huang; of the valid arithmetic operations. 3570f37ba7bSWilliam Huang; 3580f37ba7bSWilliam Huang; CHECK-LABEL: @known_power_of_two_urem_loop_negative( 3590f37ba7bSWilliam Huang; CHECK-NEXT: entry: 3600f37ba7bSWilliam Huang; CHECK-NEXT: [[START:%.*]] = shl nuw i64 1, [[A:%.*]] 3610f37ba7bSWilliam Huang; CHECK-NEXT: br label [[FOR_BODY:%.*]] 3620f37ba7bSWilliam Huang; CHECK: for.body: 3630f37ba7bSWilliam Huang; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR_BODY]] ] 3640f37ba7bSWilliam Huang; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 3650f37ba7bSWilliam Huang; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[SIZE:%.*]], [[PHI]] 3660f37ba7bSWilliam Huang; CHECK-NEXT: [[ADD]] = add nuw i64 [[SUM]], [[UREM]] 3670f37ba7bSWilliam Huang; CHECK-NEXT: [[I]] = add nuw i64 [[PHI]], 1 368a1dec5daSNikita Popov; CHECK-NEXT: [[ICMP:%.*]] = icmp ugt i64 [[PHI]], 1 369a1dec5daSNikita Popov; CHECK-NEXT: br i1 [[ICMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 3700f37ba7bSWilliam Huang; CHECK: for.end: 3710f37ba7bSWilliam Huang; CHECK-NEXT: ret i64 [[SUM]] 3720f37ba7bSWilliam Huang; 3730f37ba7bSWilliam Huangentry: 3740f37ba7bSWilliam Huang %start = shl nuw i64 1, %a 3750f37ba7bSWilliam Huang br label %for.body 3760f37ba7bSWilliam Huang 3770f37ba7bSWilliam Huangfor.body: 3780f37ba7bSWilliam Huang %phi = phi i64 [ %start, %entry ], [ %i, %for.body ] 3790f37ba7bSWilliam Huang %sum = phi i64 [ 0, %entry ], [ %add, %for.body ] 3800f37ba7bSWilliam Huang %urem = urem i64 %size, %phi 3810f37ba7bSWilliam Huang %add = add nuw i64 %sum, %urem 3820f37ba7bSWilliam Huang %i = add nuw i64 %phi, 1 383a1dec5daSNikita Popov %icmp = icmp ugt i64 %i, 2 3840f37ba7bSWilliam Huang br i1 %icmp, label %for.body, label %for.end 3850f37ba7bSWilliam Huang 3860f37ba7bSWilliam Huangfor.end: 3870f37ba7bSWilliam Huang %r = phi i64 [ %sum, %for.body ] 3880f37ba7bSWilliam Huang ret i64 %r 3890f37ba7bSWilliam Huang} 390fd0ffb74SMonad 391fd0ffb74SMonad; https://alive2.llvm.org/ce/z/3QfEHm 392fd0ffb74SMonaddefine i8 @known_power_of_two_rust_next_power_of_two(i8 %x, i8 %y) { 393fd0ffb74SMonad; CHECK-LABEL: @known_power_of_two_rust_next_power_of_two( 394fd0ffb74SMonad; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X:%.*]], -1 395fd0ffb74SMonad; CHECK-NEXT: [[TMP2:%.*]] = tail call range(i8 0, 9) i8 @llvm.ctlz.i8(i8 [[TMP1]], i1 true) 396fd0ffb74SMonad; CHECK-NEXT: [[TMP3:%.*]] = lshr i8 -1, [[TMP2]] 397fd0ffb74SMonad; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i8 [[X]], 1 398fd0ffb74SMonad; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i8 [[TMP3]], i8 0 399*a1058776SNikita Popov; CHECK-NEXT: [[R:%.*]] = and i8 [[Y:%.*]], [[TMP5]] 400fd0ffb74SMonad; CHECK-NEXT: ret i8 [[R]] 401fd0ffb74SMonad; 402fd0ffb74SMonad %2 = add i8 %x, -1 403fd0ffb74SMonad %3 = tail call i8 @llvm.ctlz.i8(i8 %2, i1 true) 404fd0ffb74SMonad %4 = lshr i8 -1, %3 405fd0ffb74SMonad %5 = add i8 %4, 1 406fd0ffb74SMonad %6 = icmp ugt i8 %x, 1 407fd0ffb74SMonad %p = select i1 %6, i8 %5, i8 1 408fd0ffb74SMonad ; Rust's implementation of `%p = next_power_of_two(%x)` 409fd0ffb74SMonad 410fd0ffb74SMonad %r = urem i8 %y, %p 411fd0ffb74SMonad ret i8 %r 412fd0ffb74SMonad} 413fd0ffb74SMonad 414fd0ffb74SMonaddefine i8 @known_power_of_two_lshr_add_one_allow_zero(i8 %x, i8 %y) { 415fd0ffb74SMonad; CHECK-LABEL: @known_power_of_two_lshr_add_one_allow_zero( 416fd0ffb74SMonad; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[X:%.*]] 417*a1058776SNikita Popov; CHECK-NEXT: [[R:%.*]] = and i8 [[Y:%.*]], [[TMP1]] 418fd0ffb74SMonad; CHECK-NEXT: ret i8 [[R]] 419fd0ffb74SMonad; 420fd0ffb74SMonad %4 = lshr i8 -1, %x 421fd0ffb74SMonad %p = add i8 %4, 1 422fd0ffb74SMonad 423fd0ffb74SMonad ; Note: y % p --> y & (p - 1) allows p == 0 424fd0ffb74SMonad %r = urem i8 %y, %p 425fd0ffb74SMonad ret i8 %r 426fd0ffb74SMonad} 427fd0ffb74SMonad 428fd0ffb74SMonaddefine i1 @known_power_of_two_lshr_add_one_nuw_deny_zero(i8 %x, i8 %y) { 429fd0ffb74SMonad; CHECK-LABEL: @known_power_of_two_lshr_add_one_nuw_deny_zero( 430fd0ffb74SMonad; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[X:%.*]] 4315532ab17SNoah Goldstein; CHECK-NEXT: [[TMP2:%.*]] = sub i8 -2, [[TMP1]] 432*a1058776SNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[Y:%.*]], [[TMP2]] 4335532ab17SNoah Goldstein; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1 434fd0ffb74SMonad; CHECK-NEXT: ret i1 [[R]] 435fd0ffb74SMonad; 436fd0ffb74SMonad %4 = lshr i8 -1, %x 437fd0ffb74SMonad %p = add nuw i8 %4, 1 438fd0ffb74SMonad 439fd0ffb74SMonad ; Note: A & B_Pow2 != B_Pow2 --> A & B_Pow2 == 0 requires B_Pow2 != 0 440fd0ffb74SMonad %and = and i8 %p, %y 441fd0ffb74SMonad %r = icmp ne i8 %and, %p 442fd0ffb74SMonad ret i1 %r 443fd0ffb74SMonad} 444fd0ffb74SMonad 445fd0ffb74SMonaddefine i1 @negative_known_power_of_two_lshr_add_one_deny_zero(i8 %x, i8 %y) { 446fd0ffb74SMonad; CHECK-LABEL: @negative_known_power_of_two_lshr_add_one_deny_zero( 447fd0ffb74SMonad; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[X:%.*]] 4485532ab17SNoah Goldstein; CHECK-NEXT: [[TMP2:%.*]] = sub i8 -2, [[TMP1]] 449*a1058776SNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[Y:%.*]], [[TMP2]] 4505532ab17SNoah Goldstein; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1 451fd0ffb74SMonad; CHECK-NEXT: ret i1 [[R]] 452fd0ffb74SMonad; 453fd0ffb74SMonad %4 = lshr i8 -1, %x 454fd0ffb74SMonad %p = add i8 %4, 1 455fd0ffb74SMonad 456fd0ffb74SMonad ; Note: A & B_Pow2 != B_Pow2 --> A & B_Pow2 == 0 requires B_Pow2 != 0 457fd0ffb74SMonad %and = and i8 %p, %y 458fd0ffb74SMonad %r = icmp ne i8 %and, %p 459fd0ffb74SMonad ret i1 %r 460fd0ffb74SMonad} 461fd0ffb74SMonad 462fd0ffb74SMonaddefine i1 @negative_known_power_of_two_lshr_add_one_nsw_deny_zero(i8 %x, i8 %y) { 463fd0ffb74SMonad; CHECK-LABEL: @negative_known_power_of_two_lshr_add_one_nsw_deny_zero( 464fd0ffb74SMonad; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[X:%.*]] 4655532ab17SNoah Goldstein; CHECK-NEXT: [[TMP2:%.*]] = sub i8 -2, [[TMP1]] 466*a1058776SNikita Popov; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[Y:%.*]], [[TMP2]] 4675532ab17SNoah Goldstein; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1 468fd0ffb74SMonad; CHECK-NEXT: ret i1 [[R]] 469fd0ffb74SMonad; 470fd0ffb74SMonad %4 = lshr i8 -1, %x 471fd0ffb74SMonad %p = add nsw i8 %4, 1 472fd0ffb74SMonad 473fd0ffb74SMonad ; Note: A & B_Pow2 != B_Pow2 --> A & B_Pow2 == 0 requires B_Pow2 != 0 474fd0ffb74SMonad %and = and i8 %p, %y 475fd0ffb74SMonad %r = icmp ne i8 %and, %p 476fd0ffb74SMonad ret i1 %r 477fd0ffb74SMonad} 478fd0ffb74SMonad 479fd0ffb74SMonaddefine i8 @known_power_of_two_lshr_add_negative_1(i8 %x, i8 %y) { 480fd0ffb74SMonad; CHECK-LABEL: @known_power_of_two_lshr_add_negative_1( 481fd0ffb74SMonad; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -2, [[X:%.*]] 482fd0ffb74SMonad; CHECK-NEXT: [[P:%.*]] = add nuw i8 [[TMP1]], 1 483fd0ffb74SMonad; CHECK-NEXT: [[R:%.*]] = urem i8 [[Y:%.*]], [[P]] 484fd0ffb74SMonad; CHECK-NEXT: ret i8 [[R]] 485fd0ffb74SMonad; 486fd0ffb74SMonad %4 = lshr i8 -2, %x 487fd0ffb74SMonad %p = add i8 %4, 1 488fd0ffb74SMonad 489fd0ffb74SMonad %r = urem i8 %y, %p 490fd0ffb74SMonad ret i8 %r 491fd0ffb74SMonad} 492fd0ffb74SMonad 493fd0ffb74SMonaddefine i8 @known_power_of_two_lshr_add_negative_2(i8 %x, i8 %y) { 494fd0ffb74SMonad; CHECK-LABEL: @known_power_of_two_lshr_add_negative_2( 495fd0ffb74SMonad; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[X:%.*]] 496fd0ffb74SMonad; CHECK-NEXT: [[P:%.*]] = add nsw i8 [[TMP1]], -1 497fd0ffb74SMonad; CHECK-NEXT: [[R:%.*]] = urem i8 [[Y:%.*]], [[P]] 498fd0ffb74SMonad; CHECK-NEXT: ret i8 [[R]] 499fd0ffb74SMonad; 500fd0ffb74SMonad %4 = lshr i8 -1, %x 501fd0ffb74SMonad %p = add i8 %4, -1 502fd0ffb74SMonad 503fd0ffb74SMonad %r = urem i8 %y, %p 504fd0ffb74SMonad ret i8 %r 505fd0ffb74SMonad} 506