[JIT] Run the SimplificationPass/ConstantPropagationPass until there are no changes.
This commit is contained in:
parent
b121f45c7f
commit
5fbcb8991e
|
@ -10,6 +10,8 @@
|
||||||
#ifndef XENIA_CPU_COMPILER_COMPILER_PASSES_H_
|
#ifndef XENIA_CPU_COMPILER_COMPILER_PASSES_H_
|
||||||
#define XENIA_CPU_COMPILER_COMPILER_PASSES_H_
|
#define XENIA_CPU_COMPILER_COMPILER_PASSES_H_
|
||||||
|
|
||||||
|
#include "xenia/cpu/compiler/passes/conditional_group_pass.h"
|
||||||
|
#include "xenia/cpu/compiler/passes/conditional_group_subpass.h"
|
||||||
#include "xenia/cpu/compiler/passes/constant_propagation_pass.h"
|
#include "xenia/cpu/compiler/passes/constant_propagation_pass.h"
|
||||||
#include "xenia/cpu/compiler/passes/context_promotion_pass.h"
|
#include "xenia/cpu/compiler/passes/context_promotion_pass.h"
|
||||||
#include "xenia/cpu/compiler/passes/control_flow_analysis_pass.h"
|
#include "xenia/cpu/compiler/passes/control_flow_analysis_pass.h"
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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 "xenia/cpu/compiler/passes/conditional_group_pass.h"
|
||||||
|
|
||||||
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
#include "xenia/base/profiling.h"
|
||||||
|
#include "xenia/cpu/compiler/compiler.h"
|
||||||
|
#include "xenia/cpu/ppc/ppc_context.h"
|
||||||
|
#include "xenia/cpu/processor.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
namespace compiler {
|
||||||
|
namespace passes {
|
||||||
|
|
||||||
|
// TODO(benvanik): remove when enums redefined.
|
||||||
|
using namespace xe::cpu::hir;
|
||||||
|
|
||||||
|
using xe::cpu::hir::Block;
|
||||||
|
using xe::cpu::hir::HIRBuilder;
|
||||||
|
using xe::cpu::hir::Instr;
|
||||||
|
using xe::cpu::hir::Value;
|
||||||
|
|
||||||
|
ConditionalGroupPass::ConditionalGroupPass() : CompilerPass() {}
|
||||||
|
|
||||||
|
ConditionalGroupPass::~ConditionalGroupPass() {}
|
||||||
|
|
||||||
|
bool ConditionalGroupPass::Initialize(Compiler* compiler) {
|
||||||
|
if (!CompilerPass::Initialize(compiler)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < passes_.size(); ++i) {
|
||||||
|
auto& pass = passes_[i];
|
||||||
|
if (!pass->Initialize(compiler)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConditionalGroupPass::Run(HIRBuilder* builder) {
|
||||||
|
bool dirty;
|
||||||
|
int loops = 0;
|
||||||
|
do {
|
||||||
|
assert_true(loops < 20); // arbitrary number
|
||||||
|
dirty = false;
|
||||||
|
for (size_t i = 0; i < passes_.size(); ++i) {
|
||||||
|
scratch_arena()->Reset();
|
||||||
|
auto& pass = passes_[i];
|
||||||
|
auto subpass = dynamic_cast<ConditionalGroupSubpass*>(pass.get());
|
||||||
|
if (!subpass) {
|
||||||
|
if (!pass->Run(builder)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bool result = false;
|
||||||
|
if (!subpass->Run(builder, result)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dirty |= result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loops++;
|
||||||
|
} while (dirty);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConditionalGroupPass::AddPass(std::unique_ptr<CompilerPass> pass) {
|
||||||
|
passes_.push_back(std::move(pass));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
|
@ -0,0 +1,45 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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 XENIA_CPU_COMPILER_PASSES_CONDITIONAL_GROUP_PASS_H_
|
||||||
|
#define XENIA_CPU_COMPILER_PASSES_CONDITIONAL_GROUP_PASS_H_
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "xenia/base/platform.h"
|
||||||
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
#include "xenia/cpu/compiler/passes/conditional_group_subpass.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
namespace compiler {
|
||||||
|
namespace passes {
|
||||||
|
|
||||||
|
class ConditionalGroupPass : public CompilerPass {
|
||||||
|
public:
|
||||||
|
ConditionalGroupPass();
|
||||||
|
virtual ~ConditionalGroupPass() override;
|
||||||
|
|
||||||
|
bool Initialize(Compiler* compiler) override;
|
||||||
|
|
||||||
|
bool Run(hir::HIRBuilder* builder) override;
|
||||||
|
|
||||||
|
void AddPass(std::unique_ptr<CompilerPass> pass);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<CompilerPass>> passes_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_CPU_COMPILER_PASSES_CONDITIONAL_GROUP_PASS_H_
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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 "xenia/cpu/compiler/passes/conditional_group_subpass.h"
|
||||||
|
|
||||||
|
#include "xenia/cpu/compiler/compiler.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
namespace compiler {
|
||||||
|
namespace passes {
|
||||||
|
|
||||||
|
ConditionalGroupSubpass::ConditionalGroupSubpass() : CompilerPass() {}
|
||||||
|
|
||||||
|
ConditionalGroupSubpass::~ConditionalGroupSubpass() = default;
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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 XENIA_CPU_COMPILER_PASSES_CONDITIONAL_GROUP_SUBPASS_H_
|
||||||
|
#define XENIA_CPU_COMPILER_PASSES_CONDITIONAL_GROUP_SUBPASS_H_
|
||||||
|
|
||||||
|
#include "xenia/base/arena.h"
|
||||||
|
#include "xenia/cpu/compiler/compiler_pass.h"
|
||||||
|
#include "xenia/cpu/hir/hir_builder.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
class Processor;
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
namespace compiler {
|
||||||
|
class Compiler;
|
||||||
|
namespace passes {
|
||||||
|
|
||||||
|
class ConditionalGroupSubpass : public CompilerPass {
|
||||||
|
public:
|
||||||
|
ConditionalGroupSubpass();
|
||||||
|
virtual ~ConditionalGroupSubpass();
|
||||||
|
|
||||||
|
bool Run(hir::HIRBuilder* builder) override {
|
||||||
|
bool dummy;
|
||||||
|
return Run(builder, dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Run(hir::HIRBuilder* builder, bool& result) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace passes
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_CPU_COMPILER_PASSES_CONDITIONAL_GROUP_SUBPASS_H_
|
|
@ -31,11 +31,12 @@ using xe::cpu::hir::HIRBuilder;
|
||||||
using xe::cpu::hir::TypeName;
|
using xe::cpu::hir::TypeName;
|
||||||
using xe::cpu::hir::Value;
|
using xe::cpu::hir::Value;
|
||||||
|
|
||||||
ConstantPropagationPass::ConstantPropagationPass() : CompilerPass() {}
|
ConstantPropagationPass::ConstantPropagationPass()
|
||||||
|
: ConditionalGroupSubpass() {}
|
||||||
|
|
||||||
ConstantPropagationPass::~ConstantPropagationPass() {}
|
ConstantPropagationPass::~ConstantPropagationPass() {}
|
||||||
|
|
||||||
bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
bool ConstantPropagationPass::Run(HIRBuilder* builder, bool& result) {
|
||||||
// Once 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.
|
// constants that can be pushed through the function.
|
||||||
// Example:
|
// Example:
|
||||||
|
@ -63,6 +64,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
// v1 = 19
|
// v1 = 19
|
||||||
// v2 = 0
|
// v2 = 0
|
||||||
|
|
||||||
|
result = false;
|
||||||
auto block = builder->first_block();
|
auto block = builder->first_block();
|
||||||
while (block) {
|
while (block) {
|
||||||
auto i = block->instr_head;
|
auto i = block->instr_head;
|
||||||
|
@ -76,6 +78,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
} else {
|
} else {
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -86,6 +89,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
} else {
|
} else {
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -98,6 +102,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
} else {
|
} else {
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_CALL_INDIRECT:
|
case OPCODE_CALL_INDIRECT:
|
||||||
|
@ -109,6 +114,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
}
|
}
|
||||||
i->Replace(&OPCODE_CALL_info, i->flags);
|
i->Replace(&OPCODE_CALL_info, i->flags);
|
||||||
i->src1.symbol = function;
|
i->src1.symbol = function;
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_CALL_INDIRECT_TRUE:
|
case OPCODE_CALL_INDIRECT_TRUE:
|
||||||
|
@ -120,6 +126,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
} else {
|
} else {
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -132,6 +139,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
} else {
|
} else {
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_BRANCH_FALSE:
|
case OPCODE_BRANCH_FALSE:
|
||||||
|
@ -143,6 +151,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
} else {
|
} else {
|
||||||
i->Remove();
|
i->Remove();
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -152,6 +161,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Cast(target_type);
|
v->Cast(target_type);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_CONVERT:
|
case OPCODE_CONVERT:
|
||||||
|
@ -160,6 +170,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Convert(target_type, RoundMode(i->flags));
|
v->Convert(target_type, RoundMode(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_ROUND:
|
case OPCODE_ROUND:
|
||||||
|
@ -167,6 +178,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Round(RoundMode(i->flags));
|
v->Round(RoundMode(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_ZERO_EXTEND:
|
case OPCODE_ZERO_EXTEND:
|
||||||
|
@ -175,6 +187,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->ZeroExtend(target_type);
|
v->ZeroExtend(target_type);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_SIGN_EXTEND:
|
case OPCODE_SIGN_EXTEND:
|
||||||
|
@ -183,6 +196,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->SignExtend(target_type);
|
v->SignExtend(target_type);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_TRUNCATE:
|
case OPCODE_TRUNCATE:
|
||||||
|
@ -191,6 +205,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Truncate(target_type);
|
v->Truncate(target_type);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -210,6 +225,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
i->Replace(&OPCODE_LOAD_MMIO_info, 0);
|
i->Replace(&OPCODE_LOAD_MMIO_info, 0);
|
||||||
i->src1.offset = reinterpret_cast<uint64_t>(mmio_range);
|
i->src1.offset = reinterpret_cast<uint64_t>(mmio_range);
|
||||||
i->src2.offset = address;
|
i->src2.offset = address;
|
||||||
|
result = true;
|
||||||
} else {
|
} else {
|
||||||
auto heap = memory->LookupHeap(address);
|
auto heap = memory->LookupHeap(address);
|
||||||
uint32_t protect;
|
uint32_t protect;
|
||||||
|
@ -222,18 +238,22 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
case INT8_TYPE:
|
case INT8_TYPE:
|
||||||
v->set_constant(xe::load<uint8_t>(host_addr));
|
v->set_constant(xe::load<uint8_t>(host_addr));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
break;
|
break;
|
||||||
case INT16_TYPE:
|
case INT16_TYPE:
|
||||||
v->set_constant(xe::load<uint16_t>(host_addr));
|
v->set_constant(xe::load<uint16_t>(host_addr));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
break;
|
break;
|
||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
v->set_constant(xe::load<uint32_t>(host_addr));
|
v->set_constant(xe::load<uint32_t>(host_addr));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
break;
|
break;
|
||||||
case INT64_TYPE:
|
case INT64_TYPE:
|
||||||
v->set_constant(xe::load<uint64_t>(host_addr));
|
v->set_constant(xe::load<uint64_t>(host_addr));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
break;
|
break;
|
||||||
case VEC128_TYPE:
|
case VEC128_TYPE:
|
||||||
vec128_t val;
|
vec128_t val;
|
||||||
|
@ -241,6 +261,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
val.high = xe::load<uint64_t>(host_addr + 8);
|
val.high = xe::load<uint64_t>(host_addr + 8);
|
||||||
v->set_constant(val);
|
v->set_constant(val);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert_unhandled_case(v->type);
|
assert_unhandled_case(v->type);
|
||||||
|
@ -270,6 +291,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
i->src1.offset = reinterpret_cast<uint64_t>(mmio_range);
|
i->src1.offset = reinterpret_cast<uint64_t>(mmio_range);
|
||||||
i->src2.offset = address;
|
i->src2.offset = address;
|
||||||
i->set_src3(value);
|
i->set_src3(value);
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -281,10 +303,12 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
auto src2 = i->src2.value;
|
auto src2 = i->src2.value;
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(src2);
|
i->set_src1(src2);
|
||||||
|
result = true;
|
||||||
} else if (i->src1.value->IsConstantFalse()) {
|
} else if (i->src1.value->IsConstantFalse()) {
|
||||||
auto src3 = i->src3.value;
|
auto src3 = i->src3.value;
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(src3);
|
i->set_src1(src3);
|
||||||
|
result = true;
|
||||||
} else if (i->src2.value->IsConstant() &&
|
} else if (i->src2.value->IsConstant() &&
|
||||||
i->src3.value->IsConstant()) {
|
i->src3.value->IsConstant()) {
|
||||||
// TODO: Select
|
// TODO: Select
|
||||||
|
@ -305,6 +329,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_constant(uint8_t(0));
|
v->set_constant(uint8_t(0));
|
||||||
}
|
}
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_IS_FALSE:
|
case OPCODE_IS_FALSE:
|
||||||
|
@ -315,6 +340,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_constant(uint8_t(0));
|
v->set_constant(uint8_t(0));
|
||||||
}
|
}
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_IS_NAN:
|
case OPCODE_IS_NAN:
|
||||||
|
@ -329,6 +355,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_constant(uint8_t(0));
|
v->set_constant(uint8_t(0));
|
||||||
}
|
}
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -338,6 +365,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantEQ(i->src2.value);
|
bool value = i->src1.value->IsConstantEQ(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_COMPARE_NE:
|
case OPCODE_COMPARE_NE:
|
||||||
|
@ -345,6 +373,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantNE(i->src2.value);
|
bool value = i->src1.value->IsConstantNE(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_COMPARE_SLT:
|
case OPCODE_COMPARE_SLT:
|
||||||
|
@ -352,6 +381,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantSLT(i->src2.value);
|
bool value = i->src1.value->IsConstantSLT(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_COMPARE_SLE:
|
case OPCODE_COMPARE_SLE:
|
||||||
|
@ -359,6 +389,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantSLE(i->src2.value);
|
bool value = i->src1.value->IsConstantSLE(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_COMPARE_SGT:
|
case OPCODE_COMPARE_SGT:
|
||||||
|
@ -366,6 +397,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantSGT(i->src2.value);
|
bool value = i->src1.value->IsConstantSGT(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_COMPARE_SGE:
|
case OPCODE_COMPARE_SGE:
|
||||||
|
@ -373,6 +405,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantSGE(i->src2.value);
|
bool value = i->src1.value->IsConstantSGE(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_COMPARE_ULT:
|
case OPCODE_COMPARE_ULT:
|
||||||
|
@ -380,6 +413,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantULT(i->src2.value);
|
bool value = i->src1.value->IsConstantULT(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_COMPARE_ULE:
|
case OPCODE_COMPARE_ULE:
|
||||||
|
@ -387,6 +421,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantULE(i->src2.value);
|
bool value = i->src1.value->IsConstantULE(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_COMPARE_UGT:
|
case OPCODE_COMPARE_UGT:
|
||||||
|
@ -394,6 +429,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantUGT(i->src2.value);
|
bool value = i->src1.value->IsConstantUGT(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_COMPARE_UGE:
|
case OPCODE_COMPARE_UGE:
|
||||||
|
@ -401,6 +437,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
bool value = i->src1.value->IsConstantUGE(i->src2.value);
|
bool value = i->src1.value->IsConstantUGE(i->src2.value);
|
||||||
i->dest->set_constant(uint8_t(value));
|
i->dest->set_constant(uint8_t(value));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -413,6 +450,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Add(i->src2.value);
|
v->Add(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_ADD_CARRY:
|
case OPCODE_ADD_CARRY:
|
||||||
|
@ -433,6 +471,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
i->set_src1(ca);
|
i->set_src1(ca);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_SUB:
|
case OPCODE_SUB:
|
||||||
|
@ -440,6 +479,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Sub(i->src2.value);
|
v->Sub(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_MUL:
|
case OPCODE_MUL:
|
||||||
|
@ -447,6 +487,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Mul(i->src2.value);
|
v->Mul(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
} else if (i->src1.value->IsConstant() ||
|
} else if (i->src1.value->IsConstant() ||
|
||||||
i->src2.value->IsConstant()) {
|
i->src2.value->IsConstant()) {
|
||||||
// Reorder the sources to make things simpler.
|
// Reorder the sources to make things simpler.
|
||||||
|
@ -460,12 +501,14 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
if (s2->type != VEC128_TYPE && s2->IsConstantOne()) {
|
if (s2->type != VEC128_TYPE && s2->IsConstantOne()) {
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(s1);
|
i->set_src1(s1);
|
||||||
|
result = true;
|
||||||
} else if (s2->type == VEC128_TYPE) {
|
} else if (s2->type == VEC128_TYPE) {
|
||||||
auto& c = s2->constant;
|
auto& c = s2->constant;
|
||||||
if (c.v128.f32[0] == 1.f && c.v128.f32[1] == 1.f &&
|
if (c.v128.f32[0] == 1.f && c.v128.f32[1] == 1.f &&
|
||||||
c.v128.f32[2] == 1.f && c.v128.f32[3] == 1.f) {
|
c.v128.f32[2] == 1.f && c.v128.f32[3] == 1.f) {
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(s1);
|
i->set_src1(s1);
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -475,6 +518,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->MulHi(i->src2.value, (i->flags & ARITHMETIC_UNSIGNED) != 0);
|
v->MulHi(i->src2.value, (i->flags & ARITHMETIC_UNSIGNED) != 0);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_DIV:
|
case OPCODE_DIV:
|
||||||
|
@ -482,6 +526,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Div(i->src2.value, (i->flags & ARITHMETIC_UNSIGNED) != 0);
|
v->Div(i->src2.value, (i->flags & ARITHMETIC_UNSIGNED) != 0);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
} else if (i->src2.value->IsConstant()) {
|
} else if (i->src2.value->IsConstant()) {
|
||||||
// Division by one = no-op.
|
// Division by one = no-op.
|
||||||
Value* src1 = i->src1.value;
|
Value* src1 = i->src1.value;
|
||||||
|
@ -489,12 +534,14 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
i->src2.value->IsConstantOne()) {
|
i->src2.value->IsConstantOne()) {
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(src1);
|
i->set_src1(src1);
|
||||||
|
result = true;
|
||||||
} else if (i->src2.value->type == VEC128_TYPE) {
|
} else if (i->src2.value->type == VEC128_TYPE) {
|
||||||
auto& c = i->src2.value->constant;
|
auto& c = i->src2.value->constant;
|
||||||
if (c.v128.f32[0] == 1.f && c.v128.f32[1] == 1.f &&
|
if (c.v128.f32[0] == 1.f && c.v128.f32[1] == 1.f &&
|
||||||
c.v128.f32[2] == 1.f && c.v128.f32[3] == 1.f) {
|
c.v128.f32[2] == 1.f && c.v128.f32[3] == 1.f) {
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(src1);
|
i->set_src1(src1);
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -505,6 +552,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
Value::MulAdd(v, i->src1.value, i->src2.value, i->src3.value);
|
Value::MulAdd(v, i->src1.value, i->src2.value, i->src3.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
} else {
|
} else {
|
||||||
// Multiply part is constant.
|
// Multiply part is constant.
|
||||||
Value* mul = builder->AllocValue();
|
Value* mul = builder->AllocValue();
|
||||||
|
@ -515,6 +563,8 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
i->Replace(&OPCODE_ADD_info, 0);
|
i->Replace(&OPCODE_ADD_info, 0);
|
||||||
i->set_src1(mul);
|
i->set_src1(mul);
|
||||||
i->set_src2(add);
|
i->set_src2(add);
|
||||||
|
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -525,6 +575,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
Value::MulSub(v, i->src1.value, i->src2.value, i->src3.value);
|
Value::MulSub(v, i->src1.value, i->src2.value, i->src3.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
} else {
|
} else {
|
||||||
// Multiply part is constant.
|
// Multiply part is constant.
|
||||||
Value* mul = builder->AllocValue();
|
Value* mul = builder->AllocValue();
|
||||||
|
@ -535,6 +586,8 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
i->Replace(&OPCODE_SUB_info, 0);
|
i->Replace(&OPCODE_SUB_info, 0);
|
||||||
i->set_src1(mul);
|
i->set_src1(mul);
|
||||||
i->set_src2(add);
|
i->set_src2(add);
|
||||||
|
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -543,6 +596,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Max(i->src2.value);
|
v->Max(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_NEG:
|
case OPCODE_NEG:
|
||||||
|
@ -550,6 +604,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Neg();
|
v->Neg();
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_ABS:
|
case OPCODE_ABS:
|
||||||
|
@ -557,6 +612,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Abs();
|
v->Abs();
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_SQRT:
|
case OPCODE_SQRT:
|
||||||
|
@ -564,6 +620,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Sqrt();
|
v->Sqrt();
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_RSQRT:
|
case OPCODE_RSQRT:
|
||||||
|
@ -571,6 +628,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->RSqrt();
|
v->RSqrt();
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_RECIP:
|
case OPCODE_RECIP:
|
||||||
|
@ -578,6 +636,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Recip();
|
v->Recip();
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_AND:
|
case OPCODE_AND:
|
||||||
|
@ -585,6 +644,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->And(i->src2.value);
|
v->And(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_OR:
|
case OPCODE_OR:
|
||||||
|
@ -592,6 +652,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Or(i->src2.value);
|
v->Or(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_XOR:
|
case OPCODE_XOR:
|
||||||
|
@ -599,11 +660,13 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Xor(i->src2.value);
|
v->Xor(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
} else if (!i->src1.value->IsConstant() &&
|
} else if (!i->src1.value->IsConstant() &&
|
||||||
!i->src2.value->IsConstant() &&
|
!i->src2.value->IsConstant() &&
|
||||||
i->src1.value == i->src2.value) {
|
i->src1.value == i->src2.value) {
|
||||||
v->set_zero(v->type);
|
v->set_zero(v->type);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_NOT:
|
case OPCODE_NOT:
|
||||||
|
@ -611,6 +674,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Not();
|
v->Not();
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_SHL:
|
case OPCODE_SHL:
|
||||||
|
@ -618,10 +682,12 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Shl(i->src2.value);
|
v->Shl(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
} else if (i->src2.value->IsConstantZero()) {
|
} else if (i->src2.value->IsConstantZero()) {
|
||||||
auto src1 = i->src1.value;
|
auto src1 = i->src1.value;
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(src1);
|
i->set_src1(src1);
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_SHR:
|
case OPCODE_SHR:
|
||||||
|
@ -629,10 +695,12 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Shr(i->src2.value);
|
v->Shr(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
} else if (i->src2.value->IsConstantZero()) {
|
} else if (i->src2.value->IsConstantZero()) {
|
||||||
auto src1 = i->src1.value;
|
auto src1 = i->src1.value;
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(src1);
|
i->set_src1(src1);
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_SHA:
|
case OPCODE_SHA:
|
||||||
|
@ -640,6 +708,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->Sha(i->src2.value);
|
v->Sha(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// TODO(benvanik): ROTATE_LEFT
|
// TODO(benvanik): ROTATE_LEFT
|
||||||
|
@ -648,6 +717,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->ByteSwap();
|
v->ByteSwap();
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_CNTLZ:
|
case OPCODE_CNTLZ:
|
||||||
|
@ -655,6 +725,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_zero(v->type);
|
v->set_zero(v->type);
|
||||||
v->CountLeadingZeros(i->src1.value);
|
v->CountLeadingZeros(i->src1.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// TODO(benvanik): INSERT/EXTRACT
|
// TODO(benvanik): INSERT/EXTRACT
|
||||||
|
@ -664,6 +735,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_zero(v->type);
|
v->set_zero(v->type);
|
||||||
v->Extract(i->src1.value, i->src2.value);
|
v->Extract(i->src1.value, i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_SPLAT:
|
case OPCODE_SPLAT:
|
||||||
|
@ -671,6 +743,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_zero(v->type);
|
v->set_zero(v->type);
|
||||||
v->Splat(i->src1.value);
|
v->Splat(i->src1.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_COMPARE_EQ:
|
case OPCODE_VECTOR_COMPARE_EQ:
|
||||||
|
@ -678,6 +751,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->VectorCompareEQ(i->src2.value, hir::TypeName(i->flags));
|
v->VectorCompareEQ(i->src2.value, hir::TypeName(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_COMPARE_SGT:
|
case OPCODE_VECTOR_COMPARE_SGT:
|
||||||
|
@ -685,6 +759,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->VectorCompareSGT(i->src2.value, hir::TypeName(i->flags));
|
v->VectorCompareSGT(i->src2.value, hir::TypeName(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_COMPARE_SGE:
|
case OPCODE_VECTOR_COMPARE_SGE:
|
||||||
|
@ -692,6 +767,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->VectorCompareSGE(i->src2.value, hir::TypeName(i->flags));
|
v->VectorCompareSGE(i->src2.value, hir::TypeName(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_COMPARE_UGT:
|
case OPCODE_VECTOR_COMPARE_UGT:
|
||||||
|
@ -699,6 +775,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->VectorCompareUGT(i->src2.value, hir::TypeName(i->flags));
|
v->VectorCompareUGT(i->src2.value, hir::TypeName(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_COMPARE_UGE:
|
case OPCODE_VECTOR_COMPARE_UGE:
|
||||||
|
@ -706,6 +783,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->VectorCompareUGE(i->src2.value, hir::TypeName(i->flags));
|
v->VectorCompareUGE(i->src2.value, hir::TypeName(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_CONVERT_F2I:
|
case OPCODE_VECTOR_CONVERT_F2I:
|
||||||
|
@ -714,6 +792,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->VectorConvertF2I(i->src1.value,
|
v->VectorConvertF2I(i->src1.value,
|
||||||
!!(i->flags & ARITHMETIC_UNSIGNED));
|
!!(i->flags & ARITHMETIC_UNSIGNED));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_CONVERT_I2F:
|
case OPCODE_VECTOR_CONVERT_I2F:
|
||||||
|
@ -722,6 +801,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->VectorConvertI2F(i->src1.value,
|
v->VectorConvertI2F(i->src1.value,
|
||||||
!!(i->flags & ARITHMETIC_UNSIGNED));
|
!!(i->flags & ARITHMETIC_UNSIGNED));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_SHL:
|
case OPCODE_VECTOR_SHL:
|
||||||
|
@ -729,6 +809,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->VectorShl(i->src2.value, hir::TypeName(i->flags));
|
v->VectorShl(i->src2.value, hir::TypeName(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_SHR:
|
case OPCODE_VECTOR_SHR:
|
||||||
|
@ -736,6 +817,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->VectorShr(i->src2.value, hir::TypeName(i->flags));
|
v->VectorShr(i->src2.value, hir::TypeName(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_ROTATE_LEFT:
|
case OPCODE_VECTOR_ROTATE_LEFT:
|
||||||
|
@ -743,6 +825,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->VectorRol(i->src2.value, hir::TypeName(i->flags));
|
v->VectorRol(i->src2.value, hir::TypeName(i->flags));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_ADD:
|
case OPCODE_VECTOR_ADD:
|
||||||
|
@ -753,6 +836,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
!!(arith_flags & ARITHMETIC_UNSIGNED),
|
!!(arith_flags & ARITHMETIC_UNSIGNED),
|
||||||
!!(arith_flags & ARITHMETIC_SATURATE));
|
!!(arith_flags & ARITHMETIC_SATURATE));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPCODE_VECTOR_SUB:
|
case OPCODE_VECTOR_SUB:
|
||||||
|
@ -763,6 +847,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
!!(arith_flags & ARITHMETIC_UNSIGNED),
|
!!(arith_flags & ARITHMETIC_UNSIGNED),
|
||||||
!!(arith_flags & ARITHMETIC_SATURATE));
|
!!(arith_flags & ARITHMETIC_SATURATE));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -771,6 +856,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->DotProduct3(i->src2.value);
|
v->DotProduct3(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -779,6 +865,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
v->set_from(i->src1.value);
|
v->set_from(i->src1.value);
|
||||||
v->DotProduct4(i->src2.value);
|
v->DotProduct4(i->src2.value);
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -790,6 +877,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
|
||||||
!!(arith_flags & ARITHMETIC_UNSIGNED),
|
!!(arith_flags & ARITHMETIC_UNSIGNED),
|
||||||
!!(arith_flags & ARITHMETIC_SATURATE));
|
!!(arith_flags & ARITHMETIC_SATURATE));
|
||||||
i->Remove();
|
i->Remove();
|
||||||
|
result = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -10,19 +10,19 @@
|
||||||
#ifndef XENIA_CPU_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||||
#define XENIA_CPU_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_CONSTANT_PROPAGATION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/passes/conditional_group_subpass.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
class ConstantPropagationPass : public CompilerPass {
|
class ConstantPropagationPass : public ConditionalGroupSubpass {
|
||||||
public:
|
public:
|
||||||
ConstantPropagationPass();
|
ConstantPropagationPass();
|
||||||
~ConstantPropagationPass() override;
|
~ConstantPropagationPass() override;
|
||||||
|
|
||||||
bool Run(hir::HIRBuilder* builder) override;
|
bool Run(hir::HIRBuilder* builder, bool& result) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,17 +23,18 @@ using xe::cpu::hir::HIRBuilder;
|
||||||
using xe::cpu::hir::Instr;
|
using xe::cpu::hir::Instr;
|
||||||
using xe::cpu::hir::Value;
|
using xe::cpu::hir::Value;
|
||||||
|
|
||||||
SimplificationPass::SimplificationPass() : CompilerPass() {}
|
SimplificationPass::SimplificationPass() : ConditionalGroupSubpass() {}
|
||||||
|
|
||||||
SimplificationPass::~SimplificationPass() {}
|
SimplificationPass::~SimplificationPass() {}
|
||||||
|
|
||||||
bool SimplificationPass::Run(HIRBuilder* builder) {
|
bool SimplificationPass::Run(HIRBuilder* builder, bool& result) {
|
||||||
EliminateConversions(builder);
|
result = false;
|
||||||
SimplifyAssignments(builder);
|
result |= EliminateConversions(builder);
|
||||||
|
result |= SimplifyAssignments(builder);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimplificationPass::EliminateConversions(HIRBuilder* builder) {
|
bool SimplificationPass::EliminateConversions(HIRBuilder* builder) {
|
||||||
// First, we check for truncates/extensions that can be skipped.
|
// First, we check for truncates/extensions that can be skipped.
|
||||||
// This generates some assignments which then the second step will clean up.
|
// This generates some assignments which then the second step will clean up.
|
||||||
// Both zero/sign extends can be skipped:
|
// Both zero/sign extends can be skipped:
|
||||||
|
@ -43,6 +44,7 @@ void SimplificationPass::EliminateConversions(HIRBuilder* builder) {
|
||||||
// v1.i64 = zero/sign_extend v0.i32 (may be dead code removed later)
|
// v1.i64 = zero/sign_extend v0.i32 (may be dead code removed later)
|
||||||
// v2.i32 = v0.i32
|
// v2.i32 = v0.i32
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
auto block = builder->first_block();
|
auto block = builder->first_block();
|
||||||
while (block) {
|
while (block) {
|
||||||
auto i = block->instr_head;
|
auto i = block->instr_head;
|
||||||
|
@ -51,20 +53,21 @@ void SimplificationPass::EliminateConversions(HIRBuilder* builder) {
|
||||||
// back to definition).
|
// back to definition).
|
||||||
if (i->opcode == &OPCODE_TRUNCATE_info) {
|
if (i->opcode == &OPCODE_TRUNCATE_info) {
|
||||||
// Matches zero/sign_extend + truncate.
|
// Matches zero/sign_extend + truncate.
|
||||||
CheckTruncate(i);
|
result |= CheckTruncate(i);
|
||||||
} else if (i->opcode == &OPCODE_BYTE_SWAP_info) {
|
} else if (i->opcode == &OPCODE_BYTE_SWAP_info) {
|
||||||
// Matches byte swap + byte swap.
|
// Matches byte swap + byte swap.
|
||||||
// This is pretty rare within the same basic block, but is in the
|
// This is pretty rare within the same basic block, but is in the
|
||||||
// memcpy hot path and (probably) worth it. Maybe.
|
// memcpy hot path and (probably) worth it. Maybe.
|
||||||
CheckByteSwap(i);
|
result |= CheckByteSwap(i);
|
||||||
}
|
}
|
||||||
i = i->next;
|
i = i->next;
|
||||||
}
|
}
|
||||||
block = block->next;
|
block = block->next;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimplificationPass::CheckTruncate(Instr* i) {
|
bool SimplificationPass::CheckTruncate(Instr* i) {
|
||||||
// Walk backward up src's chain looking for an extend. We may have
|
// Walk backward up src's chain looking for an extend. We may have
|
||||||
// assigns, so skip those.
|
// assigns, so skip those.
|
||||||
auto src = i->src1.value;
|
auto src = i->src1.value;
|
||||||
|
@ -80,6 +83,7 @@ void SimplificationPass::CheckTruncate(Instr* i) {
|
||||||
// Types match, use original by turning this into an assign.
|
// Types match, use original by turning this into an assign.
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(def->src1.value);
|
i->set_src1(def->src1.value);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
} else if (def->opcode == &OPCODE_ZERO_EXTEND_info) {
|
} else if (def->opcode == &OPCODE_ZERO_EXTEND_info) {
|
||||||
// Value comes from a zero extend.
|
// Value comes from a zero extend.
|
||||||
|
@ -87,12 +91,14 @@ void SimplificationPass::CheckTruncate(Instr* i) {
|
||||||
// Types match, use original by turning this into an assign.
|
// Types match, use original by turning this into an assign.
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(def->src1.value);
|
i->set_src1(def->src1.value);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimplificationPass::CheckByteSwap(Instr* i) {
|
bool SimplificationPass::CheckByteSwap(Instr* i) {
|
||||||
// Walk backward up src's chain looking for a byte swap. We may have
|
// Walk backward up src's chain looking for a byte swap. We may have
|
||||||
// assigns, so skip those.
|
// assigns, so skip those.
|
||||||
auto src = i->src1.value;
|
auto src = i->src1.value;
|
||||||
|
@ -107,11 +113,13 @@ void SimplificationPass::CheckByteSwap(Instr* i) {
|
||||||
// Types match, use original by turning this into an assign.
|
// Types match, use original by turning this into an assign.
|
||||||
i->Replace(&OPCODE_ASSIGN_info, 0);
|
i->Replace(&OPCODE_ASSIGN_info, 0);
|
||||||
i->set_src1(def->src1.value);
|
i->set_src1(def->src1.value);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimplificationPass::SimplifyAssignments(HIRBuilder* builder) {
|
bool SimplificationPass::SimplifyAssignments(HIRBuilder* builder) {
|
||||||
// Run over the instructions and rename assigned variables:
|
// Run over the instructions and rename assigned variables:
|
||||||
// v1 = v0
|
// v1 = v0
|
||||||
// v2 = v1
|
// v2 = v1
|
||||||
|
@ -129,27 +137,35 @@ void SimplificationPass::SimplifyAssignments(HIRBuilder* builder) {
|
||||||
// of that instr. Because we may have chains, we do this recursively until
|
// of that instr. Because we may have chains, we do this recursively until
|
||||||
// we find a non-assign def.
|
// we find a non-assign def.
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
auto block = builder->first_block();
|
auto block = builder->first_block();
|
||||||
while (block) {
|
while (block) {
|
||||||
auto i = block->instr_head;
|
auto i = block->instr_head;
|
||||||
while (i) {
|
while (i) {
|
||||||
uint32_t signature = i->opcode->signature;
|
uint32_t signature = i->opcode->signature;
|
||||||
if (GET_OPCODE_SIG_TYPE_SRC1(signature) == OPCODE_SIG_TYPE_V) {
|
if (GET_OPCODE_SIG_TYPE_SRC1(signature) == OPCODE_SIG_TYPE_V) {
|
||||||
i->set_src1(CheckValue(i->src1.value));
|
bool modified = false;
|
||||||
|
i->set_src1(CheckValue(i->src1.value, modified));
|
||||||
|
result |= modified;
|
||||||
}
|
}
|
||||||
if (GET_OPCODE_SIG_TYPE_SRC2(signature) == OPCODE_SIG_TYPE_V) {
|
if (GET_OPCODE_SIG_TYPE_SRC2(signature) == OPCODE_SIG_TYPE_V) {
|
||||||
i->set_src2(CheckValue(i->src2.value));
|
bool modified = false;
|
||||||
|
i->set_src2(CheckValue(i->src2.value, modified));
|
||||||
|
result |= modified;
|
||||||
}
|
}
|
||||||
if (GET_OPCODE_SIG_TYPE_SRC3(signature) == OPCODE_SIG_TYPE_V) {
|
if (GET_OPCODE_SIG_TYPE_SRC3(signature) == OPCODE_SIG_TYPE_V) {
|
||||||
i->set_src3(CheckValue(i->src3.value));
|
bool modified = false;
|
||||||
|
i->set_src3(CheckValue(i->src3.value, modified));
|
||||||
|
result |= modified;
|
||||||
}
|
}
|
||||||
i = i->next;
|
i = i->next;
|
||||||
}
|
}
|
||||||
block = block->next;
|
block = block->next;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* SimplificationPass::CheckValue(Value* value) {
|
Value* SimplificationPass::CheckValue(Value* value, bool& result) {
|
||||||
auto def = value->def;
|
auto def = value->def;
|
||||||
if (def && def->opcode == &OPCODE_ASSIGN_info) {
|
if (def && def->opcode == &OPCODE_ASSIGN_info) {
|
||||||
// Value comes from an assignment - recursively find if it comes from
|
// Value comes from an assignment - recursively find if it comes from
|
||||||
|
@ -162,8 +178,10 @@ Value* SimplificationPass::CheckValue(Value* value) {
|
||||||
}
|
}
|
||||||
replacement = def->src1.value;
|
replacement = def->src1.value;
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
return replacement;
|
return replacement;
|
||||||
}
|
}
|
||||||
|
result = false;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,27 +10,27 @@
|
||||||
#ifndef XENIA_CPU_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
#ifndef XENIA_CPU_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||||
#define XENIA_CPU_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
#define XENIA_CPU_COMPILER_PASSES_SIMPLIFICATION_PASS_H_
|
||||||
|
|
||||||
#include "xenia/cpu/compiler/compiler_pass.h"
|
#include "xenia/cpu/compiler/passes/conditional_group_subpass.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
namespace compiler {
|
namespace compiler {
|
||||||
namespace passes {
|
namespace passes {
|
||||||
|
|
||||||
class SimplificationPass : public CompilerPass {
|
class SimplificationPass : public ConditionalGroupSubpass {
|
||||||
public:
|
public:
|
||||||
SimplificationPass();
|
SimplificationPass();
|
||||||
~SimplificationPass() override;
|
~SimplificationPass() override;
|
||||||
|
|
||||||
bool Run(hir::HIRBuilder* builder) override;
|
bool Run(hir::HIRBuilder* builder, bool& result) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EliminateConversions(hir::HIRBuilder* builder);
|
bool EliminateConversions(hir::HIRBuilder* builder);
|
||||||
void CheckTruncate(hir::Instr* i);
|
bool CheckTruncate(hir::Instr* i);
|
||||||
void CheckByteSwap(hir::Instr* i);
|
bool CheckByteSwap(hir::Instr* i);
|
||||||
|
|
||||||
void SimplifyAssignments(hir::HIRBuilder* builder);
|
bool SimplifyAssignments(hir::HIRBuilder* builder);
|
||||||
hir::Value* CheckValue(hir::Value* value);
|
hir::Value* CheckValue(hir::Value* value, bool& result);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace passes
|
} // namespace passes
|
||||||
|
|
|
@ -53,15 +53,16 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) {
|
||||||
if (validate) compiler_->AddPass(std::make_unique<passes::ValidationPass>());
|
if (validate) compiler_->AddPass(std::make_unique<passes::ValidationPass>());
|
||||||
compiler_->AddPass(std::make_unique<passes::ContextPromotionPass>());
|
compiler_->AddPass(std::make_unique<passes::ContextPromotionPass>());
|
||||||
if (validate) compiler_->AddPass(std::make_unique<passes::ValidationPass>());
|
if (validate) compiler_->AddPass(std::make_unique<passes::ValidationPass>());
|
||||||
// TODO(gibbed): loop until these passes stop making changes?
|
|
||||||
for (int i = 0; i < 5; ++i) {
|
// Grouped simplification + constant propagation.
|
||||||
compiler_->AddPass(std::make_unique<passes::SimplificationPass>());
|
// Loops until no changes are made.
|
||||||
if (validate)
|
auto sap = std::make_unique<passes::ConditionalGroupPass>();
|
||||||
compiler_->AddPass(std::make_unique<passes::ValidationPass>());
|
sap->AddPass(std::make_unique<passes::SimplificationPass>());
|
||||||
compiler_->AddPass(std::make_unique<passes::ConstantPropagationPass>());
|
if (validate) sap->AddPass(std::make_unique<passes::ValidationPass>());
|
||||||
if (validate)
|
sap->AddPass(std::make_unique<passes::ConstantPropagationPass>());
|
||||||
compiler_->AddPass(std::make_unique<passes::ValidationPass>());
|
if (validate) sap->AddPass(std::make_unique<passes::ValidationPass>());
|
||||||
}
|
compiler_->AddPass(std::move(sap));
|
||||||
|
|
||||||
if (backend->machine_info()->supports_extended_load_store) {
|
if (backend->machine_info()->supports_extended_load_store) {
|
||||||
// Backend supports the advanced LOAD/STORE instructions.
|
// Backend supports the advanced LOAD/STORE instructions.
|
||||||
// These will save us a lot of HIR opcodes.
|
// These will save us a lot of HIR opcodes.
|
||||||
|
|
Loading…
Reference in New Issue