Commit 5d3a4e31 authored by Alyssa Rosenzweig's avatar Alyssa Rosenzweig 💜 Committed by Marge Bot
Browse files

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's avatarAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <mesa/mesa!4061>
parent eb15525a
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
This diff is collapsed.
/*
* 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
/*
* 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
/*
* 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;
}
/*
* 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 */
/*
* 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");
}
/*
* 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
/*
* 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