xref: /llvm-project/llvm/test/Analysis/ValueTracking/known-power-of-two-urem.ll (revision a105877646d68e48cdeeeadd9d1e075dc3c5d68d)
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