1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -mtriple=armv7-apple-darwin < %s -codegenprepare -S | FileCheck -check-prefix=NEON %s
3; RUN: opt -mtriple=armv6-unknown-linux < %s -codegenprepare -S | FileCheck -check-prefix=NONEON %s
4
5define <8 x i16> @sink_zext(<8 x i8> %a, <8 x i8> %b, i1 %c) {
6; NEON-LABEL: @sink_zext(
7; NEON-NEXT:  entry:
8; NEON-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
9; NEON:       if.then:
10; NEON-NEXT:    [[ZB_1:%.*]] = zext <8 x i8> [[B:%.*]] to <8 x i16>
11; NEON-NEXT:    [[TMP0:%.*]] = zext <8 x i8> [[A:%.*]] to <8 x i16>
12; NEON-NEXT:    [[RES_1:%.*]] = add <8 x i16> [[TMP0]], [[ZB_1]]
13; NEON-NEXT:    ret <8 x i16> [[RES_1]]
14; NEON:       if.else:
15; NEON-NEXT:    [[ZB_2:%.*]] = zext <8 x i8> [[B]] to <8 x i16>
16; NEON-NEXT:    [[TMP1:%.*]] = zext <8 x i8> [[A]] to <8 x i16>
17; NEON-NEXT:    [[RES_2:%.*]] = sub <8 x i16> [[TMP1]], [[ZB_2]]
18; NEON-NEXT:    ret <8 x i16> [[RES_2]]
19;
20; NONEON-LABEL: @sink_zext(
21; NONEON-NEXT:  entry:
22; NONEON-NEXT:    [[ZA:%.*]] = zext <8 x i8> [[A:%.*]] to <8 x i16>
23; NONEON-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
24; NONEON:       if.then:
25; NONEON-NEXT:    [[ZB_1:%.*]] = zext <8 x i8> [[B:%.*]] to <8 x i16>
26; NONEON-NEXT:    [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[ZB_1]]
27; NONEON-NEXT:    ret <8 x i16> [[RES_1]]
28; NONEON:       if.else:
29; NONEON-NEXT:    [[ZB_2:%.*]] = zext <8 x i8> [[B]] to <8 x i16>
30; NONEON-NEXT:    [[RES_2:%.*]] = sub <8 x i16> [[ZA]], [[ZB_2]]
31; NONEON-NEXT:    ret <8 x i16> [[RES_2]]
32;
33entry:
34  %za = zext <8 x i8> %a to <8 x i16>
35  br i1 %c, label %if.then, label %if.else
36
37if.then:
38  %zb.1 = zext <8 x i8> %b to <8 x i16>
39  %res.1 = add <8 x i16> %za, %zb.1
40  ret <8 x i16> %res.1
41
42if.else:
43  %zb.2 = zext <8 x i8> %b to <8 x i16>
44  %res.2 = sub <8 x i16> %za, %zb.2
45  ret <8 x i16> %res.2
46}
47
48define <8 x i16> @sink_sext(<8 x i8> %a, <8 x i8> %b, i1 %c) {
49; NEON-LABEL: @sink_sext(
50; NEON-NEXT:  entry:
51; NEON-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
52; NEON:       if.then:
53; NEON-NEXT:    [[ZB_1:%.*]] = sext <8 x i8> [[B:%.*]] to <8 x i16>
54; NEON-NEXT:    [[TMP0:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16>
55; NEON-NEXT:    [[RES_1:%.*]] = add <8 x i16> [[TMP0]], [[ZB_1]]
56; NEON-NEXT:    ret <8 x i16> [[RES_1]]
57; NEON:       if.else:
58; NEON-NEXT:    [[ZB_2:%.*]] = sext <8 x i8> [[B]] to <8 x i16>
59; NEON-NEXT:    [[TMP1:%.*]] = sext <8 x i8> [[A]] to <8 x i16>
60; NEON-NEXT:    [[RES_2:%.*]] = sub <8 x i16> [[TMP1]], [[ZB_2]]
61; NEON-NEXT:    ret <8 x i16> [[RES_2]]
62;
63; NONEON-LABEL: @sink_sext(
64; NONEON-NEXT:  entry:
65; NONEON-NEXT:    [[ZA:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16>
66; NONEON-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
67; NONEON:       if.then:
68; NONEON-NEXT:    [[ZB_1:%.*]] = sext <8 x i8> [[B:%.*]] to <8 x i16>
69; NONEON-NEXT:    [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[ZB_1]]
70; NONEON-NEXT:    ret <8 x i16> [[RES_1]]
71; NONEON:       if.else:
72; NONEON-NEXT:    [[ZB_2:%.*]] = sext <8 x i8> [[B]] to <8 x i16>
73; NONEON-NEXT:    [[RES_2:%.*]] = sub <8 x i16> [[ZA]], [[ZB_2]]
74; NONEON-NEXT:    ret <8 x i16> [[RES_2]]
75;
76entry:
77  %za = sext <8 x i8> %a to <8 x i16>
78  br i1 %c, label %if.then, label %if.else
79
80if.then:
81  %zb.1 = sext <8 x i8> %b to <8 x i16>
82  %res.1 = add <8 x i16> %za, %zb.1
83  ret <8 x i16> %res.1
84
85if.else:
86  %zb.2 = sext <8 x i8> %b to <8 x i16>
87  %res.2 = sub <8 x i16> %za, %zb.2
88  ret <8 x i16> %res.2
89}
90
91define <8 x i16> @do_not_sink_nonfree_zext(<8 x i8> %a, <8 x i16> %b, i1 %c) {
92;
93; NEON-LABEL: @do_not_sink_nonfree_zext(
94; NEON-NEXT:  entry:
95; NEON-NEXT:    [[ZA:%.*]] = zext <8 x i8> [[A:%.*]] to <8 x i16>
96; NEON-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
97; NEON:       if.then:
98; NEON-NEXT:    [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[B:%.*]]
99; NEON-NEXT:    ret <8 x i16> [[RES_1]]
100; NEON:       if.else:
101; NEON-NEXT:    ret <8 x i16> [[B]]
102;
103; NONEON-LABEL: @do_not_sink_nonfree_zext(
104; NONEON-NEXT:  entry:
105; NONEON-NEXT:    [[ZA:%.*]] = zext <8 x i8> [[A:%.*]] to <8 x i16>
106; NONEON-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
107; NONEON:       if.then:
108; NONEON-NEXT:    [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[B:%.*]]
109; NONEON-NEXT:    ret <8 x i16> [[RES_1]]
110; NONEON:       if.else:
111; NONEON-NEXT:    ret <8 x i16> [[B]]
112;
113entry:
114  %za = zext <8 x i8> %a to <8 x i16>
115  br i1 %c, label %if.then, label %if.else
116
117if.then:
118  %res.1 = add <8 x i16> %za, %b
119  ret <8 x i16> %res.1
120
121if.else:
122  ret <8 x i16> %b
123}
124
125define <8 x i16> @do_not_sink_nonfree_sext(<8 x i8> %a, <8 x i16> %b, i1 %c) {
126; CHECK-LABEL: @do_not_sink_nonfree_sext(
127; CHECK-NEXT:  entry:
128; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
129; CHECK:       if.then:
130; CHECK-NEXT:    [[ZB_1:%.*]] = sext <8 x i8> [[B:%.*]] to <8 x i16>
131; CHECK-NEXT:    [[TMP0:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16>
132; CHECK-NEXT:    [[RES_1:%.*]] = add <8 x i16> [[TMP0]], [[ZB_1]]
133; CHECK-NEXT:    ret <8 x i16> [[RES_1]]
134; CHECK:       if.else:
135; CHECK-NEXT:    [[ZB_2:%.*]] = sext <8 x i8> [[B]] to <8 x i16>
136; CHECK-NEXT:    ret <8 x i16> [[ZB_2]]
137;
138; NEON-LABEL: @do_not_sink_nonfree_sext(
139; NEON-NEXT:  entry:
140; NEON-NEXT:    [[ZA:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16>
141; NEON-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
142; NEON:       if.then:
143; NEON-NEXT:    [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[B:%.*]]
144; NEON-NEXT:    ret <8 x i16> [[RES_1]]
145; NEON:       if.else:
146; NEON-NEXT:    ret <8 x i16> [[B]]
147;
148; NONEON-LABEL: @do_not_sink_nonfree_sext(
149; NONEON-NEXT:  entry:
150; NONEON-NEXT:    [[ZA:%.*]] = sext <8 x i8> [[A:%.*]] to <8 x i16>
151; NONEON-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
152; NONEON:       if.then:
153; NONEON-NEXT:    [[RES_1:%.*]] = add <8 x i16> [[ZA]], [[B:%.*]]
154; NONEON-NEXT:    ret <8 x i16> [[RES_1]]
155; NONEON:       if.else:
156; NONEON-NEXT:    ret <8 x i16> [[B]]
157;
158entry:
159  %za = sext <8 x i8> %a to <8 x i16>
160  br i1 %c, label %if.then, label %if.else
161
162if.then:
163  %res.1 = add <8 x i16> %za, %b
164  ret <8 x i16> %res.1
165
166if.else:
167  ret <8 x i16> %b
168}
169
170declare void @user1(<8 x i16>)
171
172; Exts can be sunk.
173define <8 x i16> @sink_shufflevector_ext_subadd_multiuse(<16 x i8> %a, <16 x i8> %b) {
174; NEON-LABEL: @sink_shufflevector_ext_subadd_multiuse(
175; NEON-NEXT:  entry:
176; NEON-NEXT:    [[S1:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
177; NEON-NEXT:    [[S3:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
178; NEON-NEXT:    [[Z3:%.*]] = sext <8 x i8> [[S3]] to <8 x i16>
179; NEON-NEXT:    call void @user1(<8 x i16> [[Z3]])
180; NEON-NEXT:    br i1 undef, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
181; NEON:       if.then:
182; NEON-NEXT:    [[S2:%.*]] = shufflevector <16 x i8> [[B:%.*]], <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
183; NEON-NEXT:    [[Z2:%.*]] = zext <8 x i8> [[S2]] to <8 x i16>
184; NEON-NEXT:    [[TMP0:%.*]] = zext <8 x i8> [[S1]] to <8 x i16>
185; NEON-NEXT:    [[RES1:%.*]] = add <8 x i16> [[TMP0]], [[Z2]]
186; NEON-NEXT:    ret <8 x i16> [[RES1]]
187; NEON:       if.else:
188; NEON-NEXT:    [[S4:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
189; NEON-NEXT:    [[Z4:%.*]] = sext <8 x i8> [[S4]] to <8 x i16>
190; NEON-NEXT:    [[TMP1:%.*]] = sext <8 x i8> [[S3]] to <8 x i16>
191; NEON-NEXT:    [[RES2:%.*]] = sub <8 x i16> [[TMP1]], [[Z4]]
192; NEON-NEXT:    ret <8 x i16> [[RES2]]
193;
194; NONEON-LABEL: @sink_shufflevector_ext_subadd_multiuse(
195; NONEON-NEXT:  entry:
196; NONEON-NEXT:    [[S1:%.*]] = shufflevector <16 x i8> [[A:%.*]], <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
197; NONEON-NEXT:    [[Z1:%.*]] = zext <8 x i8> [[S1]] to <8 x i16>
198; NONEON-NEXT:    [[S3:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
199; NONEON-NEXT:    [[Z3:%.*]] = sext <8 x i8> [[S3]] to <8 x i16>
200; NONEON-NEXT:    call void @user1(<8 x i16> [[Z3]])
201; NONEON-NEXT:    br i1 undef, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
202; NONEON:       if.then:
203; NONEON-NEXT:    [[S2:%.*]] = shufflevector <16 x i8> [[B:%.*]], <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
204; NONEON-NEXT:    [[Z2:%.*]] = zext <8 x i8> [[S2]] to <8 x i16>
205; NONEON-NEXT:    [[RES1:%.*]] = add <8 x i16> [[Z1]], [[Z2]]
206; NONEON-NEXT:    ret <8 x i16> [[RES1]]
207; NONEON:       if.else:
208; NONEON-NEXT:    [[S4:%.*]] = shufflevector <16 x i8> [[B]], <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
209; NONEON-NEXT:    [[Z4:%.*]] = sext <8 x i8> [[S4]] to <8 x i16>
210; NONEON-NEXT:    [[RES2:%.*]] = sub <8 x i16> [[Z3]], [[Z4]]
211; NONEON-NEXT:    ret <8 x i16> [[RES2]]
212;
213entry:
214  %s1 = shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
215  %z1 = zext <8 x i8> %s1 to <8 x i16>
216  %s3 = shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
217  %z3 = sext <8 x i8> %s3 to <8 x i16>
218  call void @user1(<8 x i16> %z3)
219  br i1 undef, label %if.then, label %if.else
220
221if.then:
222  %s2 = shufflevector <16 x i8> %b, <16 x i8> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
223  %z2 = zext <8 x i8> %s2 to <8 x i16>
224  %res1 = add <8 x i16> %z1, %z2
225  ret <8 x i16> %res1
226
227if.else:
228  %s4 = shufflevector <16 x i8> %b, <16 x i8> undef, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
229  %z4 = sext <8 x i8> %s4 to <8 x i16>
230  %res2 = sub <8 x i16> %z3, %z4
231  ret <8 x i16> %res2
232}
233