;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Define the standard library builtins for the NOVEC target define(`MASK',`i1') define(`WIDTH',`1') ;; target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" ;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;; declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() nounwind readnone declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.x() nounwind readnone declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.y() nounwind readnone declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.z() nounwind readnone declare i32 @llvm.nvvm.read.ptx.sreg.nctaid.x() nounwind readnone declare i32 @llvm.nvvm.read.ptx.sreg.nctaid.y() nounwind readnone declare i32 @llvm.nvvm.read.ptx.sreg.nctaid.z() nounwind readnone declare i32 @llvm.nvvm.read.ptx.sreg.warpsize() nounwind readnone define i32 @__tid_x() nounwind readnone alwaysinline { %tid = call i32 @llvm.nvvm.read.ptx.sreg.tid.x() ret i32 %tid } define i32 @__warpsize() nounwind readnone alwaysinline { %tid = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() ret i32 %tid } define i32 @__ctaid_x() nounwind readnone alwaysinline { %bid = call i32 @llvm.nvvm.read.ptx.sreg.ctaid.x() ret i32 %bid } define i32 @__ctaid_y() nounwind readnone alwaysinline { %bid = call i32 @llvm.nvvm.read.ptx.sreg.ctaid.y() ret i32 %bid } define i32 @__ctaid_z() nounwind readnone alwaysinline { %bid = call i32 @llvm.nvvm.read.ptx.sreg.ctaid.z() ret i32 %bid } define i32 @__nctaid_x() nounwind readnone alwaysinline { %nb = call i32 @llvm.nvvm.read.ptx.sreg.nctaid.x() ret i32 %nb } define i32 @__nctaid_y() nounwind readnone alwaysinline { %nb = call i32 @llvm.nvvm.read.ptx.sreg.nctaid.y() ret i32 %nb } define i32 @__nctaid_z() nounwind readnone alwaysinline { %nb = call i32 @llvm.nvvm.read.ptx.sreg.nctaid.z() ret i32 %nb } ;;;;;;;;;;;;;; include(`util.m4') stdlib_core() packed_load_and_store() int64minmax() scans() rdrand_decls() ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; broadcast/rotate/shuffle define_shuffles() ;; declare @__smear_float(float) nounwind readnone ;; declare @__smear_double(double) nounwind readnone ;; declare @__smear_i8(i8) nounwind readnone ;; declare @__smear_i16(i16) nounwind readnone ;; declare @__smear_i32(i32) nounwind readnone ;; declare @__smear_i64(i64) nounwind readnone ;; declare @__setzero_float() nounwind readnone ;; declare @__setzero_double() nounwind readnone ;; declare @__setzero_i8() nounwind readnone ;; declare @__setzero_i16() nounwind readnone ;; declare @__setzero_i32() nounwind readnone ;; declare @__setzero_i64() nounwind readnone ;; declare @__undef_float() nounwind readnone ;; declare @__undef_double() nounwind readnone ;; declare @__undef_i8() nounwind readnone ;; declare @__undef_i16() nounwind readnone ;; declare @__undef_i32() nounwind readnone ;; declare @__undef_i64() nounwind readnone ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; aos/soa aossoa() ;; dummy 1 wide vector ops define void @__aos_to_soa4_float1(<1 x float> %v0, <1 x float> %v1, <1 x float> %v2, <1 x float> %v3, <1 x float> * noalias %out0, <1 x float> * noalias %out1, <1 x float> * noalias %out2, <1 x float> * noalias %out3) nounwind alwaysinline { store <1 x float> %v0, <1 x float > * %out0 store <1 x float> %v1, <1 x float > * %out1 store <1 x float> %v2, <1 x float > * %out2 store <1 x float> %v3, <1 x float > * %out3 ret void } define void @__soa_to_aos4_float1(<1 x float> %v0, <1 x float> %v1, <1 x float> %v2, <1 x float> %v3, <1 x float> * noalias %out0, <1 x float> * noalias %out1, <1 x float> * noalias %out2, <1 x float> * noalias %out3) nounwind alwaysinline { call void @__aos_to_soa4_float1(<1 x float> %v0, <1 x float> %v1, <1 x float> %v2, <1 x float> %v3, <1 x float> * %out0, <1 x float> * %out1, <1 x float> * %out2, <1 x float> * %out3) ret void } define void @__aos_to_soa3_float1(<1 x float> %v0, <1 x float> %v1, <1 x float> %v2, <1 x float> * %out0, <1 x float> * %out1, <1 x float> * %out2) { store <1 x float> %v0, <1 x float > * %out0 store <1 x float> %v1, <1 x float > * %out1 store <1 x float> %v2, <1 x float > * %out2 ret void } define void @__soa_to_aos3_float1(<1 x float> %v0, <1 x float> %v1, <1 x float> %v2, <1 x float> * %out0, <1 x float> * %out1, <1 x float> * %out2) { call void @__aos_to_soa3_float1(<1 x float> %v0, <1 x float> %v1, <1 x float> %v2, <1 x float> * %out0, <1 x float> * %out1, <1 x float> * %out2) ret void } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; half conversion routines declare float @__half_to_float_uniform(i16 %v) nounwind readnone declare @__half_to_float_varying( %v) nounwind readnone declare i16 @__float_to_half_uniform(float %v) nounwind readnone declare @__float_to_half_varying( %v) nounwind readnone ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; math declare void @__fastmath() nounwind ;; round/floor/ceil declare float @__round_uniform_float(float) nounwind readnone declare float @__floor_uniform_float(float) nounwind readnone declare float @__ceil_uniform_float(float) nounwind readnone declare double @__round_uniform_double(double) nounwind readnone declare double @__floor_uniform_double(double) nounwind readnone declare double @__ceil_uniform_double(double) nounwind readnone define <1 x float> @__round_varying_float(<1 x float>) nounwind readonly alwaysinline { %float_to_int_bitcast.i.i.i.i = bitcast <1 x float> %0 to <1 x i32> %bitop.i.i = and <1 x i32> %float_to_int_bitcast.i.i.i.i, %bitop.i = xor <1 x i32> %float_to_int_bitcast.i.i.i.i, %bitop.i.i %int_to_float_bitcast.i.i40.i = bitcast <1 x i32> %bitop.i to <1 x float> %binop.i = fadd <1 x float> %int_to_float_bitcast.i.i40.i, %binop21.i = fadd <1 x float> %binop.i, %float_to_int_bitcast.i.i.i = bitcast <1 x float> %binop21.i to <1 x i32> %bitop31.i = xor <1 x i32> %float_to_int_bitcast.i.i.i, %bitop.i.i %int_to_float_bitcast.i.i.i = bitcast <1 x i32> %bitop31.i to <1 x float> ret <1 x float> %int_to_float_bitcast.i.i.i } define <1 x float> @__floor_varying_float(<1 x float>) nounwind readonly alwaysinline { %calltmp.i = tail call <1 x float> @__round_varying_float(<1 x float> %0) nounwind %bincmp.i = fcmp ogt <1 x float> %calltmp.i, %0 %val_to_boolvec32.i = sext <1 x i1> %bincmp.i to <1 x i32> %bitop.i = and <1 x i32> %val_to_boolvec32.i, %int_to_float_bitcast.i.i.i = bitcast <1 x i32> %bitop.i to <1 x float> %binop.i = fadd <1 x float> %calltmp.i, %int_to_float_bitcast.i.i.i ret <1 x float> %binop.i } declare @__ceil_varying_float() nounwind readnone declare @__round_varying_double() nounwind readnone declare @__floor_varying_double() nounwind readnone declare @__ceil_varying_double() nounwind readnone ;; min/max uniform ;; declare float @__max_uniform_float(float, float) nounwind readnone ;; declare float @__min_uniform_float(float, float) nounwind readnone define float @__max_uniform_float(float, float) nounwind readonly alwaysinline { %d = fcmp ogt float %0, %1 %r = select i1 %d, float %0, float %1 ret float %r } define float @__min_uniform_float(float, float) nounwind readonly alwaysinline { %d = fcmp olt float %0, %1 %r = select i1 %d, float %0, float %1 ret float %r } ;; declare i32 @__min_uniform_int32(i32, i32) nounwind readnone ;; declare i32 @__max_uniform_int32(i32, i32) nounwind readnone define i32 @__min_uniform_int32(i32, i32) nounwind readonly alwaysinline { %c = icmp slt i32 %0, %1 %r = select i1 %c, i32 %0, i32 %1 ret i32 %r } define i32 @__max_uniform_int32(i32, i32) nounwind readonly alwaysinline { %c = icmp sgt i32 %0, %1 %r = select i1 %c, i32 %0, i32 %1 ret i32 %r } ;; declare i32 @__min_uniform_uint32(i32, i32) nounwind readnone ;; declare i32 @__max_uniform_uint32(i32, i32) nounwind readnone define i32 @__min_uniform_uint32(i32, i32) nounwind readonly alwaysinline { %c = icmp ult i32 %0, %1 %r = select i1 %c, i32 %0, i32 %1 ret i32 %r } define i32 @__max_uniform_uint32(i32, i32) nounwind readonly alwaysinline { %c = icmp ugt i32 %0, %1 %r = select i1 %c, i32 %0, i32 %1 ret i32 %r } ;; declare i64 @__min_uniform_int64(i64, i64) nounwind readnone ;; declare i64 @__max_uniform_int64(i64, i64) nounwind readnone ;; declare i64 @__min_uniform_uint64(i64, i64) nounwind readnone ;; declare i64 @__max_uniform_uint64(i64, i64) nounwind readnone ;; declare double @__min_uniform_double(double, double) nounwind readnone ;; declare double @__max_uniform_double(double, double) nounwind readnone define double @__max_uniform_double(double, double) nounwind readonly alwaysinline { %d = fcmp ogt double %0, %1 %r = select i1 %d, double %0, double %1 ret double %r } define double @__min_uniform_double(double, double) nounwind readonly alwaysinline { %d = fcmp olt double %0, %1 %r = select i1 %d, double %0, double %1 ret double %r } ;; min/max uniform ;; /* float */ define <1 x float> @__max_varying_float(<1 x float>, <1 x float>) nounwind readonly alwaysinline { %a = extractelement <1 x float> %0, i32 0 %b = extractelement <1 x float> %1, i32 0 %r = call float @__max_uniform_float(float %a, float %b) %rv = insertelement <1 x float> undef, float %r, i32 0 ret <1 x float> %rv } define <1 x float> @__min_varying_float(<1 x float>, <1 x float>) nounwind readonly alwaysinline { %a = extractelement <1 x float> %0, i32 0 %b = extractelement <1 x float> %1, i32 0 %r = call float @__min_uniform_float(float %a, float %b) %rv = insertelement <1 x float> undef, float %r, i32 0 ret <1 x float> %rv } ;; /* int32 */ define <1 x i32> @__max_varying_int32(<1 x i32>, <1 x i32>) nounwind readonly alwaysinline { %a = extractelement <1 x i32> %0, i32 0 %b = extractelement <1 x i32> %1, i32 0 %r = call i32 @__max_uniform_int32(i32 %a, i32 %b) %rv = insertelement <1 x i32> undef, i32 %r, i32 0 ret <1 x i32> %rv } define <1 x i32> @__min_varying_int32(<1 x i32>, <1 x i32>) nounwind readonly alwaysinline { %a = extractelement <1 x i32> %0, i32 0 %b = extractelement <1 x i32> %1, i32 0 %r = call i32 @__min_uniform_int32(i32 %a, i32 %b) %rv = insertelement <1 x i32> undef, i32 %r, i32 0 ret <1 x i32> %rv } ;; /* uint32 */ declare @__min_varying_uint32(, ) nounwind readnone declare @__max_varying_uint32(, ) nounwind readnone ;; declare @__min_varying_int64(, ) nounwind readnone ;; declare @__max_varying_int64(, ) nounwind readnone ;; declare @__min_varying_uint64(, ) nounwind readnone ;; declare @__max_varying_uint64(, ) nounwind readnone declare @__min_varying_double(, ) nounwind readnone declare @__max_varying_double(, ) nounwind readnone ;; sqrt/rsqrt/rcp declare float @llvm.nvvm.rsqrt.approx.f(float %f) nounwind readonly alwaysinline declare float @llvm.nvvm.sqrt.f(float %f) nounwind readonly alwaysinline declare double @llvm.nvvm.rsqrt.approx.d(double %f) nounwind readonly alwaysinline declare double @llvm.nvvm.sqrt.d(double %f) nounwind readonly alwaysinline ;; declare float @__rcp_uniform_float(float) nounwind readnone define float @__rcp_uniform_float(float) nounwind readonly alwaysinline { ; uniform float iv = extract(__rcp_u(v), 0); ; return iv * (2. - v * iv); %r = fdiv float 1.,%0 ret float %r } ;; declare float @__sqrt_uniform_float(float) nounwind readnone define float @__sqrt_uniform_float(float) nounwind readonly alwaysinline { %ret = call float @llvm.nvvm.sqrt.f(float %0) ret float %ret } ;; declare float @__rsqrt_uniform_float(float) nounwind readnone define float @__rsqrt_uniform_float(float) nounwind readonly alwaysinline { %ret = call float @llvm.nvvm.rsqrt.approx.f(float %0) ret float %ret } declare @__rcp_varying_float() nounwind readnone declare @__rsqrt_varying_float() nounwind readnone define @__sqrt_varying_float() nounwind readnone alwaysinline { %v = extractelement <1 x float> %0, i32 0 %r = call float @__sqrt_uniform_float(float %v) %rv = insertelement <1 x float> undef, float %r, i32 0 ret %rv } ;; declare double @__sqrt_uniform_double(double) nounwind readnone define double @__sqrt_uniform_double(double) nounwind readonly alwaysinline { %ret = call double @llvm.nvvm.sqrt.d(double %0) ret double %ret } declare @__sqrt_varying_double() nounwind readnone ;; bit ops declare i32 @llvm.ctpop.i32(i32) nounwind readnone define i32 @__popcnt_int32(i32) nounwind readonly alwaysinline { %call = call i32 @llvm.ctpop.i32(i32 %0) ret i32 %call } declare i64 @llvm.ctpop.i64(i64) nounwind readnone define i64 @__popcnt_int64(i64) nounwind readonly alwaysinline { %call = call i64 @llvm.ctpop.i64(i64 %0) ret i64 %call } ctlztz() ; FIXME: need either to wire these up to the 8-wide SVML entrypoints, ; or, use the macro to call the 4-wide ones twice with our 8-wide ; vectors... ;; svml include(`svml.m4') svml_stubs(float,f,WIDTH) svml_stubs(double,d,WIDTH) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; population count; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reductions define i64 @__movmsk(<1 x i1>) nounwind readnone alwaysinline { %v = extractelement <1 x i1> %0, i32 0 %v64 = zext i1 %v to i64 ret i64 %v64 } define i1 @__any(<1 x i1>) nounwind readnone alwaysinline { %v = extractelement <1 x i1> %0, i32 0 %cmp = icmp ne i1 %v, 0 ret i1 %cmp } define i1 @__all(<1 x i1>) nounwind readnone alwaysinline { %v = extractelement <1 x i1> %0, i32 0 %cmp = icmp eq i1 %v, 1 ret i1 %cmp } define i1 @__none(<1 x i1>) nounwind readnone alwaysinline { %v = extractelement <1 x i1> %0, i32 0 %cmp = icmp eq i1 %v, 0 ret i1 %cmp } declare i16 @__reduce_add_int8() nounwind readnone declare i32 @__reduce_add_int16() nounwind readnone define float @__reduce_add_float(<1 x float> %v) nounwind readonly alwaysinline { %r = extractelement <1 x float> %v, i32 0 ret float %r } define float @__reduce_min_float(<1 x float>) nounwind readnone { %r = extractelement <1 x float> %0, i32 0 ret float %r } define float @__reduce_max_float(<1 x float>) nounwind readnone { %r = extractelement <1 x float> %0, i32 0 ret float %r } define i32 @__reduce_add_int32(<1 x i32> %v) nounwind readnone { %r = extractelement <1 x i32> %v, i32 0 ret i32 %r } define i32 @__reduce_min_int32(<1 x i32>) nounwind readnone { %r = extractelement <1 x i32> %0, i32 0 ret i32 %r } define i32 @__reduce_max_int32(<1 x i32>) nounwind readnone { %r = extractelement <1 x i32> %0, i32 0 ret i32 %r } define i32 @__reduce_min_uint32(<1 x i32>) nounwind readnone { %r = extractelement <1 x i32> %0, i32 0 ret i32 %r } define i32 @__reduce_max_uint32(<1 x i32>) nounwind readnone { %r = extractelement <1 x i32> %0, i32 0 ret i32 %r } define double @__reduce_add_double(<1 x double>) nounwind readnone { %m = extractelement <1 x double> %0, i32 0 ret double %m } define double @__reduce_min_double(<1 x double>) nounwind readnone { %m = extractelement <1 x double> %0, i32 0 ret double %m } define double @__reduce_max_double(<1 x double>) nounwind readnone { %m = extractelement <1 x double> %0, i32 0 ret double %m } define i64 @__reduce_add_int64(<1 x i64>) nounwind readnone { %m = extractelement <1 x i64> %0, i32 0 ret i64 %m } define i64 @__reduce_min_int64(<1 x i64>) nounwind readnone { %m = extractelement <1 x i64> %0, i32 0 ret i64 %m } define i64 @__reduce_max_int64(<1 x i64>) nounwind readnone { %m = extractelement <1 x i64> %0, i32 0 ret i64 %m } define i64 @__reduce_min_uint64(<1 x i64>) nounwind readnone { %m = extractelement <1 x i64> %0, i32 0 ret i64 %m } define i64 @__reduce_max_uint64(<1 x i64>) nounwind readnone { %m = extractelement <1 x i64> %0, i32 0 ret i64 %m } define i1 @__reduce_equal_int32(<1 x i32> %vv, i32 * %samevalue, <1 x i1> %mask) nounwind alwaysinline { %v=extractelement <1 x i32> %vv, i32 0 store i32 %v, i32 * %samevalue ret i1 true } define i1 @__reduce_equal_float(<1 x float> %vv, float * %samevalue, <1 x i1> %mask) nounwind alwaysinline { %v=extractelement <1 x float> %vv, i32 0 store float %v, float * %samevalue ret i1 true } define i1 @__reduce_equal_int64(<1 x i64> %vv, i64 * %samevalue, <1 x i1> %mask) nounwind alwaysinline { %v=extractelement <1 x i64> %vv, i32 0 store i64 %v, i64 * %samevalue ret i1 true } define i1 @__reduce_equal_double(<1 x double> %vv, double * %samevalue, <1 x i1> %mask) nounwind alwaysinline { %v=extractelement <1 x double> %vv, i32 0 store double %v, double * %samevalue ret i1 true } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 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(float) gen_masked_store(i64) gen_masked_store(double) define void @__masked_store_blend_i8(* nocapture, , ) nounwind alwaysinline { %v = load * %0 %v1 = select %2, %1, %v store %v1, * %0 ret void } define void @__masked_store_blend_i16(* nocapture, , ) nounwind alwaysinline { %v = load * %0 %v1 = select %2, %1, %v store %v1, * %0 ret void } define void @__masked_store_blend_i32(* nocapture, , ) nounwind alwaysinline { %v = load * %0 %v1 = select %2, %1, %v store %v1, * %0 ret void } define void @__masked_store_blend_float(* nocapture, , ) nounwind alwaysinline { %v = load * %0 %v1 = select %2, %1, %v store %v1, * %0 ret void } define void @__masked_store_blend_i64(* nocapture, , ) nounwind alwaysinline { %v = load * %0 %v1 = select %2, %1, %v store %v1, * %0 ret void } define void @__masked_store_blend_double(* nocapture, , ) nounwind alwaysinline { %v = load * %0 %v1 = select %2, %1, %v store %v1, * %0 ret void } ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; gather/scatter ; define these with the macros from stdlib.m4 gen_gather_factored(i8) gen_gather_factored(i16) gen_gather_factored(i32) gen_gather_factored(float) gen_gather_factored(i64) gen_gather_factored(double) gen_scatter(i8) gen_scatter(i16) gen_scatter(i32) gen_scatter(float) gen_scatter(i64) gen_scatter(double) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; prefetch ;; define void @__prefetch_read_uniform_1(i8 * nocapture) nounwind alwaysinline { } ;; define void @__prefetch_read_uniform_2(i8 * nocapture) nounwind alwaysinline { } ;; define void @__prefetch_read_uniform_3(i8 * nocapture) nounwind alwaysinline { } ;; define void @__prefetch_read_uniform_nt(i8 * nocapture) nounwind alwaysinline { } define_prefetches() ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; int8/int16 builtins define_avgs()