summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCaio Marcelo de Oliveira Filho <[email protected]>2019-05-11 00:15:41 -0700
committerCaio Marcelo de Oliveira Filho <[email protected]>2019-05-16 10:55:03 -0700
commit8a995f2b5e1e3f2a2eafd32870ebfb43b5cfdf27 (patch)
treeabeb63ad76b1f0fd22d1c0e2854b4690fc85b87c /src
parentef88e23d0335c05ebc60a621ee91cd6b22208597 (diff)
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, incorrectly. 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: 74492ebad94 "nir: Add a pass for lowering integer division by constants" Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/compiler/nir/nir_opt_idiv_const.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/src/compiler/nir/nir_opt_idiv_const.c b/src/compiler/nir/nir_opt_idiv_const.c
index 8f70821ca2f..688186779e6 100644
--- a/src/compiler/nir/nir_opt_idiv_const.c
+++ b/src/compiler/nir/nir_opt_idiv_const.c
@@ -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);