70 lines
1.5 KiB
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;
|
|
}
|