}
if (instr->operands.size() == 1 && instr->operands[0].isTemp())
ctx.info[instr->definitions[0].tempId()].set_temp(instr->operands[0].getTemp());
- else if (instr->definitions[0].getTemp().size() == instr->operands.size())
+ else
ctx.info[instr->definitions[0].tempId()].set_vec(instr.get());
break;
}
if (!ctx.info[instr->operands[0].tempId()].is_vec())
break;
Instruction* vec = ctx.info[instr->operands[0].tempId()].instr;
- if (instr->definitions.size() != vec->operands.size())
- break;
- for (unsigned i = 0; i < instr->definitions.size(); i++) {
- Operand vec_op = vec->operands[i];
+ unsigned split_offset = 0;
+ unsigned vec_offset = 0;
+ unsigned vec_index = 0;
+ for (unsigned i = 0; i < instr->definitions.size(); split_offset += instr->definitions[i++].bytes()) {
+ while (vec_offset < split_offset && vec_index < vec->operands.size())
+ vec_offset += vec->operands[vec_index++].bytes();
+
+ if (vec_offset != split_offset || vec->operands[vec_index].bytes() != instr->definitions[i].bytes())
+ continue;
+
+ Operand vec_op = vec->operands[vec_index];
if (vec_op.isConstant()) {
if (vec_op.isLiteral())
ctx.info[instr->definitions[i].tempId()].set_literal(vec_op.constantValue());
if (instr->opcode == aco_opcode::p_split_vector) {
unsigned num_used = 0;
unsigned idx = 0;
- for (unsigned i = 0; i < instr->definitions.size(); i++) {
+ unsigned split_offset = 0;
+ for (unsigned i = 0, offset = 0; i < instr->definitions.size(); offset += instr->definitions[i++].bytes()) {
if (ctx.uses[instr->definitions[i].tempId()]) {
num_used++;
idx = i;
+ split_offset = offset;
}
}
bool done = false;
unsigned off = 0;
Operand op;
for (Operand& vec_op : vec->operands) {
- if (off == idx * instr->definitions[0].size()) {
+ if (off == split_offset) {
op = vec_op;
break;
}
- off += vec_op.size();
+ off += vec_op.bytes();
}
- if (off != instr->operands[0].size()) {
+ if (off != instr->operands[0].bytes() && op.bytes() == instr->definitions[idx].bytes()) {
ctx.uses[instr->operands[0].tempId()]--;
for (Operand& vec_op : vec->operands) {
if (vec_op.isTemp())
}
}
- if (!done && num_used == 1) {
+ if (!done && num_used == 1 &&
+ instr->operands[0].bytes() % instr->definitions[idx].bytes() == 0 &&
+ split_offset % instr->definitions[idx].bytes() == 0) {
aco_ptr<Pseudo_instruction> extract{create_instruction<Pseudo_instruction>(aco_opcode::p_extract_vector, Format::PSEUDO, 2, 1)};
extract->operands[0] = instr->operands[0];
- extract->operands[1] = Operand((uint32_t) idx);
+ extract->operands[1] = Operand((uint32_t) split_offset / instr->definitions[idx].bytes());
extract->definitions[0] = instr->definitions[idx];
instr.reset(extract.release());
}