mesa/src/freedreno/ir3/ir3_legalize_relative.c

70 lines
1.5 KiB
C

/*
* Copyright 2022 Google LLC
* SPDX-License-Identifier: MIT
*/
#include "ir3.h"
/*
* Mark (ul) on the last user of a0 before a0 is loaded again. emit_block
* makes sure a0 is loaded first if there is any user in the block. This
* allows us to process each block independently.
*
* Note that this must be called before passes that break the assumption, such
* as ir3_lower_subgroups.
*/
static bool
is_reg_relative(const struct ir3_instruction *instr)
{
foreach_dst (reg, instr) {
if (reg->flags & IR3_REG_RELATIV)
return true;
}
foreach_src (reg, instr) {
if (reg->flags & IR3_REG_RELATIV)
return true;
}
return false;
}
static bool
is_dst_a0(const struct ir3_instruction *instr)
{
foreach_dst (reg, instr) {
if (reg->num == regid(REG_A0, 0))
return true;
}
return false;
}
bool
ir3_legalize_relative(struct ir3 *ir)
{
foreach_block (block, &ir->block_list) {
struct ir3_instruction *last_user = NULL;
foreach_instr (instr, &block->instr_list) {
if (is_reg_relative(instr))
last_user = instr;
/* Is it valid to have address reg loaded from a relative src (ie.
* mova a0, c<a0.x+4>)? This marks the load (ul), which may or may
* not be valid.
*/
if (last_user && is_dst_a0(instr)) {
last_user->flags |= IR3_INSTR_UL;
last_user = NULL;
}
}
if (last_user)
last_user->flags |= IR3_INSTR_UL;
}
return true;
}