Module: Mesa Branch: master Commit: 8c02a8e2d207a1d085f7a8fb3a0117b50b769611 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=8c02a8e2d207a1d085f7a8fb3a0117b50b769611
Author: Rhys Perry <[email protected]> Date: Thu Dec 3 15:18:30 2020 +0000 aco: add get_const/is_constant_representable helpers Signed-off-by: Rhys Perry <[email protected]> Reviewed-by: Daniel Schürmann <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7798> --- src/amd/compiler/aco_ir.h | 45 ++++++++++++++++++++++++++++++ src/amd/compiler/aco_lower_to_hw_instr.cpp | 19 +++++-------- src/amd/compiler/aco_optimizer.cpp | 37 ++++-------------------- 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/amd/compiler/aco_ir.h b/src/amd/compiler/aco_ir.h index 0b313ca0dfb..daa30667a0f 100644 --- a/src/amd/compiler/aco_ir.h +++ b/src/amd/compiler/aco_ir.h @@ -556,6 +556,51 @@ public: setFixed(reg); } + /* This is useful over the constructors when you want to take a chip class + * for 1/2 PI or an unknown operand size. + */ + static Operand get_const(enum chip_class chip, uint64_t val, unsigned bytes) + { + if (val == 0x3e22f983 && bytes == 4 && chip >= GFX8) { + /* 1/2 PI can be an inline constant on GFX8+ */ + Operand op((uint32_t)val); + op.setFixed(PhysReg{248}); + return op; + } + + if (bytes == 8) + return Operand(val); + else if (bytes == 4) + return Operand((uint32_t)val); + else if (bytes == 2) + return Operand((uint16_t)val); + assert(bytes == 1); + return Operand((uint8_t)val); + } + + static bool is_constant_representable(uint64_t val, unsigned bytes, bool zext=false, bool sext=false) + { + if (bytes <= 4) + return true; + + if (zext && (val & 0xFFFFFFFF00000000) == 0x0000000000000000) + return true; + uint64_t upper33 = val & 0xFFFFFFFF80000000; + if (sext && (upper33 == 0xFFFFFFFF80000000 || upper33 == 0)) + return true; + + return val <= 64 || + val >= 0xFFFFFFFFFFFFFFF0 || /* [-16 .. -1] */ + val == 0x3FE0000000000000 || /* 0.5 */ + val == 0xBFE0000000000000 || /* -0.5 */ + val == 0x3FF0000000000000 || /* 1.0 */ + val == 0xBFF0000000000000 || /* -1.0 */ + val == 0x4000000000000000 || /* 2.0 */ + val == 0xC000000000000000 || /* -2.0 */ + val == 0x4010000000000000 || /* 4.0 */ + val == 0xC010000000000000; /* -4.0 */ + } + constexpr bool isTemp() const noexcept { return isTemp_; diff --git a/src/amd/compiler/aco_lower_to_hw_instr.cpp b/src/amd/compiler/aco_lower_to_hw_instr.cpp index c372c8779fb..1d98b931763 100644 --- a/src/amd/compiler/aco_lower_to_hw_instr.cpp +++ b/src/amd/compiler/aco_lower_to_hw_instr.cpp @@ -924,7 +924,8 @@ struct copy_operation { }; }; -void split_copy(unsigned offset, Definition *def, Operand *op, const copy_operation& src, bool ignore_uses, unsigned max_size) +void split_copy(lower_context *ctx, unsigned offset, Definition *def, Operand *op, + const copy_operation& src, bool ignore_uses, unsigned max_size) { PhysReg def_reg = src.def.physReg(); PhysReg op_reg = src.op.physReg(); @@ -952,14 +953,8 @@ void split_copy(unsigned offset, Definition *def, Operand *op, const copy_operat *def = Definition(src.def.tempId(), def_reg, def_cls); if (src.op.isConstant()) { assert(bytes >= 1 && bytes <= 8); - if (bytes == 8) - *op = Operand(src.op.constantValue64() >> (offset * 8u)); - else if (bytes == 4) - *op = Operand(uint32_t(src.op.constantValue64() >> (offset * 8u))); - else if (bytes == 2) - *op = Operand(uint16_t(src.op.constantValue64() >> (offset * 8u))); - else if (bytes == 1) - *op = Operand(uint8_t(src.op.constantValue64() >> (offset * 8u))); + uint64_t val = src.op.constantValue64() >> (offset * 8u); + *op = Operand::get_const(ctx->program->chip_class, val, bytes); } else { RegClass op_cls = bytes % 4 == 0 ? RegClass(src.op.regClass().type(), bytes / 4u) : RegClass(src.op.regClass().type(), bytes).as_subdword(); @@ -1072,7 +1067,7 @@ bool do_copy(lower_context* ctx, Builder& bld, const copy_operation& copy, bool Definition def; Operand op; - split_copy(offset, &def, &op, copy, false, 8); + split_copy(ctx, offset, &def, &op, copy, false, 8); if (def.physReg() == scc) { bld.sopc(aco_opcode::s_cmp_lg_i32, def, op, Operand(0u)); @@ -1160,7 +1155,7 @@ void do_swap(lower_context *ctx, Builder& bld, const copy_operation& copy, bool for (; offset < copy.bytes;) { Definition def; Operand op; - split_copy(offset, &def, &op, copy, true, 8); + split_copy(ctx, offset, &def, &op, copy, true, 8); assert(op.regClass() == def.regClass()); Operand def_as_op = Operand(def.physReg(), def.regClass()); @@ -1548,7 +1543,7 @@ void handle_operands(std::map<PhysReg, copy_operation>& copy_map, lower_context* } Definition def; Operand op; - split_copy(offset, &def, &op, original, false, 8); + split_copy(ctx, offset, &def, &op, original, false, 8); copy_operation new_copy = {op, def, def.bytes()}; for (unsigned i = 0; i < new_copy.bytes; i++) diff --git a/src/amd/compiler/aco_optimizer.cpp b/src/amd/compiler/aco_optimizer.cpp index b780a8f1529..3a4cf6c8556 100644 --- a/src/amd/compiler/aco_optimizer.cpp +++ b/src/amd/compiler/aco_optimizer.cpp @@ -185,37 +185,18 @@ struct ssa_info { void set_constant(chip_class chip, uint64_t constant) { Operand op16((uint16_t)constant); - Operand op32((uint32_t)constant); + Operand op32 = Operand::get_const(chip, constant, 4); add_label(label_literal); val = constant; if (chip >= GFX8 && !op16.isLiteral()) add_label(label_constant_16bit); - if (!op32.isLiteral() || ((uint32_t)constant == 0x3e22f983 && chip >= GFX8)) + if (!op32.isLiteral()) add_label(label_constant_32bit); - if (constant <= 64) { + if (Operand::is_constant_representable(constant, 8)) add_label(label_constant_64bit); - } else if (constant >= 0xFFFFFFFFFFFFFFF0) { /* [-16 .. -1] */ - add_label(label_constant_64bit); - } else if (constant == 0x3FE0000000000000) { /* 0.5 */ - add_label(label_constant_64bit); - } else if (constant == 0xBFE0000000000000) { /* -0.5 */ - add_label(label_constant_64bit); - } else if (constant == 0x3FF0000000000000) { /* 1.0 */ - add_label(label_constant_64bit); - } else if (constant == 0xBFF0000000000000) { /* -1.0 */ - add_label(label_constant_64bit); - } else if (constant == 0x4000000000000000) { /* 2.0 */ - add_label(label_constant_64bit); - } else if (constant == 0xC000000000000000) { /* -2.0 */ - add_label(label_constant_64bit); - } else if (constant == 0x4010000000000000) { /* 4.0 */ - add_label(label_constant_64bit); - } else if (constant == 0xC010000000000000) { /* -4.0 */ - add_label(label_constant_64bit); - } if (label & label_constant_64bit) { val = Operand(constant).constantValue(); @@ -809,15 +790,9 @@ unsigned get_operand_size(aco_ptr<Instruction>& instr, unsigned index) Operand get_constant_op(opt_ctx &ctx, ssa_info info, uint32_t bits) { - if (bits == 8) - return Operand((uint8_t)info.val); - if (bits == 16) - return Operand((uint16_t)info.val); - // TODO: this functions shouldn't be needed if we store Operand instead of value. - Operand op(info.val, bits == 64); - if (info.is_literal(32) && info.val == 0x3e22f983 && ctx.program->chip_class >= GFX8) - op.setFixed(PhysReg{248}); /* 1/2 PI can be an inline constant on GFX8+ */ - return op; + if (bits == 64) + return Operand(info.val, true); + return Operand::get_const(ctx.program->chip_class, info.val, bits / 8u); } bool fixed_to_exec(Operand op) _______________________________________________ mesa-commit mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-commit
