agx: Use pseudo ops for mov/not/and/xor/or
Rather than using builder magic (implicitly lowered on emit), add actual pseudo operations (explicitly lowered before encoding). In theory this is slower, I doubt it matters. This makes the instruction aliases first-class for IR prining and machine inspection, which will make optimization passes easier to write. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16268>
This commit is contained in:
@@ -121,30 +121,6 @@ enum agx_bitop_table {
|
||||
AGX_BITOP_OR = 0xE
|
||||
};
|
||||
|
||||
#define UNOP_BITOP(name, table) \
|
||||
static inline agx_instr * \
|
||||
agx_## name ##_to(agx_builder *b, agx_index dst0, agx_index src0) \
|
||||
{ \
|
||||
return agx_bitop_to(b, dst0, src0, agx_zero(), AGX_BITOP_ ## table); \
|
||||
}
|
||||
|
||||
#define BINOP_BITOP(name, table) \
|
||||
static inline agx_instr * \
|
||||
agx_## name ##_to(agx_builder *b, agx_index dst0, agx_index src0, agx_index src1) \
|
||||
{ \
|
||||
return agx_bitop_to(b, dst0, src0, src1, AGX_BITOP_ ## table); \
|
||||
}
|
||||
|
||||
UNOP_BITOP(mov, MOV)
|
||||
UNOP_BITOP(not, NOT)
|
||||
|
||||
BINOP_BITOP(and, AND)
|
||||
BINOP_BITOP(xor, XOR)
|
||||
BINOP_BITOP(or, OR)
|
||||
|
||||
#undef UNOP_BITOP
|
||||
#undef BINOP_BITOP
|
||||
|
||||
static inline agx_instr *
|
||||
agx_fmov_to(agx_builder *b, agx_index dst0, agx_index src0)
|
||||
{
|
||||
@@ -171,14 +147,6 @@ agx_ushr(agx_builder *b, agx_index s0, agx_index s1)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline agx_index
|
||||
agx_mov(agx_builder *b, enum agx_size size, agx_index s0)
|
||||
{
|
||||
agx_index tmp = agx_temp(b->shader, size);
|
||||
agx_mov_to(b, tmp, s0);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#endif
|
||||
"""
|
||||
|
||||
|
@@ -846,12 +846,16 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr)
|
||||
|
||||
layer = agx_convert(b, agx_immediate(AGX_CONVERT_F_TO_U32), layer,
|
||||
AGX_ROUND_RTZ);
|
||||
layer = agx_mov(b, AGX_SIZE_16, layer);
|
||||
|
||||
layer = agx_icmpsel(b, layer, d1, layer, d1, AGX_ICOND_ULT);
|
||||
layer = agx_mov(b, AGX_SIZE_32, layer);
|
||||
agx_index layer16 = agx_temp(b->shader, AGX_SIZE_16);
|
||||
agx_mov_to(b, layer16, layer);
|
||||
|
||||
channels[nr - 1] = layer;
|
||||
layer = agx_icmpsel(b, layer16, d1, layer16, d1, AGX_ICOND_ULT);
|
||||
|
||||
agx_index layer32 = agx_temp(b->shader, AGX_SIZE_32);
|
||||
agx_mov_to(b, layer32, layer);
|
||||
|
||||
channels[nr - 1] = layer32;
|
||||
coords = agx_p_combine(b, channels[0], channels[1], channels[2], channels[3]);
|
||||
} else {
|
||||
coords = index;
|
||||
@@ -1641,6 +1645,8 @@ agx_compile_shader_nir(nir_shader *nir,
|
||||
if (agx_debug & AGX_DBG_SHADERS && !skip_internal)
|
||||
agx_print_shader(ctx, stdout);
|
||||
|
||||
agx_lower_pseudo(ctx);
|
||||
|
||||
agx_pack_binary(ctx, binary);
|
||||
|
||||
if ((agx_debug & AGX_DBG_SHADERDB) && !skip_internal)
|
||||
|
@@ -661,6 +661,7 @@ void agx_print_instr(agx_instr *I, FILE *fp);
|
||||
void agx_print_block(agx_block *block, FILE *fp);
|
||||
void agx_print_shader(agx_context *ctx, FILE *fp);
|
||||
void agx_optimizer(agx_context *ctx);
|
||||
void agx_lower_pseudo(agx_context *ctx);
|
||||
void agx_dce(agx_context *ctx);
|
||||
void agx_ra(agx_context *ctx);
|
||||
void agx_pack_binary(agx_context *ctx, struct util_dynarray *emission);
|
||||
|
61
src/asahi/compiler/agx_lower_pseudo.c
Normal file
61
src/asahi/compiler/agx_lower_pseudo.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Alyssa Rosenzweig <alyssa@rosenzweig.io>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "agx_compiler.h"
|
||||
#include "agx_builder.h"
|
||||
|
||||
/* Lower pseudo instructions created during optimization. */
|
||||
|
||||
static void
|
||||
agx_lower_to_unary_bitop(agx_instr *I, enum agx_bitop_table table)
|
||||
{
|
||||
I->op = AGX_OPCODE_BITOP;
|
||||
I->src[1] = agx_zero();
|
||||
I->truth_table = table;
|
||||
}
|
||||
|
||||
static void
|
||||
agx_lower_to_binary_bitop(agx_instr *I, enum agx_bitop_table table)
|
||||
{
|
||||
I->op = AGX_OPCODE_BITOP;
|
||||
I->truth_table = table;
|
||||
}
|
||||
|
||||
void
|
||||
agx_lower_pseudo(agx_context *ctx)
|
||||
{
|
||||
agx_foreach_instr_global(ctx, I) {
|
||||
switch (I->op) {
|
||||
|
||||
/* Various instructions are implemented as bitwise truth tables */
|
||||
case AGX_OPCODE_MOV: agx_lower_to_unary_bitop(I, AGX_BITOP_MOV); break;
|
||||
case AGX_OPCODE_NOT: agx_lower_to_unary_bitop(I, AGX_BITOP_NOT); break;
|
||||
case AGX_OPCODE_AND: agx_lower_to_binary_bitop(I, AGX_BITOP_AND); break;
|
||||
case AGX_OPCODE_XOR: agx_lower_to_binary_bitop(I, AGX_BITOP_XOR); break;
|
||||
case AGX_OPCODE_OR: agx_lower_to_binary_bitop(I, AGX_BITOP_OR); break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -245,5 +245,12 @@ op("stop", (0x88, 0xFFFF, 2, _), dests = 0, can_eliminate = False)
|
||||
op("trap", (0x08, 0xFFFF, 2, _), dests = 0, can_eliminate = False)
|
||||
op("writeout", (0x48, 0xFF, 4, _), dests = 0, imms = [WRITEOUT], can_eliminate = False)
|
||||
|
||||
# Convenient aliases.
|
||||
op("mov", _, srcs = 1)
|
||||
op("not", _, srcs = 1)
|
||||
op("xor", _, srcs = 2)
|
||||
op("and", _, srcs = 2)
|
||||
op("or", _, srcs = 2)
|
||||
|
||||
op("p_combine", _, srcs = 4)
|
||||
op("p_extract", _, srcs = 1, imms = [COMPONENT])
|
||||
|
@@ -23,6 +23,7 @@ libasahi_agx_files = files(
|
||||
'agx_compile.c',
|
||||
'agx_dce.c',
|
||||
'agx_liveness.c',
|
||||
'agx_lower_pseudo.c',
|
||||
'agx_pack.c',
|
||||
'agx_print.c',
|
||||
'agx_optimizer.c',
|
||||
@@ -84,6 +85,7 @@ if with_tests
|
||||
'agx_tests',
|
||||
files(
|
||||
'test/test-optimizer.cpp',
|
||||
'test/test-lower-pseudo.cpp',
|
||||
),
|
||||
c_args : [c_msvc_compat_args, no_override_init_args],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
|
61
src/asahi/compiler/test/test-lower-pseudo.cpp
Normal file
61
src/asahi/compiler/test/test-lower-pseudo.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "agx_test.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#define CASE(instr, expected) INSTRUCTION_CASE(instr, expected, agx_lower_pseudo)
|
||||
#define NEGCASE(instr) CASE(instr, instr)
|
||||
|
||||
class LowerPseudo : public testing::Test {
|
||||
protected:
|
||||
LowerPseudo() {
|
||||
mem_ctx = ralloc_context(NULL);
|
||||
|
||||
wx = agx_register(0, AGX_SIZE_32);
|
||||
wy = agx_register(2, AGX_SIZE_32);
|
||||
wz = agx_register(4, AGX_SIZE_32);
|
||||
}
|
||||
|
||||
~LowerPseudo() {
|
||||
ralloc_free(mem_ctx);
|
||||
}
|
||||
|
||||
void *mem_ctx;
|
||||
agx_index wx, wy, wz;
|
||||
};
|
||||
|
||||
TEST_F(LowerPseudo, Move) {
|
||||
CASE(agx_mov_to(b, wx, wy), agx_bitop_to(b, wx, wy, agx_zero(), 0xA));
|
||||
}
|
||||
|
||||
TEST_F(LowerPseudo, Not) {
|
||||
CASE(agx_not_to(b, wx, wy), agx_bitop_to(b, wx, wy, agx_zero(), 0x5));
|
||||
}
|
||||
|
||||
TEST_F(LowerPseudo, BinaryBitwise) {
|
||||
CASE(agx_and_to(b, wx, wy, wz), agx_bitop_to(b, wx, wy, wz, 0x8));
|
||||
CASE(agx_xor_to(b, wx, wy, wz), agx_bitop_to(b, wx, wy, wz, 0x6));
|
||||
CASE(agx_or_to(b, wx, wy, wz), agx_bitop_to(b, wx, wy, wz, 0xE));
|
||||
}
|
Reference in New Issue
Block a user