brw/cse: fix operands_match corrupting non-IMM register data

The MUL case in `operands_match` was reading and writing the `.f` union
member unconditionally, even when the register's `.file != IMM`. In that
case `.f` aliases the struct containing `.nr`/`.swizzle`/etc, so the
`fabsf()` call could corrupt the `.nr` by clearing bit 31.

Guard all `.f` accesses with `.file == IMM` checks.

Fixes: 47c4b38540 ("i965/fs: Allow CSE to handle MULs with negated arguments.")
(cherry picked from commit f5e0f63216)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40092>
This commit is contained in:
Matt Turner 2026-02-10 15:07:32 -05:00 committed by Eric Engestrom
parent 547fd52a66
commit 14c7d820cd
2 changed files with 18 additions and 7 deletions

View file

@ -6404,7 +6404,7 @@
"description": "brw/cse: fix `operands_match` corrupting non-IMM register data",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "47c4b3854076adfe5a27b537f36262ac4ec4530d",
"notes": null

View file

@ -175,15 +175,24 @@ operands_match(const brw_inst *a, const brw_inst *b, bool *negate)
bool ys0_negate = ys[0].negate;
bool ys1_negate = ys[1].file == IMM ? ys[1].f < 0.0f
: ys[1].negate;
float xs1_imm = xs[1].f;
float ys1_imm = ys[1].f;
float xs1_imm = 0, ys1_imm = 0;
xs[0].negate = false;
xs[1].negate = false;
ys[0].negate = false;
ys[1].negate = false;
xs[1].f = fabsf(xs[1].f);
ys[1].f = fabsf(ys[1].f);
/* Only access .f when the register is an immediate. When it is not,
* .f aliases the struct containing nr/swizzle/etc, so fabsf() could
* corrupt the register number by clearing bit 31.
*/
if (xs[1].file == IMM) {
xs1_imm = xs[1].f;
xs[1].f = fabsf(xs1_imm);
}
if (ys[1].file == IMM) {
ys1_imm = ys[1].f;
ys[1].f = fabsf(ys1_imm);
}
bool ret = (xs[0].equals(ys[0]) && xs[1].equals(ys[1])) ||
(xs[1].equals(ys[0]) && xs[0].equals(ys[1]));
@ -192,8 +201,10 @@ operands_match(const brw_inst *a, const brw_inst *b, bool *negate)
xs[1].negate = xs[1].file == IMM ? false : xs1_negate;
ys[0].negate = ys0_negate;
ys[1].negate = ys[1].file == IMM ? false : ys1_negate;
xs[1].f = xs1_imm;
ys[1].f = ys1_imm;
if (xs[1].file == IMM)
xs[1].f = xs1_imm;
if (ys[1].file == IMM)
ys[1].f = ys1_imm;
*negate = (xs0_negate != xs1_negate) != (ys0_negate != ys1_negate);
if (*negate && (a->saturate || b->saturate))