diff --git a/builtins/target-avx-common.ll b/builtins/target-avx-common.ll index 41692823..1c467476 100644 --- a/builtins/target-avx-common.ll +++ b/builtins/target-avx-common.ll @@ -31,6 +31,10 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AVX target implementation. +;; +;; Please note that this file uses SSE intrinsics, but LLVM generates AVX +;; instructions, so it doesn't makes sense to change this implemenation. + ctlztz() define_prefetches() diff --git a/builtins/target-avx.ll b/builtins/target-avx.ll index 196e5ea4..e98a3843 100644 --- a/builtins/target-avx.ll +++ b/builtins/target-avx.ll @@ -49,11 +49,10 @@ include(`target-avx-common.ll') declare <8 x float> @llvm.x86.avx.rcp.ps.256(<8 x float>) nounwind readnone define <8 x float> @__rcp_varying_float(<8 x float>) nounwind readonly alwaysinline { + ; do one N-R iteration to improve precision ; float iv = __rcp_v(v); ; return iv * (2. - v * iv); - %call = call <8 x float> @llvm.x86.avx.rcp.ps.256(<8 x float> %0) - ; do one N-R iteration %v_iv = fmul <8 x float> %0, %call %two_minus = fsub <8 x float> , %v_iv @@ -61,6 +60,46 @@ define <8 x float> @__rcp_varying_float(<8 x float>) nounwind readonly alwaysinl ret <8 x float> %iv_mul } +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; rsqrt + +declare <8 x float> @llvm.x86.avx.rsqrt.ps.256(<8 x float>) nounwind readnone + +define <8 x float> @__rsqrt_varying_float(<8 x float> %v) nounwind readonly alwaysinline { + ; float is = __rsqrt_v(v); + %is = call <8 x float> @llvm.x86.avx.rsqrt.ps.256(<8 x float> %v) + ; Newton-Raphson iteration to improve precision + ; return 0.5 * is * (3. - (v * is) * is); + %v_is = fmul <8 x float> %v, %is + %v_is_is = fmul <8 x float> %v_is, %is + %three_sub = fsub <8 x float> , %v_is_is + %is_mul = fmul <8 x float> %is, %three_sub + %half_scale = fmul <8 x float> , %is_mul + ret <8 x float> %half_scale +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; sqrt + +declare <8 x float> @llvm.x86.avx.sqrt.ps.256(<8 x float>) nounwind readnone + +define <8 x float> @__sqrt_varying_float(<8 x float>) nounwind readonly alwaysinline { + %call = call <8 x float> @llvm.x86.avx.sqrt.ps.256(<8 x float> %0) + ret <8 x float> %call +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; double precision sqrt + +declare <4 x double> @llvm.x86.avx.sqrt.pd.256(<4 x double>) nounwind readnone + +define <8 x double> @__sqrt_varying_double(<8 x double>) nounwind alwaysinline { + unary4to8(ret, double, @llvm.x86.avx.sqrt.pd.256, %0) + ret <8 x double> %ret +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; rounding floats @@ -94,58 +133,15 @@ define <8 x double> @__round_varying_double(<8 x double>) nounwind readonly alwa } define <8 x double> @__floor_varying_double(<8 x double>) nounwind readonly alwaysinline { - ; roundpd, round down 0b01 | don't signal precision exceptions 0b1000 = 9 + ; roundpd, round down 0b01 | don't signal precision exceptions 0b1001 = 9 round4to8double(%0, 9) } - define <8 x double> @__ceil_varying_double(<8 x double>) nounwind readonly alwaysinline { - ; roundpd, round up 0b10 | don't signal precision exceptions 0b1000 = 10 + ; roundpd, round up 0b10 | don't signal precision exceptions 0b1010 = 10 round4to8double(%0, 10) } - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; rsqrt - -declare <8 x float> @llvm.x86.avx.rsqrt.ps.256(<8 x float>) nounwind readnone - -define <8 x float> @__rsqrt_varying_float(<8 x float> %v) nounwind readonly alwaysinline { - ; float is = __rsqrt_v(v); - %is = call <8 x float> @llvm.x86.avx.rsqrt.ps.256(<8 x float> %v) - ; return 0.5 * is * (3. - (v * is) * is); - %v_is = fmul <8 x float> %v, %is - %v_is_is = fmul <8 x float> %v_is, %is - %three_sub = fsub <8 x float> , %v_is_is - %is_mul = fmul <8 x float> %is, %three_sub - %half_scale = fmul <8 x float> , %is_mul - ret <8 x float> %half_scale -} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; sqrt - -declare <8 x float> @llvm.x86.avx.sqrt.ps.256(<8 x float>) nounwind readnone - -define <8 x float> @__sqrt_varying_float(<8 x float>) nounwind readonly alwaysinline { - %call = call <8 x float> @llvm.x86.avx.sqrt.ps.256(<8 x float> %0) - ret <8 x float> %call -} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; svml - -include(`svml.m4') -;; single precision -svml_declare(float,f8,8) -svml_define(float,f8,8,f) - -;; double precision -svml_declare(double,4,4) -svml_define_x(double,4,4,d,8) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; float min/max @@ -166,7 +162,37 @@ define <8 x float> @__min_varying_float(<8 x float>, ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; horizontal ops +;; double precision min/max + +declare <4 x double> @llvm.x86.avx.max.pd.256(<4 x double>, <4 x double>) nounwind readnone +declare <4 x double> @llvm.x86.avx.min.pd.256(<4 x double>, <4 x double>) nounwind readnone + +define <8 x double> @__min_varying_double(<8 x double>, <8 x double>) nounwind readnone alwaysinline { + binary4to8(ret, double, @llvm.x86.avx.min.pd.256, %0, %1) + ret <8 x double> %ret +} + +define <8 x double> @__max_varying_double(<8 x double>, <8 x double>) nounwind readnone alwaysinline { + binary4to8(ret, double, @llvm.x86.avx.max.pd.256, %0, %1) + ret <8 x double> %ret +} + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; svml + +include(`svml.m4') +;; single precision +svml_declare(float,f8,8) +svml_define(float,f8,8,f) + +;; double precision +svml_declare(double,4,4) +svml_define_x(double,4,4,d,8) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; mask handling declare i32 @llvm.x86.avx.movmsk.ps.256(<8 x float>) nounwind readnone @@ -198,6 +224,9 @@ define i1 @__none(<8 x i32>) nounwind readnone alwaysinline { ret i1 %cmp } +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; horizontal ops / reductions + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; horizontal float ops @@ -216,12 +245,36 @@ define float @__reduce_min_float(<8 x float>) nounwind readnone alwaysinline { reduce8(float, @__min_varying_float, @__min_uniform_float) } - define float @__reduce_max_float(<8 x float>) nounwind readnone alwaysinline { reduce8(float, @__max_varying_float, @__max_uniform_float) } -reduce_equal(8) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; horizontal double ops + +declare <4 x double> @llvm.x86.avx.hadd.pd.256(<4 x double>, <4 x double>) nounwind readnone + +define double @__reduce_add_double(<8 x double>) nounwind readonly alwaysinline { + %v0 = shufflevector <8 x double> %0, <8 x double> undef, + <4 x i32> + %v1 = shufflevector <8 x double> %0, <8 x double> undef, + <4 x i32> + %sum0 = call <4 x double> @llvm.x86.avx.hadd.pd.256(<4 x double> %v0, <4 x double> %v1) + %sum1 = call <4 x double> @llvm.x86.avx.hadd.pd.256(<4 x double> %sum0, <4 x double> %sum0) + %final0 = extractelement <4 x double> %sum1, i32 0 + %final1 = extractelement <4 x double> %sum1, i32 2 + %sum = fadd double %final0, %final1 + + ret double %sum +} + +define double @__reduce_min_double(<8 x double>) nounwind readnone alwaysinline { + reduce8(double, @__min_varying_double, @__min_uniform_double) +} + +define double @__reduce_max_double(<8 x double>) nounwind readnone alwaysinline { + reduce8(double, @__max_varying_double, @__max_uniform_double) +} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; horizontal int8 ops @@ -262,6 +315,7 @@ define i16 @__reduce_add_int16(<8 x i16>) nounwind readnone alwaysinline { ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; horizontal int32 ops +;; helper functions define <8 x i32> @__add_varying_int32(<8 x i32>, <8 x i32>) nounwind readnone alwaysinline { %s = add <8 x i32> %0, %1 @@ -273,16 +327,15 @@ define i32 @__add_uniform_int32(i32, i32) nounwind readnone alwaysinline { ret i32 %s } +;; reduction functions define i32 @__reduce_add_int32(<8 x i32>) nounwind readnone alwaysinline { reduce8(i32, @__add_varying_int32, @__add_uniform_int32) } - define i32 @__reduce_min_int32(<8 x i32>) nounwind readnone alwaysinline { reduce8(i32, @__min_varying_int32, @__min_uniform_int32) } - define i32 @__reduce_max_int32(<8 x i32>) nounwind readnone alwaysinline { reduce8(i32, @__max_varying_int32, @__max_uniform_int32) } @@ -295,38 +348,11 @@ define i32 @__reduce_max_uint32(<8 x i32>) nounwind readnone alwaysinline { reduce8(i32, @__max_varying_uint32, @__max_uniform_uint32) } -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; horizontal double ops - -declare <4 x double> @llvm.x86.avx.hadd.pd.256(<4 x double>, <4 x double>) nounwind readnone - -define double @__reduce_add_double(<8 x double>) nounwind readonly alwaysinline { - %v0 = shufflevector <8 x double> %0, <8 x double> undef, - <4 x i32> - %v1 = shufflevector <8 x double> %0, <8 x double> undef, - <4 x i32> - %sum0 = call <4 x double> @llvm.x86.avx.hadd.pd.256(<4 x double> %v0, <4 x double> %v1) - %sum1 = call <4 x double> @llvm.x86.avx.hadd.pd.256(<4 x double> %sum0, <4 x double> %sum0) - %final0 = extractelement <4 x double> %sum1, i32 0 - %final1 = extractelement <4 x double> %sum1, i32 2 - %sum = fadd double %final0, %final1 - - ret double %sum -} - -define double @__reduce_min_double(<8 x double>) nounwind readnone alwaysinline { - reduce8(double, @__min_varying_double, @__min_uniform_double) -} - - -define double @__reduce_max_double(<8 x double>) nounwind readnone alwaysinline { - reduce8(double, @__max_varying_double, @__max_uniform_double) -} - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; horizontal int64 ops +;; helper functions define <8 x i64> @__add_varying_int64(<8 x i64>, <8 x i64>) nounwind readnone alwaysinline { %s = add <8 x i64> %0, %1 @@ -338,6 +364,7 @@ define i64 @__add_uniform_int64(i64, i64) nounwind readnone alwaysinline { ret i64 %s } +;; reduction functions define i64 @__reduce_add_int64(<8 x i64>) nounwind readnone alwaysinline { reduce8(i64, @__add_varying_int64, @__add_uniform_int64) } @@ -362,6 +389,7 @@ define i64 @__reduce_max_uint64(<8 x i64>) nounwind readnone alwaysinline { reduce8(i64, @__max_varying_uint64, @__max_uniform_uint64) } +reduce_equal(8) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; unaligned loads/loads+broadcasts @@ -446,6 +474,10 @@ define void @__masked_store_i64(<8 x i64>* nocapture, <8 x i64>, ret void } +masked_store_float_double() + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; masked store blend masked_store_blend_8_16_by_8() @@ -517,8 +549,6 @@ define void @__masked_store_blend_i64(<8 x i64>* nocapture %ptr, <8 x i64> %new, ret void } -masked_store_float_double() - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; scatter @@ -529,30 +559,3 @@ gen_scatter(float) gen_scatter(i64) gen_scatter(double) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; double precision sqrt - -declare <4 x double> @llvm.x86.avx.sqrt.pd.256(<4 x double>) nounwind readnone - -define <8 x double> @__sqrt_varying_double(<8 x double>) nounwind alwaysinline { - unary4to8(ret, double, @llvm.x86.avx.sqrt.pd.256, %0) - ret <8 x double> %ret -} - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; double precision min/max - -declare <4 x double> @llvm.x86.avx.max.pd.256(<4 x double>, <4 x double>) nounwind readnone -declare <4 x double> @llvm.x86.avx.min.pd.256(<4 x double>, <4 x double>) nounwind readnone - -define <8 x double> @__min_varying_double(<8 x double>, <8 x double>) nounwind readnone alwaysinline { - binary4to8(ret, double, @llvm.x86.avx.min.pd.256, %0, %1) - ret <8 x double> %ret -} - -define <8 x double> @__max_varying_double(<8 x double>, <8 x double>) nounwind readnone alwaysinline { - binary4to8(ret, double, @llvm.x86.avx.max.pd.256, %0, %1) - ret <8 x double> %ret -} - diff --git a/builtins/target-sse4.ll b/builtins/target-sse4.ll index 88be6c59..16177b47 100644 --- a/builtins/target-sse4.ll +++ b/builtins/target-sse4.ll @@ -58,10 +58,10 @@ declare @__float_to_half_varying( %v) nounwind read declare <4 x float> @llvm.x86.sse.rcp.ps(<4 x float>) nounwind readnone define <4 x float> @__rcp_varying_float(<4 x float>) nounwind readonly alwaysinline { - %call = call <4 x float> @llvm.x86.sse.rcp.ps(<4 x float> %0) ; do one N-R iteration to improve precision ; float iv = __rcp_v(v); ; return iv * (2. - v * iv); + %call = call <4 x float> @llvm.x86.sse.rcp.ps(<4 x float> %0) %v_iv = fmul <4 x float> %0, %call %two_minus = fsub <4 x float> , %v_iv %iv_mul = fmul <4 x float> %call, %two_minus @@ -87,7 +87,7 @@ define <4 x float> @__rsqrt_varying_float(<4 x float> %v) nounwind readonly alwa } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; sqrt +;; sqrt declare <4 x float> @llvm.x86.sse.sqrt.ps(<4 x float>) nounwind readnone @@ -154,16 +154,34 @@ define <4 x double> @__ceil_varying_double(<4 x double>) nounwind readonly alway declare <4 x float> @llvm.x86.sse.max.ps(<4 x float>, <4 x float>) nounwind readnone declare <4 x float> @llvm.x86.sse.min.ps(<4 x float>, <4 x float>) nounwind readnone -define <4 x float> @__max_varying_float(<4 x float>, <4 x float>) nounwind readonly alwaysinline { +define <4 x float> @__max_varying_float(<4 x float>, + <4 x float>) nounwind readonly alwaysinline { %call = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> %0, <4 x float> %1) ret <4 x float> %call } -define <4 x float> @__min_varying_float(<4 x float>, <4 x float>) nounwind readonly alwaysinline { +define <4 x float> @__min_varying_float(<4 x float>, + <4 x float>) nounwind readonly alwaysinline { %call = call <4 x float> @llvm.x86.sse.min.ps(<4 x float> %0, <4 x float> %1) ret <4 x float> %call } +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; double precision min/max + +declare <2 x double> @llvm.x86.sse2.max.pd(<2 x double>, <2 x double>) nounwind readnone +declare <2 x double> @llvm.x86.sse2.min.pd(<2 x double>, <2 x double>) nounwind readnone + +define <4 x double> @__min_varying_double(<4 x double>, <4 x double>) nounwind readnone { + binary2to4(ret, double, @llvm.x86.sse2.min.pd, %0, %1) + ret <4 x double> %ret +} + +define <4 x double> @__max_varying_double(<4 x double>, <4 x double>) nounwind readnone { + binary2to4(ret, double, @llvm.x86.sse2.max.pd, %0, %1) + ret <4 x double> %ret +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; int32 min/max @@ -191,23 +209,7 @@ define <4 x i32> @__max_varying_uint32(<4 x i32>, <4 x i32>) nounwind readonly a } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; double precision min/max - -declare <2 x double> @llvm.x86.sse2.max.pd(<2 x double>, <2 x double>) nounwind readnone -declare <2 x double> @llvm.x86.sse2.min.pd(<2 x double>, <2 x double>) nounwind readnone - -define <4 x double> @__min_varying_double(<4 x double>, <4 x double>) nounwind readnone { - binary2to4(ret, double, @llvm.x86.sse2.min.pd, %0, %1) - ret <4 x double> %ret -} - -define <4 x double> @__max_varying_double(<4 x double>, <4 x double>) nounwind readnone { - binary2to4(ret, double, @llvm.x86.sse2.max.pd, %0, %1) - ret <4 x double> %ret -} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; svml stuff +;; svml stuff include(`svml.m4') ;; single precision @@ -219,7 +221,7 @@ svml_declare(double,2,2) svml_define_x(double,2,2,d,4) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; horizontal ops / reductions +;; mask handling declare i32 @llvm.x86.sse.movmsk.ps(<4 x float>) nounwind readnone @@ -251,6 +253,55 @@ define i1 @__none(<4 x i32>) nounwind readnone alwaysinline { ret i1 %cmp } +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; horizontal ops / reductions + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; horizontal float ops + +declare <4 x float> @llvm.x86.sse3.hadd.ps(<4 x float>, <4 x float>) nounwind readnone + +define float @__reduce_add_float(<4 x float>) nounwind readonly alwaysinline { + %v1 = call <4 x float> @llvm.x86.sse3.hadd.ps(<4 x float> %0, <4 x float> %0) + %v2 = call <4 x float> @llvm.x86.sse3.hadd.ps(<4 x float> %v1, <4 x float> %v1) + %scalar = extractelement <4 x float> %v2, i32 0 + ret float %scalar +} + +define float @__reduce_min_float(<4 x float>) nounwind readnone alwaysinline { + reduce4(float, @__min_varying_float, @__min_uniform_float) +} + +define float @__reduce_max_float(<4 x float>) nounwind readnone alwaysinline { + reduce4(float, @__max_varying_float, @__max_uniform_float) +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; horizontal double ops + +define double @__reduce_add_double(<4 x double>) nounwind readnone alwaysinline { + %v0 = shufflevector <4 x double> %0, <4 x double> undef, + <2 x i32> + %v1 = shufflevector <4 x double> %0, <4 x double> undef, + <2 x i32> + %sum = fadd <2 x double> %v0, %v1 + %e0 = extractelement <2 x double> %sum, i32 0 + %e1 = extractelement <2 x double> %sum, i32 1 + %m = fadd double %e0, %e1 + ret double %m +} + +define double @__reduce_min_double(<4 x double>) nounwind readnone alwaysinline { + reduce4(double, @__min_varying_double, @__min_uniform_double) +} + +define double @__reduce_max_double(<4 x double>) nounwind readnone alwaysinline { + reduce4(double, @__max_varying_double, @__max_uniform_double) +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; horizontal int8 ops + declare <2 x i64> @llvm.x86.sse2.psad.bw(<16 x i8>, <16 x i8>) nounwind readnone define i16 @__reduce_add_int8(<4 x i8>) nounwind readnone alwaysinline { @@ -266,6 +317,9 @@ define i16 @__reduce_add_int8(<4 x i8>) nounwind readnone alwaysinline { ret i16 %r16 } +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; horizontal int16 ops + define internal <4 x i16> @__add_varying_i16(<4 x i16>, <4 x i16>) nounwind readnone alwaysinline { %r = add <4 x i16> %0, %1 @@ -281,24 +335,11 @@ define i16 @__reduce_add_int16(<4 x i16>) nounwind readnone alwaysinline { reduce4(i16, @__add_varying_i16, @__add_uniform_i16) } -declare <4 x float> @llvm.x86.sse3.hadd.ps(<4 x float>, <4 x float>) nounwind readnone +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; horizontal int32 ops -define float @__reduce_add_float(<4 x float>) nounwind readonly alwaysinline { - %v1 = call <4 x float> @llvm.x86.sse3.hadd.ps(<4 x float> %0, <4 x float> %0) - %v2 = call <4 x float> @llvm.x86.sse3.hadd.ps(<4 x float> %v1, <4 x float> %v1) - %scalar = extractelement <4 x float> %v2, i32 0 - ret float %scalar -} - -define float @__reduce_min_float(<4 x float>) nounwind readnone { - reduce4(float, @__min_varying_float, @__min_uniform_float) -} - -define float @__reduce_max_float(<4 x float>) nounwind readnone { - reduce4(float, @__max_varying_float, @__max_uniform_float) -} - -define i32 @__reduce_add_int32(<4 x i32> %v) nounwind readnone { +;; reduction functions +define i32 @__reduce_add_int32(<4 x i32> %v) nounwind readnone alwaysinline { %v1 = shufflevector <4 x i32> %v, <4 x i32> undef, <4 x i32> %m1 = add <4 x i32> %v1, %v @@ -308,44 +349,27 @@ define i32 @__reduce_add_int32(<4 x i32> %v) nounwind readnone { ret i32 %sum } -define i32 @__reduce_min_int32(<4 x i32>) nounwind readnone { +define i32 @__reduce_min_int32(<4 x i32>) nounwind readnone alwaysinline { reduce4(i32, @__min_varying_int32, @__min_uniform_int32) } -define i32 @__reduce_max_int32(<4 x i32>) nounwind readnone { +define i32 @__reduce_max_int32(<4 x i32>) nounwind readnone alwaysinline { reduce4(i32, @__max_varying_int32, @__max_uniform_int32) } -define i32 @__reduce_min_uint32(<4 x i32>) nounwind readnone { +define i32 @__reduce_min_uint32(<4 x i32>) nounwind readnone alwaysinline { reduce4(i32, @__min_varying_uint32, @__min_uniform_uint32) } -define i32 @__reduce_max_uint32(<4 x i32>) nounwind readnone { +define i32 @__reduce_max_uint32(<4 x i32>) nounwind readnone alwaysinline { reduce4(i32, @__max_varying_uint32, @__max_uniform_uint32) } +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; horizontal int64 ops -define double @__reduce_add_double(<4 x double>) nounwind readnone { - %v0 = shufflevector <4 x double> %0, <4 x double> undef, - <2 x i32> - %v1 = shufflevector <4 x double> %0, <4 x double> undef, - <2 x i32> - %sum = fadd <2 x double> %v0, %v1 - %e0 = extractelement <2 x double> %sum, i32 0 - %e1 = extractelement <2 x double> %sum, i32 1 - %m = fadd double %e0, %e1 - ret double %m -} - -define double @__reduce_min_double(<4 x double>) nounwind readnone { - reduce4(double, @__min_varying_double, @__min_uniform_double) -} - -define double @__reduce_max_double(<4 x double>) nounwind readnone { - reduce4(double, @__max_varying_double, @__max_uniform_double) -} - -define i64 @__reduce_add_int64(<4 x i64>) nounwind readnone { +;; reduction functions +define i64 @__reduce_add_int64(<4 x i64>) nounwind readnone alwaysinline { %v0 = shufflevector <4 x i64> %0, <4 x i64> undef, <2 x i32> %v1 = shufflevector <4 x i64> %0, <4 x i64> undef, @@ -357,27 +381,50 @@ define i64 @__reduce_add_int64(<4 x i64>) nounwind readnone { ret i64 %m } -define i64 @__reduce_min_int64(<4 x i64>) nounwind readnone { +define i64 @__reduce_min_int64(<4 x i64>) nounwind readnone alwaysinline { reduce4(i64, @__min_varying_int64, @__min_uniform_int64) } -define i64 @__reduce_max_int64(<4 x i64>) nounwind readnone { +define i64 @__reduce_max_int64(<4 x i64>) nounwind readnone alwaysinline { reduce4(i64, @__max_varying_int64, @__max_uniform_int64) } -define i64 @__reduce_min_uint64(<4 x i64>) nounwind readnone { +define i64 @__reduce_min_uint64(<4 x i64>) nounwind readnone alwaysinline { reduce4(i64, @__min_varying_uint64, @__min_uniform_uint64) } -define i64 @__reduce_max_uint64(<4 x i64>) nounwind readnone { +define i64 @__reduce_max_uint64(<4 x i64>) nounwind readnone alwaysinline { reduce4(i64, @__max_varying_uint64, @__max_uniform_uint64) } reduce_equal(4) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; unaligned loads/loads+broadcasts + + +masked_load(i8, 1) +masked_load(i16, 2) +masked_load(i32, 4) +masked_load(float, 4) +masked_load(i64, 8) +masked_load(double, 8) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; masked store +gen_masked_store(i8) +gen_masked_store(i16) +gen_masked_store(i32) +gen_masked_store(i64) + +masked_store_float_double() + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; masked store blend + +masked_store_blend_8_16_by_4() + declare <4 x float> @llvm.x86.sse41.blendvps(<4 x float>, <4 x float>, <4 x float>) nounwind readnone @@ -444,29 +491,6 @@ define void @__masked_store_blend_i64(<4 x i64>* nocapture %ptr, <4 x i64> %new, ret void } -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; masked store - -masked_store_blend_8_16_by_4() - -gen_masked_store(i8) -gen_masked_store(i16) -gen_masked_store(i32) -gen_masked_store(i64) - -masked_store_float_double() - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; unaligned loads/loads+broadcasts - - -masked_load(i8, 1) -masked_load(i16, 2) -masked_load(i32, 4) -masked_load(float, 4) -masked_load(i64, 8) -masked_load(double, 8) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; gather/scatter