[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / test / Transforms / LoopIdiom / X86 / popcnt.ll
blob4c8920358d6ab2c05945d60ff04f4b853276df9a
1 ; RUN: opt -loop-idiom < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 -S | FileCheck %s
3 ;To recognize this pattern:
4 ;int popcount(unsigned long long a) {
5 ;    int c = 0;
6 ;    while (a) {
7 ;        c++;
8 ;        a &= a - 1;
9 ;    }
10 ;    return c;
12
13 ; CHECK: entry
14 ; CHECK: llvm.ctpop.i64
15 ; CHECK: ret
16 define i32 @popcount(i64 %a) nounwind uwtable readnone ssp {
17 entry:
18   %tobool3 = icmp eq i64 %a, 0
19   br i1 %tobool3, label %while.end, label %while.body
21 while.body:                                       ; preds = %entry, %while.body
22   %c.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
23   %a.addr.04 = phi i64 [ %and, %while.body ], [ %a, %entry ]
24   %inc = add nsw i32 %c.05, 1
25   %sub = add i64 %a.addr.04, -1
26   %and = and i64 %sub, %a.addr.04
27   %tobool = icmp eq i64 %and, 0
28   br i1 %tobool, label %while.end, label %while.body
30 while.end:                                        ; preds = %while.body, %entry
31   %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
32   ret i32 %c.0.lcssa
35 ; To recognize this pattern:
36 ;int popcount(unsigned long long a, int mydata1, int mydata2) {
37 ;    int c = 0;
38 ;    while (a) {
39 ;        c++;
40 ;        a &= a - 1;
41 ;        mydata1 *= c;
42 ;        mydata2 *= (int)a;
43 ;    }
44 ;    return c + mydata1 + mydata2;
46 ; CHECK: entry
47 ; CHECK: llvm.ctpop.i64
48 ; CHECK: ret
49 define i32 @popcount2(i64 %a, i32 %mydata1, i32 %mydata2) nounwind uwtable readnone ssp {
50 entry:
51   %tobool9 = icmp eq i64 %a, 0
52   br i1 %tobool9, label %while.end, label %while.body
54 while.body:                                       ; preds = %entry, %while.body
55   %c.013 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
56   %mydata2.addr.012 = phi i32 [ %mul1, %while.body ], [ %mydata2, %entry ]
57   %mydata1.addr.011 = phi i32 [ %mul, %while.body ], [ %mydata1, %entry ]
58   %a.addr.010 = phi i64 [ %and, %while.body ], [ %a, %entry ]
59   %inc = add nsw i32 %c.013, 1
60   %sub = add i64 %a.addr.010, -1
61   %and = and i64 %sub, %a.addr.010
62   %mul = mul nsw i32 %inc, %mydata1.addr.011
63   %conv = trunc i64 %and to i32
64   %mul1 = mul nsw i32 %conv, %mydata2.addr.012
65   %tobool = icmp eq i64 %and, 0
66   br i1 %tobool, label %while.end, label %while.body
68 while.end:                                        ; preds = %while.body, %entry
69   %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
70   %mydata2.addr.0.lcssa = phi i32 [ %mydata2, %entry ], [ %mul1, %while.body ]
71   %mydata1.addr.0.lcssa = phi i32 [ %mydata1, %entry ], [ %mul, %while.body ]
72   %add = add i32 %mydata2.addr.0.lcssa, %mydata1.addr.0.lcssa
73   %add2 = add i32 %add, %c.0.lcssa
74   ret i32 %add2
77 ; Some variants once cause crash
78 target triple = "x86_64-apple-macosx10.8.0"
80 define i32 @PopCntCrash1(i64 %a) nounwind uwtable readnone ssp {
81 entry:
82   %tobool3 = icmp eq i64 %a, 0
83   br i1 %tobool3, label %while.end, label %while.body
85 while.body:                                       ; preds = %entry, %while.body
86   %c.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
87   %a.addr.04 = phi i64 [ %and, %while.body ], [ %a, %entry ]
88   %t = add i32 %c.05, %c.05
89   %inc = add nsw i32 %t, 1
90   %sub = add i64 %a.addr.04, -1
91   %and = and i64 %sub, %a.addr.04
92   %tobool = icmp eq i64 %and, 0
93   br i1 %tobool, label %while.end, label %while.body
95 while.end:                                        ; preds = %while.body, %entry
96   %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
97   ret i32 %c.0.lcssa
99 ; CHECK: entry
100 ; CHECK: ret 
103 define i32 @PopCntCrash2(i64 %a, i32 %b) nounwind uwtable readnone ssp {
104 entry:
105   %tobool3 = icmp eq i64 %a, 0
106   br i1 %tobool3, label %while.end, label %while.body
108 while.body:                                       ; preds = %entry, %while.body
109   %c.05 = phi i32 [ %inc, %while.body ], [ %b, %entry ]
110   %a.addr.04 = phi i64 [ %and, %while.body ], [ %a, %entry ]
111   %inc = add nsw i32 %c.05, 1
112   %sub = add i64 %a.addr.04, -1
113   %and = and i64 %sub, %a.addr.04
114   %tobool = icmp eq i64 %and, 0
115   br i1 %tobool, label %while.end, label %while.body
117 while.end:                                        ; preds = %while.body, %entry
118   %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
119   ret i32 %c.0.lcssa
122 define i32 @PopCntCrash3(i64 %a, i32 %x) {
123 entry:
124   %tobool3 = icmp eq i64 %a, 0
125   %cmp = icmp eq i32 %x, 0
126   br i1 %tobool3, label %while.end, label %while.body
128 while.body:                                       ; preds = %entry, %while.body
129   %c.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
130   %a.addr.04 = phi i64 [ %and, %while.body ], [ %a, %entry ]
131   %inc = add nsw i32 %c.05, 1
132   %sub = add i64 %a.addr.04, -1
133   %and = and i64 %sub, %a.addr.04
134   %tobool = icmp eq i64 %and, 0
135   br i1 %cmp, label %while.end, label %while.body
137 while.end:                                        ; preds = %while.body, %entry
138   %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
139   ret i32 %c.0.lcssa
142 ; The a & (a - 1) in the loop is a & (b - 1) in this code. Make sure we don't
143 ; convert it.
144 define i32 @popcount_bad(i64 %a, i64 %b) nounwind uwtable readnone ssp {
145 ; CHECK-LABEL: @popcount_bad(
146 ; CHECK-NEXT:  entry:
147 ; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp eq i64 [[A:%.*]], 0
148 ; CHECK-NEXT:    br i1 [[TOBOOL3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]]
149 ; CHECK:       while.body.preheader:
150 ; CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
151 ; CHECK:       while.body:
152 ; CHECK-NEXT:    [[C_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ]
153 ; CHECK-NEXT:    [[A_ADDR_04:%.*]] = phi i64 [ [[AND:%.*]], [[WHILE_BODY]] ], [ [[A]], [[WHILE_BODY_PREHEADER]] ]
154 ; CHECK-NEXT:    [[INC]] = add nsw i32 [[C_05]], 1
155 ; CHECK-NEXT:    [[SUB:%.*]] = add i64 [[B:%.*]], -1
156 ; CHECK-NEXT:    [[AND]] = and i64 [[SUB]], [[A_ADDR_04]]
157 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[AND]], 0
158 ; CHECK-NEXT:    br i1 [[TOBOOL]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]]
159 ; CHECK:       while.end.loopexit:
160 ; CHECK-NEXT:    [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ]
161 ; CHECK-NEXT:    br label [[WHILE_END]]
162 ; CHECK:       while.end:
163 ; CHECK-NEXT:    [[C_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC_LCSSA]], [[WHILE_END_LOOPEXIT]] ]
164 ; CHECK-NEXT:    ret i32 [[C_0_LCSSA]]
166 entry:
167   %tobool3 = icmp eq i64 %a, 0
168   br i1 %tobool3, label %while.end, label %while.body
170 while.body:                                       ; preds = %entry, %while.body
171   %c.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
172   %a.addr.04 = phi i64 [ %and, %while.body ], [ %a, %entry ]
173   %inc = add nsw i32 %c.05, 1
174   %sub = add i64 %b, -1
175   %and = and i64 %sub, %a.addr.04
176   %tobool = icmp eq i64 %and, 0
177   br i1 %tobool, label %while.end, label %while.body
179 while.end:                                        ; preds = %while.body, %entry
180   %c.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
181   ret i32 %c.0.lcssa