Commit 5bed00cf authored by Caio Marcelo de Oliveira Filho's avatar Caio Marcelo de Oliveira Filho Committed by Juan Suárez Romero

nir: Fix nir_opt_idiv_const when negatives are involved

First, allow the case for negative powers of two.  Then ensure that we
use the absolute value of the non-constant value to calculate the
quotient -- this was hinted in the code by the name 'uq'.

This fixes an issue when 'd' is positive and 'n' is negative.  The
ishr will propagate the negative sign and we'll use nir_ineg() again,

v2: First version used only ishr, but that isn't sufficient, since it
    never can produce a zero as a result.  (Jason)
    Allow negative powers of two.  (Caio)

Fixes: 74492eba "nir: Add a pass for lowering integer division by constants"
Reviewed-by: Jason Ekstrand's avatarJason Ekstrand <>
(cherry picked from commit 8a995f2b)
parent b551be82
......@@ -65,15 +65,17 @@ build_umod(nir_builder *b, nir_ssa_def *n, uint64_t d)
static nir_ssa_def *
build_idiv(nir_builder *b, nir_ssa_def *n, int64_t d)
uint64_t abs_d = d < 0 ? -d : d;
if (d == 0) {
return nir_imm_intN_t(b, 0, n->bit_size);
} else if (d == 1) {
return n;
} else if (d == -1) {
return nir_ineg(b, n);
} else if (util_is_power_of_two_or_zero64(d)) {
uint64_t abs_d = d < 0 ? -d : d;
nir_ssa_def *uq = nir_ishr(b, n, nir_imm_int(b, util_logbase2_64(abs_d)));
} else if (util_is_power_of_two_or_zero64(abs_d)) {
nir_ssa_def *uq = nir_ushr(b, nir_iabs(b, n),
nir_imm_int(b, util_logbase2_64(abs_d)));
nir_ssa_def *n_neg = nir_ilt(b, n, nir_imm_intN_t(b, 0, n->bit_size));
nir_ssa_def *neg = d < 0 ? nir_inot(b, n_neg) : n_neg;
return nir_bcsel(b, neg, nir_ineg(b, uq), uq);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment