1395 lines · c
1// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s2 3typedef _Float16 half;4 5typedef half half2 __attribute__((ext_vector_type(2)));6typedef float float2 __attribute__((ext_vector_type(2)));7typedef float float4 __attribute__((ext_vector_type(4)));8typedef short int si8 __attribute__((ext_vector_type(8)));9typedef int int4 __attribute__((ext_vector_type(4)));10typedef unsigned int u4 __attribute__((ext_vector_type(4)));11typedef double double2 __attribute__((ext_vector_type(2)));12typedef double double3 __attribute__((ext_vector_type(3)));13 14__attribute__((address_space(1))) int int_as_one;15typedef int bar;16bar b;17 18struct StructWithBitfield {19 int i : 5;20 short s : 3;21 char c: 2;22 long long int lli : 3;23};24 25void test_builtin_elementwise_abs(float f1, float f2, double d1, double d2,26 float4 vf1, float4 vf2, si8 vi1, si8 vi2,27 long long int i1, long long int i2, short si,28 _BitInt(31) bi1, _BitInt(31) bi2, int i,29 char ci) {30 // CHECK-LABEL: define void @test_builtin_elementwise_abs(31 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 432 // CHECK-NEXT: call float @llvm.fabs.f32(float [[F1]])33 f2 = __builtin_elementwise_abs(f1);34 35 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 836 // CHECK-NEXT: call double @llvm.fabs.f64(double [[D1]])37 d2 = __builtin_elementwise_abs(d1);38 39 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 1640 // CHECK-NEXT: call <4 x float> @llvm.fabs.v4f32(<4 x float> [[VF1]])41 vf2 = __builtin_elementwise_abs(vf1);42 43 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 844 // CHECK-NEXT: call i64 @llvm.abs.i64(i64 [[I1]], i1 false)45 i2 = __builtin_elementwise_abs(i1);46 47 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 848 // CHECK: [[S1:%.+]] = trunc i64 [[I1]] to i1649 // CHECK-NEXT: call i16 @llvm.abs.i16(i16 [[S1]], i1 false)50 i1 = __builtin_elementwise_abs((short)i1);51 52 // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 1653 // CHECK-NEXT: call <8 x i16> @llvm.abs.v8i16(<8 x i16> [[VI1]], i1 false)54 vi2 = __builtin_elementwise_abs(vi1);55 56 // CHECK: [[CVI2:%.+]] = load <8 x i16>, ptr %cvi2, align 1657 // CHECK-NEXT: call <8 x i16> @llvm.abs.v8i16(<8 x i16> [[CVI2]], i1 false)58 const si8 cvi2 = vi2;59 vi2 = __builtin_elementwise_abs(cvi2);60 61 // CHECK: [[BI1:%.+]] = load i32, ptr %bi1.addr, align 462 // CHECK-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i3163 // CHECK-NEXT: call i31 @llvm.abs.i31(i31 [[LOADEDV]], i1 false)64 bi2 = __builtin_elementwise_abs(bi1);65 66 // CHECK: [[IA1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 467 // CHECK-NEXT: call i32 @llvm.abs.i32(i32 [[IA1]], i1 false)68 b = __builtin_elementwise_abs(int_as_one);69 70 // CHECK: store i32 %elt.abs11, ptr @b, align 471 b = __builtin_elementwise_abs(-10);72 73 // CHECK: [[SI:%.+]] = load i16, ptr %si.addr, align 274 // CHECK-NEXT: [[RES:%.+]] = call i16 @llvm.abs.i16(i16 [[SI]], i1 false)75 si = __builtin_elementwise_abs(si);76 77 struct StructWithBitfield t;78 79 // CHECK: [[BFLOAD:%.+]] = load i16, ptr %t, align 880 // CHECK-NEXT: [[BFSHL:%.+]] = shl i16 [[BFLOAD]], 1181 // CHECK-NEXT: [[BFASHR:%.+]] = ashr i16 [[BFSHL]], 1182 // CHECK-NEXT: [[BFCAST:%.+]] = sext i16 [[BFASHR]] to i3283 // CHECK-NEXT: [[RES:%.+]] = call i32 @llvm.abs.i32(i32 [[BFCAST]], i1 false)84 i = __builtin_elementwise_abs(t.i);85 86 // CHECK: [[BFLOAD:%.+]] = load i16, ptr %t, align 887 // CHECK-NEXT: [[BFSHL:%.+]] = shl i16 [[BFLOAD]], 888 // CHECK-NEXT: [[BFASHR:%.+]] = ashr i16 [[BFSHL]], 1389 // CHECK-NEXT: [[RES:%.+]] = call i16 @llvm.abs.i16(i16 [[BFASHR]], i1 false)90 si = __builtin_elementwise_abs(t.s);91 92 // CHECK: [[BFLOAD:%.+]] = load i16, ptr %t, align 893 // CHECK-NEXT: [[BFSHL:%.+]] = shl i16 [[BFLOAD]], 694 // CHECK-NEXT: [[BFASHR:%.+]] = ashr i16 [[BFSHL]], 1495 // CHECK-NEXT: [[BFCAST:%.+]] = trunc i16 [[BFASHR]] to i896 // CHECK-NEXT: [[RES:%.+]] = call i8 @llvm.abs.i8(i8 [[BFCAST]], i1 false)97 ci = __builtin_elementwise_abs(t.c);98 99 // CHECK: [[BFLOAD:%.+]] = load i16, ptr %t, align 8100 // CHECK-NEXT: [[BFSHL:%.+]] = shl i16 [[BFLOAD]], 3101 // CHECK-NEXT: [[BFASHR:%.+]] = ashr i16 [[BFSHL]], 13102 // CHECK-NEXT: [[BFCAST:%.+]] = sext i16 [[BFASHR]] to i64103 // CHECK-NEXT: [[RES:%.+]] = call i64 @llvm.abs.i64(i64 [[BFCAST]], i1 false)104 i1 = __builtin_elementwise_abs(t.lli);105}106 107void test_builtin_elementwise_add_sat(float f1, float f2, double d1, double d2,108 float4 vf1, float4 vf2, long long int i1,109 long long int i2, si8 vi1, si8 vi2,110 unsigned u1, unsigned u2, u4 vu1, u4 vu2,111 _BitInt(31) bi1, _BitInt(31) bi2,112 unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2,113 char c1, char c2, unsigned char uc1,114 unsigned char uc2, short s1, short s2,115 unsigned short us1, unsigned short us2) {116 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8117 // CHECK-NEXT: [[I2:%.+]] = load i64, ptr %i2.addr, align 8118 // CHECK-NEXT: call i64 @llvm.sadd.sat.i64(i64 [[I1]], i64 [[I2]])119 i1 = __builtin_elementwise_add_sat(i1, i2);120 121 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8122 // CHECK-NEXT: call i64 @llvm.sadd.sat.i64(i64 [[I1]], i64 10)123 i1 = __builtin_elementwise_add_sat(i1, 10ll);124 125 // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 16126 // CHECK-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %vi2.addr, align 16127 // CHECK-NEXT: call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> [[VI1]], <8 x i16> [[VI2]])128 vi1 = __builtin_elementwise_add_sat(vi1, vi2);129 130 // CHECK: [[U1:%.+]] = load i32, ptr %u1.addr, align 4131 // CHECK-NEXT: [[U2:%.+]] = load i32, ptr %u2.addr, align 4132 // CHECK-NEXT: call i32 @llvm.uadd.sat.i32(i32 [[U1]], i32 [[U2]])133 u1 = __builtin_elementwise_add_sat(u1, u2);134 135 // CHECK: [[VU1:%.+]] = load <4 x i32>, ptr %vu1.addr, align 16136 // CHECK-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %vu2.addr, align 16137 // CHECK-NEXT: call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> [[VU1]], <4 x i32> [[VU2]])138 vu1 = __builtin_elementwise_add_sat(vu1, vu2);139 140 // CHECK: [[BI1:%.+]] = load i32, ptr %bi1.addr, align 4141 // CHECK-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31142 // CHECK-NEXT: [[BI2:%.+]] = load i32, ptr %bi2.addr, align 4143 // CHECK-NEXT: [[LOADEDV1:%.+]] = trunc i32 [[BI2]] to i31144 // CHECK-NEXT: call i31 @llvm.sadd.sat.i31(i31 [[LOADEDV]], i31 [[LOADEDV1]])145 bi1 = __builtin_elementwise_add_sat(bi1, bi2);146 147 // CHECK: [[BU1:%.+]] = load i64, ptr %bu1.addr, align 8148 // CHECK-NEXT: [[LOADEDV2:%.+]] = trunc i64 [[BU1]] to i55149 // CHECK-NEXT: [[BU2:%.+]] = load i64, ptr %bu2.addr, align 8150 // CHECK-NEXT: [[LOADEDV3:%.+]] = trunc i64 [[BU2]] to i55151 // CHECK-NEXT: call i55 @llvm.uadd.sat.i55(i55 [[LOADEDV2]], i55 [[LOADEDV3]])152 bu1 = __builtin_elementwise_add_sat(bu1, bu2);153 154 // CHECK: [[IAS1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4155 // CHECK-NEXT: [[B:%.+]] = load i32, ptr @b, align 4156 // CHECK-NEXT: call i32 @llvm.sadd.sat.i32(i32 [[IAS1]], i32 [[B]])157 int_as_one = __builtin_elementwise_add_sat(int_as_one, b);158 159 // CHECK: store i64 98, ptr %i1.addr, align 8160 i1 = __builtin_elementwise_add_sat(1, 'a');161 162 // CHECK: [[C1:%.+]] = load i8, ptr %c1.addr, align 1163 // CHECK-NEXT: [[C2:%.+]] = load i8, ptr %c2.addr, align 1164 // CHECK-NEXT: call i8 @llvm.sadd.sat.i8(i8 [[C1]], i8 [[C2]])165 c1 = __builtin_elementwise_add_sat(c1, c2);166 167 // CHECK: [[UC1:%.+]] = load i8, ptr %uc1.addr, align 1168 // CHECK-NEXT: [[UC2:%.+]] = load i8, ptr %uc2.addr, align 1169 // CHECK-NEXT: call i8 @llvm.uadd.sat.i8(i8 [[UC1]], i8 [[UC2]])170 uc1 = __builtin_elementwise_add_sat(uc1, uc2);171 172 // CHECK: [[S1:%.+]] = load i16, ptr %s1.addr, align 2173 // CHECK-NEXT: [[S2:%.+]] = load i16, ptr %s2.addr, align 2174 // CHECK-NEXT: call i16 @llvm.sadd.sat.i16(i16 [[S1]], i16 [[S2]])175 s1 = __builtin_elementwise_add_sat(s1, s2);176 177 // CHECK: [[S1:%.+]] = load i16, ptr %s1.addr, align 2178 // CHECK: [[I1:%.+]] = sext i16 [[S1]] to i32179 // CHECK-NEXT: [[S2:%.+]] = load i16, ptr %s2.addr, align 2180 // CHECK: [[I2:%.+]] = sext i16 [[S2]] to i32181 // CHECK-NEXT: call i32 @llvm.sadd.sat.i32(i32 [[I1]], i32 [[I2]])182 s1 = __builtin_elementwise_add_sat((int)s1, (int)s2);183 184 // CHECK: [[US1:%.+]] = load i16, ptr %us1.addr, align 2185 // CHECK-NEXT: [[US2:%.+]] = load i16, ptr %us2.addr, align 2186 // CHECK-NEXT: call i16 @llvm.uadd.sat.i16(i16 [[US1]], i16 [[US2]])187 us1 = __builtin_elementwise_add_sat(us1, us2);188}189 190void test_builtin_elementwise_sub_sat(float f1, float f2, double d1, double d2,191 float4 vf1, float4 vf2, long long int i1,192 long long int i2, si8 vi1, si8 vi2,193 unsigned u1, unsigned u2, u4 vu1, u4 vu2,194 _BitInt(31) bi1, _BitInt(31) bi2,195 unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2,196 char c1, char c2, unsigned char uc1,197 unsigned char uc2, short s1, short s2,198 unsigned short us1, unsigned short us2) {199 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8200 // CHECK-NEXT: [[I2:%.+]] = load i64, ptr %i2.addr, align 8201 // CHECK-NEXT: call i64 @llvm.ssub.sat.i64(i64 [[I1]], i64 [[I2]])202 i1 = __builtin_elementwise_sub_sat(i1, i2);203 204 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8205 // CHECK-NEXT: call i64 @llvm.ssub.sat.i64(i64 [[I1]], i64 10)206 i1 = __builtin_elementwise_sub_sat(i1, 10ll);207 208 // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 16209 // CHECK-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %vi2.addr, align 16210 // CHECK-NEXT: call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> [[VI1]], <8 x i16> [[VI2]])211 vi1 = __builtin_elementwise_sub_sat(vi1, vi2);212 213 // CHECK: [[U1:%.+]] = load i32, ptr %u1.addr, align 4214 // CHECK-NEXT: [[U2:%.+]] = load i32, ptr %u2.addr, align 4215 // CHECK-NEXT: call i32 @llvm.usub.sat.i32(i32 [[U1]], i32 [[U2]])216 u1 = __builtin_elementwise_sub_sat(u1, u2);217 218 // CHECK: [[VU1:%.+]] = load <4 x i32>, ptr %vu1.addr, align 16219 // CHECK-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %vu2.addr, align 16220 // CHECK-NEXT: call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> [[VU1]], <4 x i32> [[VU2]])221 vu1 = __builtin_elementwise_sub_sat(vu1, vu2);222 223 // CHECK: [[BI1:%.+]] = load i32, ptr %bi1.addr, align 4224 // CHECK-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31225 // CHECK-NEXT: [[BI2:%.+]] = load i32, ptr %bi2.addr, align 4226 // CHECK-NEXT: [[LOADEDV1:%.+]] = trunc i32 [[BI2]] to i31227 // CHECK-NEXT: call i31 @llvm.ssub.sat.i31(i31 [[LOADEDV]], i31 [[LOADEDV1]])228 bi1 = __builtin_elementwise_sub_sat(bi1, bi2);229 230 // CHECK: [[BU1:%.+]] = load i64, ptr %bu1.addr, align 8231 // CHECK-NEXT: [[LOADEDV2:%.+]] = trunc i64 [[BU1]] to i55232 // CHECK-NEXT: [[BU2:%.+]] = load i64, ptr %bu2.addr, align 8233 // CHECK-NEXT: [[LOADEDV3:%.+]] = trunc i64 [[BU2]] to i55234 // CHECK-NEXT: call i55 @llvm.usub.sat.i55(i55 [[LOADEDV2]], i55 [[LOADEDV3]])235 bu1 = __builtin_elementwise_sub_sat(bu1, bu2);236 237 // CHECK: [[IAS1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4238 // CHECK-NEXT: [[B:%.+]] = load i32, ptr @b, align 4239 // CHECK-NEXT: call i32 @llvm.ssub.sat.i32(i32 [[IAS1]], i32 [[B]])240 int_as_one = __builtin_elementwise_sub_sat(int_as_one, b);241 242 // CHECK: store i64 -96, ptr %i1.addr, align 8243 i1 = __builtin_elementwise_sub_sat(1, 'a');244 245 // CHECK: [[C1:%.+]] = load i8, ptr %c1.addr, align 1246 // CHECK-NEXT: [[C2:%.+]] = load i8, ptr %c2.addr, align 1247 // CHECK-NEXT: call i8 @llvm.ssub.sat.i8(i8 [[C1]], i8 [[C2]])248 c1 = __builtin_elementwise_sub_sat(c1, c2);249 250 // CHECK: [[UC1:%.+]] = load i8, ptr %uc1.addr, align 1251 // CHECK-NEXT: [[UC2:%.+]] = load i8, ptr %uc2.addr, align 1252 // CHECK-NEXT: call i8 @llvm.usub.sat.i8(i8 [[UC1]], i8 [[UC2]])253 uc1 = __builtin_elementwise_sub_sat(uc1, uc2);254 255 // CHECK: [[S1:%.+]] = load i16, ptr %s1.addr, align 2256 // CHECK-NEXT: [[S2:%.+]] = load i16, ptr %s2.addr, align 2257 // CHECK-NEXT: call i16 @llvm.ssub.sat.i16(i16 [[S1]], i16 [[S2]])258 s1 = __builtin_elementwise_sub_sat(s1, s2);259 260 // CHECK: [[US1:%.+]] = load i16, ptr %us1.addr, align 2261 // CHECK-NEXT: [[US2:%.+]] = load i16, ptr %us2.addr, align 2262 // CHECK-NEXT: call i16 @llvm.usub.sat.i16(i16 [[US1]], i16 [[US2]])263 us1 = __builtin_elementwise_sub_sat(us1, us2);264}265 266void test_builtin_elementwise_maximum(float f1, float f2, double d1, double d2,267 float4 vf1, float4 vf2, long long int i1,268 long long int i2, si8 vi1, si8 vi2,269 unsigned u1, unsigned u2, u4 vu1, u4 vu2,270 _BitInt(31) bi1, _BitInt(31) bi2,271 unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {272 // CHECK-LABEL: define void @test_builtin_elementwise_maximum(273 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4274 // CHECK-NEXT: [[F2:%.+]] = load float, ptr %f2.addr, align 4275 // CHECK-NEXT: call float @llvm.maximum.f32(float [[F1]], float [[F2]])276 f1 = __builtin_elementwise_maximum(f1, f2);277 278 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8279 // CHECK-NEXT: [[D2:%.+]] = load double, ptr %d2.addr, align 8280 // CHECK-NEXT: call double @llvm.maximum.f64(double [[D1]], double [[D2]])281 d1 = __builtin_elementwise_maximum(d1, d2);282 283 // CHECK: [[D2:%.+]] = load double, ptr %d2.addr, align 8284 // CHECK-NEXT: call double @llvm.maximum.f64(double 2.000000e+01, double [[D2]])285 d1 = __builtin_elementwise_maximum(20.0, d2);286 287 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16288 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16289 // CHECK-NEXT: call <4 x float> @llvm.maximum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])290 vf1 = __builtin_elementwise_maximum(vf1, vf2);291 292 // CHECK: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16293 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16294 // CHECK-NEXT: call <4 x float> @llvm.maximum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])295 const float4 cvf1 = vf1;296 vf1 = __builtin_elementwise_maximum(cvf1, vf2);297 298 // CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16299 // CHECK-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16300 // CHECK-NEXT: call <4 x float> @llvm.maximum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])301 vf1 = __builtin_elementwise_maximum(vf2, cvf1);302}303 304void test_builtin_elementwise_minimum(float f1, float f2, double d1, double d2,305 float4 vf1, float4 vf2, long long int i1,306 long long int i2, si8 vi1, si8 vi2,307 unsigned u1, unsigned u2, u4 vu1, u4 vu2,308 _BitInt(31) bi1, _BitInt(31) bi2,309 unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {310 // CHECK-LABEL: define void @test_builtin_elementwise_minimum(311 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4312 // CHECK-NEXT: [[F2:%.+]] = load float, ptr %f2.addr, align 4313 // CHECK-NEXT: call float @llvm.minimum.f32(float [[F1]], float [[F2]])314 f1 = __builtin_elementwise_minimum(f1, f2);315 316 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8317 // CHECK-NEXT: [[D2:%.+]] = load double, ptr %d2.addr, align 8318 // CHECK-NEXT: call double @llvm.minimum.f64(double [[D1]], double [[D2]])319 d1 = __builtin_elementwise_minimum(d1, d2);320 321 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8322 // CHECK-NEXT: call double @llvm.minimum.f64(double [[D1]], double 2.000000e+00)323 d1 = __builtin_elementwise_minimum(d1, 2.0);324 325 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16326 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16327 // CHECK-NEXT: call <4 x float> @llvm.minimum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])328 vf1 = __builtin_elementwise_minimum(vf1, vf2);329 330 // CHECK: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16331 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16332 // CHECK-NEXT: call <4 x float> @llvm.minimum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])333 const float4 cvf1 = vf1;334 vf1 = __builtin_elementwise_minimum(cvf1, vf2);335 336 // CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16337 // CHECK-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16338 // CHECK-NEXT: call <4 x float> @llvm.minimum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])339 vf1 = __builtin_elementwise_minimum(vf2, cvf1);340}341 342void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,343 float4 vf1, float4 vf2, long long int i1,344 long long int i2, si8 vi1, si8 vi2,345 unsigned u1, unsigned u2, u4 vu1, u4 vu2,346 _BitInt(31) bi1, _BitInt(31) bi2,347 unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {348 // CHECK-LABEL: define void @test_builtin_elementwise_max(349 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4350 // CHECK-NEXT: [[F2:%.+]] = load float, ptr %f2.addr, align 4351 // CHECK-NEXT: call float @llvm.maxnum.f32(float [[F1]], float [[F2]])352 f1 = __builtin_elementwise_max(f1, f2);353 354 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8355 // CHECK-NEXT: [[D2:%.+]] = load double, ptr %d2.addr, align 8356 // CHECK-NEXT: call double @llvm.maxnum.f64(double [[D1]], double [[D2]])357 d1 = __builtin_elementwise_max(d1, d2);358 359 // CHECK: [[D2:%.+]] = load double, ptr %d2.addr, align 8360 // CHECK-NEXT: call double @llvm.maxnum.f64(double 2.000000e+01, double [[D2]])361 d1 = __builtin_elementwise_max(20.0, d2);362 363 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16364 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16365 // CHECK-NEXT: call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])366 vf1 = __builtin_elementwise_max(vf1, vf2);367 368 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8369 // CHECK-NEXT: [[I2:%.+]] = load i64, ptr %i2.addr, align 8370 // CHECK-NEXT: call i64 @llvm.smax.i64(i64 [[I1]], i64 [[I2]])371 i1 = __builtin_elementwise_max(i1, i2);372 373 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8374 // CHECK-NEXT: call i64 @llvm.smax.i64(i64 [[I1]], i64 10)375 i1 = __builtin_elementwise_max(i1, 10ll);376 377 // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 16378 // CHECK-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %vi2.addr, align 16379 // CHECK-NEXT: call <8 x i16> @llvm.smax.v8i16(<8 x i16> [[VI1]], <8 x i16> [[VI2]])380 vi1 = __builtin_elementwise_max(vi1, vi2);381 382 // CHECK: [[U1:%.+]] = load i32, ptr %u1.addr, align 4383 // CHECK-NEXT: [[U2:%.+]] = load i32, ptr %u2.addr, align 4384 // CHECK-NEXT: call i32 @llvm.umax.i32(i32 [[U1]], i32 [[U2]])385 u1 = __builtin_elementwise_max(u1, u2);386 387 // CHECK: [[VU1:%.+]] = load <4 x i32>, ptr %vu1.addr, align 16388 // CHECK-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %vu2.addr, align 16389 // CHECK-NEXT: call <4 x i32> @llvm.umax.v4i32(<4 x i32> [[VU1]], <4 x i32> [[VU2]])390 vu1 = __builtin_elementwise_max(vu1, vu2);391 392 // CHECK: [[BI1:%.+]] = load i32, ptr %bi1.addr, align 4393 // CHECK-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31394 // CHECK-NEXT: [[BI2:%.+]] = load i32, ptr %bi2.addr, align 4395 // CHECK-NEXT: [[LOADEDV1:%.+]] = trunc i32 [[BI2]] to i31396 // CHECK-NEXT: call i31 @llvm.smax.i31(i31 [[LOADEDV]], i31 [[LOADEDV1]])397 bi1 = __builtin_elementwise_max(bi1, bi2);398 399 // CHECK: [[BU1:%.+]] = load i64, ptr %bu1.addr, align 8400 // CHECK-NEXT: [[LOADEDV2:%.+]] = trunc i64 [[BU1]] to i55401 // CHECK-NEXT: [[BU2:%.+]] = load i64, ptr %bu2.addr, align 8402 // CHECK-NEXT: [[LOADEDV3:%.+]] = trunc i64 [[BU2]] to i55403 // CHECK-NEXT: call i55 @llvm.umax.i55(i55 [[LOADEDV2]], i55 [[LOADEDV3]])404 bu1 = __builtin_elementwise_max(bu1, bu2);405 406 // CHECK: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16407 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16408 // CHECK-NEXT: call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])409 const float4 cvf1 = vf1;410 vf1 = __builtin_elementwise_max(cvf1, vf2);411 412 // CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16413 // CHECK-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16414 // CHECK-NEXT: call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])415 vf1 = __builtin_elementwise_max(vf2, cvf1);416 417 // CHECK: [[IAS1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4418 // CHECK-NEXT: [[B:%.+]] = load i32, ptr @b, align 4419 // CHECK-NEXT: call i32 @llvm.smax.i32(i32 [[IAS1]], i32 [[B]])420 int_as_one = __builtin_elementwise_max(int_as_one, b);421 422 // CHECK: store i64 97, ptr [[I1:%.+]], align 8423 i1 = __builtin_elementwise_max(1, 'a');424}425 426void test_builtin_elementwise_min(float f1, float f2, double d1, double d2,427 float4 vf1, float4 vf2, long long int i1,428 long long int i2, si8 vi1, si8 vi2,429 unsigned u1, unsigned u2, u4 vu1, u4 vu2,430 _BitInt(31) bi1, _BitInt(31) bi2,431 unsigned _BitInt(55) bu1, unsigned _BitInt(55) bu2) {432 // CHECK-LABEL: define void @test_builtin_elementwise_min(433 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4434 // CHECK-NEXT: [[F2:%.+]] = load float, ptr %f2.addr, align 4435 // CHECK-NEXT: call float @llvm.minnum.f32(float [[F1]], float [[F2]])436 f1 = __builtin_elementwise_min(f1, f2);437 438 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8439 // CHECK-NEXT: [[D2:%.+]] = load double, ptr %d2.addr, align 8440 // CHECK-NEXT: call double @llvm.minnum.f64(double [[D1]], double [[D2]])441 d1 = __builtin_elementwise_min(d1, d2);442 443 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8444 // CHECK-NEXT: call double @llvm.minnum.f64(double [[D1]], double 2.000000e+00)445 d1 = __builtin_elementwise_min(d1, 2.0);446 447 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16448 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16449 // CHECK-NEXT: call <4 x float> @llvm.minnum.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])450 vf1 = __builtin_elementwise_min(vf1, vf2);451 452 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8453 // CHECK-NEXT: [[I2:%.+]] = load i64, ptr %i2.addr, align 8454 // CHECK-NEXT: call i64 @llvm.smin.i64(i64 [[I1]], i64 [[I2]])455 i1 = __builtin_elementwise_min(i1, i2);456 457 // CHECK: [[I2:%.+]] = load i64, ptr %i2.addr, align 8458 // CHECK-NEXT: call i64 @llvm.smin.i64(i64 -11, i64 [[I2]])459 i1 = __builtin_elementwise_min(-11ll, i2);460 461 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8462 // CHECK: [[S1:%.+]] = trunc i64 [[I1]] to i16463 // CHECK-NEXT: [[I2:%.+]] = load i64, ptr %i2.addr, align 8464 // CHECK: [[S2:%.+]] = trunc i64 [[I2]] to i16465 // CHECK-NEXT: call i16 @llvm.smin.i16(i16 [[S1]], i16 [[S2]])466 i1 = __builtin_elementwise_min((short)i1, (short)i2);467 468 // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 16469 // CHECK-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %vi2.addr, align 16470 // CHECK-NEXT: call <8 x i16> @llvm.smin.v8i16(<8 x i16> [[VI1]], <8 x i16> [[VI2]])471 vi1 = __builtin_elementwise_min(vi1, vi2);472 473 // CHECK: [[U1:%.+]] = load i32, ptr %u1.addr, align 4474 // CHECK-NEXT: [[U2:%.+]] = load i32, ptr %u2.addr, align 4475 // CHECK-NEXT: call i32 @llvm.umin.i32(i32 [[U1]], i32 [[U2]])476 u1 = __builtin_elementwise_min(u1, u2);477 478 // CHECK: [[VU1:%.+]] = load <4 x i32>, ptr %vu1.addr, align 16479 // CHECK-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %vu2.addr, align 16480 // CHECK-NEXT: call <4 x i32> @llvm.umin.v4i32(<4 x i32> [[VU1]], <4 x i32> [[VU2]])481 vu1 = __builtin_elementwise_min(vu1, vu2);482 483 // CHECK: [[BI1:%.+]] = load i32, ptr %bi1.addr, align 4484 // CHECK-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31485 // CHECK-NEXT: [[BI2:%.+]] = load i32, ptr %bi2.addr, align 4486 // CHECK-NEXT: [[LOADEDV1:%.+]] = trunc i32 [[BI2]] to i31487 // CHECK-NEXT: call i31 @llvm.smin.i31(i31 [[LOADEDV]], i31 [[LOADEDV1]])488 bi1 = __builtin_elementwise_min(bi1, bi2);489 490 // CHECK: [[BU1:%.+]] = load i64, ptr %bu1.addr, align 8491 // CHECK-NEXT: [[LOADEDV2:%.+]] = trunc i64 [[BU1]] to i55492 // CHECK-NEXT: [[BU2:%.+]] = load i64, ptr %bu2.addr, align 8493 // CHECK-NEXT: [[LOADEDV3:%.+]] = trunc i64 [[BU2]] to i55494 // CHECK-NEXT: call i55 @llvm.umin.i55(i55 [[LOADEDV2]], i55 [[LOADEDV3]])495 bu1 = __builtin_elementwise_min(bu1, bu2);496 497 // CHECK: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16498 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16499 // CHECK-NEXT: call <4 x float> @llvm.minnum.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])500 const float4 cvf1 = vf1;501 vf1 = __builtin_elementwise_min(cvf1, vf2);502 503 // CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16504 // CHECK-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 16505 // CHECK-NEXT: call <4 x float> @llvm.minnum.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])506 vf1 = __builtin_elementwise_min(vf2, cvf1);507 508 // CHECK: [[IAS1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4509 // CHECK-NEXT: [[B:%.+]] = load i32, ptr @b, align 4510 // CHECK-NEXT: call i32 @llvm.smin.i32(i32 [[IAS1]], i32 [[B]])511 int_as_one = __builtin_elementwise_min(int_as_one, b);512 513 // CHECK: store i64 2, ptr [[I1:%.+]], align 8514 i1 = __builtin_elementwise_min(2, 'b');515}516 517void test_builtin_elementwise_bitreverse(si8 vi1, si8 vi2,518 long long int i1, long long int i2, short si,519 _BitInt(31) bi1, _BitInt(31) bi2,520 char ci) {521 522 523 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8524 // CHECK-NEXT: call i64 @llvm.bitreverse.i64(i64 [[I1]])525 i2 = __builtin_elementwise_bitreverse(i1);526 527 // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 16528 // CHECK-NEXT: call <8 x i16> @llvm.bitreverse.v8i16(<8 x i16> [[VI1]])529 vi2 = __builtin_elementwise_bitreverse(vi1);530 531 // CHECK: [[CVI2:%.+]] = load <8 x i16>, ptr %cvi2, align 16532 // CHECK-NEXT: call <8 x i16> @llvm.bitreverse.v8i16(<8 x i16> [[CVI2]])533 const si8 cvi2 = vi2;534 vi2 = __builtin_elementwise_bitreverse(cvi2);535 536 // CHECK: [[BI1:%.+]] = load i32, ptr %bi1.addr, align 4537 // CHECK-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31538 // CHECK-NEXT: call i31 @llvm.bitreverse.i31(i31 [[LOADEDV]])539 bi2 = __builtin_elementwise_bitreverse(bi1);540 541 // CHECK: [[IA1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4542 // CHECK-NEXT: call i32 @llvm.bitreverse.i32(i32 [[IA1]])543 b = __builtin_elementwise_bitreverse(int_as_one);544 545 // CHECK: store i32 1879048191, ptr @b, align 4546 b = __builtin_elementwise_bitreverse(-10);547 548 // CHECK: [[SI:%.+]] = load i16, ptr %si.addr, align 2549 // CHECK-NEXT: [[RES:%.+]] = call i16 @llvm.bitreverse.i16(i16 [[SI]])550 si = __builtin_elementwise_bitreverse(si);551 552 // CHECK: store i16 28671, ptr %si.addr, align 2553 si = __builtin_elementwise_bitreverse((short)-10);554 555 // CHECK: store i16 28671, ptr %si.addr, align 2556 si = __builtin_elementwise_bitreverse((unsigned short)-10);557 558 // CHECK: [[CI:%.+]] = load i8, ptr %ci.addr, align 1559 // CHECK-NEXT: [[RES:%.+]] = call i8 @llvm.bitreverse.i8(i8 [[CI]])560 ci = __builtin_elementwise_bitreverse(ci);561 562 // CHECK: store i8 111, ptr %ci.addr, align 1563 ci = __builtin_elementwise_bitreverse((unsigned char)-10);564 565 // CHECK: store i8 111, ptr %ci.addr, align 1566 ci = __builtin_elementwise_bitreverse((char)-10);567}568 569void test_builtin_elementwise_ceil(float f1, float f2, double d1, double d2,570 float4 vf1, float4 vf2) {571 // CHECK-LABEL: define void @test_builtin_elementwise_ceil(572 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4573 // CHECK-NEXT: call float @llvm.ceil.f32(float [[F1]])574 f2 = __builtin_elementwise_ceil(f1);575 576 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8577 // CHECK-NEXT: call double @llvm.ceil.f64(double [[D1]])578 d2 = __builtin_elementwise_ceil(d1);579 580 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16581 // CHECK-NEXT: call <4 x float> @llvm.ceil.v4f32(<4 x float> [[VF1]])582 vf2 = __builtin_elementwise_ceil(vf1);583}584 585void test_builtin_elementwise_acos(float f1, float f2, double d1, double d2,586 float4 vf1, float4 vf2) {587 // CHECK-LABEL: define void @test_builtin_elementwise_acos(588 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4589 // CHECK-NEXT: call float @llvm.acos.f32(float [[F1]])590 f2 = __builtin_elementwise_acos(f1);591 592 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8593 // CHECK-NEXT: call double @llvm.acos.f64(double [[D1]])594 d2 = __builtin_elementwise_acos(d1);595 596 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16597 // CHECK-NEXT: call <4 x float> @llvm.acos.v4f32(<4 x float> [[VF1]])598 vf2 = __builtin_elementwise_acos(vf1);599}600 601void test_builtin_elementwise_asin(float f1, float f2, double d1, double d2,602 float4 vf1, float4 vf2) {603 // CHECK-LABEL: define void @test_builtin_elementwise_asin(604 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4605 // CHECK-NEXT: call float @llvm.asin.f32(float [[F1]])606 f2 = __builtin_elementwise_asin(f1);607 608 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8609 // CHECK-NEXT: call double @llvm.asin.f64(double [[D1]])610 d2 = __builtin_elementwise_asin(d1);611 612 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16613 // CHECK-NEXT: call <4 x float> @llvm.asin.v4f32(<4 x float> [[VF1]])614 vf2 = __builtin_elementwise_asin(vf1);615}616 617void test_builtin_elementwise_atan(float f1, float f2, double d1, double d2,618 float4 vf1, float4 vf2) {619 // CHECK-LABEL: define void @test_builtin_elementwise_atan(620 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4621 // CHECK-NEXT: call float @llvm.atan.f32(float [[F1]])622 f2 = __builtin_elementwise_atan(f1);623 624 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8625 // CHECK-NEXT: call double @llvm.atan.f64(double [[D1]])626 d2 = __builtin_elementwise_atan(d1);627 628 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16629 // CHECK-NEXT: call <4 x float> @llvm.atan.v4f32(<4 x float> [[VF1]])630 vf2 = __builtin_elementwise_atan(vf1);631}632 633void test_builtin_elementwise_atan2(float f1, float f2, float f3, double d1,634 double d2, double d3, float4 vf1,635 float4 vf2, float4 vf3) {636 // CHECK-LABEL: define void @test_builtin_elementwise_atan2(637 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4638 // CHECK-NEXT: [[F2:%.+]] = load float, ptr %f2.addr, align 4639 // CHECK-NEXT: call float @llvm.atan2.f32(float [[F1]], float [[F2]])640 f3 = __builtin_elementwise_atan2(f1, f2);641 642 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8643 // CHECK-NEXT: [[D2:%.+]] = load double, ptr %d2.addr, align 8644 // CHECK-NEXT: call double @llvm.atan2.f64(double [[D1]], double [[D2]])645 d3 = __builtin_elementwise_atan2(d1, d2);646 647 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16648 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16649 // CHECK-NEXT: call <4 x float> @llvm.atan2.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])650 vf3 = __builtin_elementwise_atan2(vf1, vf2);651}652 653void test_builtin_elementwise_cos(float f1, float f2, double d1, double d2,654 float4 vf1, float4 vf2) {655 // CHECK-LABEL: define void @test_builtin_elementwise_cos(656 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4657 // CHECK-NEXT: call float @llvm.cos.f32(float [[F1]])658 f2 = __builtin_elementwise_cos(f1);659 660 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8661 // CHECK-NEXT: call double @llvm.cos.f64(double [[D1]])662 d2 = __builtin_elementwise_cos(d1);663 664 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16665 // CHECK-NEXT: call <4 x float> @llvm.cos.v4f32(<4 x float> [[VF1]])666 vf2 = __builtin_elementwise_cos(vf1);667}668 669void test_builtin_elementwise_cosh(float f1, float f2, double d1, double d2,670 float4 vf1, float4 vf2) {671 // CHECK-LABEL: define void @test_builtin_elementwise_cosh(672 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4673 // CHECK-NEXT: call float @llvm.cosh.f32(float [[F1]])674 f2 = __builtin_elementwise_cosh(f1);675 676 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8677 // CHECK-NEXT: call double @llvm.cosh.f64(double [[D1]])678 d2 = __builtin_elementwise_cosh(d1);679 680 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16681 // CHECK-NEXT: call <4 x float> @llvm.cosh.v4f32(<4 x float> [[VF1]])682 vf2 = __builtin_elementwise_cosh(vf1);683}684 685void test_builtin_elementwise_exp(float f1, float f2, double d1, double d2,686 float4 vf1, float4 vf2) {687 // CHECK-LABEL: define void @test_builtin_elementwise_exp(688 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4689 // CHECK-NEXT: call float @llvm.exp.f32(float [[F1]])690 f2 = __builtin_elementwise_exp(f1);691 692 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8693 // CHECK-NEXT: call double @llvm.exp.f64(double [[D1]])694 d2 = __builtin_elementwise_exp(d1);695 696 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16697 // CHECK-NEXT: call <4 x float> @llvm.exp.v4f32(<4 x float> [[VF1]])698 vf2 = __builtin_elementwise_exp(vf1);699}700 701void test_builtin_elementwise_exp2(float f1, float f2, double d1, double d2,702 float4 vf1, float4 vf2) {703 // CHECK-LABEL: define void @test_builtin_elementwise_exp2(704 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4705 // CHECK-NEXT: call float @llvm.exp2.f32(float [[F1]])706 f2 = __builtin_elementwise_exp2(f1);707 708 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8709 // CHECK-NEXT: call double @llvm.exp2.f64(double [[D1]])710 d2 = __builtin_elementwise_exp2(d1);711 712 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16713 // CHECK-NEXT: call <4 x float> @llvm.exp2.v4f32(<4 x float> [[VF1]])714 vf2 = __builtin_elementwise_exp2(vf1);715}716 717void test_builtin_elementwise_exp10(float f1, float f2, double d1, double d2,718 float4 vf1, float4 vf2) {719 // CHECK-LABEL: define void @test_builtin_elementwise_exp10(720 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4721 // CHECK-NEXT: call float @llvm.exp10.f32(float [[F1]])722 f2 = __builtin_elementwise_exp10(f1);723 724 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8725 // CHECK-NEXT: call double @llvm.exp10.f64(double [[D1]])726 d2 = __builtin_elementwise_exp10(d1);727 728 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16729 // CHECK-NEXT: call <4 x float> @llvm.exp10.v4f32(<4 x float> [[VF1]])730 vf2 = __builtin_elementwise_exp10(vf1);731}732 733void test_builtin_elementwise_ldexp(float f1, float f2, double d1, double d2,734 float4 vf1, float4 vf2, int i1, int4 vi1, short s1, long l1) {735 // CHECK-LABEL: define void @test_builtin_elementwise_ldexp(736 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4737 // CHECK: [[I1:%.+]] = load i32, ptr %i1.addr, align 4738 // CHECK-NEXT: call float @llvm.ldexp.f32.i32(float [[F1]], i32 [[I1]])739 f2 = __builtin_elementwise_ldexp(f1, i1);740 741 // CHECK: [[F2:%.+]] = load float, ptr %f1.addr, align 4742 // CHECK: [[S1:%.+]] = load i16, ptr %s1.addr, align 2743 // CHECK: [[Ext1:%.+]] = sext i16 [[S1]] to i32744 // CHECK-NEXT: call float @llvm.ldexp.f32.i32(float [[F2]], i32 [[Ext1]])745 f2 = __builtin_elementwise_ldexp(f1, s1);746 747 // CHECK: [[F3:%.+]] = load float, ptr %f1.addr, align 4748 // CHECK: [[L1:%.+]] = load i64, ptr %l1.addr, align 8749 // CHECK-NEXT: call float @llvm.ldexp.f32.i64(float [[F3]], i64 [[L1]])750 f2 = __builtin_elementwise_ldexp(f1, l1);751 752 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8753 // CHECK: [[I2:%.+]] = load i32, ptr %i1.addr, align 4754 // CHECK-NEXT: call double @llvm.ldexp.f64.i32(double [[D1]], i32 [[I2]])755 d2 = __builtin_elementwise_ldexp(d1, i1);756 757 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16758 // CHECK: [[VI1:%.+]] = load <4 x i32>, ptr %vi1.addr, align 16759 // CHECK-NEXT: call <4 x float> @llvm.ldexp.v4f32.v4i32(<4 x float> [[VF1]], <4 x i32> [[VI1]])760 vf2 = __builtin_elementwise_ldexp(vf1, vi1);761}762 763void test_builtin_elementwise_floor(float f1, float f2, double d1, double d2,764 float4 vf1, float4 vf2) {765 // CHECK-LABEL: define void @test_builtin_elementwise_floor(766 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4767 // CHECK-NEXT: call float @llvm.floor.f32(float [[F1]])768 f2 = __builtin_elementwise_floor(f1);769 770 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8771 // CHECK-NEXT: call double @llvm.floor.f64(double [[D1]])772 d2 = __builtin_elementwise_floor(d1);773 774 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16775 // CHECK-NEXT: call <4 x float> @llvm.floor.v4f32(<4 x float> [[VF1]])776 vf2 = __builtin_elementwise_floor(vf1);777}778 779void test_builtin_elementwise_log(float f1, float f2, double d1, double d2,780 float4 vf1, float4 vf2) {781 // CHECK-LABEL: define void @test_builtin_elementwise_log(782 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4783 // CHECK-NEXT: call float @llvm.log.f32(float [[F1]])784 f2 = __builtin_elementwise_log(f1);785 786 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8787 // CHECK-NEXT: call double @llvm.log.f64(double [[D1]])788 d2 = __builtin_elementwise_log(d1);789 790 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16791 // CHECK-NEXT: call <4 x float> @llvm.log.v4f32(<4 x float> [[VF1]])792 vf2 = __builtin_elementwise_log(vf1);793}794 795void test_builtin_elementwise_log10(float f1, float f2, double d1, double d2,796 float4 vf1, float4 vf2) {797 // CHECK-LABEL: define void @test_builtin_elementwise_log10(798 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4799 // CHECK-NEXT: call float @llvm.log10.f32(float [[F1]])800 f2 = __builtin_elementwise_log10(f1);801 802 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8803 // CHECK-NEXT: call double @llvm.log10.f64(double [[D1]])804 d2 = __builtin_elementwise_log10(d1);805 806 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16807 // CHECK-NEXT: call <4 x float> @llvm.log10.v4f32(<4 x float> [[VF1]])808 vf2 = __builtin_elementwise_log10(vf1);809}810 811void test_builtin_elementwise_log2(float f1, float f2, double d1, double d2,812 float4 vf1, float4 vf2) {813 // CHECK-LABEL: define void @test_builtin_elementwise_log2(814 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4815 // CHECK-NEXT: call float @llvm.log2.f32(float [[F1]])816 f2 = __builtin_elementwise_log2(f1);817 818 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8819 // CHECK-NEXT: call double @llvm.log2.f64(double [[D1]])820 d2 = __builtin_elementwise_log2(d1);821 822 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16823 // CHECK-NEXT: call <4 x float> @llvm.log2.v4f32(<4 x float> [[VF1]])824 vf2 = __builtin_elementwise_log2(vf1);825}826 827void test_builtin_elementwise_popcount(si8 vi1, si8 vi2, long long int i1,828 long long int i2, short si,829 _BitInt(31) bi1, _BitInt(31) bi2,830 char ci) {831 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr, align 8832 // CHECK-NEXT: call i64 @llvm.ctpop.i64(i64 [[I1]])833 i2 = __builtin_elementwise_popcount(i1);834 835 // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr, align 16836 // CHECK-NEXT: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> [[VI1]])837 vi2 = __builtin_elementwise_popcount(vi1);838 839 // CHECK: [[CVI2:%.+]] = load <8 x i16>, ptr %cvi2, align 16840 // CHECK-NEXT: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> [[CVI2]])841 const si8 cvi2 = vi2;842 vi2 = __builtin_elementwise_popcount(cvi2);843 844 // CHECK: [[BI1:%.+]] = load i32, ptr %bi1.addr, align 4845 // CHECK-NEXT: [[LOADEDV:%.+]] = trunc i32 [[BI1]] to i31846 // CHECK-NEXT: call i31 @llvm.ctpop.i31(i31 [[LOADEDV]])847 bi2 = __builtin_elementwise_popcount(bi1);848 849 // CHECK: [[IA1:%.+]] = load i32, ptr addrspace(1) @int_as_one, align 4850 // CHECK-NEXT: call i32 @llvm.ctpop.i32(i32 [[IA1]])851 b = __builtin_elementwise_popcount(int_as_one);852 853 // CHECK: store i32 30, ptr @b, align 4854 b = __builtin_elementwise_popcount(-10);855 856 // CHECK: [[SI:%.+]] = load i16, ptr %si.addr, align 2857 // CHECK-NEXT: [[RES:%.+]] = call i16 @llvm.ctpop.i16(i16 [[SI]])858 si = __builtin_elementwise_popcount(si);859 860 // CHECK: store i16 3, ptr %si.addr, align 2861 si = __builtin_elementwise_popcount((unsigned short)32771);862 863 // CHECK: store i16 3, ptr %si.addr, align 2864 si = __builtin_elementwise_popcount((short)32771);865 866 // CHECK: [[CI:%.+]] = load i8, ptr %ci.addr, align 1867 // CHECK-NEXT: [[RES:%.+]] = call i8 @llvm.ctpop.i8(i8 [[CI]])868 ci = __builtin_elementwise_popcount(ci);869 870 // CHECK: store i8 2, ptr %ci.addr, align 1871 ci = __builtin_elementwise_popcount((unsigned char)192);872 873 // CHECK: store i8 2, ptr %ci.addr, align 1874 ci = __builtin_elementwise_popcount((char)192);875}876 877void test_builtin_elementwise_fmod(float f1, float f2, double d1, double d2,878 float4 vf1, float4 vf2) {879 880 // CHECK-LABEL: define void @test_builtin_elementwise_fmod(881 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4882 // CHECK: [[F2:%.+]] = load float, ptr %f2.addr, align 4883 // CHECK-NEXT: frem float [[F1]], [[F2]]884 f2 = __builtin_elementwise_fmod(f1, f2);885 886 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8887 // CHECK: [[D2:%.+]] = load double, ptr %d2.addr, align 8888 // CHECK-NEXT: frem double [[D1]], [[D2]]889 d2 = __builtin_elementwise_fmod(d1, d2);890 891 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16892 // CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16893 // CHECK-NEXT: frem <4 x float> [[VF1]], [[VF2]]894 vf2 = __builtin_elementwise_fmod(vf1, vf2);895}896 897void test_builtin_elementwise_pow(float f1, float f2, double d1, double d2,898 float4 vf1, float4 vf2) {899 900 // CHECK-LABEL: define void @test_builtin_elementwise_pow(901 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4902 // CHECK: [[F2:%.+]] = load float, ptr %f2.addr, align 4903 // CHECK-NEXT: call float @llvm.pow.f32(float [[F1]], float [[F2]])904 f2 = __builtin_elementwise_pow(f1, f2);905 906 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8907 // CHECK: [[D2:%.+]] = load double, ptr %d2.addr, align 8908 // CHECK-NEXT: call double @llvm.pow.f64(double [[D1]], double [[D2]])909 d2 = __builtin_elementwise_pow(d1, d2);910 911 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16912 // CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 16913 // CHECK-NEXT: call <4 x float> @llvm.pow.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])914 vf2 = __builtin_elementwise_pow(vf1, vf2);915}916 917void test_builtin_elementwise_roundeven(float f1, float f2, double d1, double d2,918 float4 vf1, float4 vf2) {919 // CHECK-LABEL: define void @test_builtin_elementwise_roundeven(920 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4921 // CHECK-NEXT: call float @llvm.roundeven.f32(float [[F1]])922 f2 = __builtin_elementwise_roundeven(f1);923 924 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8925 // CHECK-NEXT: call double @llvm.roundeven.f64(double [[D1]])926 d2 = __builtin_elementwise_roundeven(d1);927 928 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16929 // CHECK-NEXT: call <4 x float> @llvm.roundeven.v4f32(<4 x float> [[VF1]])930 vf2 = __builtin_elementwise_roundeven(vf1);931}932 933void test_builtin_elementwise_round(float f1, float f2, double d1, double d2,934 float4 vf1, float4 vf2) {935 // CHECK-LABEL: define void @test_builtin_elementwise_round(936 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4937 // CHECK-NEXT: call float @llvm.round.f32(float [[F1]])938 f2 = __builtin_elementwise_round(f1);939 940 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8941 // CHECK-NEXT: call double @llvm.round.f64(double [[D1]])942 d2 = __builtin_elementwise_round(d1);943 944 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16945 // CHECK-NEXT: call <4 x float> @llvm.round.v4f32(<4 x float> [[VF1]])946 vf2 = __builtin_elementwise_round(vf1);947}948 949void test_builtin_elementwise_rint(float f1, float f2, double d1, double d2,950 float4 vf1, float4 vf2) {951 // CHECK-LABEL: define void @test_builtin_elementwise_rint(952 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4953 // CHECK-NEXT: call float @llvm.rint.f32(float [[F1]])954 f2 = __builtin_elementwise_rint(f1);955 956 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8957 // CHECK-NEXT: call double @llvm.rint.f64(double [[D1]])958 d2 = __builtin_elementwise_rint(d1);959 960 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16961 // CHECK-NEXT: call <4 x float> @llvm.rint.v4f32(<4 x float> [[VF1]])962 vf2 = __builtin_elementwise_rint(vf1);963}964 965void test_builtin_elementwise_nearbyint(float f1, float f2, double d1, double d2,966 float4 vf1, float4 vf2) {967 // CHECK-LABEL: define void @test_builtin_elementwise_nearbyint(968 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4969 // CHECK-NEXT: call float @llvm.nearbyint.f32(float [[F1]])970 f2 = __builtin_elementwise_nearbyint(f1);971 972 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8973 // CHECK-NEXT: call double @llvm.nearbyint.f64(double [[D1]])974 d2 = __builtin_elementwise_nearbyint(d1);975 976 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16977 // CHECK-NEXT: call <4 x float> @llvm.nearbyint.v4f32(<4 x float> [[VF1]])978 vf2 = __builtin_elementwise_nearbyint(vf1);979}980 981void test_builtin_elementwise_sin(float f1, float f2, double d1, double d2,982 float4 vf1, float4 vf2) {983 // CHECK-LABEL: define void @test_builtin_elementwise_sin(984 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 4985 // CHECK-NEXT: call float @llvm.sin.f32(float [[F1]])986 f2 = __builtin_elementwise_sin(f1);987 988 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 8989 // CHECK-NEXT: call double @llvm.sin.f64(double [[D1]])990 d2 = __builtin_elementwise_sin(d1);991 992 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 16993 // CHECK-NEXT: call <4 x float> @llvm.sin.v4f32(<4 x float> [[VF1]])994 vf2 = __builtin_elementwise_sin(vf1);995}996 997void test_builtin_elementwise_sinh(float f1, float f2, double d1, double d2,998 float4 vf1, float4 vf2) {999 // CHECK-LABEL: define void @test_builtin_elementwise_sinh(1000 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 41001 // CHECK-NEXT: call float @llvm.sinh.f32(float [[F1]])1002 f2 = __builtin_elementwise_sinh(f1);1003 1004 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 81005 // CHECK-NEXT: call double @llvm.sinh.f64(double [[D1]])1006 d2 = __builtin_elementwise_sinh(d1);1007 1008 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 161009 // CHECK-NEXT: call <4 x float> @llvm.sinh.v4f32(<4 x float> [[VF1]])1010 vf2 = __builtin_elementwise_sinh(vf1);1011}1012 1013void test_builtin_elementwise_sqrt(float f1, float f2, double d1, double d2,1014 float4 vf1, float4 vf2) {1015 // CHECK-LABEL: define void @test_builtin_elementwise_sqrt(1016 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 41017 // CHECK-NEXT: call float @llvm.sqrt.f32(float [[F1]])1018 f2 = __builtin_elementwise_sqrt(f1);1019 1020 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 81021 // CHECK-NEXT: call double @llvm.sqrt.f64(double [[D1]])1022 d2 = __builtin_elementwise_sqrt(d1);1023 1024 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 161025 // CHECK-NEXT: call <4 x float> @llvm.sqrt.v4f32(<4 x float> [[VF1]])1026 vf2 = __builtin_elementwise_sqrt(vf1);1027}1028 1029void test_builtin_elementwise_tan(float f1, float f2, double d1, double d2,1030 float4 vf1, float4 vf2) {1031 // CHECK-LABEL: define void @test_builtin_elementwise_tan(1032 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 41033 // CHECK-NEXT: call float @llvm.tan.f32(float [[F1]])1034 f2 = __builtin_elementwise_tan(f1);1035 1036 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 81037 // CHECK-NEXT: call double @llvm.tan.f64(double [[D1]])1038 d2 = __builtin_elementwise_tan(d1);1039 1040 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 161041 // CHECK-NEXT: call <4 x float> @llvm.tan.v4f32(<4 x float> [[VF1]])1042 vf2 = __builtin_elementwise_tan(vf1);1043}1044 1045void test_builtin_elementwise_tanh(float f1, float f2, double d1, double d2,1046 float4 vf1, float4 vf2) {1047 // CHECK-LABEL: define void @test_builtin_elementwise_tanh(1048 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 41049 // CHECK-NEXT: call float @llvm.tanh.f32(float [[F1]])1050 f2 = __builtin_elementwise_tanh(f1);1051 1052 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 81053 // CHECK-NEXT: call double @llvm.tanh.f64(double [[D1]])1054 d2 = __builtin_elementwise_tanh(d1);1055 1056 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 161057 // CHECK-NEXT: call <4 x float> @llvm.tanh.v4f32(<4 x float> [[VF1]])1058 vf2 = __builtin_elementwise_tanh(vf1);1059}1060 1061void test_builtin_elementwise_trunc(float f1, float f2, double d1, double d2,1062 float4 vf1, float4 vf2) {1063 // CHECK-LABEL: define void @test_builtin_elementwise_trunc(1064 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 41065 // CHECK-NEXT: call float @llvm.trunc.f32(float [[F1]])1066 f2 = __builtin_elementwise_trunc(f1);1067 1068 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 81069 // CHECK-NEXT: call double @llvm.trunc.f64(double [[D1]])1070 d2 = __builtin_elementwise_trunc(d1);1071 1072 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 161073 // CHECK-NEXT: call <4 x float> @llvm.trunc.v4f32(<4 x float> [[VF1]])1074 vf2 = __builtin_elementwise_trunc(vf1);1075}1076 1077void test_builtin_elementwise_canonicalize(float f1, float f2, double d1, double d2,1078 float4 vf1, float4 vf2) {1079 // CHECK-LABEL: define void @test_builtin_elementwise_canonicalize(1080 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 41081 // CHECK-NEXT: call float @llvm.canonicalize.f32(float [[F1]])1082 f2 = __builtin_elementwise_canonicalize(f1);1083 1084 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 81085 // CHECK-NEXT: call double @llvm.canonicalize.f64(double [[D1]])1086 d2 = __builtin_elementwise_canonicalize(d1);1087 1088 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 161089 // CHECK-NEXT: call <4 x float> @llvm.canonicalize.v4f32(<4 x float> [[VF1]])1090 vf2 = __builtin_elementwise_canonicalize(vf1);1091}1092 1093void test_builtin_elementwise_copysign(float f1, float f2, double d1, double d2,1094 float4 vf1, float4 vf2, double2 v2f64) {1095 // CHECK-LABEL: define void @test_builtin_elementwise_copysign(1096 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr, align 41097 // CHECK-NEXT: [[F2:%.+]] = load float, ptr %f2.addr, align 41098 // CHECK-NEXT: call float @llvm.copysign.f32(float %0, float %1)1099 f1 = __builtin_elementwise_copysign(f1, f2);1100 1101 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 81102 // CHECK-NEXT: [[D2:%.+]] = load double, ptr %d2.addr, align 81103 // CHECK-NEXT: call double @llvm.copysign.f64(double [[D1]], double [[D2]])1104 d1 = __builtin_elementwise_copysign(d1, d2);1105 1106 // CHECK: [[D1:%.+]] = load double, ptr %d1.addr, align 81107 // CHECK-NEXT: call double @llvm.copysign.f64(double [[D1]], double 2.000000e+00)1108 d1 = __builtin_elementwise_copysign(d1, 2.0);1109 1110 // CHECK: [[VF1:%.+]] = load <4 x float>, ptr %vf1.addr, align 161111 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 161112 // CHECK-NEXT: call <4 x float> @llvm.copysign.v4f32(<4 x float> [[VF1]], <4 x float> [[VF2]])1113 vf1 = __builtin_elementwise_copysign(vf1, vf2);1114 1115 // CHECK: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 161116 // CHECK-NEXT: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 161117 // CHECK-NEXT: call <4 x float> @llvm.copysign.v4f32(<4 x float> [[CVF1]], <4 x float> [[VF2]])1118 const float4 cvf1 = vf1;1119 vf1 = __builtin_elementwise_copysign(cvf1, vf2);1120 1121 // CHECK: [[VF2:%.+]] = load <4 x float>, ptr %vf2.addr, align 161122 // CHECK-NEXT: [[CVF1:%.+]] = load <4 x float>, ptr %cvf1, align 161123 // CHECK-NEXT: call <4 x float> @llvm.copysign.v4f32(<4 x float> [[VF2]], <4 x float> [[CVF1]])1124 vf1 = __builtin_elementwise_copysign(vf2, cvf1);1125 1126 1127 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr1128 // CHECK-NEXT: call float @llvm.copysign.f32(float [[F1]], float 2.000000e+00)1129 f1 = __builtin_elementwise_copysign(f1, 2.0f);1130 1131 // CHECK: [[F1:%.+]] = load float, ptr %f1.addr1132 // CHECK-NEXT: call float @llvm.copysign.f32(float 2.000000e+00, float [[F1]])1133 f1 = __builtin_elementwise_copysign(2.0f, f1);1134 1135 // CHECK: [[V2F64:%.+]] = load <2 x double>, ptr %v2f64.addr, align 161136 // CHECK-NEXT: call <2 x double> @llvm.copysign.v2f64(<2 x double> splat (double 1.000000e+00), <2 x double> [[V2F64]])1137 v2f64 = __builtin_elementwise_copysign((double2)1.0, v2f64);1138}1139 1140void test_builtin_elementwise_fma(float f32, double f64,1141 float2 v2f32, float4 v4f32,1142 double2 v2f64, double3 v3f64,1143 const float4 c_v4f32,1144 half f16, half2 v2f16) {1145 // CHECK-LABEL: define void @test_builtin_elementwise_fma(1146 // CHECK: [[F32_0:%.+]] = load float, ptr %f32.addr1147 // CHECK-NEXT: [[F32_1:%.+]] = load float, ptr %f32.addr1148 // CHECK-NEXT: [[F32_2:%.+]] = load float, ptr %f32.addr1149 // CHECK-NEXT: call float @llvm.fma.f32(float [[F32_0]], float [[F32_1]], float [[F32_2]])1150 float f2 = __builtin_elementwise_fma(f32, f32, f32);1151 1152 // CHECK: [[F64_0:%.+]] = load double, ptr %f64.addr1153 // CHECK-NEXT: [[F64_1:%.+]] = load double, ptr %f64.addr1154 // CHECK-NEXT: [[F64_2:%.+]] = load double, ptr %f64.addr1155 // CHECK-NEXT: call double @llvm.fma.f64(double [[F64_0]], double [[F64_1]], double [[F64_2]])1156 double d2 = __builtin_elementwise_fma(f64, f64, f64);1157 1158 // CHECK: [[V4F32_0:%.+]] = load <4 x float>, ptr %v4f32.addr1159 // CHECK-NEXT: [[V4F32_1:%.+]] = load <4 x float>, ptr %v4f32.addr1160 // CHECK-NEXT: [[V4F32_2:%.+]] = load <4 x float>, ptr %v4f32.addr1161 // CHECK-NEXT: call <4 x float> @llvm.fma.v4f32(<4 x float> [[V4F32_0]], <4 x float> [[V4F32_1]], <4 x float> [[V4F32_2]])1162 float4 tmp_v4f32 = __builtin_elementwise_fma(v4f32, v4f32, v4f32);1163 1164 1165 // FIXME: Are we really still doing the 3 vector load workaround1166 // CHECK: [[V3F64_LOAD_0:%.+]] = load <4 x double>, ptr %v3f64.addr1167 // CHECK-NEXT: [[V3F64_0:%.+]] = shufflevector1168 // CHECK-NEXT: [[V3F64_LOAD_1:%.+]] = load <4 x double>, ptr %v3f64.addr1169 // CHECK-NEXT: [[V3F64_1:%.+]] = shufflevector1170 // CHECK-NEXT: [[V3F64_LOAD_2:%.+]] = load <4 x double>, ptr %v3f64.addr1171 // CHECK-NEXT: [[V3F64_2:%.+]] = shufflevector1172 // CHECK-NEXT: call <3 x double> @llvm.fma.v3f64(<3 x double> [[V3F64_0]], <3 x double> [[V3F64_1]], <3 x double> [[V3F64_2]])1173 v3f64 = __builtin_elementwise_fma(v3f64, v3f64, v3f64);1174 1175 // CHECK: [[F64_0:%.+]] = load double, ptr %f64.addr1176 // CHECK-NEXT: [[F64_1:%.+]] = load double, ptr %f64.addr1177 // CHECK-NEXT: [[F64_2:%.+]] = load double, ptr %f64.addr1178 // CHECK-NEXT: call double @llvm.fma.f64(double [[F64_0]], double [[F64_1]], double [[F64_2]])1179 v2f64 = __builtin_elementwise_fma(f64, f64, f64);1180 1181 // CHECK: [[V4F32_0:%.+]] = load <4 x float>, ptr %c_v4f32.addr1182 // CHECK-NEXT: [[V4F32_1:%.+]] = load <4 x float>, ptr %c_v4f32.addr1183 // CHECK-NEXT: [[V4F32_2:%.+]] = load <4 x float>, ptr %c_v4f32.addr1184 // CHECK-NEXT: call <4 x float> @llvm.fma.v4f32(<4 x float> [[V4F32_0]], <4 x float> [[V4F32_1]], <4 x float> [[V4F32_2]])1185 v4f32 = __builtin_elementwise_fma(c_v4f32, c_v4f32, c_v4f32);1186 1187 // CHECK: [[F16_0:%.+]] = load half, ptr %f16.addr1188 // CHECK-NEXT: [[F16_1:%.+]] = load half, ptr %f16.addr1189 // CHECK-NEXT: [[F16_2:%.+]] = load half, ptr %f16.addr1190 // CHECK-NEXT: call half @llvm.fma.f16(half [[F16_0]], half [[F16_1]], half [[F16_2]])1191 half tmp_f16 = __builtin_elementwise_fma(f16, f16, f16);1192 1193 // CHECK: [[V2F16_0:%.+]] = load <2 x half>, ptr %v2f16.addr1194 // CHECK-NEXT: [[V2F16_1:%.+]] = load <2 x half>, ptr %v2f16.addr1195 // CHECK-NEXT: [[V2F16_2:%.+]] = load <2 x half>, ptr %v2f16.addr1196 // CHECK-NEXT: call <2 x half> @llvm.fma.v2f16(<2 x half> [[V2F16_0]], <2 x half> [[V2F16_1]], <2 x half> [[V2F16_2]])1197 half2 tmp0_v2f16 = __builtin_elementwise_fma(v2f16, v2f16, v2f16);1198 1199 // CHECK: [[V2F16_0:%.+]] = load <2 x half>, ptr %v2f16.addr1200 // CHECK-NEXT: [[V2F16_1:%.+]] = load <2 x half>, ptr %v2f16.addr1201 // CHECK-NEXT: [[F16_2:%.+]] = load half, ptr %f16.addr1202 // CHECK-NEXT: [[V2F16_2_INSERT:%.+]] = insertelement1203 // CHECK-NEXT: [[V2F16_2:%.+]] = shufflevector <2 x half> [[V2F16_2_INSERT]], <2 x half> poison, <2 x i32> zeroinitializer1204 // CHECK-NEXT: call <2 x half> @llvm.fma.v2f16(<2 x half> [[V2F16_0]], <2 x half> [[V2F16_1]], <2 x half> [[V2F16_2]])1205 half2 tmp1_v2f16 = __builtin_elementwise_fma(v2f16, v2f16, (half2)f16);1206 1207 // CHECK: [[V2F16_0:%.+]] = load <2 x half>, ptr %v2f16.addr1208 // CHECK-NEXT: [[V2F16_1:%.+]] = load <2 x half>, ptr %v2f16.addr1209 // CHECK-NEXT: call <2 x half> @llvm.fma.v2f16(<2 x half> [[V2F16_0]], <2 x half> [[V2F16_1]], <2 x half> splat (half 0xH4400))1210 half2 tmp2_v2f16 = __builtin_elementwise_fma(v2f16, v2f16, (half2)4.0);1211 1212}1213 1214void test_builtin_elementwise_fshl(long long int i1, long long int i2,1215 long long int i3, unsigned short us1,1216 unsigned short us2, unsigned short us3,1217 char c1, char c2, char c3,1218 unsigned char uc1, unsigned char uc2,1219 unsigned char uc3, si8 vi1, si8 vi2,1220 si8 vi3, u4 vu1, u4 vu2, u4 vu3) {1221 // CHECK: [[I1:%.+]] = load i64, ptr %i1.addr1222 // CHECK-NEXT: [[I2:%.+]] = load i64, ptr %i2.addr1223 // CHECK-NEXT: [[I3:%.+]] = load i64, ptr %i3.addr1224 // CHECK-NEXT: [[I4:%.+]] = call i64 @llvm.fshl.i64(i64 [[I1]], i64 [[I2]], i64 [[I3]])1225 // CHECK-NEXT: store i64 [[I4]], ptr %tmp_lli_l1226 // CHECK-NEXT: [[I5:%.+]] = load i64, ptr %i1.addr1227 // CHECK-NEXT: [[I6:%.+]] = load i64, ptr %i2.addr1228 // CHECK-NEXT: [[I7:%.+]] = load i64, ptr %i3.addr1229 // CHECK-NEXT: [[I8:%.+]] = call i64 @llvm.fshr.i64(i64 [[I5]], i64 [[I6]], i64 [[I7]])1230 // CHECK-NEXT: store i64 [[I8]], ptr %tmp_lli_r1231 long long int tmp_lli_l = __builtin_elementwise_fshl(i1, i2, i3);1232 long long int tmp_lli_r = __builtin_elementwise_fshr(i1, i2, i3);1233 1234 // CHECK: [[US1:%.+]] = load i16, ptr %us1.addr1235 // CHECK-NEXT: [[US2:%.+]] = load i16, ptr %us2.addr1236 // CHECK-NEXT: [[US3:%.+]] = load i16, ptr %us3.addr1237 // CHECK-NEXT: [[US4:%.+]] = call i16 @llvm.fshl.i16(i16 [[US1]], i16 [[US2]], i16 [[US3]])1238 // CHECK-NEXT: store i16 [[US4]], ptr %tmp_usi_l1239 // CHECK-NEXT: [[US5:%.+]] = load i16, ptr %us1.addr1240 // CHECK-NEXT: [[US6:%.+]] = load i16, ptr %us2.addr1241 // CHECK-NEXT: [[US7:%.+]] = load i16, ptr %us3.addr1242 // CHECK-NEXT: [[US8:%.+]] = call i16 @llvm.fshr.i16(i16 [[US5]], i16 [[US6]], i16 [[US7]])1243 // CHECK-NEXT: store i16 [[US8]], ptr %tmp_usi_r1244 unsigned short tmp_usi_l = __builtin_elementwise_fshl(us1, us2, us3);1245 unsigned short tmp_usi_r = __builtin_elementwise_fshr(us1, us2, us3);1246 1247 // CHECK: [[C1:%.+]] = load i8, ptr %c1.addr1248 // CHECK-NEXT: [[C2:%.+]] = load i8, ptr %c2.addr1249 // CHECK-NEXT: [[C3:%.+]] = load i8, ptr %c3.addr1250 // CHECK-NEXT: [[C4:%.+]] = call i8 @llvm.fshl.i8(i8 [[C1]], i8 [[C2]], i8 [[C3]])1251 // CHECK-NEXT: store i8 [[C4]], ptr %tmp_c_l1252 // CHECK-NEXT: [[C5:%.+]] = load i8, ptr %c1.addr1253 // CHECK-NEXT: [[C6:%.+]] = load i8, ptr %c2.addr1254 // CHECK-NEXT: [[C7:%.+]] = load i8, ptr %c3.addr1255 // CHECK-NEXT: [[C8:%.+]] = call i8 @llvm.fshr.i8(i8 [[C5]], i8 [[C6]], i8 [[C7]])1256 // CHECK-NEXT: store i8 [[C8]], ptr %tmp_c_r1257 char tmp_c_l = __builtin_elementwise_fshl(c1, c2, c3);1258 char tmp_c_r = __builtin_elementwise_fshr(c1, c2, c3);1259 1260 // CHECK: [[UC1:%.+]] = load i8, ptr %uc1.addr1261 // CHECK-NEXT: [[UC2:%.+]] = load i8, ptr %uc2.addr1262 // CHECK-NEXT: [[UC3:%.+]] = load i8, ptr %uc3.addr1263 // CHECK-NEXT: [[UC4:%.+]] = call i8 @llvm.fshl.i8(i8 [[UC1]], i8 [[UC2]], i8 [[UC3]])1264 // CHECK-NEXT: store i8 [[UC4]], ptr %tmp_uc_l1265 // CHECK-NEXT: [[UC5:%.+]] = load i8, ptr %uc1.addr1266 // CHECK-NEXT: [[UC6:%.+]] = load i8, ptr %uc2.addr1267 // CHECK-NEXT: [[UC7:%.+]] = load i8, ptr %uc3.addr1268 // CHECK-NEXT: [[UC8:%.+]] = call i8 @llvm.fshr.i8(i8 [[UC5]], i8 [[UC6]], i8 [[UC7]])1269 // CHECK-NEXT: store i8 [[UC8]], ptr %tmp_uc_r1270 unsigned char tmp_uc_l = __builtin_elementwise_fshl(uc1, uc2, uc3);1271 unsigned char tmp_uc_r = __builtin_elementwise_fshr(uc1, uc2, uc3);1272 1273 // CHECK: [[VI1:%.+]] = load <8 x i16>, ptr %vi1.addr1274 // CHECK-NEXT: [[VI2:%.+]] = load <8 x i16>, ptr %vi2.addr1275 // CHECK-NEXT: [[VI3:%.+]] = load <8 x i16>, ptr %vi3.addr1276 // CHECK-NEXT: [[VI4:%.+]] = call <8 x i16> @llvm.fshl.v8i16(<8 x i16> [[VI1]], <8 x i16> [[VI2]], <8 x i16> [[VI3]])1277 // CHECK-NEXT: store <8 x i16> [[VI4]], ptr %tmp_vi_l1278 // CHECK-NEXT: [[VI5:%.+]] = load <8 x i16>, ptr %vi1.addr1279 // CHECK-NEXT: [[VI6:%.+]] = load <8 x i16>, ptr %vi2.addr1280 // CHECK-NEXT: [[VI7:%.+]] = load <8 x i16>, ptr %vi3.addr1281 // CHECK-NEXT: [[VI8:%.+]] = call <8 x i16> @llvm.fshr.v8i16(<8 x i16> [[VI5]], <8 x i16> [[VI6]], <8 x i16> [[VI7]])1282 // CHECK-NEXT: store <8 x i16> [[VI8]], ptr %tmp_vi_r1283 si8 tmp_vi_l = __builtin_elementwise_fshl(vi1, vi2, vi3);1284 si8 tmp_vi_r = __builtin_elementwise_fshr(vi1, vi2, vi3);1285 1286 // CHECK: [[VU1:%.+]] = load <4 x i32>, ptr %vu1.addr1287 // CHECK-NEXT: [[VU2:%.+]] = load <4 x i32>, ptr %vu2.addr1288 // CHECK-NEXT: [[VU3:%.+]] = load <4 x i32>, ptr %vu3.addr1289 // CHECK-NEXT: [[VU4:%.+]] = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> [[VU1]], <4 x i32> [[VU2]], <4 x i32> [[VU3]])1290 // CHECK-NEXT: store <4 x i32> [[VU4]], ptr %tmp_vu_l1291 // CHECK-NEXT: [[VU5:%.+]] = load <4 x i32>, ptr %vu1.addr1292 // CHECK-NEXT: [[VU6:%.+]] = load <4 x i32>, ptr %vu2.addr1293 // CHECK-NEXT: [[VU7:%.+]] = load <4 x i32>, ptr %vu3.addr1294 // CHECK-NEXT: [[VU8:%.+]] = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> [[VU5]], <4 x i32> [[VU6]], <4 x i32> [[VU7]])1295 // CHECK-NEXT: store <4 x i32> [[VU8]], ptr %tmp_vu_r1296 u4 tmp_vu_l = __builtin_elementwise_fshl(vu1, vu2, vu3);1297 u4 tmp_vu_r = __builtin_elementwise_fshr(vu1, vu2, vu3);1298}1299 1300void test_builtin_elementwise_clzg(si8 vs1, si8 vs2, u4 vu1,1301 long long int lli, short si,1302 _BitInt(31) bi, int i,1303 char ci) {1304 // CHECK: [[V8S1:%.+]] = load <8 x i16>, ptr %vs1.addr1305 // CHECK-NEXT: call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> [[V8S1]], i1 true)1306 vs1 = __builtin_elementwise_clzg(vs1);1307 1308 // CHECK: [[V8S1:%.+]] = load <8 x i16>, ptr %vs1.addr1309 // CHECK-NEXT: [[CLZ:%.+]] = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> [[V8S1]], i1 true)1310 // CHECK-NEXT: [[ISZERO:%.+]] = icmp eq <8 x i16> [[V8S1]], zeroinitializer1311 // CHECK-NEXT: [[V8S2:%.+]] = load <8 x i16>, ptr %vs2.addr1312 // select <8 x i1> [[ISZERO]], <8 x i16> [[CLZ]], <8 x i16> [[V8S2]]1313 vs1 = __builtin_elementwise_clzg(vs1, vs2);1314 1315 // CHECK: [[V4U1:%.+]] = load <4 x i32>, ptr %vu1.addr1316 // CHECK-NEXT: call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> [[V4U1]], i1 true)1317 vu1 = __builtin_elementwise_clzg(vu1);1318 1319 // CHECK: [[LLI:%.+]] = load i64, ptr %lli.addr1320 // CHECK-NEXT: call i64 @llvm.ctlz.i64(i64 [[LLI]], i1 true)1321 lli = __builtin_elementwise_clzg(lli);1322 1323 // CHECK: [[SI:%.+]] = load i16, ptr %si.addr1324 // CHECK-NEXT: call i16 @llvm.ctlz.i16(i16 [[SI]], i1 true)1325 si = __builtin_elementwise_clzg(si);1326 1327 // CHECK: [[BI1:%.+]] = load i32, ptr %bi.addr1328 // CHECK-NEXT: [[BI2:%.+]] = trunc i32 [[BI1]] to i311329 // CHECK-NEXT: call i31 @llvm.ctlz.i31(i31 [[BI2]], i1 true)1330 bi = __builtin_elementwise_clzg(bi);1331 1332 // CHECK: [[BI1:%.+]] = load i32, ptr %bi.addr1333 // CHECK-NEXT: [[BI2:%.+]] = trunc i32 [[BI1]] to i311334 // CHECK-NEXT: [[CLZ:%.+]] = call i31 @llvm.ctlz.i31(i31 [[BI2]], i1 true)1335 // CHECK-NEXT: [[ISZERO:%.+]] = icmp eq i31 [[BI2]], 01336 // CHECK-NEXT: select i1 [[ISZERO]], i31 1, i31 [[CLZ]]1337 bi = __builtin_elementwise_clzg(bi, (_BitInt(31))1);1338 1339 // CHECK: [[I:%.+]] = load i32, ptr %i.addr1340 // CHECK-NEXT: call i32 @llvm.ctlz.i32(i32 [[I]], i1 true)1341 i = __builtin_elementwise_clzg(i);1342 1343 // CHECK: [[CI:%.+]] = load i8, ptr %ci.addr1344 // CHECK-NEXT: call i8 @llvm.ctlz.i8(i8 [[CI]], i1 true)1345 ci = __builtin_elementwise_clzg(ci);1346}1347 1348void test_builtin_elementwise_ctzg(si8 vs1, si8 vs2, u4 vu1,1349 long long int lli, short si,1350 _BitInt(31) bi, int i,1351 char ci) {1352 // CHECK: [[V8S1:%.+]] = load <8 x i16>, ptr %vs1.addr1353 // CHECK-NEXT: call <8 x i16> @llvm.cttz.v8i16(<8 x i16> [[V8S1]], i1 true)1354 vs1 = __builtin_elementwise_ctzg(vs1);1355 1356 // CHECK: [[V8S1:%.+]] = load <8 x i16>, ptr %vs1.addr1357 // CHECK-NEXT: [[ctz:%.+]] = call <8 x i16> @llvm.cttz.v8i16(<8 x i16> [[V8S1]], i1 true)1358 // CHECK-NEXT: [[ISZERO:%.+]] = icmp eq <8 x i16> [[V8S1]], zeroinitializer1359 // CHECK-NEXT: [[V8S2:%.+]] = load <8 x i16>, ptr %vs2.addr1360 // select <8 x i1> [[ISZERO]], <8 x i16> [[ctz]], <8 x i16> [[V8S2]]1361 vs1 = __builtin_elementwise_ctzg(vs1, vs2);1362 1363 // CHECK: [[V4U1:%.+]] = load <4 x i32>, ptr %vu1.addr1364 // CHECK-NEXT: call <4 x i32> @llvm.cttz.v4i32(<4 x i32> [[V4U1]], i1 true)1365 vu1 = __builtin_elementwise_ctzg(vu1);1366 1367 // CHECK: [[LLI:%.+]] = load i64, ptr %lli.addr1368 // CHECK-NEXT: call i64 @llvm.cttz.i64(i64 [[LLI]], i1 true)1369 lli = __builtin_elementwise_ctzg(lli);1370 1371 // CHECK: [[SI:%.+]] = load i16, ptr %si.addr1372 // CHECK-NEXT: call i16 @llvm.cttz.i16(i16 [[SI]], i1 true)1373 si = __builtin_elementwise_ctzg(si);1374 1375 // CHECK: [[BI1:%.+]] = load i32, ptr %bi.addr1376 // CHECK-NEXT: [[BI2:%.+]] = trunc i32 [[BI1]] to i311377 // CHECK-NEXT: call i31 @llvm.cttz.i31(i31 [[BI2]], i1 true)1378 bi = __builtin_elementwise_ctzg(bi);1379 1380 // CHECK: [[BI1:%.+]] = load i32, ptr %bi.addr1381 // CHECK-NEXT: [[BI2:%.+]] = trunc i32 [[BI1]] to i311382 // CHECK-NEXT: [[ctz:%.+]] = call i31 @llvm.cttz.i31(i31 [[BI2]], i1 true)1383 // CHECK-NEXT: [[ISZERO:%.+]] = icmp eq i31 [[BI2]], 01384 // CHECK-NEXT: select i1 [[ISZERO]], i31 1, i31 [[ctz]]1385 bi = __builtin_elementwise_ctzg(bi, (_BitInt(31))1);1386 1387 // CHECK: [[I:%.+]] = load i32, ptr %i.addr1388 // CHECK-NEXT: call i32 @llvm.cttz.i32(i32 [[I]], i1 true)1389 i = __builtin_elementwise_ctzg(i);1390 1391 // CHECK: [[CI:%.+]] = load i8, ptr %ci.addr1392 // CHECK-NEXT: call i8 @llvm.cttz.i8(i8 [[CI]], i1 true)1393 ci = __builtin_elementwise_ctzg(ci);1394}1395