Mesa (main): aco/optimizer: propagate and fold inline constants on VOP3P instructions
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Dec 21 16:37:45 UTC 2021
Module: Mesa
Branch: main
Commit: 30a7199e37cb26c189495860f3b04a2408144eb1
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=30a7199e37cb26c189495860f3b04a2408144eb1
Author: Daniel Schürmann <daniel at schuermann.dev>
Date: Mon Dec 13 19:58:46 2021 +0100
aco/optimizer: propagate and fold inline constants on VOP3P instructions
This patch aims to propagate and fold constants on VOP3P instructions
by using omod selection and the fneg modifier.
Reviewed-by: Rhys Perry <pendingchaos02 at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13688>
---
src/amd/compiler/aco_optimizer.cpp | 74 ++++++++++++++++++++++++++++++++++++--
1 file changed, 72 insertions(+), 2 deletions(-)
diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp
index 0336d5f66a8..faa82fdf9e9 100644
--- a/src/amd/compiler/aco_optimizer.cpp
+++ b/src/amd/compiler/aco_optimizer.cpp
@@ -860,6 +860,72 @@ get_constant_op(opt_ctx& ctx, ssa_info info, uint32_t bits)
return Operand::get_const(ctx.program->chip_class, info.val, bits / 8u);
}
+void
+propagate_constants_vop3p(opt_ctx& ctx, aco_ptr<Instruction>& instr, ssa_info& info, unsigned i)
+{
+ if (!info.is_constant_or_literal(32))
+ return;
+
+ assert(instr->operands[i].isTemp());
+ unsigned bits = get_operand_size(instr, i);
+ if (info.is_constant(bits)) {
+ instr->operands[i] = get_constant_op(ctx, info, bits);
+ return;
+ }
+
+ /* try to fold inline constants */
+ VOP3P_instruction* vop3p = &instr->vop3p();
+ Operand const_lo = Operand::c16(info.val);
+ Operand const_hi = Operand::c16(info.val >> 16);
+ bool opsel_lo = (vop3p->opsel_lo >> i) & 1;
+ bool opsel_hi = (vop3p->opsel_hi >> i) & 1;
+
+ if (const_hi.isLiteral() && (opsel_lo || opsel_hi))
+ return;
+ if (const_lo.isLiteral() && !(opsel_lo && opsel_hi))
+ return;
+
+ if (opsel_lo == opsel_hi) {
+ /* use the single 16bit value */
+ instr->operands[i] = opsel_lo ? const_hi : const_lo;
+
+ /* opsel must point to lo for both halves */
+ vop3p->opsel_lo &= ~(1 << i);
+ vop3p->opsel_hi &= ~(1 << i);
+ } else if (const_lo == const_hi) {
+ /* both constants are the same */
+ instr->operands[i] = const_lo;
+
+ /* opsel must point to lo for both halves */
+ vop3p->opsel_lo &= ~(1 << i);
+ vop3p->opsel_hi &= ~(1 << i);
+ } else if (const_lo == Operand::c16(0)) {
+ /* don't inline FP constants into integer instructions */
+ // TODO: check if negative integers are zero- or sign-extended
+ if (bits == 32 && const_hi.constantValue() > 64u)
+ return;
+
+ instr->operands[i] = const_hi;
+
+ /* redirect opsel selection */
+ vop3p->opsel_lo ^= (1 << i);
+ vop3p->opsel_hi ^= (1 << i);
+ } else if (bits == 16 && const_lo.constantValue() == (const_hi.constantValue() ^ (1 << 15))) {
+ /* const_lo == -const_hi */
+ if (!instr_info.can_use_input_modifiers[(int)instr->opcode])
+ return;
+
+ instr->operands[i] = Operand::c16(const_lo.constantValue() & 0x7FFF);
+ bool neg_lo = const_lo.constantValue() & (1 << 15);
+ vop3p->neg_lo[i] ^= opsel_lo ^ neg_lo;
+ vop3p->neg_hi[i] ^= opsel_hi ^ neg_lo;
+
+ /* opsel must point to lo for both operands */
+ vop3p->opsel_lo &= ~(1 << i);
+ vop3p->opsel_hi &= ~(1 << i);
+ }
+}
+
bool
fixed_to_exec(Operand op)
{
@@ -1149,14 +1215,18 @@ label_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
continue;
}
+ if (instr->isVOP3P()) {
+ propagate_constants_vop3p(ctx, instr, info, i);
+ continue;
+ }
+
unsigned bits = get_operand_size(instr, i);
if (info.is_constant(bits) && alu_can_accept_constant(instr->opcode, i) &&
(!instr->isSDWA() || ctx.program->chip_class >= GFX9)) {
Operand op = get_constant_op(ctx, info, bits);
perfwarn(ctx.program, instr->opcode == aco_opcode::v_cndmask_b32 && i == 2,
"v_cndmask_b32 with a constant selector", instr.get());
- if (i == 0 || instr->isSDWA() || instr->isVOP3P() ||
- instr->opcode == aco_opcode::v_readlane_b32 ||
+ if (i == 0 || instr->isSDWA() || instr->opcode == aco_opcode::v_readlane_b32 ||
instr->opcode == aco_opcode::v_writelane_b32) {
instr->format = withoutDPP(instr->format);
instr->operands[i] = op;
More information about the mesa-commit
mailing list