From 576f92d9007bd49d0a79aac9a6d8219bc3393604 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Sch=C3=BCrmann?= Date: Wed, 28 Aug 2019 12:08:12 +0200 Subject: [PATCH] aco: only skip RAR dependencies if the variable is killed somewhere This patch changes VMEM scheduling in a way that they can only be moved upwards by previous VMEM instructions but not downwards. This way, it improves the order of VMEM instructions in relation to their users. Reviewed-by: Rhys Perry --- src/amd/compiler/aco_scheduler.cpp | 67 ++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/src/amd/compiler/aco_scheduler.cpp b/src/amd/compiler/aco_scheduler.cpp index f1b4472a942..30a82e68ce8 100644 --- a/src/amd/compiler/aco_scheduler.cpp +++ b/src/amd/compiler/aco_scheduler.cpp @@ -276,7 +276,7 @@ void schedule_SMEM(sched_ctx& ctx, Block* block, continue; } - /* check if register pressure is low enough: the diff is negative if register pressure is decreased */ + /* check if register pressure is low enough: the diff is negative if register pressure is increased */ const RegisterDemand candidate_diff = getLiveChanges(candidate); const RegisterDemand tempDemand = getTempRegisters(candidate); if (RegisterDemand(register_pressure - candidate_diff).exceeds(ctx.max_registers)) @@ -433,9 +433,13 @@ void schedule_VMEM(sched_ctx& ctx, Block* block, /* create the initial set of values which current depends on */ std::fill(ctx.depends_on.begin(), ctx.depends_on.end(), false); + std::fill(ctx.RAR_dependencies.begin(), ctx.RAR_dependencies.end(), false); for (const Operand& op : current->operands) { - if (op.isTemp()) + if (op.isTemp()) { ctx.depends_on[op.tempId()] = true; + if (op.isFirstKill()) + ctx.RAR_dependencies[op.tempId()] = true; + } } /* maintain how many registers remain free when moving instructions */ @@ -467,7 +471,7 @@ void schedule_VMEM(sched_ctx& ctx, Block* block, register_pressure.update(register_demand[candidate_idx]); /* if current depends on candidate, add additional dependencies and continue */ - bool can_move_down = true; + bool can_move_down = !candidate->isVMEM(); bool writes_exec = false; for (const Definition& def : candidate->definitions) { if (def.isTemp() && ctx.depends_on[def.tempId()]) @@ -486,8 +490,11 @@ void schedule_VMEM(sched_ctx& ctx, Block* block, moving_spill |= is_spill_reload(candidate); if (!can_move_down) { for (const Operand& op : candidate->operands) { - if (op.isTemp()) + if (op.isTemp()) { ctx.depends_on[op.tempId()] = true; + if (op.isFirstKill()) + ctx.RAR_dependencies[op.tempId()] = true; + } } continue; } @@ -495,20 +502,23 @@ void schedule_VMEM(sched_ctx& ctx, Block* block, bool register_pressure_unknown = false; /* check if one of candidate's operands is killed by depending instruction */ for (const Operand& op : candidate->operands) { - if (op.isTemp() && ctx.depends_on[op.tempId()]) { + if (op.isTemp() && ctx.RAR_dependencies[op.tempId()]) { // FIXME: account for difference in register pressure register_pressure_unknown = true; } } if (register_pressure_unknown) { for (const Operand& op : candidate->operands) { - if (op.isTemp()) + if (op.isTemp()) { ctx.depends_on[op.tempId()] = true; + if (op.isFirstKill()) + ctx.RAR_dependencies[op.tempId()] = true; + } } continue; } - /* check if register pressure is low enough: the diff is negative if register pressure is decreased */ + /* check if register pressure is low enough: the diff is negative if register pressure is increased */ const RegisterDemand candidate_diff = getLiveChanges(candidate); const RegisterDemand temp = getTempRegisters(candidate);; if (RegisterDemand(register_pressure - candidate_diff).exceeds(ctx.max_registers)) @@ -594,6 +604,11 @@ void schedule_VMEM(sched_ctx& ctx, Block* block, register_pressure = register_demand[insert_idx - 1]; continue; } + } else if (candidate->isVMEM()) { + for (const Definition& def : candidate->definitions) { + if (def.isTemp()) + ctx.depends_on[def.tempId()] = true; + } } /* update register pressure */ @@ -606,13 +621,13 @@ void schedule_VMEM(sched_ctx& ctx, Block* block, bool register_pressure_unknown = false; /* check if candidate uses/kills an operand which is used by a dependency */ for (const Operand& op : candidate->operands) { - if (op.isTemp() && ctx.RAR_dependencies[op.tempId()]) + if (op.isTemp() && op.isFirstKill() && ctx.RAR_dependencies[op.tempId()]) register_pressure_unknown = true; } if (register_pressure_unknown) { for (const Definition& def : candidate->definitions) { if (def.isTemp()) - ctx.RAR_dependencies[def.tempId()] = true; + ctx.depends_on[def.tempId()] = true; } for (const Operand& op : candidate->operands) { if (op.isTemp()) @@ -657,9 +672,13 @@ void schedule_position_export(sched_ctx& ctx, Block* block, /* create the initial set of values which current depends on */ std::fill(ctx.depends_on.begin(), ctx.depends_on.end(), false); - for (unsigned i = 0; i < current->operands.size(); i++) { - if (current->operands[i].isTemp()) - ctx.depends_on[current->operands[i].tempId()] = true; + std::fill(ctx.RAR_dependencies.begin(), ctx.RAR_dependencies.end(), false); + for (const Operand& op : current->operands) { + if (op.isTemp()) { + ctx.depends_on[op.tempId()] = true; + if (op.isFirstKill()) + ctx.RAR_dependencies[op.tempId()] = true; + } } /* maintain how many registers remain free when moving instructions */ @@ -705,30 +724,36 @@ void schedule_position_export(sched_ctx& ctx, Block* block, moving_interaction |= get_barrier_interaction(candidate.get()); moving_spill |= is_spill_reload(candidate); if (!can_move_down) { - for (unsigned i = 0; i < candidate->operands.size(); i++) { - if (candidate->operands[i].isTemp()) - ctx.depends_on[candidate->operands[i].tempId()] = true; + for (const Operand& op : candidate->operands) { + if (op.isTemp()) { + ctx.depends_on[op.tempId()] = true; + if (op.isFirstKill()) + ctx.RAR_dependencies[op.tempId()] = true; + } } continue; } bool register_pressure_unknown = false; /* check if one of candidate's operands is killed by depending instruction */ - for (unsigned i = 0; i < candidate->operands.size(); i++) { - if (candidate->operands[i].isTemp() && ctx.depends_on[candidate->operands[i].tempId()]) { + for (const Operand& op : candidate->operands) { + if (op.isTemp() && ctx.RAR_dependencies[op.tempId()]) { // FIXME: account for difference in register pressure register_pressure_unknown = true; } } if (register_pressure_unknown) { - for (unsigned i = 0; i < candidate->operands.size(); i++) { - if (candidate->operands[i].isTemp()) - ctx.depends_on[candidate->operands[i].tempId()] = true; + for (const Operand& op : candidate->operands) { + if (op.isTemp()) { + ctx.depends_on[op.tempId()] = true; + if (op.isFirstKill()) + ctx.RAR_dependencies[op.tempId()] = true; + } } continue; } - /* check if register pressure is low enough: the diff is negative if register pressure is decreased */ + /* check if register pressure is low enough: the diff is negative if register pressure is increased */ const RegisterDemand candidate_diff = getLiveChanges(candidate); const RegisterDemand temp = getTempRegisters(candidate);; if (RegisterDemand(register_pressure - candidate_diff).exceeds(ctx.max_registers)) -- 2.30.2