aco/ra: prevent underflow register for p_create_vector operands

It could happen that we tested negative out-of-range
registers for p_create_vector operands resulting in a crash.

Fixes: 8962510e38 ('aco/ra: Conservatively refactor get_reg_specified to use PhysRegInterval')
Closes: #4697
Reviewed-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Tony Wasserka <tony.wasserka@gmx.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10799>
(cherry picked from commit d659ce0d6c)
This commit is contained in:
Daniel Schürmann 2021-05-14 11:29:33 +02:00 committed by Eric Engestrom
parent df7c4454a9
commit fbc49e9116
2 changed files with 12 additions and 7 deletions

View file

@ -121,7 +121,7 @@
"description": "aco/ra: prevent underflow register for p_create_vector operands",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"master_sha": null,
"because_sha": "8962510e38fbaff792f60bc17d46507bb77401ac"
},

View file

@ -152,11 +152,11 @@ struct PhysRegInterval {
}
bool contains(PhysReg reg) const {
return lo() <= reg && reg < hi();
return lo() <= reg && reg < hi();
}
bool contains(const PhysRegInterval& needle) const {
return needle.lo() >= lo() && needle.hi() <= hi();
return needle.lo() >= lo() && needle.hi() <= hi();
}
PhysRegIterator begin() const {
@ -255,6 +255,7 @@ public:
/* Returns true if any of the bytes in the given range are allocated or blocked */
bool test(PhysReg start, unsigned num_bytes) {
for (PhysReg i = start; i.reg_b < start.reg_b + num_bytes; i = PhysReg(i + 1)) {
assert(i <= 511);
if (regs[i] & 0x0FFFFFFF)
return true;
if (regs[i] == 0xF0000000) {
@ -1187,6 +1188,7 @@ bool get_reg_specified(ra_ctx& ctx,
aco_ptr<Instruction>& instr,
PhysReg reg)
{
assert(reg <= 511);
std::pair<unsigned, unsigned> sdw_def_info;
if (rc.is_subdword())
sdw_def_info = get_subdword_definition_info(ctx.program, instr, rc);
@ -1197,7 +1199,7 @@ bool get_reg_specified(ra_ctx& ctx,
return false;
if (rc.type() == RegType::sgpr && reg % get_stride(rc) != 0)
return false;
return false;
PhysRegInterval reg_win = { reg, rc.size() };
PhysRegInterval bounds = get_reg_bounds(ctx.program, rc.type());
@ -1385,9 +1387,12 @@ PhysReg get_reg(ra_ctx& ctx,
op.getTemp().type() == temp.type() &&
ctx.assignments[op.tempId()].assigned) {
PhysReg reg = ctx.assignments[op.tempId()].reg;
reg.reg_b += (byte_offset - k);
if (get_reg_specified(ctx, reg_file, temp.regClass(), instr, reg))
return reg;
/* prevent underflow */
if (int(reg.reg_b + byte_offset - k) >= 0) {
reg.reg_b += (byte_offset - k);
if (get_reg_specified(ctx, reg_file, temp.regClass(), instr, reg))
return reg;
}
}
k += op.bytes();
}