xref: /llvm-project/llvm/test/Transforms/InstCombine/shufflevec-bitcast-inseltpoison.ll (revision 8b56da5e9f3ba737a5ff4bf5dee654416849042f)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare void @use(<4 x i16>)
5
6define void @test(<16 x i8> %w, ptr %o1, ptr %o2) {
7; CHECK-LABEL: @test(
8; CHECK-NEXT:    [[V_BC:%.*]] = bitcast <16 x i8> [[W:%.*]] to <4 x i32>
9; CHECK-NEXT:    [[V_EXTRACT:%.*]] = extractelement <4 x i32> [[V_BC]], i64 3
10; CHECK-NEXT:    [[V_BC1:%.*]] = bitcast <16 x i8> [[W]] to <4 x float>
11; CHECK-NEXT:    [[V_EXTRACT2:%.*]] = extractelement <4 x float> [[V_BC1]], i64 3
12; CHECK-NEXT:    store i32 [[V_EXTRACT]], ptr [[O1:%.*]], align 4
13; CHECK-NEXT:    store float [[V_EXTRACT2]], ptr [[O2:%.*]], align 4
14; CHECK-NEXT:    ret void
15;
16  %v = shufflevector <16 x i8> %w, <16 x i8> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
17  %f = bitcast <4 x i8> %v to float
18  %i = bitcast <4 x i8> %v to i32
19  store i32 %i, ptr %o1, align 4
20  store float %f, ptr %o2, align 4
21  ret void
22}
23
24; Shuffle-of-bitcast-splat --> splat-bitcast
25
26define <4 x i16> @splat_bitcast_operand(<8 x i8> %x) {
27; CHECK-LABEL: @splat_bitcast_operand(
28; CHECK-NEXT:    [[S1:%.*]] = shufflevector <8 x i8> [[X:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
29; CHECK-NEXT:    [[S2:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16>
30; CHECK-NEXT:    ret <4 x i16> [[S2]]
31;
32  %s1 = shufflevector <8 x i8> %x, <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
33  %bc = bitcast <8 x i8> %s1 to <4 x i16>
34  %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <4 x i32> <i32 0, i32 2, i32 1, i32 0>
35  ret <4 x i16> %s2
36}
37
38; Shuffle-of-bitcast-splat --> splat-bitcast
39
40define <4 x i16> @splat_bitcast_operand_uses(<8 x i8> %x) {
41; CHECK-LABEL: @splat_bitcast_operand_uses(
42; CHECK-NEXT:    [[S1:%.*]] = shufflevector <8 x i8> [[X:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
43; CHECK-NEXT:    [[BC:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16>
44; CHECK-NEXT:    call void @use(<4 x i16> [[BC]])
45; CHECK-NEXT:    [[S2:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16>
46; CHECK-NEXT:    ret <4 x i16> [[S2]]
47;
48  %s1 = shufflevector <8 x i8> %x, <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
49  %bc = bitcast <8 x i8> %s1 to <4 x i16>
50  call void @use(<4 x i16> %bc)
51  %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <4 x i32> <i32 0, i32 2, i32 1, i32 0>
52  ret <4 x i16> %s2
53}
54
55; Shuffle-of-bitcast-splat --> splat-bitcast
56
57define <4 x i32> @splat_bitcast_operand_same_size_src_elt(<4 x float> %x) {
58; CHECK-LABEL: @splat_bitcast_operand_same_size_src_elt(
59; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x float> [[X:%.*]] to <4 x i32>
60; CHECK-NEXT:    [[BC:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
61; CHECK-NEXT:    ret <4 x i32> [[BC]]
62;
63  %s1 = shufflevector <4 x float> %x, <4 x float> poison, <4 x i32> <i32 2, i32 2, i32 2, i32 2>
64  %bc = bitcast <4 x float> %s1 to <4 x i32>
65  %s2 = shufflevector <4 x i32> %bc, <4 x i32> poison, <4 x i32> <i32 0, i32 2, i32 1, i32 0>
66  ret <4 x i32> %s2
67}
68
69; Scaled mask is inverse of first mask.
70
71define <4 x i32> @shuf_bitcast_operand(<16 x i8> %x) {
72; CHECK-LABEL: @shuf_bitcast_operand(
73; CHECK-NEXT:    [[S2:%.*]] = bitcast <16 x i8> [[X:%.*]] to <4 x i32>
74; CHECK-NEXT:    ret <4 x i32> [[S2]]
75;
76  %s1 = shufflevector <16 x i8> %x, <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
77  %bc = bitcast <16 x i8> %s1 to <4 x i32>
78  %s2 = shufflevector <4 x i32> %bc, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
79  ret <4 x i32> %s2
80}
81
82; TODO: Could allow fold for length-changing shuffles.
83
84define <5 x i16> @splat_bitcast_operand_change_type(<8 x i8> %x) {
85; CHECK-LABEL: @splat_bitcast_operand_change_type(
86; CHECK-NEXT:    [[S1:%.*]] = shufflevector <8 x i8> [[X:%.*]], <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
87; CHECK-NEXT:    [[BC:%.*]] = bitcast <8 x i8> [[S1]] to <4 x i16>
88; CHECK-NEXT:    [[S2:%.*]] = shufflevector <4 x i16> [[BC]], <4 x i16> poison, <5 x i32> <i32 0, i32 2, i32 1, i32 0, i32 3>
89; CHECK-NEXT:    ret <5 x i16> [[S2]]
90;
91  %s1 = shufflevector <8 x i8> %x, <8 x i8> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
92  %bc = bitcast <8 x i8> %s1 to <4 x i16>
93  %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <5 x i32> <i32 0, i32 2, i32 1, i32 0, i32 3>
94  ret <5 x i16> %s2
95}
96
97; Shuffle-of-bitcast-splat --> splat-bitcast
98
99define <4 x i16> @splat_bitcast_operand_wider_src_elt(<2 x i32> %x) {
100; CHECK-LABEL: @splat_bitcast_operand_wider_src_elt(
101; CHECK-NEXT:    [[S1:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> <i32 1, i32 1>
102; CHECK-NEXT:    [[S2:%.*]] = bitcast <2 x i32> [[S1]] to <4 x i16>
103; CHECK-NEXT:    ret <4 x i16> [[S2]]
104;
105  %s1 = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> <i32 1, i32 1>
106  %bc = bitcast <2 x i32> %s1 to <4 x i16>
107  %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
108  ret <4 x i16> %s2
109}
110
111; Shuffle-of-bitcast-splat --> splat-bitcast
112
113define <4 x i16> @splat_bitcast_operand_wider_src_elt_uses(<2 x i32> %x) {
114; CHECK-LABEL: @splat_bitcast_operand_wider_src_elt_uses(
115; CHECK-NEXT:    [[S1:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> <i32 1, i32 1>
116; CHECK-NEXT:    [[BC:%.*]] = bitcast <2 x i32> [[S1]] to <4 x i16>
117; CHECK-NEXT:    call void @use(<4 x i16> [[BC]])
118; CHECK-NEXT:    [[S2:%.*]] = bitcast <2 x i32> [[S1]] to <4 x i16>
119; CHECK-NEXT:    ret <4 x i16> [[S2]]
120;
121  %s1 = shufflevector <2 x i32> %x, <2 x i32> poison, <2 x i32> <i32 1, i32 1>
122  %bc = bitcast <2 x i32> %s1 to <4 x i16>
123  call void @use(<4 x i16> %bc)
124  %s2 = shufflevector <4 x i16> %bc, <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
125  ret <4 x i16> %s2
126}
127
128; Scaled mask is inverse of first mask.
129
130define <16 x i8> @shuf_bitcast_operand_wider_src(<4 x i32> %x) {
131; CHECK-LABEL: @shuf_bitcast_operand_wider_src(
132; CHECK-NEXT:    [[S2:%.*]] = bitcast <4 x i32> [[X:%.*]] to <16 x i8>
133; CHECK-NEXT:    ret <16 x i8> [[S2]]
134;
135  %s1 = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
136  %bc = bitcast <4 x i32> %s1 to <16 x i8>
137  %s2 = shufflevector <16 x i8> %bc, <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
138  ret <16 x i8> %s2
139}
140
141; Negative test - the 2nd mask can't be widened
142
143define <16 x i8> @shuf_bitcast_operand_cannot_widen(<4 x i32> %x) {
144; CHECK-LABEL: @shuf_bitcast_operand_cannot_widen(
145; CHECK-NEXT:    [[S1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
146; CHECK-NEXT:    [[BC:%.*]] = bitcast <4 x i32> [[S1]] to <16 x i8>
147; CHECK-NEXT:    [[S2:%.*]] = shufflevector <16 x i8> [[BC]], <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 12, i32 13, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
148; CHECK-NEXT:    ret <16 x i8> [[S2]]
149;
150  %s1 = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
151  %bc = bitcast <4 x i32> %s1 to <16 x i8>
152  %s2 = shufflevector <16 x i8> %bc, <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 12, i32 13, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
153  ret <16 x i8> %s2
154}
155
156; Negative test - the 2nd mask can't be widened
157
158define <16 x i8> @shuf_bitcast_operand_cannot_widen_undef(<4 x i32> %x) {
159; CHECK-LABEL: @shuf_bitcast_operand_cannot_widen_undef(
160; CHECK-NEXT:    [[S1:%.*]] = shufflevector <4 x i32> [[X:%.*]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
161; CHECK-NEXT:    [[BC:%.*]] = bitcast <4 x i32> [[S1]] to <16 x i8>
162; CHECK-NEXT:    [[S2:%.*]] = shufflevector <16 x i8> [[BC]], <16 x i8> poison, <16 x i32> <i32 12, i32 poison, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
163; CHECK-NEXT:    ret <16 x i8> [[S2]]
164;
165  %s1 = shufflevector <4 x i32> %x, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
166  %bc = bitcast <4 x i32> %s1 to <16 x i8>
167  %s2 = shufflevector <16 x i8> %bc, <16 x i8> poison, <16 x i32> <i32 12, i32 undef, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3>
168  ret <16 x i8> %s2
169}
170