Basic constant propagation.

This commit is contained in:
Ben Vanik
2013-12-07 05:52:51 -08:00
parent 57432d5996
commit 3b268f07ef
10 changed files with 584 additions and 147 deletions

View File

@@ -10,7 +10,7 @@
#ifndef ALLOY_COMPILER_PASSES_H_
#define ALLOY_COMPILER_PASSES_H_
//#include <alloy/compiler/passes/constant_propagation_pass.h>
#include <alloy/compiler/passes/constant_propagation_pass.h>
#include <alloy/compiler/passes/context_promotion_pass.h>
#include <alloy/compiler/passes/dead_code_elimination_pass.h>
//#include <alloy/compiler/passes/dead_store_elimination_pass.h>
@@ -72,7 +72,7 @@
// instead as it may be faster (at least on the block-level).
//
// - ConstantPropagation
// One ContextPromotion has run there will likely be a whole slew of
// Once ContextPromotion has run there will likely be a whole slew of
// constants that can be pushed through the function.
// Example:
// store_context +100, 1000

View File

@@ -0,0 +1,215 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <alloy/compiler/passes/constant_propagation_pass.h>
using namespace alloy;
using namespace alloy::compiler;
using namespace alloy::compiler::passes;
using namespace alloy::hir;
ConstantPropagationPass::ConstantPropagationPass() :
Pass() {
}
ConstantPropagationPass::~ConstantPropagationPass() {
}
int ConstantPropagationPass::Run(FunctionBuilder* builder) {
// Once ContextPromotion has run there will likely be a whole slew of
// constants that can be pushed through the function.
// Example:
// store_context +100, 1000
// v0 = load_context +100
// v1 = add v0, v0
// store_context +200, v1
// after PromoteContext:
// store_context +100, 1000
// v0 = 1000
// v1 = add v0, v0
// store_context +200, v1
// after PropagateConstants:
// store_context +100, 1000
// v0 = 1000
// v1 = add 1000, 1000
// store_context +200, 2000
// A DCE run after this should clean up any of the values no longer needed.
Block* block = builder->first_block();
while (block) {
Instr* i = block->instr_head;
while (i) {
Value* v = i->dest;
switch (i->opcode->num) {
case OPCODE_CAST:
if (i->src1.value->IsConstant()) {
TypeName target_type = v->type;
v->set_from(i->src1.value);
v->Cast(target_type);
i->Remove();
}
break;
case OPCODE_ZERO_EXTEND:
if (i->src1.value->IsConstant()) {
TypeName target_type = v->type;
v->set_from(i->src1.value);
v->ZeroExtend(target_type);
i->Remove();
}
break;
case OPCODE_SIGN_EXTEND:
if (i->src1.value->IsConstant()) {
TypeName target_type = v->type;
v->set_from(i->src1.value);
v->SignExtend(target_type);
i->Remove();
}
break;
case OPCODE_TRUNCATE:
if (i->src1.value->IsConstant()) {
TypeName target_type = v->type;
v->set_from(i->src1.value);
v->Truncate(target_type);
i->Remove();
}
break;
case OPCODE_ADD:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Add(i->src2.value);
i->Remove();
}
break;
// TODO(benvanik): ADD_CARRY
case OPCODE_SUB:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Sub(i->src2.value);
i->Remove();
}
break;
case OPCODE_MUL:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Mul(i->src2.value);
i->Remove();
}
break;
case OPCODE_DIV:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Div(i->src2.value);
i->Remove();
}
break;
case OPCODE_REM:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Rem(i->src2.value);
i->Remove();
}
break;
// case OPCODE_MULADD:
// case OPCODE_MULSUB
case OPCODE_NEG:
if (i->src1.value->IsConstant()) {
v->set_from(i->src1.value);
v->Neg();
i->Remove();
}
break;
case OPCODE_ABS:
if (i->src1.value->IsConstant()) {
v->set_from(i->src1.value);
v->Abs();
i->Remove();
}
break;
case OPCODE_SQRT:
if (i->src1.value->IsConstant()) {
v->set_from(i->src1.value);
v->Sqrt();
i->Remove();
}
break;
case OPCODE_RSQRT:
if (i->src1.value->IsConstant()) {
v->set_from(i->src1.value);
v->RSqrt();
i->Remove();
}
break;
case OPCODE_AND:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->And(i->src2.value);
i->Remove();
}
break;
case OPCODE_OR:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Or(i->src2.value);
i->Remove();
}
break;
case OPCODE_XOR:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Xor(i->src2.value);
i->Remove();
}
break;
case OPCODE_NOT:
if (i->src1.value->IsConstant()) {
v->set_from(i->src1.value);
v->Not();
i->Remove();
}
break;
case OPCODE_SHL:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Shl(i->src2.value);
i->Remove();
}
break;
case OPCODE_SHR:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Shr(i->src2.value);
i->Remove();
}
break;
case OPCODE_SHA:
if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) {
v->set_from(i->src1.value);
v->Sha(i->src2.value);
i->Remove();
}
break;
case OPCODE_BYTE_SWAP:
if (i->src1.value->IsConstant()) {
v->set_from(i->src1.value);
v->ByteSwap();
i->Remove();
}
break;
}
i = i->next;
}
block = block->next;
}
return 0;
}

View File

@@ -0,0 +1,37 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef ALLOY_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
#define ALLOY_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
#include <alloy/compiler/pass.h>
namespace alloy {
namespace compiler {
namespace passes {
class ConstantPropagationPass : public Pass {
public:
ConstantPropagationPass();
virtual ~ConstantPropagationPass();
virtual int Run(hir::FunctionBuilder* builder);
private:
};
} // namespace passes
} // namespace compiler
} // namespace alloy
#endif // ALLOY_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_

View File

@@ -1,8 +1,8 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
#'constant_propagation_pass.cc',
#'constant_propagation_pass.h',
'constant_propagation_pass.cc',
'constant_propagation_pass.h',
'context_promotion_pass.cc',
'context_promotion_pass.h',
'dead_code_elimination_pass.cc',