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:
parent
b10de4c1d8
commit
8c02a8e2d2
|
@ -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_;
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue