diff options
author | Dave Airlie <[email protected]> | 2019-12-13 13:09:42 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2019-12-21 13:06:58 +1000 |
commit | c717ac1247c3c7243af2f1b2732cccb882b75f11 (patch) | |
tree | 05ddef4f7e5da72a98e5a6266147b05d74f2b55e /src/gallium/auxiliary/gallivm/lp_bld_nir.c | |
parent | 7d65614422736de32214fc28b0054692f4e5e48f (diff) |
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 <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2303>
Diffstat (limited to 'src/gallium/auxiliary/gallivm/lp_bld_nir.c')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_nir.c | 25 |
1 files 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]); |