summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Lehmann <dadschoorse@gmail.com>2022-09-24 18:49:10 +0200
committerMarge Bot <emma+marge@anholt.net>2022-11-28 18:43:53 +0000
commit73be938c48d63e6c3c20d5cbd4f203c337f073aa (patch)
treebdf3e44e6a158e8cf054685a707e0e1f97b1ff41
parent853d2cb6f15e2d70459abb666eac3decf801eb4b (diff)
aco: Combine bit test to s_bitcmp.
Foz-DB Navi21: Totals from 6396 (4.74% of 134913) affected shaders: VGPRs: 483280 -> 483152 (-0.03%); split: -0.03%, +0.01% SpillSGPRs: 8119 -> 7941 (-2.19%) CodeSize: 63377880 -> 63268556 (-0.17%); split: -0.20%, +0.03% MaxWaves: 86778 -> 86810 (+0.04%) Instrs: 11745621 -> 11725857 (-0.17%); split: -0.20%, +0.03% Latency: 162400148 -> 162282230 (-0.07%); split: -0.08%, +0.01% InvThroughput: 29179429 -> 29133173 (-0.16%); split: -0.16%, +0.00% VClause: 208032 -> 208100 (+0.03%); split: -0.01%, +0.05% SClause: 431390 -> 430849 (-0.13%); split: -0.24%, +0.11% Copies: 896222 -> 893285 (-0.33%); split: -0.62%, +0.30% Branches: 349806 -> 348770 (-0.30%); split: -0.90%, +0.60% PreSGPRs: 618908 -> 613773 (-0.83%); split: -0.83%, +0.00% PreVGPRs: 482901 -> 482893 (-0.00%) Signed-off-by: Georg Lehmann <dadschoorse@gmail.com> Reviewed-by: Daniel Schürmann <daniel@schuermann.dev> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18870>
-rw-r--r--src/amd/compiler/aco_optimizer.cpp69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp
index e78472b8f19..6832dbf78f6 100644
--- a/src/amd/compiler/aco_optimizer.cpp
+++ b/src/amd/compiler/aco_optimizer.cpp
@@ -2810,6 +2810,68 @@ use_absdiff:
return true;
}
+/* s_cmp_{lg,eq}(s_and(a, s_lshl(1, b)), 0) -> s_bitcmp[10](a, b)*/
+bool
+combine_s_bitcmp(opt_ctx& ctx, aco_ptr<Instruction>& instr)
+{
+ bool lg = false;
+ bool b64 = false;
+ switch (instr->opcode) {
+ case aco_opcode::s_cmp_lg_i32:
+ case aco_opcode::s_cmp_lg_u32: lg = true; break;
+ case aco_opcode::s_cmp_eq_i32:
+ case aco_opcode::s_cmp_eq_u32: break;
+ case aco_opcode::s_cmp_lg_u64: lg = true; FALLTHROUGH;
+ case aco_opcode::s_cmp_eq_u64: b64 = true; break;
+ default: return false;
+ }
+
+ aco_opcode s_and = b64 ? aco_opcode::s_and_b64 : aco_opcode::s_and_b32;
+ aco_opcode s_lshl = b64 ? aco_opcode::s_lshl_b64 : aco_opcode::s_lshl_b32;
+
+ for (unsigned cmp_idx = 0; cmp_idx < 2; cmp_idx++) {
+ Instruction* and_instr = follow_operand(ctx, instr->operands[cmp_idx], false);
+ if (!and_instr || and_instr->opcode != s_and)
+ continue;
+
+ for (unsigned and_idx = 0; and_idx < 2; and_idx++) {
+ Instruction* lshl_instr = follow_operand(ctx, and_instr->operands[and_idx], true);
+ if (!lshl_instr || lshl_instr->opcode != s_lshl ||
+ !lshl_instr->operands[0].constantEquals(1) ||
+ (lshl_instr->operands[1].isLiteral() && and_instr->operands[!and_idx].isLiteral()))
+ continue;
+
+ bool test1 = false;
+ if (instr->operands[!cmp_idx].constantEquals(0)) {
+ test1 = lg;
+ } else if (instr->operands[!cmp_idx].isTemp() &&
+ instr->operands[!cmp_idx].tempId() == lshl_instr->definitions[0].tempId()) {
+ test1 = !lg;
+ ctx.uses[lshl_instr->definitions[0].tempId()]--;
+ } else {
+ continue;
+ }
+
+ if (test1 && b64)
+ instr->opcode = aco_opcode::s_bitcmp1_b64;
+ else if (!test1 && b64)
+ instr->opcode = aco_opcode::s_bitcmp0_b64;
+ else if (test1 && !b64)
+ instr->opcode = aco_opcode::s_bitcmp1_b32;
+ else
+ instr->opcode = aco_opcode::s_bitcmp0_b32;
+
+ instr->operands[0] = copy_operand(ctx, and_instr->operands[!and_idx]);
+ instr->operands[1] = copy_operand(ctx, lshl_instr->operands[1]);
+ decrease_uses(ctx, and_instr);
+ decrease_op_uses_if_dead(ctx, lshl_instr);
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool
combine_add_sub_b2i(opt_ctx& ctx, aco_ptr<Instruction>& instr, aco_opcode new_op, uint8_t ops)
{
@@ -4226,6 +4288,13 @@ combine_instruction(opt_ctx& ctx, aco_ptr<Instruction>& instr)
}
} else if (instr->opcode == aco_opcode::s_abs_i32) {
combine_sabsdiff(ctx, instr);
+ } else if (instr->opcode == aco_opcode::s_cmp_lg_i32 ||
+ instr->opcode == aco_opcode::s_cmp_lg_u32 ||
+ instr->opcode == aco_opcode::s_cmp_lg_u64 ||
+ instr->opcode == aco_opcode::s_cmp_eq_i32 ||
+ instr->opcode == aco_opcode::s_cmp_eq_u32 ||
+ instr->opcode == aco_opcode::s_cmp_eq_u64) {
+ combine_s_bitcmp(ctx, instr);
} else if (instr->opcode == aco_opcode::v_and_b32) {
combine_and_subbrev(ctx, instr);
} else if (instr->opcode == aco_opcode::v_fma_f32 || instr->opcode == aco_opcode::v_fma_f16) {