@@ -18,6 +18,23 @@ define i32 @shrinkExtractElt_i64_to_i32_0(<3 x i64> %x) {
1818 ret i32 %t
1919}
2020
21+ define i32 @shrinkShiftExtractElt_i64_to_i32_0 (<3 x i64 > %x ) {
22+ ; LE-LABEL: @shrinkShiftExtractElt_i64_to_i32_0(
23+ ; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
24+ ; LE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 1
25+ ; LE-NEXT: ret i32 [[T]]
26+ ;
27+ ; BE-LABEL: @shrinkShiftExtractElt_i64_to_i32_0(
28+ ; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <6 x i32>
29+ ; BE-NEXT: [[T:%.*]] = extractelement <6 x i32> [[TMP1]], i64 0
30+ ; BE-NEXT: ret i32 [[T]]
31+ ;
32+ %e = extractelement <3 x i64 > %x , i32 0
33+ %s = lshr i64 %e , 32
34+ %t = trunc i64 %s to i32
35+ ret i32 %t
36+ }
37+
2138define i32 @vscale_shrinkExtractElt_i64_to_i32_0 (<vscale x 3 x i64 > %x ) {
2239; LE-LABEL: @vscale_shrinkExtractElt_i64_to_i32_0(
2340; LE-NEXT: [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32>
@@ -34,6 +51,22 @@ define i32 @vscale_shrinkExtractElt_i64_to_i32_0(<vscale x 3 x i64> %x) {
3451 ret i32 %t
3552}
3653
54+ define i32 @vscale_shrinkShiftExtractElt_i64_to_i32_0 (<vscale x 3 x i64 > %x ) {
55+ ; LE-LABEL: @vscale_shrinkShiftExtractElt_i64_to_i32_0(
56+ ; LE-NEXT: [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32>
57+ ; LE-NEXT: [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 1
58+ ; LE-NEXT: ret i32 [[T]]
59+ ;
60+ ; BE-LABEL: @vscale_shrinkShiftExtractElt_i64_to_i32_0(
61+ ; BE-NEXT: [[TMP1:%.*]] = bitcast <vscale x 3 x i64> [[X:%.*]] to <vscale x 6 x i32>
62+ ; BE-NEXT: [[T:%.*]] = extractelement <vscale x 6 x i32> [[TMP1]], i64 0
63+ ; BE-NEXT: ret i32 [[T]]
64+ ;
65+ %e = extractelement <vscale x 3 x i64 > %x , i32 0
66+ %s = lshr i64 %e , 32
67+ %t = trunc i64 %s to i32
68+ ret i32 %t
69+ }
3770
3871define i32 @shrinkExtractElt_i64_to_i32_1 (<3 x i64 > %x ) {
3972; LE-LABEL: @shrinkExtractElt_i64_to_i32_1(
@@ -83,6 +116,23 @@ define i16 @shrinkExtractElt_i64_to_i16_0(<3 x i64> %x) {
83116 ret i16 %t
84117}
85118
119+ define i16 @shrinkShiftExtractElt_i64_to_i16_0 (<3 x i64 > %x ) {
120+ ; LE-LABEL: @shrinkShiftExtractElt_i64_to_i16_0(
121+ ; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
122+ ; LE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 3
123+ ; LE-NEXT: ret i16 [[T]]
124+ ;
125+ ; BE-LABEL: @shrinkShiftExtractElt_i64_to_i16_0(
126+ ; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
127+ ; BE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 0
128+ ; BE-NEXT: ret i16 [[T]]
129+ ;
130+ %e = extractelement <3 x i64 > %x , i16 0
131+ %s = ashr i64 %e , 48
132+ %t = trunc i64 %s to i16
133+ ret i16 %t
134+ }
135+
86136define i16 @shrinkExtractElt_i64_to_i16_1 (<3 x i64 > %x ) {
87137; LE-LABEL: @shrinkExtractElt_i64_to_i16_1(
88138; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X:%.*]] to <12 x i16>
@@ -157,6 +207,20 @@ define i30 @shrinkExtractElt_i40_to_i30_1(<3 x i40> %x) {
157207 ret i30 %t
158208}
159209
210+ ; Do not optimize if the shift amount isn't a whole number of truncated bits.
211+ define i16 @shrinkShiftExtractElt_i64_to_i16_0_badshift (<3 x i64 > %x ) {
212+ ; ANY-LABEL: @shrinkShiftExtractElt_i64_to_i16_0_badshift(
213+ ; ANY-NEXT: [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 0
214+ ; ANY-NEXT: [[S:%.*]] = lshr i64 [[E]], 31
215+ ; ANY-NEXT: [[T:%.*]] = trunc i64 [[S]] to i16
216+ ; ANY-NEXT: ret i16 [[T]]
217+ ;
218+ %e = extractelement <3 x i64 > %x , i16 0
219+ %s = lshr i64 %e , 31
220+ %t = trunc i64 %s to i16
221+ ret i16 %t
222+ }
223+
160224; Do not canonicalize if that would increase the instruction count.
161225declare void @use (i64 )
162226define i16 @shrinkExtractElt_i64_to_i16_2_extra_use (<3 x i64 > %x ) {
@@ -172,6 +236,45 @@ define i16 @shrinkExtractElt_i64_to_i16_2_extra_use(<3 x i64> %x) {
172236 ret i16 %t
173237}
174238
239+ ; Do not canonicalize if that would increase the instruction count.
240+ define i16 @shrinkShiftExtractElt_i64_to_i16_2_extra_shift_use (<3 x i64 > %x ) {
241+ ; ANY-LABEL: @shrinkShiftExtractElt_i64_to_i16_2_extra_shift_use(
242+ ; ANY-NEXT: [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2
243+ ; ANY-NEXT: [[S:%.*]] = lshr i64 [[E]], 48
244+ ; ANY-NEXT: call void @use(i64 [[S]])
245+ ; ANY-NEXT: [[T:%.*]] = trunc nuw i64 [[S]] to i16
246+ ; ANY-NEXT: ret i16 [[T]]
247+ ;
248+ %e = extractelement <3 x i64 > %x , i64 2
249+ %s = lshr i64 %e , 48
250+ call void @use (i64 %s )
251+ %t = trunc i64 %s to i16
252+ ret i16 %t
253+ }
254+
255+ ; OK to reuse the extract if we remove the shift+trunc.
256+ define i16 @shrinkShiftExtractElt_i64_to_i16_2_extra_extract_use (<3 x i64 > %x ) {
257+ ; LE-LABEL: @shrinkShiftExtractElt_i64_to_i16_2_extra_extract_use(
258+ ; LE-NEXT: [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2
259+ ; LE-NEXT: call void @use(i64 [[E]])
260+ ; LE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X]] to <12 x i16>
261+ ; LE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 11
262+ ; LE-NEXT: ret i16 [[T]]
263+ ;
264+ ; BE-LABEL: @shrinkShiftExtractElt_i64_to_i16_2_extra_extract_use(
265+ ; BE-NEXT: [[E:%.*]] = extractelement <3 x i64> [[X:%.*]], i64 2
266+ ; BE-NEXT: call void @use(i64 [[E]])
267+ ; BE-NEXT: [[TMP1:%.*]] = bitcast <3 x i64> [[X]] to <12 x i16>
268+ ; BE-NEXT: [[T:%.*]] = extractelement <12 x i16> [[TMP1]], i64 8
269+ ; BE-NEXT: ret i16 [[T]]
270+ ;
271+ %e = extractelement <3 x i64 > %x , i64 2
272+ call void @use (i64 %e )
273+ %s = lshr i64 %e , 48
274+ %t = trunc i64 %s to i16
275+ ret i16 %t
276+ }
277+
175278; Check to ensure PR45314 remains fixed.
176279define <4 x i64 > @PR45314 (<4 x i64 > %x ) {
177280; LE-LABEL: @PR45314(
0 commit comments