mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-03 16:39:01 -06:00 
			
		
		
		
	shader: Read branch conditions from an instruction
Fixes the identity removal pass.
This commit is contained in:
		@@ -200,7 +200,7 @@ void Precolor(EmitContext& ctx, const IR::Program& program) {
 | 
			
		||||
            }
 | 
			
		||||
            // Add reference to the phi node on the phi predecessor to avoid overwritting it
 | 
			
		||||
            for (size_t i = 0; i < num_args; ++i) {
 | 
			
		||||
                IR::IREmitter{*phi.PhiBlock(i)}.DummyReference(IR::Value{&phi});
 | 
			
		||||
                IR::IREmitter{*phi.PhiBlock(i)}.Reference(IR::Value{&phi});
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,10 @@ void EmitIdentity(EmitContext&, IR::Inst& inst, const IR::Value& value) {
 | 
			
		||||
    Alias(inst, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmitConditionRef(EmitContext&, IR::Inst& inst, const IR::Value& value) {
 | 
			
		||||
    Alias(inst, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmitBitCastU16F16(EmitContext&, IR::Inst& inst, const IR::Value& value) {
 | 
			
		||||
    Alias(inst, value);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,8 @@ class EmitContext;
 | 
			
		||||
void EmitPhi(EmitContext& ctx, IR::Inst& inst);
 | 
			
		||||
void EmitVoid(EmitContext& ctx);
 | 
			
		||||
void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
 | 
			
		||||
void EmitDummyReference(EmitContext&);
 | 
			
		||||
void EmitConditionRef(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
 | 
			
		||||
void EmitReference(EmitContext&);
 | 
			
		||||
void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value);
 | 
			
		||||
void EmitJoin(EmitContext& ctx);
 | 
			
		||||
void EmitDemoteToHelperInvocation(EmitContext& ctx);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ void EmitPhi(EmitContext&, IR::Inst&) {}
 | 
			
		||||
 | 
			
		||||
void EmitVoid(EmitContext&) {}
 | 
			
		||||
 | 
			
		||||
void EmitDummyReference(EmitContext&) {}
 | 
			
		||||
void EmitReference(EmitContext&) {}
 | 
			
		||||
 | 
			
		||||
void EmitPhiMove(EmitContext& ctx, const IR::Value& phi, const IR::Value& value) {
 | 
			
		||||
    if (phi == value) {
 | 
			
		||||
 
 | 
			
		||||
@@ -139,6 +139,7 @@ void RegAlloc::Free(Id id) {
 | 
			
		||||
/*static*/ bool RegAlloc::IsAliased(const IR::Inst& inst) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::Identity:
 | 
			
		||||
    case IR::Opcode::ConditionRef:
 | 
			
		||||
    case IR::Opcode::BitCastU16F16:
 | 
			
		||||
    case IR::Opcode::BitCastU32F32:
 | 
			
		||||
    case IR::Opcode::BitCastU64F64:
 | 
			
		||||
 
 | 
			
		||||
@@ -469,7 +469,15 @@ Id EmitIdentity(EmitContext& ctx, const IR::Value& value) {
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmitDummyReference(EmitContext&) {}
 | 
			
		||||
Id EmitConditionRef(EmitContext& ctx, const IR::Value& value) {
 | 
			
		||||
    const Id id{ctx.Def(value)};
 | 
			
		||||
    if (!Sirit::ValidId(id)) {
 | 
			
		||||
        throw NotImplementedException("Forward identity declaration");
 | 
			
		||||
    }
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmitReference(EmitContext&) {}
 | 
			
		||||
 | 
			
		||||
void EmitPhiMove(EmitContext&) {
 | 
			
		||||
    throw LogicError("Unreachable instruction");
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,8 @@ class EmitContext;
 | 
			
		||||
Id EmitPhi(EmitContext& ctx, IR::Inst* inst);
 | 
			
		||||
void EmitVoid(EmitContext& ctx);
 | 
			
		||||
Id EmitIdentity(EmitContext& ctx, const IR::Value& value);
 | 
			
		||||
void EmitDummyReference(EmitContext&);
 | 
			
		||||
Id EmitConditionRef(EmitContext& ctx, const IR::Value& value);
 | 
			
		||||
void EmitReference(EmitContext&);
 | 
			
		||||
void EmitPhiMove(EmitContext&);
 | 
			
		||||
void EmitJoin(EmitContext& ctx);
 | 
			
		||||
void EmitDemoteToHelperInvocation(EmitContext& ctx);
 | 
			
		||||
 
 | 
			
		||||
@@ -61,8 +61,12 @@ F64 IREmitter::Imm64(f64 value) const {
 | 
			
		||||
    return F64{Value{value}};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IREmitter::DummyReference(const Value& value) {
 | 
			
		||||
    Inst(Opcode::DummyReference, value);
 | 
			
		||||
U1 IREmitter::ConditionRef(const U1& value) {
 | 
			
		||||
    return Inst<U1>(Opcode::ConditionRef, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IREmitter::Reference(const Value& value) {
 | 
			
		||||
    Inst(Opcode::Reference, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IREmitter::PhiMove(IR::Inst& phi, const Value& value) {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,9 @@ public:
 | 
			
		||||
    [[nodiscard]] U64 Imm64(s64 value) const;
 | 
			
		||||
    [[nodiscard]] F64 Imm64(f64 value) const;
 | 
			
		||||
 | 
			
		||||
    void DummyReference(const Value& value);
 | 
			
		||||
    U1 ConditionRef(const U1& value);
 | 
			
		||||
    void Reference(const Value& value);
 | 
			
		||||
 | 
			
		||||
    void PhiMove(IR::Inst& phi, const Value& value);
 | 
			
		||||
 | 
			
		||||
    void Prologue();
 | 
			
		||||
 
 | 
			
		||||
@@ -56,7 +56,8 @@ Inst::~Inst() {
 | 
			
		||||
 | 
			
		||||
bool Inst::MayHaveSideEffects() const noexcept {
 | 
			
		||||
    switch (op) {
 | 
			
		||||
    case Opcode::DummyReference:
 | 
			
		||||
    case Opcode::ConditionRef:
 | 
			
		||||
    case Opcode::Reference:
 | 
			
		||||
    case Opcode::PhiMove:
 | 
			
		||||
    case Opcode::Prologue:
 | 
			
		||||
    case Opcode::Epilogue:
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,8 @@
 | 
			
		||||
OPCODE(Phi,                                                 Opaque,                                                                                         )
 | 
			
		||||
OPCODE(Identity,                                            Opaque,         Opaque,                                                                         )
 | 
			
		||||
OPCODE(Void,                                                Void,                                                                                           )
 | 
			
		||||
OPCODE(DummyReference,                                      Void,           Opaque,                                                                         )
 | 
			
		||||
OPCODE(ConditionRef,                                        U1,             U1,                                                                             )
 | 
			
		||||
OPCODE(Reference,                                           Void,           Opaque,                                                                         )
 | 
			
		||||
OPCODE(PhiMove,                                             Void,           Opaque,         Opaque,                                                         )
 | 
			
		||||
 | 
			
		||||
// Special operations
 | 
			
		||||
 
 | 
			
		||||
@@ -703,8 +703,7 @@ private:
 | 
			
		||||
 | 
			
		||||
                // Implement if header block
 | 
			
		||||
                IR::IREmitter ir{*current_block};
 | 
			
		||||
                const IR::U1 cond{VisitExpr(ir, *stmt.cond)};
 | 
			
		||||
                ir.DummyReference(cond);
 | 
			
		||||
                const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))};
 | 
			
		||||
 | 
			
		||||
                const size_t if_node_index{syntax_list.size()};
 | 
			
		||||
                syntax_list.emplace_back();
 | 
			
		||||
@@ -754,8 +753,7 @@ private:
 | 
			
		||||
 | 
			
		||||
                // The continue block is located at the end of the loop
 | 
			
		||||
                IR::IREmitter ir{*continue_block};
 | 
			
		||||
                const IR::U1 cond{VisitExpr(ir, *stmt.cond)};
 | 
			
		||||
                ir.DummyReference(cond);
 | 
			
		||||
                const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))};
 | 
			
		||||
 | 
			
		||||
                IR::Block* const body_block{syntax_list.at(body_block_index).data.block};
 | 
			
		||||
                loop_header_block->AddBranch(body_block);
 | 
			
		||||
@@ -791,8 +789,7 @@ private:
 | 
			
		||||
                IR::Block* const skip_block{MergeBlock(parent, stmt)};
 | 
			
		||||
 | 
			
		||||
                IR::IREmitter ir{*current_block};
 | 
			
		||||
                const IR::U1 cond{VisitExpr(ir, *stmt.cond)};
 | 
			
		||||
                ir.DummyReference(cond);
 | 
			
		||||
                const IR::U1 cond{ir.ConditionRef(VisitExpr(ir, *stmt.cond))};
 | 
			
		||||
                current_block->AddBranch(break_block);
 | 
			
		||||
                current_block->AddBranch(skip_block);
 | 
			
		||||
                current_block = skip_block;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user