diff options
author | Ian Romanick <ian.d.romanick@intel.com> | 2019-02-19 20:11:06 -0800 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2019-03-26 10:29:22 -0700 |
commit | 63e9b863613fc1c03018410122b2f57f45320ab1 (patch) | |
tree | e77556d56ca12719683fb2c4ab52b3c761d842b0 /src | |
parent | bd46de24404c851415d12577a7caf18b4e2df40e (diff) |
WIP: intel/compiler: Add a code builder that consumes a bytecode
Diffstat (limited to 'src')
-rw-r--r-- | src/intel/compiler/codegen_builder.cpp | 203 | ||||
-rw-r--r-- | src/intel/compiler/codegen_builder.h | 222 | ||||
-rw-r--r-- | src/intel/compiler/meson.build | 2 |
3 files changed, 427 insertions, 0 deletions
diff --git a/src/intel/compiler/codegen_builder.cpp b/src/intel/compiler/codegen_builder.cpp new file mode 100644 index 000000000000..3f052a17cd86 --- /dev/null +++ b/src/intel/compiler/codegen_builder.cpp @@ -0,0 +1,203 @@ +/* + * Copyright © 2019 Intel Corporation + * + * 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 "codegen_builder.h" + +void +emit_instructions_from_bytecode(const brw::fs_builder &bld, + const struct bytecode_instruction *bi, + const fs_reg &result, + const fs_reg *inputs, + const union immediate_value *imm, + bool implicit_saturate) +{ + fs_reg operands[16]; + unsigned num_operands = 0; + fs_reg temporaries[16]; + unsigned num_temps = 0; + fs_inst *inst = NULL; + + while (bi->op != end_of_stream) { + switch (bi->op) { + case append_output: + assert(num_operands < ARRAY_SIZE(operands)); + operands[num_operands++] = result; + break; + + case append_input: + assert(num_operands < ARRAY_SIZE(operands)); + operands[num_operands++] = inputs[bi->index]; + break; + + case append_constant: + assert(num_operands < ARRAY_SIZE(operands)); + + switch (bi->reg_type) { + case BRW_REGISTER_TYPE_DF: + operands[num_operands++] = brw_imm_df(imm[bi->index].df); + break; + case BRW_REGISTER_TYPE_F: + operands[num_operands++] = brw_imm_f(imm[bi->index].f); + break; + + case BRW_REGISTER_TYPE_Q: + operands[num_operands++] = brw_imm_q(imm[bi->index].q); + break; + case BRW_REGISTER_TYPE_UQ: + operands[num_operands++] = brw_imm_uq(imm[bi->index].uq); + break; + case BRW_REGISTER_TYPE_D: + operands[num_operands++] = brw_imm_d(imm[bi->index].d); + break; + case BRW_REGISTER_TYPE_UD: + operands[num_operands++] = brw_imm_ud(imm[bi->index].ud); + break; + case BRW_REGISTER_TYPE_W: + operands[num_operands++] = brw_imm_w(imm[bi->index].w); + break; + case BRW_REGISTER_TYPE_UW: + operands[num_operands++] = brw_imm_uw(imm[bi->index].uw); + break; + + case BRW_REGISTER_TYPE_NF: + case BRW_REGISTER_TYPE_HF: + case BRW_REGISTER_TYPE_VF: + case BRW_REGISTER_TYPE_B: + case BRW_REGISTER_TYPE_UB: + case BRW_REGISTER_TYPE_V: + case BRW_REGISTER_TYPE_UV: + unreachable("Unsupported type"); + }; + break; + + case append_temporary: + assert(num_operands < ARRAY_SIZE(operands)); + assert(bi->index < num_temps); + operands[num_operands++] = temporaries[bi->index]; + break; + + case append_null_reg: + assert(num_operands < ARRAY_SIZE(operands)); + operands[num_operands++] = retype(bld.null_reg_ud(), + bi->reg_type); + break; + + case append_vec1_grf: + assert(num_operands < ARRAY_SIZE(operands)); + operands[num_operands++] = brw_vec1_grf(bi->index, bi->blob); + break; + + case append_vec2_grf: + assert(num_operands < ARRAY_SIZE(operands)); + operands[num_operands++] = brw_vec2_grf(bi->index, bi->blob); + break; + + case append_vec4_grf: + assert(num_operands < ARRAY_SIZE(operands)); + operands[num_operands++] = brw_vec4_grf(bi->index, bi->blob); + break; + + case append_vec8_grf: + assert(num_operands < ARRAY_SIZE(operands)); + operands[num_operands++] = brw_vec8_grf(bi->index, bi->blob); + break; + + case append_vec16_grf: + assert(num_operands < ARRAY_SIZE(operands)); + operands[num_operands++] = brw_vec16_grf(bi->index, bi->blob); + break; + + case declare_temporary: + assert(num_temps < ARRAY_SIZE(temporaries)); + + if (bi->reg_type == BRW_REGISTER_TYPE_VF) + temporaries[num_temps++] = bld.vgrf(result.type, 1); + else + temporaries[num_temps++] = bld.vgrf(bi->reg_type, 1); + break; + + case neg_operand: + assert(num_operands > 0); + operands[num_operands - 1].negate = !operands[num_operands - 1].negate; + break; + + case abs_operand: + assert(num_operands > 0); + operands[num_operands - 1].negate = false; + operands[num_operands - 1].abs = true; + break; + + case retype_operand: + assert(num_operands > 0); + operands[num_operands - 1] = retype(operands[num_operands - 1], + bi->reg_type); + break; + + case subscript_operand: + assert(num_operands > 0); + operands[num_operands - 1] = subscript(operands[num_operands - 1], + bi->reg_type, + bi->index); + break; + + case emit_instruction: + if (num_operands == 0) { + inst = bld.emit(bi->gen_opcode); + } else { + inst = bld.emit(bi->gen_opcode, + operands[0], + &operands[1], + num_operands - 1); + num_operands = 0; + } + + break; + + case saturate_instruction: + assert(inst != NULL); + inst->saturate = true; + break; + + case conditional_mod: + assert(inst != NULL); + inst->conditional_mod = bi->cmod; + break; + + case predicate_instruction: + assert(inst != NULL); + inst->predicate = bi->pred; + break; + + case end_of_stream: + unreachable("Should have already exited loop."); + } + + bi++; + } + + if (implicit_saturate) + inst->saturate = true; + + /* There should be no operands hanging around. */ + assert(num_operands == 0); +} diff --git a/src/intel/compiler/codegen_builder.h b/src/intel/compiler/codegen_builder.h new file mode 100644 index 000000000000..b7cf5f504b0c --- /dev/null +++ b/src/intel/compiler/codegen_builder.h @@ -0,0 +1,222 @@ +/* -*- c++ -*- */ +/* + * Copyright © 2019 Intel Corporation + * + * 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 CODEGEN_BUILDER_H +#define CODEGEN_BUILDER_H + +#include "brw_fs.h" + +enum PACKED operation { + append_output, + + /** + * Appends a new operand from the input in the operand list. + * + * The input to be appended is selected by \c ::index. + */ + append_input, + + /** + * Appends a new operand from a constant in the imm list. + * + * The constant to be appended is selected by \c ::index, and its type is + * specified in \c ::reg_type. + */ + append_constant, + + /** + * Appends a new operand from a temporary in the operand list. + * + * The temporary to be appended is selected by \c ::index. + */ + append_temporary, + + /** + * Appends a new null register in the operand list. + * + * The type of the null register is specified in \c ::reg_type. + */ + append_null_reg, + + append_vec1_grf, + append_vec2_grf, + append_vec4_grf, + append_vec8_grf, + append_vec16_grf, + + /** + * Allocate a register for the next temporary slot + * + * The type of the temporary is specified in \c ::reg_type. Registers + * cannot have type \c BRW_REGISTER_TYPE_VF, \c BRW_REGISTER_TYPE_V, or + * \c BRW_REGISTER_TYPE_VU. If the type \c BRW_REGISTER_TYPE_VF is used to + * declare a temporary, it has the special meaning to copy the result type. + */ + declare_temporary, + + /** + * Toggles the negate flag of the last added operand. + */ + neg_operand, + + /** + * Sets the absolute value flag of the last added operand. + * + * Also clears the negate flag. + */ + abs_operand, + + /** + * Changes the type of the last added operand. + * + * The new type of the operand is specified in \c ::reg_type. + */ + retype_operand, + + subscript_operand, + + /** + * Emit an instruction + * + * The opcode of the instruction is specified in \c ::gen_opcode. All + * operands are consumed by the new instruction. + */ + emit_instruction, + + /** + * Sets the saturate flag for the most recently emitted instruction. + */ + saturate_instruction, + + /** + * Sets the conditional modifier for the most recently emitted instruction. + */ + conditional_mod, + + predicate_instruction, + + /** + * Denotes the end of the byte code stream. + */ + end_of_stream +}; + +struct bytecode_instruction { + enum operation op; + + union { + enum PACKED opcode gen_opcode; + enum brw_reg_type reg_type; + enum brw_conditional_mod cmod; + enum brw_predicate pred; + uint8_t blob; + }; + + uint16_t index; + + bytecode_instruction(enum operation _op, enum opcode _gen_opcode) + : op(_op), gen_opcode(_gen_opcode), index(0) + { + assert(op == emit_instruction); + } + + bytecode_instruction(enum operation _op, enum brw_reg_type _reg_type) + : op(_op), reg_type(_reg_type), index(0) + { + assert(op == retype_operand || + op == declare_temporary || + op == append_null_reg); + } + + bytecode_instruction(enum operation _op, enum brw_reg_type _reg_type, + uint16_t _index) + : op(_op), reg_type(_reg_type), index(_index) + { + assert(op == subscript_operand || + op == append_constant); + } + + bytecode_instruction(enum operation _op, enum brw_predicate _pred) + : op(_op), pred(_pred), index(0) + { + assert(op == predicate_instruction); + } + + bytecode_instruction(enum operation _op, enum brw_conditional_mod _cmod) + : op(_op), cmod(_cmod), index(0) + { + assert(op == conditional_mod); + } + + bytecode_instruction(enum operation _op, uint16_t _index) + : op(_op), blob(0), index(_index) + { + assert(op == append_input || + op == append_temporary); + } + + bytecode_instruction(enum operation _op, uint8_t subnr, uint16_t nr) + : op(_op), blob(subnr), index(nr) + { + assert(op == append_vec1_grf || + op == append_vec2_grf || + op == append_vec4_grf || + op == append_vec8_grf || + op == append_vec16_grf); + } + + bytecode_instruction(enum operation _op) + : op(_op), blob(0), index(0) + { + assert(op == abs_operand || + op == neg_operand || + op == saturate_instruction || + op == append_output || + op == end_of_stream); + } +}; + +union immediate_value { + uint64_t uq; + int64_t q; + double df; + float f; + int d; + unsigned ud; + int16_t w; + uint16_t uw; + int8_t b; + uint8_t ub; +}; + +//STATIC_ASSERT(sizeof(struct bytecode_instruction) <= 4); + +void emit_instructions_from_bytecode(const brw::fs_builder &bld, + const struct bytecode_instruction *bi, + const fs_reg &result, + const fs_reg *inputs, + const union immediate_value *imm, + bool implicit_saturate); + +#endif /* CODEGEN_BUILDER_H */ diff --git a/src/intel/compiler/meson.build b/src/intel/compiler/meson.build index 21614c5baf99..d0bec0fccf28 100644 --- a/src/intel/compiler/meson.build +++ b/src/intel/compiler/meson.build @@ -19,6 +19,8 @@ # SOFTWARE. libintel_compiler_files = files( + 'codegen_builder.cpp', + 'codegen_builder.h', 'brw_cfg.cpp', 'brw_cfg.h', 'brw_clip.h', |