Commit 1155446c authored by Alyssa Rosenzweig's avatar Alyssa Rosenzweig 💜

panfrost/midgard: Split up midgard_compile.c (RA)

This commit moves the register allocator out of midgard_compile.c and
into its own midgard_ra.c file. In doing so, a number of dependencies
are identified and moved into their own files in turn. midgard_compile.c
is still fairly monolithic, but this should help.

Code churn, but no functional changes should be introduced by this
commit.
Signed-off-by: Alyssa Rosenzweig's avatarAlyssa Rosenzweig <alyssa@rosenzweig.io>
parent 9cd8cd26
Pipeline #37718 passed with stages
in 9 minutes and 44 seconds
......@@ -27,6 +27,11 @@ files_panfrost = files(
'pan_resource.h',
'midgard/midgard_compile.c',
'midgard/midgard_print.c',
'midgard/midgard_ra.c',
'midgard/midgard_liveness.c',
'midgard/midgard_ops.c',
'midgard/nir_lower_blend.c',
'midgard/cppwrap.cpp',
'midgard/disassemble.c',
......@@ -97,6 +102,10 @@ driver_panfrost = declare_dependency(
files_midgard = files(
'midgard/midgard_compile.c',
'midgard/midgard_print.c',
'midgard/midgard_ra.c',
'midgard/midgard_liveness.c',
'midgard/midgard_ops.c',
'midgard/cppwrap.cpp',
'midgard/disassemble.c',
'midgard/cmdline.c',
......@@ -153,6 +162,7 @@ files_pandecode = files(
'pan_pretty_print.c',
'midgard/disassemble.c',
'midgard/midgard_ops.c',
'bifrost/disassemble.c',
)
......
This diff is collapsed.
......@@ -31,6 +31,7 @@
#include <string.h>
#include "midgard.h"
#include "midgard-parse.h"
#include "midgard_ops.h"
#include "disassemble.h"
#include "helpers.h"
#include "util/half_float.h"
......
/* Author(s):
* Alyssa Rosenzweig
*
* Copyright (c) 2018 Alyssa Rosenzweig (alyssa@rosenzweig.io)
/* Copyright (c) 2018-2019 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
......@@ -22,6 +19,9 @@
* THE SOFTWARE.
*/
#ifndef __MDG_HELPERS_H
#define __MDG_HELPERS_H
#define OP_IS_STORE_VARY(op) (\
op == midgard_op_st_vary_16 || \
op == midgard_op_st_vary_32 \
......@@ -150,140 +150,12 @@
#define UNITS_VECTOR (UNIT_VMUL | UNIT_VADD)
#define UNITS_ANY_VECTOR (UNITS_VECTOR | UNIT_VLUT)
/* Table of mapping opcodes to accompanying properties relevant to
* scheduling/emission/etc */
static struct {
struct mir_op_props {
const char *name;
unsigned props;
} alu_opcode_props[256] = {
[midgard_alu_op_fadd] = {"fadd", UNITS_ADD | OP_COMMUTES},
[midgard_alu_op_fmul] = {"fmul", UNITS_MUL | UNIT_VLUT | OP_COMMUTES},
[midgard_alu_op_fmin] = {"fmin", UNITS_MUL | UNITS_ADD | OP_COMMUTES},
[midgard_alu_op_fmax] = {"fmax", UNITS_MUL | UNITS_ADD | OP_COMMUTES},
[midgard_alu_op_imin] = {"imin", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_imax] = {"imax", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_umin] = {"umin", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_umax] = {"umax", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_fmov] = {"fmov", UNITS_ALL | QUIRK_FLIPPED_R24},
[midgard_alu_op_fround] = {"fround", UNITS_ADD},
[midgard_alu_op_froundeven] = {"froundeven", UNITS_ADD},
[midgard_alu_op_ftrunc] = {"ftrunc", UNITS_ADD},
[midgard_alu_op_ffloor] = {"ffloor", UNITS_ADD},
[midgard_alu_op_fceil] = {"fceil", UNITS_ADD},
[midgard_alu_op_ffma] = {"ffma", UNIT_VLUT},
/* Though they output a scalar, they need to run on a vector unit
* since they process vectors */
[midgard_alu_op_fdot3] = {"fdot3", UNIT_VMUL | OP_CHANNEL_COUNT(3) | OP_COMMUTES},
[midgard_alu_op_fdot3r] = {"fdot3r", UNIT_VMUL | OP_CHANNEL_COUNT(3) | OP_COMMUTES},
[midgard_alu_op_fdot4] = {"fdot4", UNIT_VMUL | OP_CHANNEL_COUNT(4) | OP_COMMUTES},
/* Incredibly, iadd can run on vmul, etc */
[midgard_alu_op_iadd] = {"iadd", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_iabs] = {"iabs", UNITS_ADD},
[midgard_alu_op_isub] = {"isub", UNITS_MOST},
[midgard_alu_op_imul] = {"imul", UNITS_MUL | OP_COMMUTES},
[midgard_alu_op_imov] = {"imov", UNITS_MOST | QUIRK_FLIPPED_R24},
/* For vector comparisons, use ball etc */
[midgard_alu_op_feq] = {"feq", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_fne] = {"fne", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_fle] = {"fle", UNITS_MOST},
[midgard_alu_op_flt] = {"flt", UNITS_MOST},
[midgard_alu_op_ieq] = {"ieq", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_ine] = {"ine", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_ilt] = {"ilt", UNITS_MOST},
[midgard_alu_op_ile] = {"ile", UNITS_MOST},
[midgard_alu_op_ult] = {"ult", UNITS_MOST},
[midgard_alu_op_ule] = {"ule", UNITS_MOST},
[midgard_alu_op_icsel] = {"icsel", UNITS_ADD},
[midgard_alu_op_icsel_v] = {"icsel_v", UNITS_ADD},
[midgard_alu_op_fcsel_v] = {"fcsel_v", UNITS_ADD},
[midgard_alu_op_fcsel] = {"fcsel", UNITS_ADD | UNIT_SMUL},
[midgard_alu_op_frcp] = {"frcp", UNIT_VLUT},
[midgard_alu_op_frsqrt] = {"frsqrt", UNIT_VLUT},
[midgard_alu_op_fsqrt] = {"fsqrt", UNIT_VLUT},
[midgard_alu_op_fpow_pt1] = {"fpow_pt1", UNIT_VLUT},
[midgard_alu_op_fexp2] = {"fexp2", UNIT_VLUT},
[midgard_alu_op_flog2] = {"flog2", UNIT_VLUT},
[midgard_alu_op_f2i] = {"f2i", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_f2u] = {"f2u", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_f2u8] = {"f2u8", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_i2f] = {"i2f", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_u2f] = {"u2f", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_fsin] = {"fsin", UNIT_VLUT},
[midgard_alu_op_fcos] = {"fcos", UNIT_VLUT},
/* XXX: Test case where it's right on smul but not sadd */
[midgard_alu_op_iand] = {"iand", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_iandnot] = {"iandnot", UNITS_MOST},
[midgard_alu_op_ior] = {"ior", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_iornot] = {"iornot", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_inor] = {"inor", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_ixor] = {"ixor", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_inxor] = {"inxor", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_iclz] = {"iclz", UNITS_ADD},
[midgard_alu_op_ibitcount8] = {"ibitcount8", UNITS_ADD},
[midgard_alu_op_inand] = {"inand", UNITS_MOST},
[midgard_alu_op_ishl] = {"ishl", UNITS_ADD},
[midgard_alu_op_iasr] = {"iasr", UNITS_ADD},
[midgard_alu_op_ilsr] = {"ilsr", UNITS_ADD},
[midgard_alu_op_fball_eq] = {"fball_eq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_fbany_neq] = {"fbany_neq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_iball_eq] = {"iball_eq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_iball_neq] = {"iball_neq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_ibany_eq] = {"ibany_eq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_ibany_neq] = {"ibany_neq", UNITS_VECTOR | OP_COMMUTES},
/* These instructions are not yet emitted by the compiler, so
* don't speculate about units yet */
[midgard_alu_op_ishladd] = {"ishladd", 0},
[midgard_alu_op_uball_lt] = {"uball_lt", 0},
[midgard_alu_op_uball_lte] = {"uball_lte", 0},
[midgard_alu_op_iball_lt] = {"iball_lt", 0},
[midgard_alu_op_iball_lte] = {"iball_lte", 0},
[midgard_alu_op_ubany_lt] = {"ubany_lt", 0},
[midgard_alu_op_ubany_lte] = {"ubany_lte", 0},
[midgard_alu_op_ibany_lt] = {"ibany_lt", 0},
[midgard_alu_op_ibany_lte] = {"ibany_lte", 0},
[midgard_alu_op_freduce] = {"freduce", 0},
[midgard_alu_op_bball_eq] = {"bball_eq", 0 | OP_COMMUTES},
[midgard_alu_op_bbany_neq] = {"bball_eq", 0 | OP_COMMUTES},
[midgard_alu_op_fatan2_pt1] = {"fatan2_pt1", 0},
[midgard_alu_op_fatan_pt2] = {"fatan_pt2", 0},
};
/* Is this opcode that of an integer (regardless of signedness)? Instruction
* names authoritatively determine types */
static inline bool
midgard_is_integer_op(int op)
{
const char *name = alu_opcode_props[op].name;
if (!name)
return false;
return (name[0] == 'i') || (name[0] == 'u');
}
/* Does this opcode *write* an integer? Same as is_integer_op, unless it's a
* conversion between int<->float in which case we do the opposite */
static inline bool
midgard_is_integer_out_op(int op)
{
bool is_int = midgard_is_integer_op(op);
bool is_conversion = alu_opcode_props[op].props & OP_TYPE_CONVERT;
/* This file is common, so don't define the tables themselves. #include
* midgard_op.h if you need that, or edit midgard_ops.c directly */
return is_int ^ is_conversion;
}
#endif
......@@ -536,54 +536,4 @@ __attribute__((__packed__))
}
midgard_texture_word;
static char *load_store_opcode_names[256] = {
[midgard_op_st_cubemap_coords] = "st_cubemap_coords",
[midgard_op_ld_global_id] = "ld_global_id",
[midgard_op_atomic_add] = "atomic_add",
[midgard_op_atomic_and] = "atomic_and",
[midgard_op_atomic_or] = "atomic_or",
[midgard_op_atomic_xor] = "atomic_xor",
[midgard_op_atomic_imin] = "atomic_imin",
[midgard_op_atomic_umin] = "atomic_umin",
[midgard_op_atomic_imax] = "atomic_imax",
[midgard_op_atomic_umax] = "atomic_umax",
[midgard_op_atomic_xchg] = "atomic_xchg",
[midgard_op_ld_char] = "ld_char",
[midgard_op_ld_char2] = "ld_char2",
[midgard_op_ld_short] = "ld_short",
[midgard_op_ld_char4] = "ld_char4",
[midgard_op_ld_short4] = "ld_short4",
[midgard_op_ld_int4] = "ld_int4",
[midgard_op_ld_attr_32] = "ld_attr_32",
[midgard_op_ld_attr_16] = "ld_attr_16",
[midgard_op_ld_attr_32i] = "ld_attr_32i",
[midgard_op_ld_vary_32] = "ld_vary_32",
[midgard_op_ld_vary_16] = "ld_vary_16",
[midgard_op_ld_vary_32i] = "ld_vary_32i",
[midgard_op_ld_color_buffer_16] = "ld_color_buffer_16",
[midgard_op_ld_uniform_16] = "ld_uniform_16",
[midgard_op_ld_uniform_32] = "ld_uniform_32",
[midgard_op_ld_color_buffer_8] = "ld_color_buffer_8",
[midgard_op_st_char] = "st_char",
[midgard_op_st_char2] = "st_char2",
[midgard_op_st_char4] = "st_char4",
[midgard_op_st_short4] = "st_short4",
[midgard_op_st_int4] = "st_int4",
[midgard_op_st_vary_32] = "st_vary_32",
[midgard_op_st_vary_16] = "st_vary_16",
[midgard_op_st_vary_32i] = "st_vary_32i",
[midgard_op_st_image_f] = "st_image_f",
[midgard_op_st_image_ui] = "st_image_ui",
[midgard_op_st_image_i] = "st_image_i",
};
#endif
/*
* Copyright (C) 2018-2019 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.
*/
/* mir_is_live_after performs liveness analysis on the MIR, used primarily
* as part of register allocation. TODO: Algorithmic improvements for
* compiler performance (this is the worst algorithm possible -- see
* backlog with Connor on IRC) */
#include "compiler.h"
static bool
midgard_is_live_in_instr(midgard_instruction *ins, int src)
{
if (ins->ssa_args.src0 == src) return true;
if (ins->ssa_args.src1 == src) return true;
return false;
}
/* Determine if a variable is live in the successors of a block */
static bool
is_live_after_successors(compiler_context *ctx, midgard_block *bl, int src)
{
for (unsigned i = 0; i < bl->nr_successors; ++i) {
midgard_block *succ = bl->successors[i];
/* If we already visited, the value we're seeking
* isn't down this path (or we would have short
* circuited */
if (succ->visited) continue;
/* Otherwise (it's visited *now*), check the block */
succ->visited = true;
mir_foreach_instr_in_block(succ, ins) {
if (midgard_is_live_in_instr(ins, src))
return true;
}
/* ...and also, check *its* successors */
if (is_live_after_successors(ctx, succ, src))
return true;
}
/* Welp. We're really not live. */
return false;
}
bool
mir_is_live_after(compiler_context *ctx, midgard_block *block, midgard_instruction *start, int src)
{
/* Check the rest of the block for liveness */
mir_foreach_instr_in_block_from(block, ins, mir_next_op(start)) {
if (midgard_is_live_in_instr(ins, src))
return true;
}
/* Check the rest of the blocks for liveness recursively */
bool succ = is_live_after_successors(ctx, block, src);
mir_foreach_block(ctx, block) {
block->visited = false;
}
return succ;
}
/* Copyright (c) 2018-2019 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 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 "midgard.h"
/* Include the definitions of the macros and such */
#define MIDGARD_OPS_TABLE
#include "helpers.h"
#undef MIDGARD_OPS_TABLE
/* Table of mapping opcodes to accompanying properties. This is used for both
* the disassembler and the compiler. It is placed in a .c file like this to
* avoid duplications in the binary */
struct mir_op_props alu_opcode_props[256] = {
[midgard_alu_op_fadd] = {"fadd", UNITS_ADD | OP_COMMUTES},
[midgard_alu_op_fmul] = {"fmul", UNITS_MUL | UNIT_VLUT | OP_COMMUTES},
[midgard_alu_op_fmin] = {"fmin", UNITS_MUL | UNITS_ADD | OP_COMMUTES},
[midgard_alu_op_fmax] = {"fmax", UNITS_MUL | UNITS_ADD | OP_COMMUTES},
[midgard_alu_op_imin] = {"imin", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_imax] = {"imax", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_umin] = {"umin", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_umax] = {"umax", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_fmov] = {"fmov", UNITS_ALL | QUIRK_FLIPPED_R24},
[midgard_alu_op_fround] = {"fround", UNITS_ADD},
[midgard_alu_op_froundeven] = {"froundeven", UNITS_ADD},
[midgard_alu_op_ftrunc] = {"ftrunc", UNITS_ADD},
[midgard_alu_op_ffloor] = {"ffloor", UNITS_ADD},
[midgard_alu_op_fceil] = {"fceil", UNITS_ADD},
[midgard_alu_op_ffma] = {"ffma", UNIT_VLUT},
/* Though they output a scalar, they need to run on a vector unit
* since they process vectors */
[midgard_alu_op_fdot3] = {"fdot3", UNIT_VMUL | OP_CHANNEL_COUNT(3) | OP_COMMUTES},
[midgard_alu_op_fdot3r] = {"fdot3r", UNIT_VMUL | OP_CHANNEL_COUNT(3) | OP_COMMUTES},
[midgard_alu_op_fdot4] = {"fdot4", UNIT_VMUL | OP_CHANNEL_COUNT(4) | OP_COMMUTES},
/* Incredibly, iadd can run on vmul, etc */
[midgard_alu_op_iadd] = {"iadd", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_iabs] = {"iabs", UNITS_ADD},
[midgard_alu_op_isub] = {"isub", UNITS_MOST},
[midgard_alu_op_imul] = {"imul", UNITS_MUL | OP_COMMUTES},
[midgard_alu_op_imov] = {"imov", UNITS_MOST | QUIRK_FLIPPED_R24},
/* For vector comparisons, use ball etc */
[midgard_alu_op_feq] = {"feq", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_fne] = {"fne", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_fle] = {"fle", UNITS_MOST},
[midgard_alu_op_flt] = {"flt", UNITS_MOST},
[midgard_alu_op_ieq] = {"ieq", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_ine] = {"ine", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_ilt] = {"ilt", UNITS_MOST},
[midgard_alu_op_ile] = {"ile", UNITS_MOST},
[midgard_alu_op_ult] = {"ult", UNITS_MOST},
[midgard_alu_op_ule] = {"ule", UNITS_MOST},
[midgard_alu_op_icsel] = {"icsel", UNITS_ADD},
[midgard_alu_op_icsel_v] = {"icsel_v", UNITS_ADD},
[midgard_alu_op_fcsel_v] = {"fcsel_v", UNITS_ADD},
[midgard_alu_op_fcsel] = {"fcsel", UNITS_ADD | UNIT_SMUL},
[midgard_alu_op_frcp] = {"frcp", UNIT_VLUT},
[midgard_alu_op_frsqrt] = {"frsqrt", UNIT_VLUT},
[midgard_alu_op_fsqrt] = {"fsqrt", UNIT_VLUT},
[midgard_alu_op_fpow_pt1] = {"fpow_pt1", UNIT_VLUT},
[midgard_alu_op_fexp2] = {"fexp2", UNIT_VLUT},
[midgard_alu_op_flog2] = {"flog2", UNIT_VLUT},
[midgard_alu_op_f2i] = {"f2i", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_f2u] = {"f2u", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_f2u8] = {"f2u8", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_i2f] = {"i2f", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_u2f] = {"u2f", UNITS_ADD | OP_TYPE_CONVERT},
[midgard_alu_op_fsin] = {"fsin", UNIT_VLUT},
[midgard_alu_op_fcos] = {"fcos", UNIT_VLUT},
/* XXX: Test case where it's right on smul but not sadd */
[midgard_alu_op_iand] = {"iand", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_iandnot] = {"iandnot", UNITS_MOST},
[midgard_alu_op_ior] = {"ior", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_iornot] = {"iornot", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_inor] = {"inor", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_ixor] = {"ixor", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_inxor] = {"inxor", UNITS_MOST | OP_COMMUTES},
[midgard_alu_op_iclz] = {"iclz", UNITS_ADD},
[midgard_alu_op_ibitcount8] = {"ibitcount8", UNITS_ADD},
[midgard_alu_op_inand] = {"inand", UNITS_MOST},
[midgard_alu_op_ishl] = {"ishl", UNITS_ADD},
[midgard_alu_op_iasr] = {"iasr", UNITS_ADD},
[midgard_alu_op_ilsr] = {"ilsr", UNITS_ADD},
[midgard_alu_op_fball_eq] = {"fball_eq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_fbany_neq] = {"fbany_neq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_iball_eq] = {"iball_eq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_iball_neq] = {"iball_neq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_ibany_eq] = {"ibany_eq", UNITS_VECTOR | OP_COMMUTES},
[midgard_alu_op_ibany_neq] = {"ibany_neq", UNITS_VECTOR | OP_COMMUTES},
/* These instructions are not yet emitted by the compiler, so
* don't speculate about units yet */
[midgard_alu_op_ishladd] = {"ishladd", 0},
[midgard_alu_op_uball_lt] = {"uball_lt", 0},
[midgard_alu_op_uball_lte] = {"uball_lte", 0},
[midgard_alu_op_iball_lt] = {"iball_lt", 0},
[midgard_alu_op_iball_lte] = {"iball_lte", 0},
[midgard_alu_op_ubany_lt] = {"ubany_lt", 0},
[midgard_alu_op_ubany_lte] = {"ubany_lte", 0},
[midgard_alu_op_ibany_lt] = {"ibany_lt", 0},
[midgard_alu_op_ibany_lte] = {"ibany_lte", 0},
[midgard_alu_op_freduce] = {"freduce", 0},
[midgard_alu_op_bball_eq] = {"bball_eq", 0 | OP_COMMUTES},
[midgard_alu_op_bbany_neq] = {"bball_eq", 0 | OP_COMMUTES},
[midgard_alu_op_fatan2_pt1] = {"fatan2_pt1", 0},
[midgard_alu_op_fatan_pt2] = {"fatan_pt2", 0},
};
const char *load_store_opcode_names[256] = {
[midgard_op_st_cubemap_coords] = "st_cubemap_coords",
[midgard_op_ld_global_id] = "ld_global_id",
[midgard_op_atomic_add] = "atomic_add",
[midgard_op_atomic_and] = "atomic_and",
[midgard_op_atomic_or] = "atomic_or",
[midgard_op_atomic_xor] = "atomic_xor",
[midgard_op_atomic_imin] = "atomic_imin",
[midgard_op_atomic_umin] = "atomic_umin",
[midgard_op_atomic_imax] = "atomic_imax",
[midgard_op_atomic_umax] = "atomic_umax",
[midgard_op_atomic_xchg] = "atomic_xchg",
[midgard_op_ld_char] = "ld_char",
[midgard_op_ld_char2] = "ld_char2",
[midgard_op_ld_short] = "ld_short",
[midgard_op_ld_char4] = "ld_char4",
[midgard_op_ld_short4] = "ld_short4",
[midgard_op_ld_int4] = "ld_int4",
[midgard_op_ld_attr_32] = "ld_attr_32",
[midgard_op_ld_attr_16] = "ld_attr_16",
[midgard_op_ld_attr_32i] = "ld_attr_32i",
[midgard_op_ld_vary_32] = "ld_vary_32",
[midgard_op_ld_vary_16] = "ld_vary_16",
[midgard_op_ld_vary_32i] = "ld_vary_32i",
[midgard_op_ld_color_buffer_16] = "ld_color_buffer_16",
[midgard_op_ld_uniform_16] = "ld_uniform_16",
[midgard_op_ld_uniform_32] = "ld_uniform_32",
[midgard_op_ld_color_buffer_8] = "ld_color_buffer_8",
[midgard_op_st_char] = "st_char",
[midgard_op_st_char2] = "st_char2",
[midgard_op_st_char4] = "st_char4",
[midgard_op_st_short4] = "st_short4",
[midgard_op_st_int4] = "st_int4",
[midgard_op_st_vary_32] = "st_vary_32",
[midgard_op_st_vary_16] = "st_vary_16",
[midgard_op_st_vary_32i] = "st_vary_32i",
[midgard_op_st_image_f] = "st_image_f",
[midgard_op_st_image_ui] = "st_image_ui",
[midgard_op_st_image_i] = "st_image_i",
};
/* Copyright (c) 2018-2019 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 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 "helpers.h"
/* Forward declare */
extern struct mir_op_props alu_opcode_props[256];
extern const char *load_store_opcode_names[256];
/* Is this opcode that of an integer (regardless of signedness)? Instruction
* names authoritatively determine types */
static inline bool
midgard_is_integer_op(int op)
{
const char *name = alu_opcode_props[op].name;
if (!name)
return false;
return (name[0] == 'i') || (name[0] == 'u');
}
/* Does this opcode *write* an integer? Same as is_integer_op, unless it's a
* conversion between int<->float in which case we do the opposite */
static inline bool
midgard_is_integer_out_op(int op)
{
bool is_int = midgard_is_integer_op(op);
bool is_conversion = alu_opcode_props[op].props & OP_TYPE_CONVERT;
return is_int ^ is_conversion;
}
/*
* Copyright (C) 2018-2019 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 "compiler.h"
#include "helpers.h"
#include "midgard_ops.h"
/* Pretty printer for Midgard IR, for use debugging compiler-internal
* passes like register allocation. The output superficially resembles
* Midgard assembly, with the exception that unit information and such is
* (normally) omitted, and generic indices are usually used instead of
* registers */
static void
mir_print_source(int source)
{
if (source >= SSA_FIXED_MINIMUM) {
/* Specific register */
int reg = SSA_REG_FROM_FIXED(source);
/* TODO: Moving threshold */
if (reg > 16 && reg < 24)
printf("u%d", 23 - reg);
else
printf("r%d", reg);
} else {
printf("%d", source);
}
}
void
mir_print_instruction(midgard_instruction *ins)
{
printf("\t");
switch (ins->type) {
case TAG_ALU_4: {
midgard_alu_op op = ins->alu.op;
const char *name = alu_opcode_props[op].name;
if (ins->unit)
printf("%d.", ins->unit);
printf("%s", name ? name : "??");
break;
}
case TAG_LOAD_STORE_4: {
midgard_load_store_op op = ins->load_store.op;
const char *name = load_store_opcode_names[op];
assert(name);
printf("%s", name);
break;
}
case TAG_TEXTURE_4: {
printf("texture");
break;
}
default:
assert(0);
}
ssa_args *args = &ins->ssa_args;
printf(" %d, ", args->dest);
mir_print_source(args->src0);
printf(", ");
if (args->inline_constant)
printf("#%d", ins->inline_constant);
else
mir_print_source(args->src1);
if (ins->has_constants)
printf(" <%f, %f, %f, %f>", ins->constants[0], ins->constants[1], ins->constants[2], ins->constants[3]);
printf("\n");