mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-25 00:00:11 +01:00
nouveau/mme: Fix while loops pre-Turing
Pre-Turing, we don't have a full condition built into the loop so, for
mme_while(b, ine, x, y) we have to generate the following:
[top] BR -> [cond]
/* loop body */
[cond] XOR tmp, x, y
BRZ !tmp -> [top]
However, due to an accounting error, we were generating
[top] BR -> [cond]
/* loop body */
XOR tmp, x, y
[cond] BRZ !tmp -> [top]
which meant that the XOR (or ADD if one is an immediate) was getting
skipped, leading to the loop either never terminating or always
terminating. The way to fix this accounting error is to close the while
first, then compute the condition value, then do the jump.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
parent
ccf004837a
commit
08a200193f
2 changed files with 59 additions and 5 deletions
|
|
@ -520,12 +520,14 @@ mme_fermi_start_while(struct mme_builder *b)
|
|||
|
||||
static void
|
||||
mme_fermi_end_while_zero(struct mme_builder *b,
|
||||
struct mme_cf cf,
|
||||
struct mme_value cond,
|
||||
bool is_zero)
|
||||
{
|
||||
struct mme_fermi_builder *fb = &b->fermi;
|
||||
|
||||
struct mme_cf cf = mme_fermi_end_cf(b, MME_CF_TYPE_WHILE);
|
||||
if (fb->inst_parts)
|
||||
mme_fermi_new_inst(fb);
|
||||
|
||||
int delta = fb->inst_count - cf.start_ip - 2;
|
||||
mme_fermi_branch(fb, mme_value_alu_reg(cond), -delta, !is_zero);
|
||||
|
|
@ -540,13 +542,15 @@ mme_fermi_end_while(struct mme_builder *b,
|
|||
{
|
||||
assert(op == MME_CMP_OP_EQ);
|
||||
|
||||
struct mme_cf cf = mme_fermi_end_cf(b, MME_CF_TYPE_WHILE);
|
||||
|
||||
if (mme_is_zero(x)) {
|
||||
mme_fermi_end_while_zero(b, y, if_true);
|
||||
mme_fermi_end_while_zero(b, cf, y, if_true);
|
||||
} else if (mme_is_zero(y)) {
|
||||
mme_fermi_end_while_zero(b, x, if_true);
|
||||
mme_fermi_end_while_zero(b, cf, x, if_true);
|
||||
} else {
|
||||
struct mme_value tmp = mme_fermi_neq(b, x, y);
|
||||
mme_fermi_end_while_zero(b, tmp, if_true);
|
||||
mme_fermi_end_while_zero(b, cf, tmp, if_true);
|
||||
mme_free_reg(b, tmp);
|
||||
}
|
||||
}
|
||||
|
|
@ -569,7 +573,7 @@ mme_fermi_end_loop(struct mme_builder *b)
|
|||
struct mme_fermi_builder *fb = &b->fermi;
|
||||
|
||||
mme_sub_to(b, fb->loop_counter, fb->loop_counter, mme_imm(1));
|
||||
mme_fermi_end_while_zero(b, fb->loop_counter, false);
|
||||
mme_fermi_end_while(b, MME_CMP_OP_EQ, false, fb->loop_counter, mme_zero());
|
||||
|
||||
mme_free_reg(b, fb->loop_counter);
|
||||
fb->loop_counter = mme_zero();
|
||||
|
|
|
|||
|
|
@ -259,3 +259,53 @@ TEST_F(mme_builder_test, merge)
|
|||
ASSERT_SIM_DATA(sim);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(mme_builder_test, while_ine)
|
||||
{
|
||||
static const uint32_t cases[] = { 1, 3, 5, 8 };
|
||||
|
||||
for (auto sim : sims) {
|
||||
mme_builder b;
|
||||
mme_builder_init(&b, sim->devinfo);
|
||||
|
||||
mme_value inc = mme_load(&b);
|
||||
mme_value bound = mme_load(&b);
|
||||
|
||||
mme_value x = mme_mov(&b, mme_zero());
|
||||
mme_value y = mme_mov(&b, mme_zero());
|
||||
mme_value z = mme_mov(&b, mme_zero());
|
||||
|
||||
mme_value i = mme_mov(&b, mme_zero());
|
||||
mme_while(&b, ine, i, bound) {
|
||||
mme_add_to(&b, x, x, mme_imm(1));
|
||||
mme_add_to(&b, y, y, mme_imm(2));
|
||||
mme_add_to(&b, z, z, mme_imm(3));
|
||||
mme_add_to(&b, i, i, inc);
|
||||
}
|
||||
|
||||
sim->mme_store_data(&b, 0, x);
|
||||
sim->mme_store_data(&b, 1, y);
|
||||
sim->mme_store_data(&b, 2, z);
|
||||
sim->mme_store_data(&b, 3, i);
|
||||
|
||||
auto macro = mme_builder_finish_vec(&b);
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(cases); i++) {
|
||||
const uint32_t inc = cases[i];
|
||||
const uint32_t count = cases[ARRAY_SIZE(cases) - i];
|
||||
const uint32_t bound = inc * count;
|
||||
|
||||
std::vector<uint32_t> params;
|
||||
params.push_back(inc);
|
||||
params.push_back(bound);
|
||||
|
||||
expected[0] = count * 1;
|
||||
expected[1] = count * 2;
|
||||
expected[2] = count * 3;
|
||||
expected[3] = count * inc;
|
||||
|
||||
sim->run_macro(macro, params);
|
||||
ASSERT_SIM_DATA(sim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue