From 03e6f285e5fcb0327bd4ef4eccf426f0916a5065 Mon Sep 17 00:00:00 2001 From: Matt Turner Date: Tue, 10 Feb 2026 15:25:00 -0500 Subject: [PATCH] elk/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: 47c4b385407 ("i965/fs: Allow CSE to handle MULs with negated arguments.") (cherry picked from commit 93f39f87c46976e7b05b194fd805b750c89f001e) Part-of: --- .pick_status.json | 2 +- src/intel/compiler/elk/elk_fs_cse.cpp | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 42e2b68c132..dd7f589623b 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -6384,7 +6384,7 @@ "description": "elk/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 diff --git a/src/intel/compiler/elk/elk_fs_cse.cpp b/src/intel/compiler/elk/elk_fs_cse.cpp index 7b3b0f026d4..e5399bf365f 100644 --- a/src/intel/compiler/elk/elk_fs_cse.cpp +++ b/src/intel/compiler/elk/elk_fs_cse.cpp @@ -131,15 +131,24 @@ operands_match(const elk_fs_inst *a, const elk_fs_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])); @@ -148,8 +157,10 @@ operands_match(const elk_fs_inst *a, const elk_fs_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))