1 // RUN: %clang_cc1 %s -triple x86_64-linux-gnu -Wno-unused -std=c++11 -emit-llvm -o - | FileCheck %s
2 
3 using FourShorts = short __attribute__((ext_vector_type(4)));
4 using TwoInts = int __attribute__((ext_vector_type(2)));
5 using TwoUInts = unsigned __attribute__((ext_vector_type(2)));
6 using FourInts = int __attribute__((ext_vector_type(4)));
7 using FourUInts = unsigned __attribute__((ext_vector_type(4)));
8 using TwoLongLong = long long __attribute__((ext_vector_type(2)));
9 using FourLongLong = long long __attribute__((ext_vector_type(4)));
10 using TwoFloats = float __attribute__((ext_vector_type(2)));
11 using FourFloats = float __attribute__((ext_vector_type(4)));
12 using TwoDoubles = double __attribute__((ext_vector_type(2)));
13 using FourDoubles = double __attribute__((ext_vector_type(4)));
14 
15 FourShorts four_shorts;
16 TwoInts two_ints;
17 TwoUInts two_uints;
18 FourInts four_ints;
19 FourUInts four_uints;
20 TwoLongLong two_ll;
21 FourLongLong four_ll;
22 TwoFloats two_floats;
23 FourFloats four_floats;
24 TwoDoubles two_doubles;
25 FourDoubles four_doubles;
26 
27 short some_short;
28 unsigned short some_ushort;
29 int some_int;
30 float some_float;
31 unsigned int some_uint;
32 long long some_ll;
33 unsigned long long some_ull;
34 double some_double;
35 
36 // CHECK: TwoVectorOps
TwoVectorOps()37 void TwoVectorOps() {
38   two_ints ? two_ints : two_ints;
39   // CHECK: [[COND:%.+]] = load <2 x i32>
40   // CHECK: [[LHS:%.+]] = load <2 x i32>
41   // CHECK: [[RHS:%.+]] = load <2 x i32>
42   // CHECK: [[NEG:%.+]] = icmp slt <2 x i32> [[COND]], zeroinitializer
43   // CHECK: [[SEXT:%.+]] = sext <2 x i1> [[NEG]] to <2 x i32>
44   // CHECK: [[XOR:%.+]] = xor <2 x i32> [[SEXT]], <i32 -1, i32 -1>
45   // CHECK: [[RHS_AND:%.+]] = and <2 x i32> [[RHS]], [[XOR]]
46   // CHECK: [[LHS_AND:%.+]] = and <2 x i32> [[LHS]], [[SEXT]]
47   // CHECK: = or <2 x i32> [[RHS_AND]], [[LHS_AND]]
48 
49   two_ints ? two_floats : two_floats;
50   // CHECK: [[COND:%.+]] = load <2 x i32>
51   // CHECK: [[LHS:%.+]] = load <2 x float>
52   // CHECK: [[RHS:%.+]] = load <2 x float>
53   // CHECK: [[NEG:%.+]] = icmp slt <2 x i32> [[COND]], zeroinitializer
54   // CHECK: [[SEXT:%.+]] = sext <2 x i1> [[NEG]] to <2 x i32>
55   // CHECK: [[XOR:%.+]] = xor <2 x i32> [[SEXT]], <i32 -1, i32 -1>
56   // CHECK: [[RHS_EXT:%.+]] = bitcast <2 x float> [[RHS]] to <2 x i32>
57   // CHECK: [[LHS_EXT:%.+]] = bitcast <2 x float> [[LHS]] to <2 x i32>
58   // CHECK: [[RHS_AND:%.+]] = and <2 x i32> [[RHS_EXT]], [[XOR]]
59   // CHECK: [[LHS_AND:%.+]] = and <2 x i32> [[LHS_EXT]], [[SEXT]]
60   // CHECK: [[OR:%.+]] = or <2 x i32> [[RHS_AND]], [[LHS_AND]]
61   // CHECK: = bitcast <2 x i32> [[OR]] to <2 x float>
62 
63   two_ll ? two_doubles : two_doubles;
64   // CHECK: [[COND:%.+]] = load <2 x i64>
65   // CHECK: [[LHS:%.+]] = load <2 x double>
66   // CHECK: [[RHS:%.+]] = load <2 x double>
67   // CHECK: [[NEG:%.+]] = icmp slt <2 x i64> [[COND]], zeroinitializer
68   // CHECK: [[SEXT:%.+]] = sext <2 x i1> [[NEG]] to <2 x i64>
69   // CHECK: [[XOR:%.+]] = xor <2 x i64> [[SEXT]], <i64 -1, i64 -1>
70   // CHECK: [[RHS_EXT:%.+]] = bitcast <2 x double> [[RHS]] to <2 x i64>
71   // CHECK: [[LHS_EXT:%.+]] = bitcast <2 x double> [[LHS]] to <2 x i64>
72   // CHECK: [[RHS_AND:%.+]] = and <2 x i64> [[RHS_EXT]], [[XOR]]
73   // CHECK: [[LHS_AND:%.+]] = and <2 x i64> [[LHS_EXT]], [[SEXT]]
74   // CHECK: [[OR:%.+]] = or <2 x i64> [[RHS_AND]], [[LHS_AND]]
75   // CHECK: = bitcast <2 x i64> [[OR]] to <2 x double>
76 }
77 
78 // CHECK: TwoScalarOps
TwoScalarOps()79 void TwoScalarOps() {
80   four_shorts ? some_short : some_short;
81   // CHECK: [[COND:%.+]] = load <4 x i16>
82   // CHECK: [[LHS:%.+]] = load i16
83   // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[LHS]], i32 0
84   // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i16> [[LHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
85   // CHECK: [[RHS:%.+]] = load i16
86   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[RHS]], i32 0
87   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i16> [[RHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
88   // CHECK: [[NEG:%.+]] = icmp slt <4 x i16> [[COND]], zeroinitializer
89   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i16>
90   // CHECK: [[XOR:%.+]] = xor <4 x i16> [[SEXT]], <i16 -1, i16 -1, i16 -1, i16 -1>
91   // CHECK: [[RHS_AND:%.+]] = and <4 x i16> [[RHS_SPLAT]], [[XOR]]
92   // CHECK: [[LHS_AND:%.+]] = and <4 x i16> [[LHS_SPLAT]], [[SEXT]]
93   // CHECK: = or <4 x i16> [[RHS_AND]], [[LHS_AND]]
94 
95   four_shorts ? some_ushort : some_ushort;
96   // CHECK: [[COND:%.+]] = load <4 x i16>
97   // CHECK: [[LHS:%.+]] = load i16
98   // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[LHS]], i32 0
99   // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i16> [[LHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
100   // CHECK: [[RHS:%.+]] = load i16
101   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i16> poison, i16 [[RHS]], i32 0
102   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i16> [[RHS_SPLAT_INSERT]], <4 x i16> poison, <4 x i32> zeroinitializer
103   // CHECK: [[NEG:%.+]] = icmp slt <4 x i16> [[COND]], zeroinitializer
104   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i16>
105   // CHECK: [[XOR:%.+]] = xor <4 x i16> [[SEXT]], <i16 -1, i16 -1, i16 -1, i16 -1>
106   // CHECK: [[RHS_AND:%.+]] = and <4 x i16> [[RHS_SPLAT]], [[XOR]]
107   // CHECK: [[LHS_AND:%.+]] = and <4 x i16> [[LHS_SPLAT]], [[SEXT]]
108   // CHECK: = or <4 x i16> [[RHS_AND]], [[LHS_AND]]
109 
110   four_ints ? some_ushort : some_short;
111   // CHECK: [[COND:%.+]] = load <4 x i32>
112   // CHECK: [[LHS:%.+]] = load i16
113   // CHECK: [[LHS_ZEXT:%.+]] = zext i16 [[LHS]] to i32
114   // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[LHS_ZEXT]], i32 0
115   // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i32> [[LHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
116   // CHECK: [[RHS:%.+]] = load i16
117   // CHECK: [[RHS_SEXT:%.+]] = sext i16 [[RHS]] to i32
118   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[RHS_SEXT]], i32 0
119   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i32> [[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
120   // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
121   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
122   // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
123   // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_SPLAT]], [[XOR]]
124   // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_SPLAT]], [[SEXT]]
125   // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
126 
127   four_ints ? some_int : some_float;
128   // CHECK: [[COND:%.+]] = load <4 x i32>
129   // CHECK: [[LHS:%.+]] = load i32
130   // CHECK: [[LHS_CONV:%.+]] = sitofp i32 [[LHS]] to float
131   // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x float> poison, float [[LHS_CONV]], i32 0
132   // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x float> [[LHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer
133   // CHECK: [[RHS:%.+]] = load float
134   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x float> poison, float [[RHS]], i32 0
135   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x float> [[RHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer
136   // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
137   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
138   // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
139   // CHECK: [[RHS_CAST:%.+]] = bitcast <4 x float> [[RHS_SPLAT]] to <4 x i32>
140   // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x float> [[LHS_SPLAT]] to <4 x i32>
141   // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_CAST]], [[XOR]]
142   // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_CAST]], [[SEXT]]
143   // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
144 
145   four_ll ? some_double : some_ll;
146   // CHECK: [[COND:%.+]] = load <4 x i64>
147   // CHECK: [[LHS:%.+]] = load double
148   // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x double> poison, double [[LHS]], i32 0
149   // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x double> [[LHS_SPLAT_INSERT]], <4 x double> poison, <4 x i32> zeroinitializer
150   // CHECK: [[RHS:%.+]] = load i64
151   // CHECK: [[RHS_CONV:%.+]] = sitofp i64 [[RHS]] to double
152   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x double> poison, double [[RHS_CONV]], i32 0
153   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x double> [[RHS_SPLAT_INSERT]], <4 x double> poison, <4 x i32> zeroinitializer
154   // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
155   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
156   // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
157   // CHECK: [[RHS_CAST:%.+]] = bitcast <4 x double> [[RHS_SPLAT]] to <4 x i64>
158   // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x double> [[LHS_SPLAT]] to <4 x i64>
159   // CHECK: [[RHS_AND:%.+]] = and <4 x i64> [[RHS_CAST]], [[XOR]]
160   // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS_CAST]], [[SEXT]]
161   // CHECK: = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
162 
163   four_ints ? some_int : some_short;
164   // CHECK: [[COND:%.+]] = load <4 x i32>
165   // CHECK: [[LHS:%.+]] = load i32
166   // CHECK: [[LHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[LHS]], i32 0
167   // CHECK: [[LHS_SPLAT:%.+]] = shufflevector <4 x i32> [[LHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
168   // CHECK: [[RHS:%.+]] = load i16
169   // CHECK: [[RHS_SEXT:%.+]] = sext i16 [[RHS]] to i32
170   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[RHS_SEXT]], i32 0
171   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i32> [[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
172   // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
173   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
174   // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
175   // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_SPLAT]], [[XOR]]
176   // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_SPLAT]], [[SEXT]]
177   // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
178 }
179 
180 // CHECK: OneScalarOp
OneScalarOp()181 void OneScalarOp() {
182   four_ints ? four_ints : some_int;
183   // CHECK: [[COND:%.+]] = load <4 x i32>
184   // CHECK: [[LHS:%.+]] = load <4 x i32>
185   // CHECK: [[RHS:%.+]] = load i32
186   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i32> poison, i32 [[RHS]], i32 0
187   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i32> [[RHS_SPLAT_INSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
188   // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
189   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
190   // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
191   // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_SPLAT]], [[XOR]]
192   // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS]], [[SEXT]]
193   // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
194 
195   four_ints ? four_ints : 5;
196   // CHECK: [[COND:%.+]] = load <4 x i32>
197   // CHECK: [[LHS:%.+]] = load <4 x i32>
198   // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
199   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
200   // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
201   // CHECK: [[RHS_AND:%.+]] = and <4 x i32> <i32 5, i32 5, i32 5, i32 5>, [[XOR]]
202   // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS]], [[SEXT]]
203   // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
204 
205   four_ints ? four_floats : some_float;
206   // CHECK: [[COND:%.+]] = load <4 x i32>
207   // CHECK: [[LHS:%.+]] = load <4 x float>
208   // CHECK: [[RHS:%.+]] = load float
209   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x float> poison, float [[RHS]], i32 0
210   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x float> [[RHS_SPLAT_INSERT]], <4 x float> poison, <4 x i32> zeroinitializer
211   // CHECK: [[NEG:%.+]] = icmp slt <4 x i32> [[COND]], zeroinitializer
212   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i32>
213   // CHECK: [[XOR:%.+]] = xor <4 x i32> [[SEXT]], <i32 -1, i32 -1, i32 -1, i32 -1>
214   // CHECK: [[RHS_CAST:%.+]] = bitcast <4 x float> [[RHS_SPLAT]] to <4 x i32>
215   // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x float> [[LHS]] to <4 x i32>
216   // CHECK: [[RHS_AND:%.+]] = and <4 x i32> [[RHS_CAST]], [[XOR]]
217   // CHECK: [[LHS_AND:%.+]] = and <4 x i32> [[LHS_CAST]], [[SEXT]]
218   // CHECK: = or <4 x i32> [[RHS_AND]], [[LHS_AND]]
219 
220   four_ll ? four_doubles : 6.0;
221   // CHECK: [[COND:%.+]] = load <4 x i64>
222   // CHECK: [[LHS:%.+]] = load <4 x double>
223   // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
224   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
225   // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
226   // CHECK: [[LHS_CAST:%.+]] = bitcast <4 x double> [[LHS]] to <4 x i64>
227   // CHECK: [[RHS_AND:%.+]] = and <4 x i64> <i64 4618441417868443648, i64 4618441417868443648, i64 4618441417868443648, i64 4618441417868443648>, [[XOR]]
228   // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS_CAST]], [[SEXT]]
229   // CHECK: = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
230 
231   four_ll ? four_ll : 6;
232   // CHECK: [[COND:%.+]] = load <4 x i64>
233   // CHECK: [[LHS:%.+]] = load <4 x i64>
234   // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
235   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
236   // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
237   // CHECK: [[RHS_AND:%.+]] = and <4 x i64> <i64 6, i64 6, i64 6, i64 6>, [[XOR]]
238   // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS]], [[SEXT]]
239   // CHECK: [[OR:%.+]] = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
240 
241   four_ll ? four_ll : some_int;
242   // CHECK: [[COND:%.+]] = load <4 x i64>
243   // CHECK: [[LHS:%.+]] = load <4 x i64>
244   // CHECK: [[RHS:%.+]] = load i32
245   // CHECK: [[RHS_CONV:%.+]] = sext i32 [[RHS]] to i64
246   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i64> poison, i64 [[RHS_CONV]], i32 0
247   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i64> [[RHS_SPLAT_INSERT]], <4 x i64> poison, <4 x i32> zeroinitializer
248   // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
249   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
250   // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
251   // CHECK: [[RHS_AND:%.+]] = and <4 x i64> [[RHS_SPLAT]], [[XOR]]
252   // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS]], [[SEXT]]
253   // CHECK: [[OR:%.+]] = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
254 
255   four_ll ? four_ll : some_ll;
256   // CHECK: [[COND:%.+]] = load <4 x i64>
257   // CHECK: [[LHS:%.+]] = load <4 x i64>
258   // CHECK: [[RHS:%.+]] = load i64
259   // CHECK: [[RHS_SPLAT_INSERT:%.+]] = insertelement <4 x i64> poison, i64 [[RHS]], i32 0
260   // CHECK: [[RHS_SPLAT:%.+]] = shufflevector <4 x i64> [[RHS_SPLAT_INSERT]], <4 x i64> poison, <4 x i32> zeroinitializer
261   // CHECK: [[NEG:%.+]] = icmp slt <4 x i64> [[COND]], zeroinitializer
262   // CHECK: [[SEXT:%.+]] = sext <4 x i1> [[NEG]] to <4 x i64>
263   // CHECK: [[XOR:%.+]] = xor <4 x i64> [[SEXT]], <i64 -1, i64 -1, i64 -1, i64 -1>
264   // CHECK: [[RHS_AND:%.+]] = and <4 x i64> [[RHS_SPLAT]], [[XOR]]
265   // CHECK: [[LHS_AND:%.+]] = and <4 x i64> [[LHS]], [[SEXT]]
266   // CHECK: [[OR:%.+]] = or <4 x i64> [[RHS_AND]], [[LHS_AND]]
267 }
268