From f2348301ea59bfd1fa96cbe684780dfc36a1a69d Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 15 Dec 2013 14:40:18 -0800 Subject: [PATCH] More aggressive constant propagation pass. --- .../passes/constant_propagation_pass.cc | 108 ++++++++++++++++++ src/alloy/hir/instr.cc | 10 +- src/alloy/hir/instr.h | 1 + 3 files changed, 118 insertions(+), 1 deletion(-) diff --git a/src/alloy/compiler/passes/constant_propagation_pass.cc b/src/alloy/compiler/passes/constant_propagation_pass.cc index 2ddbce90f..2f49c41ad 100644 --- a/src/alloy/compiler/passes/constant_propagation_pass.cc +++ b/src/alloy/compiler/passes/constant_propagation_pass.cc @@ -48,6 +48,72 @@ int ConstantPropagationPass::Run(FunctionBuilder* builder) { while (i) { Value* v = i->dest; switch (i->opcode->num) { + case OPCODE_DEBUG_BREAK_TRUE: + if (i->src1.value->IsConstant()) { + if (i->src1.value->IsConstantTrue()) { + i->Replace(&OPCODE_DEBUG_BREAK_info, i->flags); + } else { + i->Remove(); + } + } + break; + + case OPCODE_TRAP_TRUE: + if (i->src1.value->IsConstant()) { + if (i->src1.value->IsConstantTrue()) { + i->Replace(&OPCODE_TRAP_info, i->flags); + } else { + i->Remove(); + } + } + break; + + case OPCODE_CALL_TRUE: + if (i->src1.value->IsConstant()) { + if (i->src1.value->IsConstantTrue()) { + auto symbol_info = i->src2.symbol_info; + i->Replace(&OPCODE_CALL_info, i->flags); + i->src1.symbol_info = symbol_info; + } else { + i->Remove(); + } + } + break; + case OPCODE_CALL_INDIRECT_TRUE: + if (i->src1.value->IsConstant()) { + if (i->src1.value->IsConstantTrue()) { + auto value = i->src2.value; + i->Replace(&OPCODE_CALL_INDIRECT_info, i->flags); + i->set_src1(value); + } else { + i->Remove(); + } + } + break; + + case OPCODE_BRANCH_TRUE: + if (i->src1.value->IsConstant()) { + if (i->src1.value->IsConstantTrue()) { + auto label = i->src2.label; + i->Replace(&OPCODE_BRANCH_info, i->flags); + i->src1.label = label; + } else { + i->Remove(); + } + } + break; + case OPCODE_BRANCH_FALSE: + if (i->src1.value->IsConstant()) { + if (i->src1.value->IsConstantFalse()) { + auto label = i->src2.label; + i->Replace(&OPCODE_BRANCH_info, i->flags); + i->src1.label = label; + } else { + i->Remove(); + } + } + break; + case OPCODE_CAST: if (i->src1.value->IsConstant()) { TypeName target_type = v->type; @@ -81,6 +147,39 @@ int ConstantPropagationPass::Run(FunctionBuilder* builder) { } break; + case OPCODE_SELECT: + if (i->src1.value->IsConstant()) { + if (i->src1.value->IsConstantTrue()) { + v->set_from(i->src2.value); + } else { + v->set_from(i->src3.value); + } + i->Remove(); + } + break; + case OPCODE_IS_TRUE: + if (i->src1.value->IsConstant()) { + if (i->src1.value->IsConstantTrue()) { + v->set_constant((int8_t)1); + } else { + v->set_constant((int8_t)0); + } + i->Remove(); + } + break; + case OPCODE_IS_FALSE: + if (i->src1.value->IsConstant()) { + if (i->src1.value->IsConstantFalse()) { + v->set_constant((int8_t)1); + } else { + v->set_constant((int8_t)0); + } + i->Remove(); + } + break; + + // TODO(benvanik): compares + case OPCODE_ADD: if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) { v->set_from(i->src1.value); @@ -183,6 +282,7 @@ int ConstantPropagationPass::Run(FunctionBuilder* builder) { i->Remove(); } break; + // TODO(benvanik): VECTOR_SHL case OPCODE_SHR: if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) { v->set_from(i->src1.value); @@ -197,6 +297,7 @@ int ConstantPropagationPass::Run(FunctionBuilder* builder) { i->Remove(); } break; + // TODO(benvanik): ROTATE_LEFT case OPCODE_BYTE_SWAP: if (i->src1.value->IsConstant()) { v->set_from(i->src1.value); @@ -204,6 +305,13 @@ int ConstantPropagationPass::Run(FunctionBuilder* builder) { i->Remove(); } break; + // TODO(benvanik): INSERT/EXTRACT + // TODO(benvanik): SPLAT/PERMUTE/SWIZZLE + case OPCODE_SPLAT: + if (i->src1.value->IsConstant()) { + // Quite a few of these, from building vec128s. + } + break; } i = i->next; } diff --git a/src/alloy/hir/instr.cc b/src/alloy/hir/instr.cc index 0cc38464c..b800a24dd 100644 --- a/src/alloy/hir/instr.cc +++ b/src/alloy/hir/instr.cc @@ -48,7 +48,10 @@ void Instr::set_src3(Value* value) { src3_use = value ? value->AddUse(block->arena, this) : NULL; } -void Instr::Remove() { +void Instr::Replace(const OpcodeInfo* opcode, uint16_t flags) { + this->opcode = opcode; + this->flags = flags; + if (dest) { dest->def = NULL; } @@ -64,6 +67,11 @@ void Instr::Remove() { src3.value->RemoveUse(src3_use); src3_use = NULL; } +} + +void Instr::Remove() { + // Remove all srcs/dest. + Replace(&OPCODE_NOP_info, 0); if (prev) { prev->next = next; diff --git a/src/alloy/hir/instr.h b/src/alloy/hir/instr.h index 517232cc5..764c62ef8 100644 --- a/src/alloy/hir/instr.h +++ b/src/alloy/hir/instr.h @@ -54,6 +54,7 @@ public: void set_src2(Value* value); void set_src3(Value* value); + void Replace(const OpcodeInfo* opcode, uint16_t flags); void Remove(); };