1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -mtriple=thumbv8.1m.main -simplifycfg -S %s -o - | FileCheck %s --check-prefix=V8M
3; RUN: opt -mtriple=thumbv8m.main -simplifycfg -S %s -o - | FileCheck %s --check-prefix=V8M
4; RUN: opt -mtriple=thumbv8m.base -simplifycfg -S %s -o - | FileCheck %s --check-prefix=V8M
5; RUN: opt -mtriple=armv8a -simplifycfg -S %s -o - | FileCheck %s --check-prefix=V8A
6
7; Test that the phis from for.inc.preheader aren't hoisted into sw.bb92 because
8; the cost is too great - we can make a better decision later on.
9; FIXME: The Arm cost model needs to be updated for SizeAndLatency.
10define i32 @multiple_spec_select_costs(i8* %a, i32* %idx, i8 %in) {
11; V8M-LABEL: @multiple_spec_select_costs(
12; V8M-NEXT:  entry:
13; V8M-NEXT:    [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2
14; V8M-NEXT:    [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3
15; V8M-NEXT:    [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0
16; V8M-NEXT:    br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]]
17; V8M:       sw.bb92:
18; V8M-NEXT:    [[C_OFF_I150:%.*]] = add i8 [[IN]], -48
19; V8M-NEXT:    [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9
20; V8M-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[UGT_9]], i1 false, i1 true
21; V8M-NEXT:    [[SPEC_SELECT1:%.*]] = select i1 [[UGT_9]], i32 1, i32 7
22; V8M-NEXT:    br label [[FOR_INC_PREHEADER]]
23; V8M:       for.inc.preheader:
24; V8M-NEXT:    [[STR_PH_0:%.*]] = phi i8* [ [[GEP_A_2]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ]
25; V8M-NEXT:    [[CMP:%.*]] = phi i1 [ false, [[ENTRY]] ], [ [[SPEC_SELECT]], [[SW_BB92]] ]
26; V8M-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[SPEC_SELECT1]], [[SW_BB92]] ]
27; V8M-NEXT:    br label [[FOR_INC:%.*]]
28; V8M:       for.inc:
29; V8M-NEXT:    [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ]
30; V8M-NEXT:    [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1
31; V8M-NEXT:    [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1
32; V8M-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0
33; V8M-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]]
34; V8M-NEXT:    br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]]
35; V8M:       for.body:
36; V8M-NEXT:    [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1
37; V8M-NEXT:    br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]]
38; V8M:       exit:
39; V8M-NEXT:    ret i32 [[PHI_RES]]
40;
41; V8A-LABEL: @multiple_spec_select_costs(
42; V8A-NEXT:  entry:
43; V8A-NEXT:    [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2
44; V8A-NEXT:    [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3
45; V8A-NEXT:    [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0
46; V8A-NEXT:    br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]]
47; V8A:       sw.bb92:
48; V8A-NEXT:    [[C_OFF_I150:%.*]] = add i8 [[IN]], -48
49; V8A-NEXT:    [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9
50; V8A-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[UGT_9]], i1 false, i1 true
51; V8A-NEXT:    [[SPEC_SELECT1:%.*]] = select i1 [[UGT_9]], i32 1, i32 7
52; V8A-NEXT:    br label [[FOR_INC_PREHEADER]]
53; V8A:       for.inc.preheader:
54; V8A-NEXT:    [[STR_PH_0:%.*]] = phi i8* [ [[GEP_A_2]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ]
55; V8A-NEXT:    [[CMP:%.*]] = phi i1 [ false, [[ENTRY]] ], [ [[SPEC_SELECT]], [[SW_BB92]] ]
56; V8A-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[SPEC_SELECT1]], [[SW_BB92]] ]
57; V8A-NEXT:    br label [[FOR_INC:%.*]]
58; V8A:       for.inc:
59; V8A-NEXT:    [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ]
60; V8A-NEXT:    [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1
61; V8A-NEXT:    [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1
62; V8A-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0
63; V8A-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]]
64; V8A-NEXT:    br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]]
65; V8A:       for.body:
66; V8A-NEXT:    [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1
67; V8A-NEXT:    br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]]
68; V8A:       exit:
69; V8A-NEXT:    ret i32 [[PHI_RES]]
70;
71entry:
72  %gep.a.2 = getelementptr inbounds i8, i8* %a, i32 2
73  %incdec.ptr109.c4 = getelementptr inbounds i8, i8* %a, i32 3
74  %zero = icmp ne i8 %in, 0
75  br i1 %zero , label %for.inc.preheader, label %sw.bb92
76
77sw.bb92:
78  %c.off.i150 = add i8 %in, -48
79  %ugt.9 = icmp ugt i8 %c.off.i150, 9
80  br i1 %ugt.9, label %for.inc.preheader, label %select.unfold198
81
82select.unfold198:
83  br label %for.inc.preheader
84
85for.inc.preheader:
86  %str.ph.0 = phi i8* [ %incdec.ptr109.c4, %select.unfold198 ], [ %incdec.ptr109.c4, %sw.bb92 ], [ %gep.a.2, %entry ]
87  %cmp = phi i1 [ true, %select.unfold198 ], [ false, %sw.bb92 ], [ false, %entry ]
88  %phi.res = phi i32 [ 7, %select.unfold198 ], [ 1, %sw.bb92 ], [ 1, %entry ]
89  br label %for.inc
90
91for.inc:
92  %str.ph.1 = phi i8* [ %incdec.ptr109, %for.body ], [ %str.ph.0, %for.inc.preheader ]
93  %incdec.ptr109 = getelementptr inbounds i8, i8* %str.ph.1, i32 1
94  %load.1 = load i8, i8* %incdec.ptr109, align 1
95  %tobool = icmp ne i8 %load.1, 0
96  %and = and i1 %cmp, %tobool
97  br i1 %and, label %for.body, label %exit
98
99for.body:
100  %cmp.1 = icmp eq i8 %load.1, 1
101  br i1 %cmp.1, label %for.inc, label %sw.bb92
102
103exit:
104  ret i32 %phi.res
105}
106
107define i32 @multiple_spec_select_costs_minsize(i8* %a, i32* %idx, i8 %in) #0 {
108; V8M-LABEL: @multiple_spec_select_costs_minsize(
109; V8M-NEXT:  entry:
110; V8M-NEXT:    [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2
111; V8M-NEXT:    [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3
112; V8M-NEXT:    [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0
113; V8M-NEXT:    br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]]
114; V8M:       sw.bb92:
115; V8M-NEXT:    [[C_OFF_I150:%.*]] = add i8 [[IN]], -48
116; V8M-NEXT:    [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9
117; V8M-NEXT:    br i1 [[UGT_9]], label [[FOR_INC_PREHEADER]], label [[SELECT_UNFOLD198:%.*]]
118; V8M:       select.unfold198:
119; V8M-NEXT:    br label [[FOR_INC_PREHEADER]]
120; V8M:       for.inc.preheader:
121; V8M-NEXT:    [[STR_PH_0:%.*]] = phi i8* [ [[INCDEC_PTR109_C4]], [[SELECT_UNFOLD198]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ], [ [[GEP_A_2]], [[ENTRY:%.*]] ]
122; V8M-NEXT:    [[CMP:%.*]] = phi i1 [ true, [[SELECT_UNFOLD198]] ], [ false, [[SW_BB92]] ], [ false, [[ENTRY]] ]
123; V8M-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 7, [[SELECT_UNFOLD198]] ], [ 1, [[SW_BB92]] ], [ 1, [[ENTRY]] ]
124; V8M-NEXT:    br label [[FOR_INC:%.*]]
125; V8M:       for.inc:
126; V8M-NEXT:    [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ]
127; V8M-NEXT:    [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1
128; V8M-NEXT:    [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1
129; V8M-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0
130; V8M-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]]
131; V8M-NEXT:    br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]]
132; V8M:       for.body:
133; V8M-NEXT:    [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1
134; V8M-NEXT:    br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]]
135; V8M:       exit:
136; V8M-NEXT:    ret i32 [[PHI_RES]]
137;
138; V8A-LABEL: @multiple_spec_select_costs_minsize(
139; V8A-NEXT:  entry:
140; V8A-NEXT:    [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2
141; V8A-NEXT:    [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3
142; V8A-NEXT:    [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0
143; V8A-NEXT:    br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]]
144; V8A:       sw.bb92:
145; V8A-NEXT:    [[C_OFF_I150:%.*]] = add i8 [[IN]], -48
146; V8A-NEXT:    [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9
147; V8A-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[UGT_9]], i1 false, i1 true
148; V8A-NEXT:    [[SPEC_SELECT1:%.*]] = select i1 [[UGT_9]], i32 1, i32 7
149; V8A-NEXT:    br label [[FOR_INC_PREHEADER]]
150; V8A:       for.inc.preheader:
151; V8A-NEXT:    [[STR_PH_0:%.*]] = phi i8* [ [[GEP_A_2]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ]
152; V8A-NEXT:    [[CMP:%.*]] = phi i1 [ false, [[ENTRY]] ], [ [[SPEC_SELECT]], [[SW_BB92]] ]
153; V8A-NEXT:    [[PHI_RES:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[SPEC_SELECT1]], [[SW_BB92]] ]
154; V8A-NEXT:    br label [[FOR_INC:%.*]]
155; V8A:       for.inc:
156; V8A-NEXT:    [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ]
157; V8A-NEXT:    [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1
158; V8A-NEXT:    [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1
159; V8A-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0
160; V8A-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]]
161; V8A-NEXT:    br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]]
162; V8A:       for.body:
163; V8A-NEXT:    [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1
164; V8A-NEXT:    br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]]
165; V8A:       exit:
166; V8A-NEXT:    ret i32 [[PHI_RES]]
167;
168entry:
169  %gep.a.2 = getelementptr inbounds i8, i8* %a, i32 2
170  %incdec.ptr109.c4 = getelementptr inbounds i8, i8* %a, i32 3
171  %zero = icmp ne i8 %in, 0
172  br i1 %zero , label %for.inc.preheader, label %sw.bb92
173
174sw.bb92:
175  %c.off.i150 = add i8 %in, -48
176  %ugt.9 = icmp ugt i8 %c.off.i150, 9
177  br i1 %ugt.9, label %for.inc.preheader, label %select.unfold198
178
179select.unfold198:
180  br label %for.inc.preheader
181
182for.inc.preheader:
183  %str.ph.0 = phi i8* [ %incdec.ptr109.c4, %select.unfold198 ], [ %incdec.ptr109.c4, %sw.bb92 ], [ %gep.a.2, %entry ]
184  %cmp = phi i1 [ true, %select.unfold198 ], [ false, %sw.bb92 ], [ false, %entry ]
185  %phi.res = phi i32 [ 7, %select.unfold198 ], [ 1, %sw.bb92 ], [ 1, %entry ]
186  br label %for.inc
187
188for.inc:
189  %str.ph.1 = phi i8* [ %incdec.ptr109, %for.body ], [ %str.ph.0, %for.inc.preheader ]
190  %incdec.ptr109 = getelementptr inbounds i8, i8* %str.ph.1, i32 1
191  %load.1 = load i8, i8* %incdec.ptr109, align 1
192  %tobool = icmp ne i8 %load.1, 0
193  %and = and i1 %cmp, %tobool
194  br i1 %and, label %for.body, label %exit
195
196for.body:
197  %cmp.1 = icmp eq i8 %load.1, 1
198  br i1 %cmp.1, label %for.inc, label %sw.bb92
199
200exit:
201  ret i32 %phi.res
202}
203
204attributes #0 = { minsize optsize }
205