xref: /llvm-project/llvm/test/Transforms/LoopIdiom/X86/cttz.ll (revision 48c6b2729e2111bec08799c65b8b459e12413546)
16e9e5389SCraig Topper; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2*48c6b272SRoman Lebedev; RUN: opt -passes=loop-idiom -mtriple=x86_64 -mcpu=core-avx2 < %s -S | FileCheck --check-prefix=ALL %s
3*48c6b272SRoman Lebedev; RUN: opt -passes=loop-idiom -mtriple=x86_64 -mcpu=corei7 < %s -S | FileCheck --check-prefix=ALL %s
4cee313d2SEric Christopher
5cee313d2SEric Christopher; Recognize CTTZ builtin pattern.
6cee313d2SEric Christopher; Here it will replace the loop -
7cee313d2SEric Christopher; assume builtin is always profitable.
8cee313d2SEric Christopher;
9cee313d2SEric Christopher; int cttz_zero_check(int n)
10cee313d2SEric Christopher; {
11cee313d2SEric Christopher;   int i = 0;
12cee313d2SEric Christopher;   while(n) {
13cee313d2SEric Christopher;     n <<= 1;
14cee313d2SEric Christopher;     i++;
15cee313d2SEric Christopher;   }
16cee313d2SEric Christopher;   return i;
17cee313d2SEric Christopher; }
18cee313d2SEric Christopher;
19cee313d2SEric Christopherdefine i32 @cttz_zero_check(i32 %n) {
206e9e5389SCraig Topper; ALL-LABEL: @cttz_zero_check(
216e9e5389SCraig Topper; ALL-NEXT:  entry:
226e9e5389SCraig Topper; ALL-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[N:%.*]], 0
236e9e5389SCraig Topper; ALL-NEXT:    br i1 [[TOBOOL4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
246e9e5389SCraig Topper; ALL:       while.body.preheader:
256e9e5389SCraig Topper; ALL-NEXT:    [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[N]], i1 true)
266e9e5389SCraig Topper; ALL-NEXT:    [[TMP1:%.*]] = sub i32 32, [[TMP0]]
276e9e5389SCraig Topper; ALL-NEXT:    br label [[WHILE_BODY:%.*]]
286e9e5389SCraig Topper; ALL:       while.body:
296e9e5389SCraig Topper; ALL-NEXT:    [[TCPHI:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TCDEC:%.*]], [[WHILE_BODY]] ]
306e9e5389SCraig Topper; ALL-NEXT:    [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
316e9e5389SCraig Topper; ALL-NEXT:    [[N_ADDR_05:%.*]] = phi i32 [ [[SHL:%.*]], [[WHILE_BODY]] ], [ [[N]], [[WHILE_BODY_PREHEADER]] ]
326e9e5389SCraig Topper; ALL-NEXT:    [[SHL]] = shl i32 [[N_ADDR_05]], 1
336e9e5389SCraig Topper; ALL-NEXT:    [[INC]] = add nsw i32 [[I_06]], 1
346e9e5389SCraig Topper; ALL-NEXT:    [[TCDEC]] = sub nsw i32 [[TCPHI]], 1
356e9e5389SCraig Topper; ALL-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TCDEC]], 0
366e9e5389SCraig Topper; ALL-NEXT:    br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
376e9e5389SCraig Topper; ALL:       while.end.loopexit:
386e9e5389SCraig Topper; ALL-NEXT:    [[INC_LCSSA:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY]] ]
396e9e5389SCraig Topper; ALL-NEXT:    br label [[WHILE_END]]
406e9e5389SCraig Topper; ALL:       while.end:
416e9e5389SCraig Topper; ALL-NEXT:    [[I_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
426e9e5389SCraig Topper; ALL-NEXT:    ret i32 [[I_0_LCSSA]]
436e9e5389SCraig Topper;
44cee313d2SEric Christopherentry:
45cee313d2SEric Christopher  %tobool4 = icmp eq i32 %n, 0
46cee313d2SEric Christopher  br i1 %tobool4, label %while.end, label %while.body.preheader
47cee313d2SEric Christopher
48cee313d2SEric Christopherwhile.body.preheader:                             ; preds = %entry
49cee313d2SEric Christopher  br label %while.body
50cee313d2SEric Christopher
51cee313d2SEric Christopherwhile.body:                                       ; preds = %while.body.preheader, %while.body
52cee313d2SEric Christopher  %i.06 = phi i32 [ %inc, %while.body ], [ 0, %while.body.preheader ]
53cee313d2SEric Christopher  %n.addr.05 = phi i32 [ %shl, %while.body ], [ %n, %while.body.preheader ]
54cee313d2SEric Christopher  %shl = shl i32 %n.addr.05, 1
55cee313d2SEric Christopher  %inc = add nsw i32 %i.06, 1
56cee313d2SEric Christopher  %tobool = icmp eq i32 %shl, 0
57cee313d2SEric Christopher  br i1 %tobool, label %while.end.loopexit, label %while.body
58cee313d2SEric Christopher
59cee313d2SEric Christopherwhile.end.loopexit:                               ; preds = %while.body
60cee313d2SEric Christopher  br label %while.end
61cee313d2SEric Christopher
62cee313d2SEric Christopherwhile.end:                                        ; preds = %while.end.loopexit, %entry
63cee313d2SEric Christopher  %i.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.end.loopexit ]
64cee313d2SEric Christopher  ret i32 %i.0.lcssa
65cee313d2SEric Christopher}
66cee313d2SEric Christopher
67cee313d2SEric Christopher; Recognize CTTZ builtin pattern.
68cee313d2SEric Christopher; Here it will replace the loop -
69cee313d2SEric Christopher; assume builtin is always profitable.
70cee313d2SEric Christopher;
71cee313d2SEric Christopher; int cttz(int n)
72cee313d2SEric Christopher; {
73cee313d2SEric Christopher;   int i = 0;
74cee313d2SEric Christopher;   while(n <<= 1) {
75cee313d2SEric Christopher;     i++;
76cee313d2SEric Christopher;   }
77cee313d2SEric Christopher;   return i;
78cee313d2SEric Christopher; }
79cee313d2SEric Christopher;
80cee313d2SEric Christopherdefine i32 @cttz(i32 %n) {
816e9e5389SCraig Topper; ALL-LABEL: @cttz(
826e9e5389SCraig Topper; ALL-NEXT:  entry:
836e9e5389SCraig Topper; ALL-NEXT:    [[TMP0:%.*]] = shl i32 [[N:%.*]], 1
846e9e5389SCraig Topper; ALL-NEXT:    [[TMP1:%.*]] = call i32 @llvm.cttz.i32(i32 [[TMP0]], i1 false)
856e9e5389SCraig Topper; ALL-NEXT:    [[TMP2:%.*]] = sub i32 32, [[TMP1]]
866e9e5389SCraig Topper; ALL-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], 1
876e9e5389SCraig Topper; ALL-NEXT:    br label [[WHILE_COND:%.*]]
886e9e5389SCraig Topper; ALL:       while.cond:
896e9e5389SCraig Topper; ALL-NEXT:    [[TCPHI:%.*]] = phi i32 [ [[TMP3]], [[ENTRY:%.*]] ], [ [[TCDEC:%.*]], [[WHILE_COND]] ]
906e9e5389SCraig Topper; ALL-NEXT:    [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[SHL:%.*]], [[WHILE_COND]] ]
916e9e5389SCraig Topper; ALL-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[WHILE_COND]] ]
926e9e5389SCraig Topper; ALL-NEXT:    [[SHL]] = shl i32 [[N_ADDR_0]], 1
936e9e5389SCraig Topper; ALL-NEXT:    [[TCDEC]] = sub nsw i32 [[TCPHI]], 1
946e9e5389SCraig Topper; ALL-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TCDEC]], 0
956e9e5389SCraig Topper; ALL-NEXT:    [[INC]] = add nsw i32 [[I_0]], 1
966e9e5389SCraig Topper; ALL-NEXT:    br i1 [[TOBOOL]], label [[WHILE_END:%.*]], label [[WHILE_COND]]
976e9e5389SCraig Topper; ALL:       while.end:
986e9e5389SCraig Topper; ALL-NEXT:    [[I_0_LCSSA:%.*]] = phi i32 [ [[TMP2]], [[WHILE_COND]] ]
996e9e5389SCraig Topper; ALL-NEXT:    ret i32 [[I_0_LCSSA]]
1006e9e5389SCraig Topper;
101cee313d2SEric Christopherentry:
102cee313d2SEric Christopher  br label %while.cond
103cee313d2SEric Christopher
104cee313d2SEric Christopherwhile.cond:                                       ; preds = %while.cond, %entry
105cee313d2SEric Christopher  %n.addr.0 = phi i32 [ %n, %entry ], [ %shl, %while.cond ]
106cee313d2SEric Christopher  %i.0 = phi i32 [ 0, %entry ], [ %inc, %while.cond ]
107cee313d2SEric Christopher  %shl = shl i32 %n.addr.0, 1
108cee313d2SEric Christopher  %tobool = icmp eq i32 %shl, 0
109cee313d2SEric Christopher  %inc = add nsw i32 %i.0, 1
110cee313d2SEric Christopher  br i1 %tobool, label %while.end, label %while.cond
111cee313d2SEric Christopher
112cee313d2SEric Christopherwhile.end:                                        ; preds = %while.cond
113cee313d2SEric Christopher  ret i32 %i.0
114cee313d2SEric Christopher}
115cee313d2SEric Christopher
1162acd5a47SCraig Topper; Recognize CTTZ builtin pattern.
1172acd5a47SCraig Topper; Here it will replace the loop -
1182acd5a47SCraig Topper; assume builtin is always profitable.
1192acd5a47SCraig Topper;
1202acd5a47SCraig Topper; int ctlz_decrement(int n)
1212acd5a47SCraig Topper; {
1222acd5a47SCraig Topper;   int i = 32;
1232acd5a47SCraig Topper;   while(n) {
1242acd5a47SCraig Topper;     n <<= 1;
1252acd5a47SCraig Topper;     i--;
1262acd5a47SCraig Topper;   }
1272acd5a47SCraig Topper;   return i;
1282acd5a47SCraig Topper; }
1292acd5a47SCraig Topper;
1302acd5a47SCraig Topperdefine i32 @cttz_decrement(i32 %n) {
1312acd5a47SCraig Topper; ALL-LABEL: @cttz_decrement(
1322acd5a47SCraig Topper; ALL-NEXT:  entry:
1332acd5a47SCraig Topper; ALL-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[N:%.*]], 0
1342acd5a47SCraig Topper; ALL-NEXT:    br i1 [[TOBOOL4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
1352acd5a47SCraig Topper; ALL:       while.body.preheader:
13625067f17SCraig Topper; ALL-NEXT:    [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[N]], i1 true)
13725067f17SCraig Topper; ALL-NEXT:    [[TMP1:%.*]] = sub i32 32, [[TMP0]]
13825067f17SCraig Topper; ALL-NEXT:    [[TMP2:%.*]] = sub i32 32, [[TMP1]]
1392acd5a47SCraig Topper; ALL-NEXT:    br label [[WHILE_BODY:%.*]]
1402acd5a47SCraig Topper; ALL:       while.body:
14125067f17SCraig Topper; ALL-NEXT:    [[TCPHI:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TCDEC:%.*]], [[WHILE_BODY]] ]
1422acd5a47SCraig Topper; ALL-NEXT:    [[I_06:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 32, [[WHILE_BODY_PREHEADER]] ]
1432acd5a47SCraig Topper; ALL-NEXT:    [[N_ADDR_05:%.*]] = phi i32 [ [[SHL:%.*]], [[WHILE_BODY]] ], [ [[N]], [[WHILE_BODY_PREHEADER]] ]
1442acd5a47SCraig Topper; ALL-NEXT:    [[SHL]] = shl i32 [[N_ADDR_05]], 1
1452acd5a47SCraig Topper; ALL-NEXT:    [[INC]] = add nsw i32 [[I_06]], -1
14625067f17SCraig Topper; ALL-NEXT:    [[TCDEC]] = sub nsw i32 [[TCPHI]], 1
14725067f17SCraig Topper; ALL-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TCDEC]], 0
1482acd5a47SCraig Topper; ALL-NEXT:    br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
1492acd5a47SCraig Topper; ALL:       while.end.loopexit:
15025067f17SCraig Topper; ALL-NEXT:    [[INC_LCSSA:%.*]] = phi i32 [ [[TMP2]], [[WHILE_BODY]] ]
1512acd5a47SCraig Topper; ALL-NEXT:    br label [[WHILE_END]]
1522acd5a47SCraig Topper; ALL:       while.end:
1532acd5a47SCraig Topper; ALL-NEXT:    [[I_0_LCSSA:%.*]] = phi i32 [ 32, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
1542acd5a47SCraig Topper; ALL-NEXT:    ret i32 [[I_0_LCSSA]]
1552acd5a47SCraig Topper;
1562acd5a47SCraig Topperentry:
1572acd5a47SCraig Topper  %tobool4 = icmp eq i32 %n, 0
1582acd5a47SCraig Topper  br i1 %tobool4, label %while.end, label %while.body.preheader
1592acd5a47SCraig Topper
1602acd5a47SCraig Topperwhile.body.preheader:                             ; preds = %entry
1612acd5a47SCraig Topper  br label %while.body
1622acd5a47SCraig Topper
1632acd5a47SCraig Topperwhile.body:                                       ; preds = %while.body.preheader, %while.body
1642acd5a47SCraig Topper  %i.06 = phi i32 [ %inc, %while.body ], [ 32, %while.body.preheader ]
1652acd5a47SCraig Topper  %n.addr.05 = phi i32 [ %shl, %while.body ], [ %n, %while.body.preheader ]
1662acd5a47SCraig Topper  %shl = shl i32 %n.addr.05, 1
1672acd5a47SCraig Topper  %inc = add nsw i32 %i.06, -1
1682acd5a47SCraig Topper  %tobool = icmp eq i32 %shl, 0
1692acd5a47SCraig Topper  br i1 %tobool, label %while.end.loopexit, label %while.body
1702acd5a47SCraig Topper
1712acd5a47SCraig Topperwhile.end.loopexit:                               ; preds = %while.body
1722acd5a47SCraig Topper  br label %while.end
1732acd5a47SCraig Topper
1742acd5a47SCraig Topperwhile.end:                                        ; preds = %while.end.loopexit, %entry
1752acd5a47SCraig Topper  %i.0.lcssa = phi i32 [ 32, %entry ], [ %inc, %while.end.loopexit ]
1762acd5a47SCraig Topper  ret i32 %i.0.lcssa
1772acd5a47SCraig Topper}
1782acd5a47SCraig Topper
1792acd5a47SCraig Topper; Recognize CTTZ builtin pattern.
1802acd5a47SCraig Topper; Here it will replace the loop -
1812acd5a47SCraig Topper; assume builtin is always profitable.
1822acd5a47SCraig Topper;
1832acd5a47SCraig Topper; int cttz_shl_decrement(int n)
1842acd5a47SCraig Topper; {
1852acd5a47SCraig Topper;   int i = 31;
1862acd5a47SCraig Topper;   while(n <<= 1) {
1872acd5a47SCraig Topper;     i--;
1882acd5a47SCraig Topper;   }
1892acd5a47SCraig Topper;   return i;
1902acd5a47SCraig Topper; }
1912acd5a47SCraig Topper;
1922acd5a47SCraig Topperdefine i32 @cttz_shl_decrement(i32 %n) {
1932acd5a47SCraig Topper; ALL-LABEL: @cttz_shl_decrement(
1942acd5a47SCraig Topper; ALL-NEXT:  entry:
19525067f17SCraig Topper; ALL-NEXT:    [[TMP0:%.*]] = shl i32 [[N:%.*]], 1
19625067f17SCraig Topper; ALL-NEXT:    [[TMP1:%.*]] = call i32 @llvm.cttz.i32(i32 [[TMP0]], i1 false)
19725067f17SCraig Topper; ALL-NEXT:    [[TMP2:%.*]] = sub i32 32, [[TMP1]]
19825067f17SCraig Topper; ALL-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], 1
19925067f17SCraig Topper; ALL-NEXT:    [[TMP4:%.*]] = sub i32 31, [[TMP2]]
2002acd5a47SCraig Topper; ALL-NEXT:    br label [[WHILE_COND:%.*]]
2012acd5a47SCraig Topper; ALL:       while.cond:
20225067f17SCraig Topper; ALL-NEXT:    [[TCPHI:%.*]] = phi i32 [ [[TMP3]], [[ENTRY:%.*]] ], [ [[TCDEC:%.*]], [[WHILE_COND]] ]
20325067f17SCraig Topper; ALL-NEXT:    [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[SHL:%.*]], [[WHILE_COND]] ]
2042acd5a47SCraig Topper; ALL-NEXT:    [[I_0:%.*]] = phi i32 [ 31, [[ENTRY]] ], [ [[INC:%.*]], [[WHILE_COND]] ]
2052acd5a47SCraig Topper; ALL-NEXT:    [[SHL]] = shl i32 [[N_ADDR_0]], 1
20625067f17SCraig Topper; ALL-NEXT:    [[TCDEC]] = sub nsw i32 [[TCPHI]], 1
20725067f17SCraig Topper; ALL-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TCDEC]], 0
2082acd5a47SCraig Topper; ALL-NEXT:    [[INC]] = add nsw i32 [[I_0]], -1
2092acd5a47SCraig Topper; ALL-NEXT:    br i1 [[TOBOOL]], label [[WHILE_END:%.*]], label [[WHILE_COND]]
2102acd5a47SCraig Topper; ALL:       while.end:
21125067f17SCraig Topper; ALL-NEXT:    [[I_0_LCSSA:%.*]] = phi i32 [ [[TMP4]], [[WHILE_COND]] ]
2122acd5a47SCraig Topper; ALL-NEXT:    ret i32 [[I_0_LCSSA]]
2132acd5a47SCraig Topper;
2142acd5a47SCraig Topperentry:
2152acd5a47SCraig Topper  br label %while.cond
2162acd5a47SCraig Topper
2172acd5a47SCraig Topperwhile.cond:                                       ; preds = %while.cond, %entry
2182acd5a47SCraig Topper  %n.addr.0 = phi i32 [ %n, %entry ], [ %shl, %while.cond ]
2192acd5a47SCraig Topper  %i.0 = phi i32 [ 31, %entry ], [ %inc, %while.cond ]
2202acd5a47SCraig Topper  %shl = shl i32 %n.addr.0, 1
2212acd5a47SCraig Topper  %tobool = icmp eq i32 %shl, 0
2222acd5a47SCraig Topper  %inc = add nsw i32 %i.0, -1
2232acd5a47SCraig Topper  br i1 %tobool, label %while.end, label %while.cond
2242acd5a47SCraig Topper
2252acd5a47SCraig Topperwhile.end:                                        ; preds = %while.cond
2262acd5a47SCraig Topper  ret i32 %i.0
2272acd5a47SCraig Topper}
228