From 0bd1cd3230119686189296b54dd385f3be938622 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Thu, 3 Jul 2025 11:56:28 -0400 Subject: [PATCH] agx: fix incorrect 16-bit promotions with comparisons hardware seems to sign extend with a signed comparison, which I guess is reasonable! so our logic was busted if we had a zero-extend source with a signed comparison. this broke someone's OpenCL app, and could probably be hit from GLES/Vulkan too... on fossil-db, only parallel-rdp affected: Totals from 312 (0.58% of 53701) affected shaders: Instrs: 404772 -> 405697 (+0.23%); split: -0.01%, +0.24% CodeSize: 2863314 -> 2868998 (+0.20%); split: -0.01%, +0.21% Spills: 40239 -> 40286 (+0.12%); split: -0.02%, +0.14% Fills: 33763 -> 33810 (+0.14%); split: -0.03%, +0.17% ALU: 290757 -> 291071 (+0.11%); split: -0.02%, +0.13% FSCIB: 261844 -> 262652 (+0.31%); split: -0.02%, +0.33% IC: 230312 -> 230336 (+0.01%); split: -0.01%, +0.02% GPRs: 24656 -> 24648 (-0.03%); split: -0.05%, +0.02% Reported-by: RowanG Signed-off-by: Alyssa Rosenzweig Part-of: --- src/asahi/compiler/agx_optimizer.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/asahi/compiler/agx_optimizer.c b/src/asahi/compiler/agx_optimizer.c index ef9cd20428d..78da05ddd27 100644 --- a/src/asahi/compiler/agx_optimizer.c +++ b/src/asahi/compiler/agx_optimizer.c @@ -247,13 +247,30 @@ agx_optimizer_fmov_rev(agx_instr *I, agx_instr *use) return true; } +static bool +agx_icond_is_unsigned(enum agx_icond cond) +{ + switch (cond) { + case AGX_ICOND_UEQ: + case AGX_ICOND_ULT: + case AGX_ICOND_UGT: + return true; + + case AGX_ICOND_SEQ: + case AGX_ICOND_SLT: + case AGX_ICOND_SGT: + return false; + } + + unreachable("invalid condition"); +} + static bool agx_supports_zext(agx_instr *I, unsigned s) { switch (I->op) { case AGX_OPCODE_IADD: case AGX_OPCODE_IMAD: - case AGX_OPCODE_ICMP: case AGX_OPCODE_INTL: case AGX_OPCODE_FFS: case AGX_OPCODE_BITREV: @@ -268,9 +285,15 @@ agx_supports_zext(agx_instr *I, unsigned s) case AGX_OPCODE_ICMP_BALLOT: case AGX_OPCODE_ICMP_QUAD_BALLOT: return true; + + case AGX_OPCODE_ICMP: case AGX_OPCODE_ICMPSEL: - /* Only the comparisons can be extended, not the selection */ - return s < 2; + /* Only the comparisons can be extended, not the selection. And we can + * only zero-extend with unsigned comparison. Presumably the hardware + * sign-extends with signed comparisons but we don't handle that yet. + */ + return (s < 2) && agx_icond_is_unsigned(I->icond); + default: return false; }