aco: add get_const/is_constant_representable helpers

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7798>
This commit is contained in:
Rhys Perry 2020-12-03 15:18:30 +00:00 committed by Marge Bot
parent b10de4c1d8
commit 8c02a8e2d2
3 changed files with 58 additions and 43 deletions

View File

@ -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_;

View File

@ -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++)

View File

@ -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)