From c717ac1247c3c7243af2f1b2732cccb882b75f11 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 13 Dec 2019 13:09:42 +1000 Subject: [PATCH] gallivm/nir: wrap idiv to avoid divide by 0 (v2) This code is taken from the TGSI paths, and should fix the regression seens with GLES2 v2: use the udiv path which has d3d10 defined return. Reviewed-by: Roland Scheidegger Part-of: --- src/gallium/auxiliary/gallivm/lp_bld_nir.c | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_nir.c b/src/gallium/auxiliary/gallivm/lp_bld_nir.c index c21ca55f6ed..770352b8daa 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_nir.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_nir.c @@ -385,6 +385,25 @@ merge_64bit(struct lp_build_nir_context *bld_base, return LLVMBuildShuffleVector(builder, input, input2, LLVMConstVector(shuffles, len), ""); } +static LLVMValueRef +do_int_divide(struct lp_build_nir_context *bld_base, + bool is_unsigned, unsigned src_bit_size, + LLVMValueRef src, LLVMValueRef src2) +{ + struct gallivm_state *gallivm = bld_base->base.gallivm; + LLVMBuilderRef builder = gallivm->builder; + struct lp_build_context *int_bld = get_int_bld(bld_base, is_unsigned, src_bit_size); + LLVMValueRef div_mask = lp_build_cmp(int_bld, PIPE_FUNC_EQUAL, src2, + int_bld->zero); + LLVMValueRef divisor = LLVMBuildOr(builder, + div_mask, + src2, ""); + LLVMValueRef result = lp_build_div(int_bld, src, divisor); + /* udiv by zero is guaranteed to return 0xffffffff at least with d3d10 + * may as well do same for idiv */ + return LLVMBuildOr(builder, div_mask, result, ""); +} + static LLVMValueRef do_alu_action(struct lp_build_nir_context *bld_base, nir_op op, unsigned src_bit_size[4], LLVMValueRef src[4]) { @@ -576,8 +595,7 @@ static LLVMValueRef do_alu_action(struct lp_build_nir_context *bld_base, src[0], src[1]); break; case nir_op_idiv: - result = lp_build_div(&bld_base->int_bld, - src[0], src[1]); + result = do_int_divide(bld_base, false, src_bit_size[0], src[0], src[1]); break; case nir_op_ieq32: result = icmp32(bld_base, PIPE_FUNC_EQUAL, false, src_bit_size[0], src); @@ -660,8 +678,7 @@ static LLVMValueRef do_alu_action(struct lp_build_nir_context *bld_base, result = LLVMBuildZExt(builder, src[0], bld_base->uint64_bld.vec_type, ""); break; case nir_op_udiv: - result = lp_build_div(&bld_base->uint_bld, - src[0], src[1]); + result = do_int_divide(bld_base, true, src_bit_size[0], src[0], src[1]); break; case nir_op_ufind_msb: { struct lp_build_context *uint_bld = get_int_bld(bld_base, true, src_bit_size[0]); -- 2.30.2