mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-21 04:20:24 +01:00
pan/bi: Gut old compiler
We're making some pretty dramatic design pivots so this early on it'll be easier to start from scratch, I think. Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4061>
This commit is contained in:
parent
eb15525ab7
commit
5d3a4e3113
15 changed files with 54 additions and 2110 deletions
|
|
@ -1,16 +1,7 @@
|
|||
bifrost_FILES := \
|
||||
bifrost/bifrost_compile.c \
|
||||
bifrost/bifrost_compile.h \
|
||||
bifrost/bifrost.h \
|
||||
bifrost/bifrost_ops.h \
|
||||
bifrost/bifrost_opts.c \
|
||||
bifrost/bifrost_opts.h \
|
||||
bifrost/bifrost_print.c \
|
||||
bifrost/bifrost_print.h \
|
||||
bifrost/bifrost_sched.c \
|
||||
bifrost/bifrost_sched.h \
|
||||
bifrost/bifrost_compile.h \
|
||||
bifrost/cmdline.c \
|
||||
bifrost/compiler_defines.h \
|
||||
bifrost/disassemble.c \
|
||||
bifrost/disassemble.h
|
||||
|
||||
|
|
|
|||
|
|
@ -239,4 +239,23 @@ struct bifrost_regs {
|
|||
unsigned ctrl : 4;
|
||||
};
|
||||
|
||||
enum bifrost_branch_cond {
|
||||
BR_COND_LT = 0,
|
||||
BR_COND_LE = 1,
|
||||
BR_COND_GE = 2,
|
||||
BR_COND_GT = 3,
|
||||
// Equal vs. not-equal determined by src0/src1 comparison
|
||||
BR_COND_EQ = 4,
|
||||
// floating-point comparisons
|
||||
// Becomes UNE when you flip the arguments
|
||||
BR_COND_OEQ = 5,
|
||||
// TODO what happens when you flip the arguments?
|
||||
BR_COND_OGT = 6,
|
||||
BR_COND_OLT = 7,
|
||||
};
|
||||
|
||||
enum bifrost_branch_code {
|
||||
BR_ALWAYS = 63,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
* 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"),
|
||||
|
|
@ -21,49 +21,59 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __bifrost_compile_h__
|
||||
#define __bifrost_compile_h__
|
||||
#ifndef __BIFROST_PUBLIC_H_
|
||||
#define __BIFROST_PUBLIC_H_
|
||||
|
||||
#include "compiler/nir/nir.h"
|
||||
#include "util/u_dynarray.h"
|
||||
|
||||
struct bifrost_program {
|
||||
typedef struct {
|
||||
struct util_dynarray compiled;
|
||||
};
|
||||
} bifrost_program;
|
||||
|
||||
int
|
||||
bifrost_compile_shader_nir(nir_shader *nir, struct bifrost_program *program);
|
||||
bifrost_compile_shader_nir(nir_shader *nir, bifrost_program *program);
|
||||
|
||||
static const nir_shader_compiler_options bifrost_nir_options = {
|
||||
.fuse_ffma = true,
|
||||
.lower_flrp16 = true,
|
||||
.lower_ffma = true,
|
||||
.lower_sub = true,
|
||||
.lower_scmp = true,
|
||||
.lower_flrp32 = true,
|
||||
.lower_flrp64 = true,
|
||||
.lower_ffract = true,
|
||||
.lower_fmod = true,
|
||||
.lower_bitfield_extract = true,
|
||||
.lower_bitfield_extract_to_shifts = true,
|
||||
.lower_bitfield_insert = true,
|
||||
.lower_bitfield_insert_to_shifts = true,
|
||||
.lower_bitfield_reverse = true,
|
||||
.lower_fdiv = true,
|
||||
.lower_idiv = true,
|
||||
.lower_isign = true,
|
||||
.lower_fsign = true,
|
||||
.lower_ffract = true,
|
||||
.lower_fpow = true,
|
||||
.lower_find_lsb = true,
|
||||
.lower_fdph = true,
|
||||
|
||||
.lower_wpos_pntc = true,
|
||||
.lower_fsign = true,
|
||||
|
||||
.lower_extract_byte = true,
|
||||
.lower_extract_word = true,
|
||||
.lower_rotate = true,
|
||||
|
||||
.lower_pack_half_2x16 = true,
|
||||
.lower_pack_half_2x16_split = true,
|
||||
.lower_pack_unorm_2x16 = true,
|
||||
.lower_pack_snorm_2x16 = true,
|
||||
.lower_pack_unorm_4x8 = true,
|
||||
.lower_pack_snorm_4x8 = true,
|
||||
.lower_unpack_half_2x16 = true,
|
||||
.lower_unpack_half_2x16_split = true,
|
||||
.lower_unpack_unorm_2x16 = true,
|
||||
.lower_unpack_snorm_2x16 = true,
|
||||
.lower_unpack_unorm_4x8 = true,
|
||||
.lower_unpack_snorm_4x8 = true,
|
||||
.lower_extract_byte = true,
|
||||
.lower_extract_word = true,
|
||||
.lower_all_io_to_temps = true,
|
||||
.lower_all_io_to_elements = true,
|
||||
|
||||
.lower_doubles_options = nir_lower_dmod,
|
||||
|
||||
.lower_bitfield_extract_to_shifts = true,
|
||||
.vectorize_io = true,
|
||||
.use_interpolated_input_intrinsics = true
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __bifrost_ops_h__
|
||||
#define __bifrost_ops_h__
|
||||
|
||||
enum bifrost_ir_ops {
|
||||
op_fma_f32 = 0x0,
|
||||
op_fmul_f32,
|
||||
op_fadd_f32,
|
||||
op_frcp_fast_f32,
|
||||
op_max_f32,
|
||||
op_min_f32,
|
||||
op_add_i32,
|
||||
op_sub_i32,
|
||||
op_imad,
|
||||
op_mul_i32,
|
||||
op_or_i32,
|
||||
op_and_i32,
|
||||
op_lshift_i32,
|
||||
op_xor_i32,
|
||||
op_rshift_i32,
|
||||
op_arshift_i32,
|
||||
op_csel_i32,
|
||||
op_imin3_i32,
|
||||
op_umin3_i32,
|
||||
op_imax3_i32,
|
||||
op_umax3_i32,
|
||||
|
||||
op_branch,
|
||||
|
||||
// unary
|
||||
op_trunc,
|
||||
op_ceil,
|
||||
op_floor,
|
||||
op_round,
|
||||
op_roundeven,
|
||||
|
||||
op_mov,
|
||||
op_movi,
|
||||
|
||||
op_ld_ubo_v1,
|
||||
op_ld_ubo_v2,
|
||||
op_ld_ubo_v3,
|
||||
op_ld_ubo_v4,
|
||||
|
||||
op_ld_attr_v1,
|
||||
op_ld_attr_v2,
|
||||
op_ld_attr_v3,
|
||||
op_ld_attr_v4,
|
||||
|
||||
op_ld_var_addr,
|
||||
op_st_vary_v1,
|
||||
op_st_vary_v2,
|
||||
op_st_vary_v3,
|
||||
op_st_vary_v4,
|
||||
|
||||
op_store_v1,
|
||||
op_store_v2,
|
||||
op_store_v3,
|
||||
op_store_v4,
|
||||
|
||||
op_create_vector,
|
||||
op_extract_element,
|
||||
op_last,
|
||||
};
|
||||
|
||||
|
||||
enum branch_cond {
|
||||
BR_COND_LT = 0,
|
||||
BR_COND_LE = 1,
|
||||
BR_COND_GE = 2,
|
||||
BR_COND_GT = 3,
|
||||
// Equal vs. not-equal determined by src0/src1 comparison
|
||||
BR_COND_EQ = 4,
|
||||
// floating-point comparisons
|
||||
// Becomes UNE when you flip the arguments
|
||||
BR_COND_OEQ = 5,
|
||||
// TODO what happens when you flip the arguments?
|
||||
BR_COND_OGT = 6,
|
||||
BR_COND_OLT = 7,
|
||||
};
|
||||
|
||||
enum branch_code {
|
||||
BR_ALWAYS = 63,
|
||||
};
|
||||
|
||||
enum csel_cond {
|
||||
CSEL_NEQ_0 = 0,
|
||||
CSEL_FEQ,
|
||||
CSEL_FGTR,
|
||||
CSEL_FGE,
|
||||
CSEL_IEQ,
|
||||
CSEL_IGT,
|
||||
CSEL_IGE,
|
||||
CSEL_UGT,
|
||||
CSEL_UGE,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
*
|
||||
* 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 "bifrost_opts.h"
|
||||
#include "compiler_defines.h"
|
||||
|
||||
bool
|
||||
bifrost_opt_branch_fusion(compiler_context *ctx, bifrost_block *block)
|
||||
{
|
||||
bool progress = false;
|
||||
mir_foreach_instr_in_block_safe(block, instr) {
|
||||
if (instr->op != op_branch) continue;
|
||||
if (instr->literal_args[0] != BR_COND_EQ) continue;
|
||||
|
||||
unsigned src1 = instr->ssa_args.src0;
|
||||
|
||||
// Only work on SSA values
|
||||
if (src1 >= SSA_FIXED_MINIMUM) continue;
|
||||
|
||||
// Find the source for this conditional branch instruction
|
||||
// It'll be a CSEL instruction
|
||||
// If it's comparision is one of the ops that our conditional branch supports
|
||||
// then we can merge the two
|
||||
mir_foreach_instr_in_block_from_rev(block, next_instr, instr) {
|
||||
if (next_instr->op != op_csel_i32) continue;
|
||||
|
||||
if (next_instr->ssa_args.dest == src1) {
|
||||
// We found the CSEL instruction that is the source here
|
||||
// Check its condition to make sure it matches what we can fuse
|
||||
unsigned cond = next_instr->literal_args[0];
|
||||
if (cond == CSEL_IEQ) {
|
||||
// This CSEL is doing an IEQ for our conditional branch doing EQ
|
||||
// We can just emit a conditional branch that does the comparison
|
||||
struct bifrost_instruction new_instr = {
|
||||
.op = op_branch,
|
||||
.dest_components = 0,
|
||||
.ssa_args = {
|
||||
.dest = SSA_INVALID_VALUE,
|
||||
.src0 = next_instr->ssa_args.src0,
|
||||
.src1 = next_instr->ssa_args.src1,
|
||||
.src2 = SSA_INVALID_VALUE,
|
||||
.src3 = SSA_INVALID_VALUE,
|
||||
},
|
||||
.literal_args[0] = BR_COND_EQ,
|
||||
.literal_args[1] = instr->literal_args[1],
|
||||
};
|
||||
mir_insert_instr_before(instr, new_instr);
|
||||
mir_remove_instr(instr);
|
||||
progress |= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef bifrost_opts_h
|
||||
#define bifrost_opts_h
|
||||
#include "compiler_defines.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool
|
||||
bifrost_opt_branch_fusion(compiler_context *ctx, bifrost_block *block);
|
||||
|
||||
#endif /* bifrost_opts_h */
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
*
|
||||
* 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_defines.h"
|
||||
#include "bifrost_print.h"
|
||||
|
||||
const char *ir_names[op_last + 1] = {
|
||||
"fma.f32",
|
||||
"fmul.f32",
|
||||
"fadd.f32",
|
||||
"frcp_fast.f32",
|
||||
"max.f32",
|
||||
"min.f32",
|
||||
"add.i32",
|
||||
"sub.i32",
|
||||
"imad",
|
||||
"mul.i32",
|
||||
"or.i32",
|
||||
"and.i32",
|
||||
"lshift.i32",
|
||||
"xor.i32",
|
||||
"rshift.i32",
|
||||
"arshift.i32",
|
||||
"csel.i32",
|
||||
"imin3.i32",
|
||||
"umin3.i32",
|
||||
"imax3.i32",
|
||||
"umax3.i32",
|
||||
|
||||
"branch",
|
||||
|
||||
// unary
|
||||
"trunc",
|
||||
"ceil",
|
||||
"floor",
|
||||
"round",
|
||||
"roundeven",
|
||||
|
||||
"mov",
|
||||
"movi",
|
||||
|
||||
"ld_ubo.v1",
|
||||
"ld_ubo.v2",
|
||||
"ld_ubo.v3",
|
||||
"ld_ubo.v4",
|
||||
|
||||
"ld_attr.v1",
|
||||
"ld_attr.v2",
|
||||
"ld_attr.v3",
|
||||
"ld_attr.v4",
|
||||
|
||||
"ld_var_addr",
|
||||
"st_vary.v1",
|
||||
"st_vary.v2",
|
||||
"st_vary.v3",
|
||||
"st_vary.v4",
|
||||
|
||||
"store.v1",
|
||||
"store.v2",
|
||||
"store.v3",
|
||||
"store.v4",
|
||||
|
||||
"create_vector",
|
||||
"extract_element",
|
||||
"last",
|
||||
};
|
||||
|
||||
void
|
||||
print_mir_instruction(struct bifrost_instruction *instr, bool post_ra)
|
||||
{
|
||||
printf("\t");
|
||||
if (instr->dest_components != 0) {
|
||||
if (post_ra) {
|
||||
if (instr->dest_components == 1) {
|
||||
printf("r%d = ", instr->args.dest);
|
||||
} else {
|
||||
printf("r%d..r%d = ", instr->args.dest, instr->args.dest + instr->dest_components - 1);
|
||||
|
||||
}
|
||||
} else {
|
||||
printf("%%0x%08x = ", instr->ssa_args.dest);
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s ", ir_names[instr->op]);
|
||||
|
||||
if (post_ra) {
|
||||
uint32_t sources[4] = {
|
||||
instr->args.src0,
|
||||
instr->args.src1,
|
||||
instr->args.src2,
|
||||
instr->args.src3
|
||||
};
|
||||
for (unsigned i = 0; i < 4; ++i) {
|
||||
if (sources[i] == SSA_INVALID_VALUE) break;
|
||||
bool last = i + 1 == 4 ||
|
||||
sources[i + 1] == SSA_INVALID_VALUE;
|
||||
|
||||
if (sources[i] == SSA_FIXED_CONST_0) {
|
||||
printf("#0%s", last ? "" : ", ");
|
||||
} else if (sources[i] >= SSA_FIXED_UREG_MINIMUM) {
|
||||
printf("u%d%s", SSA_UREG_FROM_FIXED(sources[i]), last ? "" : ", ");
|
||||
} else {
|
||||
printf("r%d%s", sources[i], last ? "" : ", ");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32_t sources[4] = {
|
||||
instr->ssa_args.src0,
|
||||
instr->ssa_args.src1,
|
||||
instr->ssa_args.src2,
|
||||
instr->ssa_args.src3
|
||||
};
|
||||
for (unsigned i = 0; i < 4; ++i) {
|
||||
if (sources[i] == SSA_INVALID_VALUE) break;
|
||||
bool last = i + 1 == 4 ||
|
||||
sources[i + 1] == SSA_INVALID_VALUE;
|
||||
|
||||
printf("%%0x%08x%s", sources[i], last ? "" : ", ");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
print_mir_block(struct bifrost_block *block, bool post_ra)
|
||||
{
|
||||
printf("{\n");
|
||||
|
||||
mir_foreach_instr_in_block(block, instr) {
|
||||
print_mir_instruction(instr, post_ra);
|
||||
}
|
||||
|
||||
printf("}\n");
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __bifrost_print_h__
|
||||
#define __bifrost_print_h__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct bifrost_instruction;
|
||||
struct bifrost_block;
|
||||
|
||||
void print_mir_instruction(struct bifrost_instruction *ins, bool post_ra);
|
||||
void print_mir_block(struct bifrost_block *block, bool post_ra);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,395 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
*
|
||||
* 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 "util/register_allocate.h"
|
||||
#include "compiler_defines.h"
|
||||
#include "bifrost_sched.h"
|
||||
#include "bifrost_compile.h"
|
||||
#include "bifrost_print.h"
|
||||
|
||||
#define BI_DEBUG
|
||||
const unsigned max_primary_reg = 64; /* Overestimate because of special regs */
|
||||
const unsigned max_vec2_reg = 32;
|
||||
const unsigned max_vec3_reg = 16; // XXX: Do we need to align vec3 to vec4 boundary?
|
||||
const unsigned max_vec4_reg = 16;
|
||||
const unsigned max_registers = 128; /* Sum of classes */
|
||||
const unsigned primary_base = 0;
|
||||
const unsigned vec2_base = 64;
|
||||
const unsigned vec3_base = 96; /* above base + max_class_reg */
|
||||
const unsigned vec4_base = 112;
|
||||
const unsigned vec4_end = 128;
|
||||
|
||||
static unsigned
|
||||
find_or_allocate_temp(compiler_context *ctx, unsigned hash)
|
||||
{
|
||||
if (hash >= SSA_FIXED_MINIMUM)
|
||||
return hash;
|
||||
|
||||
unsigned temp = (uintptr_t) _mesa_hash_table_u64_search(ctx->hash_to_temp, hash + 1);
|
||||
|
||||
if (temp)
|
||||
return temp - 1;
|
||||
|
||||
/* If no temp is find, allocate one */
|
||||
temp = ctx->num_temps++;
|
||||
ctx->max_hash = MAX2(ctx->max_hash, hash);
|
||||
|
||||
_mesa_hash_table_u64_insert(ctx->hash_to_temp, hash + 1, (void *) ((uintptr_t) temp + 1));
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_live_in_instr(bifrost_instruction *instr, unsigned temp)
|
||||
{
|
||||
if (instr->ssa_args.src0 == temp) return true;
|
||||
if (instr->ssa_args.src1 == temp) return true;
|
||||
if (instr->ssa_args.src2 == temp) return true;
|
||||
if (instr->ssa_args.src3 == temp) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_live_after_instr(compiler_context *ctx, bifrost_block *blk, bifrost_instruction *instr, unsigned temp)
|
||||
{
|
||||
// Scan forward in the block from this location to see if we are still live.
|
||||
|
||||
mir_foreach_instr_in_block_from(blk, ins, mir_next_instr(instr)) {
|
||||
if (is_live_in_instr(ins, temp))
|
||||
return true;
|
||||
}
|
||||
|
||||
// XXX: Walk all successor blocks and ensure the value isn't used there
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ra_select_callback(struct ra_graph *g, BITSET_WORD *regs, void *data)
|
||||
{
|
||||
for (int i = primary_base; i < vec4_end; ++i) {
|
||||
if (BITSET_TEST(regs, i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ra_get_phys_reg(compiler_context *ctx, struct ra_graph *g, unsigned temp, unsigned max_reg)
|
||||
{
|
||||
if (temp == SSA_INVALID_VALUE ||
|
||||
temp >= SSA_FIXED_UREG_MINIMUM ||
|
||||
temp == SSA_FIXED_CONST_0)
|
||||
return temp;
|
||||
|
||||
if (temp >= SSA_FIXED_MINIMUM)
|
||||
return SSA_REG_FROM_FIXED(temp);
|
||||
|
||||
assert(temp < max_reg);
|
||||
uint32_t r = ra_get_node_reg(g, temp);
|
||||
if (r >= vec4_base)
|
||||
return (r - vec4_base) * 4;
|
||||
else if (r >= vec3_base)
|
||||
return (r - vec3_base) * 4;
|
||||
else if (r >= vec2_base)
|
||||
return (r - vec2_base) * 2;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
allocate_registers(compiler_context *ctx)
|
||||
{
|
||||
struct ra_regs *regs = ra_alloc_reg_set(NULL, max_registers, true);
|
||||
|
||||
int primary_class = ra_alloc_reg_class(regs);
|
||||
int vec2_class = ra_alloc_reg_class(regs);
|
||||
int vec3_class = ra_alloc_reg_class(regs);
|
||||
int vec4_class = ra_alloc_reg_class(regs);
|
||||
|
||||
// Allocate our register classes and conflicts
|
||||
{
|
||||
unsigned reg = 0;
|
||||
unsigned primary_base = 0;
|
||||
|
||||
// Add all of our primary scalar registers
|
||||
for (unsigned i = 0; i < max_primary_reg; ++i) {
|
||||
ra_class_add_reg(regs, primary_class, reg);
|
||||
reg++;
|
||||
}
|
||||
|
||||
// Add all of our vec2 class registers
|
||||
// These alias with the scalar registers
|
||||
for (unsigned i = 0; i < max_vec2_reg; ++i) {
|
||||
ra_class_add_reg(regs, vec2_class, reg);
|
||||
|
||||
// Tell RA that this conflicts with primary class registers
|
||||
// Make sure to tell the RA utility all conflict slots
|
||||
ra_add_reg_conflict(regs, reg, primary_base + i*2 + 0);
|
||||
ra_add_reg_conflict(regs, reg, primary_base + i*2 + 1);
|
||||
|
||||
reg++;
|
||||
}
|
||||
|
||||
// Add all of our vec3 class registers
|
||||
// These alias with the scalar registers
|
||||
for (unsigned i = 0; i < max_vec3_reg; ++i) {
|
||||
ra_class_add_reg(regs, vec3_class, reg);
|
||||
|
||||
// Tell RA that this conflicts with primary class registers
|
||||
// Make sure to tell the RA utility all conflict slots
|
||||
// These are aligned to vec4 even though they only conflict with a vec3 wide slot
|
||||
ra_add_reg_conflict(regs, reg, primary_base + i*4 + 0);
|
||||
ra_add_reg_conflict(regs, reg, primary_base + i*4 + 1);
|
||||
ra_add_reg_conflict(regs, reg, primary_base + i*4 + 2);
|
||||
|
||||
// State that this class conflicts with the vec2 class
|
||||
ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 0);
|
||||
ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 1);
|
||||
|
||||
reg++;
|
||||
}
|
||||
|
||||
// Add all of our vec4 class registers
|
||||
// These alias with the scalar registers
|
||||
for (unsigned i = 0; i < max_vec4_reg; ++i) {
|
||||
ra_class_add_reg(regs, vec4_class, reg);
|
||||
|
||||
// Tell RA that this conflicts with primary class registers
|
||||
// Make sure to tell the RA utility all conflict slots
|
||||
// These are aligned to vec4 even though they only conflict with a vec3 wide slot
|
||||
ra_add_reg_conflict(regs, reg, primary_base + i*4 + 0);
|
||||
ra_add_reg_conflict(regs, reg, primary_base + i*4 + 1);
|
||||
ra_add_reg_conflict(regs, reg, primary_base + i*4 + 2);
|
||||
ra_add_reg_conflict(regs, reg, primary_base + i*4 + 3);
|
||||
|
||||
// State that this class conflicts with the vec2 class
|
||||
ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 0);
|
||||
ra_add_reg_conflict(regs, reg, vec2_base + i*2 + 1);
|
||||
|
||||
// State that this class conflicts with the vec3 class
|
||||
// They conflict on the exact same location due to alignments
|
||||
ra_add_reg_conflict(regs, reg, vec3_base + i);
|
||||
|
||||
reg++;
|
||||
}
|
||||
}
|
||||
|
||||
ra_set_finalize(regs, NULL);
|
||||
mir_foreach_block(ctx, block) {
|
||||
mir_foreach_instr_in_block(block, instr) {
|
||||
instr->ssa_args.src0 = find_or_allocate_temp(ctx, instr->ssa_args.src0);
|
||||
instr->ssa_args.src1 = find_or_allocate_temp(ctx, instr->ssa_args.src1);
|
||||
instr->ssa_args.src2 = find_or_allocate_temp(ctx, instr->ssa_args.src2);
|
||||
instr->ssa_args.src3 = find_or_allocate_temp(ctx, instr->ssa_args.src3);
|
||||
instr->ssa_args.dest = find_or_allocate_temp(ctx, instr->ssa_args.dest);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t nodes = ctx->num_temps;
|
||||
struct ra_graph *g = ra_alloc_interference_graph(regs, nodes);
|
||||
|
||||
mir_foreach_block(ctx, block) {
|
||||
mir_foreach_instr_in_block(block, instr) {
|
||||
if (instr->ssa_args.dest >= SSA_FIXED_MINIMUM) continue;
|
||||
if (instr->dest_components == 4)
|
||||
ra_set_node_class(g, instr->ssa_args.dest, vec4_class);
|
||||
else if (instr->dest_components == 3)
|
||||
ra_set_node_class(g, instr->ssa_args.dest, vec3_class);
|
||||
else if (instr->dest_components == 2)
|
||||
ra_set_node_class(g, instr->ssa_args.dest, vec2_class);
|
||||
else
|
||||
ra_set_node_class(g, instr->ssa_args.dest, primary_class);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *live_start = malloc(nodes * sizeof(uint32_t));
|
||||
uint32_t *live_end = malloc(nodes * sizeof(uint32_t));
|
||||
|
||||
memset(live_start, 0xFF, nodes * sizeof(uint32_t));
|
||||
memset(live_end, 0xFF, nodes * sizeof(uint32_t));
|
||||
|
||||
uint32_t location = 0;
|
||||
mir_foreach_block(ctx, block) {
|
||||
mir_foreach_instr_in_block(block, instr) {
|
||||
if (instr->ssa_args.dest < SSA_FIXED_MINIMUM) {
|
||||
// If the destination isn't yet live before this point
|
||||
// then this is the point it becomes live since we wrote to it
|
||||
if (live_start[instr->ssa_args.dest] == ~0U) {
|
||||
live_start[instr->ssa_args.dest] = location;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t sources[4] = {
|
||||
instr->ssa_args.src0,
|
||||
instr->ssa_args.src1,
|
||||
instr->ssa_args.src2,
|
||||
instr->ssa_args.src3,
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < 4; ++i) {
|
||||
if (sources[i] >= SSA_FIXED_MINIMUM)
|
||||
continue;
|
||||
|
||||
// If the source is no longer live after this instruction then we can end its liveness
|
||||
if (!is_live_after_instr(ctx, block, instr, sources[i])) {
|
||||
live_end[sources[i]] = location;
|
||||
}
|
||||
}
|
||||
++location;
|
||||
}
|
||||
}
|
||||
|
||||
// Spin through the nodes quick and ensure they are all killed by the end of the program
|
||||
for (unsigned i = 0; i < nodes; ++i) {
|
||||
if (live_end[i] == ~0U)
|
||||
live_end[i] = location;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nodes; ++i) {
|
||||
for (int j = i + 1; j < nodes; ++j) {
|
||||
if (!(live_start[i] >= live_end[j] || live_start[j] >= live_end[i])) {
|
||||
ra_add_node_interference(g, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ra_set_select_reg_callback(g, ra_select_callback, NULL);
|
||||
|
||||
if (!ra_allocate(g)) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
free(live_start);
|
||||
free(live_end);
|
||||
|
||||
mir_foreach_block(ctx, block) {
|
||||
mir_foreach_instr_in_block(block, instr) {
|
||||
instr->args.src0 = ra_get_phys_reg(ctx, g, instr->ssa_args.src0, nodes);
|
||||
instr->args.src1 = ra_get_phys_reg(ctx, g, instr->ssa_args.src1, nodes);
|
||||
instr->args.src2 = ra_get_phys_reg(ctx, g, instr->ssa_args.src2, nodes);
|
||||
instr->args.src3 = ra_get_phys_reg(ctx, g, instr->ssa_args.src3, nodes);
|
||||
instr->args.dest = ra_get_phys_reg(ctx, g, instr->ssa_args.dest, nodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bundle_block(compiler_context *ctx, bifrost_block *block)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
remove_create_vectors(compiler_context *ctx, bifrost_block *block)
|
||||
{
|
||||
mir_foreach_instr_in_block_safe(block, instr) {
|
||||
if (instr->op != op_create_vector) continue;
|
||||
|
||||
uint32_t vector_ssa_sources[4] = {
|
||||
instr->ssa_args.src0,
|
||||
instr->ssa_args.src1,
|
||||
instr->ssa_args.src2,
|
||||
instr->ssa_args.src3,
|
||||
};
|
||||
|
||||
mir_foreach_instr_in_block_from_rev(block, next_instr, instr) {
|
||||
// Walk our block backwards and find the creators of this vector creation instruction
|
||||
for (unsigned i = 0; i < instr->dest_components; ++i) {
|
||||
// If this instruction is ther one that writes this register then forward it to the real register
|
||||
if (vector_ssa_sources[i] == next_instr->ssa_args.dest) {
|
||||
next_instr->ssa_args.dest = vector_ssa_sources[i];
|
||||
// Source instruction destination is a vector register of size dest_components
|
||||
// So dest + i gets the components of it
|
||||
next_instr->args.dest = instr->args.dest + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the instruction now that we have copied over all the sources
|
||||
mir_remove_instr(instr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_extract_elements(compiler_context *ctx, bifrost_block *block)
|
||||
{
|
||||
mir_foreach_instr_in_block_safe(block, instr) {
|
||||
if (instr->op != op_extract_element) continue;
|
||||
|
||||
mir_foreach_instr_in_block_from(block, next_instr, instr) {
|
||||
// Walk our block forward to replace uses of this register with a real register
|
||||
// src0 = vector
|
||||
// src1 = index in to vector
|
||||
uint32_t vector_ssa_sources[4] = {
|
||||
next_instr->ssa_args.src0,
|
||||
next_instr->ssa_args.src1,
|
||||
next_instr->ssa_args.src2,
|
||||
next_instr->ssa_args.src3,
|
||||
};
|
||||
uint32_t *vector_sources[4] = {
|
||||
&next_instr->args.src0,
|
||||
&next_instr->args.src1,
|
||||
&next_instr->args.src2,
|
||||
&next_instr->args.src3,
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < 4; ++i) {
|
||||
if (vector_ssa_sources[i] == instr->ssa_args.dest) {
|
||||
// This source uses this vector extraction
|
||||
// Replace its usage with the real register
|
||||
// src0 is a vector register and src1 is the constant element of the vector
|
||||
*vector_sources[i] = instr->args.src0 + instr->literal_args[0];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Remove the instruction now that we have copied over all the sources
|
||||
mir_remove_instr(instr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void bifrost_schedule_program(compiler_context *ctx)
|
||||
{
|
||||
// XXX: we should move instructions together before RA that can feed in to each other and be scheduled in the same clause
|
||||
allocate_registers(ctx);
|
||||
|
||||
mir_foreach_block(ctx, block) {
|
||||
remove_create_vectors(ctx, block);
|
||||
remove_extract_elements(ctx, block);
|
||||
}
|
||||
|
||||
mir_foreach_block(ctx, block) {
|
||||
#ifdef BI_DEBUG
|
||||
print_mir_block(block, true);
|
||||
#endif
|
||||
|
||||
bundle_block(ctx, block);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef bifrost_ra_h
|
||||
#define bifrost_ra_h
|
||||
#include "compiler_defines.h"
|
||||
|
||||
void bifrost_schedule_program(compiler_context *ctx);
|
||||
|
||||
#endif /* bifrost_ra_h */
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
#include "compiler/glsl/gl_nir.h"
|
||||
#include "compiler/nir_types.h"
|
||||
#include "util/u_dynarray.h"
|
||||
|
||||
#include "bifrost_compile.h"
|
||||
|
||||
static void
|
||||
|
|
@ -52,7 +51,7 @@ compile_shader(char **argv)
|
|||
prog = standalone_compile_shader(&options, 2, argv, &local_ctx);
|
||||
prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program->info.stage = MESA_SHADER_FRAGMENT;
|
||||
|
||||
struct bifrost_program compiled;
|
||||
bifrost_program compiled;
|
||||
for (unsigned i = 0; i < 2; ++i) {
|
||||
nir[i] = glsl_to_nir(&local_ctx, prog, shader_types[i], &bifrost_nir_options);
|
||||
NIR_PASS_V(nir[i], nir_lower_global_vars_to_local);
|
||||
|
|
@ -66,7 +65,7 @@ compile_shader(char **argv)
|
|||
|
||||
NIR_PASS_V(nir[i], gl_nir_lower_buffers, prog);
|
||||
NIR_PASS_V(nir[i], nir_opt_constant_folding);
|
||||
bifrost_compile_shader_nir(nir[i], &compiled);
|
||||
//bifrost_compile_shader_nir(nir[i], &compiled);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Ryan Houdek <Sonicadvance1@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __compiler_defines_h__
|
||||
#define __compiler_defines_h__
|
||||
#include "bifrost.h"
|
||||
#include "bifrost_compile.h"
|
||||
#include "bifrost_ops.h"
|
||||
|
||||
struct nir_builder;
|
||||
|
||||
typedef struct ssa_args {
|
||||
uint32_t dest;
|
||||
uint32_t src0, src1, src2, src3;
|
||||
} ssa_args;
|
||||
|
||||
/**
|
||||
* @brief Singular unpacked instruction that lives outside of the clause bundle
|
||||
*/
|
||||
typedef struct bifrost_instruction {
|
||||
// Must be first
|
||||
struct list_head link;
|
||||
|
||||
/**
|
||||
* @brief Pre-RA arguments
|
||||
*/
|
||||
struct ssa_args ssa_args;
|
||||
uint32_t literal_args[4];
|
||||
uint32_t src_modifiers;
|
||||
unsigned op;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Post-RA arguments
|
||||
*/
|
||||
struct ssa_args args;
|
||||
|
||||
/**
|
||||
* @brief The number of components that the destination takes up
|
||||
*
|
||||
* This allows the RA to understand when it needs to allocate registers from different classes
|
||||
*/
|
||||
unsigned dest_components;
|
||||
|
||||
} bifrost_instruction;
|
||||
|
||||
typedef struct bifrost_clause {
|
||||
struct bifrost_header header;
|
||||
|
||||
/* List of bifrost_instructions emitted for the current clause */
|
||||
struct list_head instructions;
|
||||
|
||||
} bifrost_clause;
|
||||
|
||||
typedef struct bifrost_block {
|
||||
/* Link to next block. Must be first for mir_get_block */
|
||||
struct list_head link;
|
||||
|
||||
/* List of bifrost_instructions emitted for the current block */
|
||||
struct list_head instructions;
|
||||
|
||||
/* List of bifrost clauses to be emitted for the current block*/
|
||||
struct util_dynarray clauses;
|
||||
|
||||
/* Maximum number of successors is 2 */
|
||||
struct bifrost_block *successors[2];
|
||||
uint32_t num_successors;
|
||||
|
||||
} bifrost_block;
|
||||
|
||||
typedef struct compiler_context {
|
||||
nir_shader *nir;
|
||||
gl_shader_stage stage;
|
||||
|
||||
/* Current NIR function */
|
||||
nir_function *func;
|
||||
struct nir_builder *b;
|
||||
|
||||
/* Unordered list of bifrost_blocks */
|
||||
uint32_t block_count;
|
||||
struct list_head blocks;
|
||||
|
||||
/* The current block we are operating on */
|
||||
struct bifrost_block *current_block;
|
||||
|
||||
struct hash_table_u64 *ssa_constants;
|
||||
|
||||
/* Uniform IDs */
|
||||
struct hash_table_u64 *uniform_nir_to_bi;
|
||||
uint32_t uniform_count;
|
||||
|
||||
struct hash_table_u64 *varying_nir_to_bi;
|
||||
uint32_t varying_count;
|
||||
|
||||
struct hash_table_u64 *outputs_nir_to_bi;
|
||||
uint32_t outputs_count;
|
||||
|
||||
/* Count of instructions emitted from NIR overall, across all blocks */
|
||||
uint32_t instruction_count;
|
||||
|
||||
uint32_t mir_temp;
|
||||
|
||||
struct hash_table_u64 *hash_to_temp;
|
||||
uint32_t num_temps;
|
||||
|
||||
uint32_t max_hash;
|
||||
|
||||
} compiler_context;
|
||||
|
||||
#define mir_foreach_block(ctx, v) list_for_each_entry(struct bifrost_block, v, &ctx->blocks, link)
|
||||
#define mir_foreach_block_from(ctx, from, v) list_for_each_entry_from(struct bifrost_block, v, from, &ctx->blocks, link)
|
||||
|
||||
#define mir_last_block(ctx) list_last_entry(&ctx->blocks, struct bifrost_block, link)
|
||||
|
||||
#define mir_foreach_instr(ctx, v) list_for_each_entry(struct bifrost_instruction, v, &ctx->current_block->instructions, link)
|
||||
#define mir_foreach_instr_in_block(block, v) list_for_each_entry(struct bifrost_instruction, v, &block->instructions, link)
|
||||
#define mir_foreach_instr_in_block_from(block, v, from) list_for_each_entry_from(struct bifrost_instruction, v, from, &block->instructions, link)
|
||||
#define mir_foreach_instr_in_block_safe(block, v) list_for_each_entry_safe(struct bifrost_instruction, v, &block->instructions, link)
|
||||
#define mir_last_instr_in_block(block) list_last_entry(&block->instructions, struct bifrost_instruction, link)
|
||||
#define mir_foreach_instr_in_block_from_rev(block, v, from) list_for_each_entry_from_rev(struct bifrost_instruction, v, from, &block->instructions, link)
|
||||
|
||||
#define mir_next_instr(from) list_first_entry(&(from->link), struct bifrost_instruction, link)
|
||||
#define mir_remove_instr(instr) list_del(&instr->link)
|
||||
|
||||
#define mir_insert_instr_before(before, ins) list_addtail(&(mir_alloc_ins(ins))->link, &before->link)
|
||||
|
||||
#define SSA_INVALID_VALUE ~0U
|
||||
#define SSA_TEMP_SHIFT 24
|
||||
#define SSA_FIXED_REGISTER_SHIFT 25
|
||||
|
||||
#define SSA_FIXED_REGISTER(x) ((1U << SSA_FIXED_REGISTER_SHIFT) + (x))
|
||||
#define SSA_REG_FROM_FIXED(x) ((x) & ~(1U << SSA_FIXED_REGISTER_SHIFT))
|
||||
|
||||
#define SSA_FIXED_MINIMUM SSA_FIXED_REGISTER(0)
|
||||
#define SSA_FIXED_UREG_MINIMUM SSA_FIXED_REGISTER(64)
|
||||
#define SSA_FIXED_CONST_0 SSA_FIXED_REGISTER(256 + 64)
|
||||
|
||||
#define SSA_FIXED_UREGISTER(x) (SSA_FIXED_REGISTER(x + 64))
|
||||
#define SSA_UREG_FROM_FIXED(x) (SSA_REG_FROM_FIXED(x) - 64)
|
||||
|
||||
#define SSA_TEMP_VALUE(x) ((1U << SSA_TEMP_SHIFT) + (x))
|
||||
#define SSA_TEMP_FROM_VALUE(x) (((x) & ~(1U << SSA_TEMP_SHIFT)))
|
||||
#define MIR_TEMP_MINIMUM SSA_TEMP_VALUE(0)
|
||||
|
||||
#define SRC_MOD_ABS 1
|
||||
#define SRC_MOD_NEG 2
|
||||
#define MOD_SIZE 2
|
||||
#define SOURCE_MODIFIER(src, mod) (mod << (src * MOD_SIZE))
|
||||
|
||||
struct bifrost_instruction *
|
||||
mir_alloc_ins(struct bifrost_instruction instr);
|
||||
|
||||
#endif
|
||||
|
|
@ -31,7 +31,6 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "bifrost.h"
|
||||
#include "bifrost_ops.h"
|
||||
#include "disassemble.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
|
|
@ -1339,11 +1338,11 @@ static void dump_add(FILE *fp, uint64_t word, struct bifrost_regs regs,
|
|||
}
|
||||
fprintf(fp, ".v%d", ((ADD.op >> 5) & 0x3) + 1);
|
||||
} else if (info.src_type == ADD_BRANCH) {
|
||||
enum branch_code branchCode = (enum branch_code) ((ADD.op >> 6) & 0x3f);
|
||||
enum bifrost_branch_code branchCode = (enum bifrost_branch_code) ((ADD.op >> 6) & 0x3f);
|
||||
if (branchCode == BR_ALWAYS) {
|
||||
// unconditional branch
|
||||
} else {
|
||||
enum branch_cond cond = (enum branch_cond) ((ADD.op >> 6) & 0x7);
|
||||
enum bifrost_branch_cond cond = (enum bifrost_branch_cond) ((ADD.op >> 6) & 0x7);
|
||||
enum branch_bit_size size = (enum branch_bit_size) ((ADD.op >> 9) & 0x7);
|
||||
bool portSwapped = (ADD.op & 0x7) < ADD.src0;
|
||||
// See the comment in branch_bit_size
|
||||
|
|
@ -1814,7 +1813,7 @@ static void dump_add(FILE *fp, uint64_t word, struct bifrost_regs regs,
|
|||
dump_16swizzle(fp, (ADD.op >> 8) & 0x3);
|
||||
break;
|
||||
case ADD_BRANCH: {
|
||||
enum branch_code code = (enum branch_code) ((ADD.op >> 6) & 0x3f);
|
||||
enum bifrost_branch_code code = (enum bifrost_branch_code) ((ADD.op >> 6) & 0x3f);
|
||||
enum branch_bit_size size = (enum branch_bit_size) ((ADD.op >> 9) & 0x7);
|
||||
if (code != BR_ALWAYS) {
|
||||
dump_src(fp, ADD.src0, regs, consts, false);
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@
|
|||
# SOFTWARE.
|
||||
|
||||
libpanfrost_bifrost_files = files(
|
||||
'bifrost_compile.c',
|
||||
'bifrost_opts.c',
|
||||
'bifrost_sched.c',
|
||||
'bifrost_print.c',
|
||||
'disassemble.c',
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue