ssa_rewrite: Recursively remove phis

This commit is contained in:
IndecisiveTurtle 2024-12-04 20:19:38 +02:00
parent 38ac0024bf
commit b5ac4c5569
4 changed files with 25 additions and 11 deletions

View file

@ -330,6 +330,7 @@ private:
template <typename T = Value, typename... Args>
T Inst(Opcode op, Args... args) {
auto it{block->PrependNewInst(insertion_point, op, {Value{args}...})};
it->SetParent(block);
return T{Value{&*it}};
}
@ -347,6 +348,7 @@ private:
u32 raw_flags{};
std::memcpy(&raw_flags, &flags.proxy, sizeof(flags.proxy));
auto it{block->PrependNewInst(insertion_point, op, {Value{args}...}, raw_flags)};
it->SetParent(block);
return T{Value{&*it}};
}
};

View file

@ -150,7 +150,6 @@ void Inst::AddPhiOperand(Block* predecessor, const Value& value) {
}
void Inst::Invalidate() {
ASSERT(uses.empty());
ClearArgs();
ReplaceOpcode(Opcode::Void);
}

View file

@ -164,7 +164,6 @@ IR::Opcode UndefOpcode(const FlagTag) noexcept {
enum class Status {
Start,
SetValue,
PreparePhiArgument,
PushPhiArgument,
};
@ -253,12 +252,10 @@ public:
IR::Inst* const phi{stack.back().phi};
phi->AddPhiOperand(*stack.back().pred_it, stack.back().result);
++stack.back().pred_it;
}
[[fallthrough]];
case Status::PreparePhiArgument:
prepare_phi_operand();
break;
}
}
} while (stack.size() > 1);
return stack.back().result;
}
@ -266,16 +263,13 @@ public:
void SealBlock(IR::Block* block) {
const auto it{incomplete_phis.find(block)};
if (it != incomplete_phis.end()) {
for (auto& pair : it->second) {
auto& variant{pair.first};
auto& phi{pair.second};
for (auto& [variant, phi] : it->second) {
std::visit([&](auto& variable) { AddPhiOperands(variable, *phi, block); }, variant);
}
}
block->SsaSeal();
}
private:
template <typename Type>
IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) {
for (IR::Block* const imm_pred : block->ImmPredecessors()) {
@ -317,6 +311,12 @@ private:
list.insert(reinsert_point, phi);
phi.ReplaceUsesWith(same);
// TODO: Try to recursively remove all phi users, which might have become trivial
const auto users = phi.Uses();
for (const auto& [user, arg_index] : users) {
if (user->GetOpcode() == IR::Opcode::Phi) {
TryRemoveTrivialPhi(*user, user->GetParent(), undef_opcode);
}
}
return same;
}

View file

@ -129,6 +129,14 @@ public:
Inst& operator=(Inst&&) = delete;
Inst(Inst&&) = delete;
IR::Block* GetParent() {
ASSERT(parent);
return parent;
}
void SetParent(IR::Block* block) {
parent = block;
}
/// Get the number of uses this instruction has.
[[nodiscard]] int UseCount() const noexcept {
return uses.size();
@ -214,6 +222,10 @@ public:
return std::bit_cast<DefinitionType>(definition);
}
const auto Uses() const {
return uses;
}
private:
struct NonTriviallyDummy {
NonTriviallyDummy() noexcept {}
@ -226,6 +238,7 @@ private:
IR::Opcode op{};
u32 flags{};
u32 definition{};
IR::Block* parent{};
union {
NonTriviallyDummy dummy{};
boost::container::small_vector<std::pair<Block*, Value>, 2> phi_args;
@ -234,7 +247,7 @@ private:
boost::container::list<IR::Use> uses;
};
static_assert(sizeof(Inst) <= 152, "Inst size unintentionally increased");
static_assert(sizeof(Inst) <= 160, "Inst size unintentionally increased");
using U1 = TypedValue<Type::U1>;
using U8 = TypedValue<Type::U8>;
@ -392,4 +405,4 @@ template <>
struct hash<Shader::IR::Value> {
std::size_t operator()(const Shader::IR::Value& v) const;
};
} // namespace std
} // namespace std