spirv: Move phi arguments emit to a separate function

This commit is contained in:
ReinUsesLisp 2021-02-24 18:37:47 -03:00 committed by ameerj
parent 3bc857f2f3
commit 726625cf50

View File

@ -163,6 +163,31 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit
} }
} }
} }
Id PhiArgDef(EmitContext& ctx, IR::Inst* inst, size_t index) {
// Phi nodes can have forward declarations, if an argument is not defined provide a forward
// declaration of it. Invoke will take care of giving it the right definition when it's
// actually defined.
const IR::Value arg{inst->Arg(index)};
if (arg.IsImmediate()) {
// Let the context handle immediate definitions, as it already knows how
return ctx.Def(arg);
}
IR::Inst* const arg_inst{arg.Inst()};
if (const Id def{arg_inst->Definition<Id>()}; Sirit::ValidId(def)) {
// Return the current definition if it exists
return def;
}
if (arg_inst == inst) {
// This is a self referencing phi node
// Self-referencing definition will be set by the caller, so just grab the current id
return ctx.CurrentId();
}
// If it hasn't been defined and it's not a self reference, get a forward declaration
const Id def{ctx.ForwardDeclarationId()};
arg_inst->SetDefinition<Id>(def);
return def;
}
} // Anonymous namespace } // Anonymous namespace
std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program) { std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program) {
@ -205,33 +230,8 @@ Id EmitPhi(EmitContext& ctx, IR::Inst* inst) {
boost::container::small_vector<Id, 32> operands; boost::container::small_vector<Id, 32> operands;
operands.reserve(num_args * 2); operands.reserve(num_args * 2);
for (size_t index = 0; index < num_args; ++index) { for (size_t index = 0; index < num_args; ++index) {
// Phi nodes can have forward declarations, if an argument is not defined provide a forward operands.push_back(PhiArgDef(ctx, inst, index));
// declaration of it. Invoke will take care of giving it the right definition when it's operands.push_back(inst->PhiBlock(index)->Definition<Id>());
// actually defined.
const IR::Value arg{inst->Arg(index)};
Id def{};
if (arg.IsImmediate()) {
// Let the context handle immediate definitions, as it already knows how
def = ctx.Def(arg);
} else {
IR::Inst* const arg_inst{arg.Inst()};
def = arg_inst->Definition<Id>();
if (!Sirit::ValidId(def)) {
if (arg_inst == inst) {
// This is a self referencing phi node
def = ctx.CurrentId();
// Self-referencing definition will be set by the caller
} else {
// If it hasn't been defined and it's not a self reference,
// get a forward declaration
def = ctx.ForwardDeclarationId();
arg_inst->SetDefinition<Id>(def);
}
}
}
IR::Block* const phi_block{inst->PhiBlock(index)};
operands.push_back(def);
operands.push_back(phi_block->Definition<Id>());
} }
const Id result_type{TypeId(ctx, inst->Arg(0).Type())}; const Id result_type{TypeId(ctx, inst->Arg(0).Type())};
return ctx.OpPhi(result_type, std::span(operands.data(), operands.size())); return ctx.OpPhi(result_type, std::span(operands.data(), operands.size()));