From f2ad6b8cb8748db78781db914cd15b8f4ce68cd5 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sun, 26 Jun 2016 13:03:42 -0500 Subject: [PATCH] OPCODE_RECIP --- src/xenia/cpu/backend/x64/x64_sequences.cc | 23 +++++++++++++++++++ .../passes/constant_propagation_pass.cc | 8 ++++++- src/xenia/cpu/hir/hir_builder.cc | 9 ++++++++ src/xenia/cpu/hir/hir_builder.h | 1 + src/xenia/cpu/hir/opcodes.h | 1 + src/xenia/cpu/hir/opcodes.inl | 6 +++++ src/xenia/cpu/hir/value.cc | 19 +++++++++++++++ src/xenia/cpu/hir/value.h | 1 + src/xenia/cpu/ppc/ppc_emit_altivec.cc | 3 +-- 9 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/xenia/cpu/backend/x64/x64_sequences.cc b/src/xenia/cpu/backend/x64/x64_sequences.cc index 1a255e447..4f3730c8b 100644 --- a/src/xenia/cpu/backend/x64/x64_sequences.cc +++ b/src/xenia/cpu/backend/x64/x64_sequences.cc @@ -4863,6 +4863,28 @@ struct RSQRT_V128 : Sequence> { }; EMITTER_OPCODE_TABLE(OPCODE_RSQRT, RSQRT_F32, RSQRT_F64, RSQRT_V128); +// ============================================================================ +// OPCODE_RECIP +// ============================================================================ +struct RECIP_F32 : Sequence> { + static void Emit(X64Emitter& e, const EmitArgType& i) { + e.vrcpss(i.dest, i.src1); + } +}; +struct RECIP_F64 : Sequence> { + static void Emit(X64Emitter& e, const EmitArgType& i) { + e.vcvtsd2ss(i.dest, i.src1); + e.vrcpss(i.dest, i.dest); + e.vcvtss2sd(i.dest, i.dest); + } +}; +struct RECIP_V128 : Sequence> { + static void Emit(X64Emitter& e, const EmitArgType& i) { + e.vrcpps(i.dest, i.src1); + } +}; +EMITTER_OPCODE_TABLE(OPCODE_RECIP, RECIP_F32, RECIP_F64, RECIP_V128); + // ============================================================================ // OPCODE_POW2 // ============================================================================ @@ -7582,6 +7604,7 @@ void RegisterSequences() { Register_OPCODE_ABS(); Register_OPCODE_SQRT(); Register_OPCODE_RSQRT(); + Register_OPCODE_RECIP(); Register_OPCODE_POW2(); Register_OPCODE_LOG2(); Register_OPCODE_DOT_PRODUCT_3(); diff --git a/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc b/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc index 309cb24d9..b4f2df5f7 100644 --- a/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc +++ b/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc @@ -487,7 +487,13 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) { i->Remove(); } break; - + case OPCODE_RECIP: + if (i->src1.value->IsConstant()) { + v->set_from(i->src1.value); + v->Recip(); + i->Remove(); + } + break; case OPCODE_AND: if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) { v->set_from(i->src1.value); diff --git a/src/xenia/cpu/hir/hir_builder.cc b/src/xenia/cpu/hir/hir_builder.cc index db278cd81..774599215 100644 --- a/src/xenia/cpu/hir/hir_builder.cc +++ b/src/xenia/cpu/hir/hir_builder.cc @@ -1659,6 +1659,15 @@ Value* HIRBuilder::RSqrt(Value* value) { return i->dest; } +Value* HIRBuilder::Recip(Value* value) { + ASSERT_FLOAT_OR_VECTOR_TYPE(value); + + Instr* i = AppendInstr(OPCODE_RECIP_info, 0, AllocValue(value->type)); + i->set_src1(value); + i->src2.value = i->src3.value = NULL; + return i->dest; +} + Value* HIRBuilder::Pow2(Value* value) { ASSERT_FLOAT_OR_VECTOR_TYPE(value); diff --git a/src/xenia/cpu/hir/hir_builder.h b/src/xenia/cpu/hir/hir_builder.h index 44a528f53..a596ddfbe 100644 --- a/src/xenia/cpu/hir/hir_builder.h +++ b/src/xenia/cpu/hir/hir_builder.h @@ -196,6 +196,7 @@ class HIRBuilder { Value* Abs(Value* value); Value* Sqrt(Value* value); Value* RSqrt(Value* value); + Value* Recip(Value* value); Value* Pow2(Value* value); Value* Log2(Value* value); Value* DotProduct3(Value* value1, Value* value2); diff --git a/src/xenia/cpu/hir/opcodes.h b/src/xenia/cpu/hir/opcodes.h index 8e440c73e..7e127ac32 100644 --- a/src/xenia/cpu/hir/opcodes.h +++ b/src/xenia/cpu/hir/opcodes.h @@ -194,6 +194,7 @@ enum Opcode { OPCODE_ABS, OPCODE_SQRT, OPCODE_RSQRT, + OPCODE_RECIP, OPCODE_POW2, OPCODE_LOG2, OPCODE_DOT_PRODUCT_3, diff --git a/src/xenia/cpu/hir/opcodes.inl b/src/xenia/cpu/hir/opcodes.inl index a2968e238..a49fb4a5e 100644 --- a/src/xenia/cpu/hir/opcodes.inl +++ b/src/xenia/cpu/hir/opcodes.inl @@ -470,6 +470,12 @@ DEFINE_OPCODE( OPCODE_SIG_V_V, 0) +DEFINE_OPCODE( + OPCODE_RECIP, + "recip", + OPCODE_SIG_V_V, + 0) + DEFINE_OPCODE( OPCODE_POW2, "pow2", diff --git a/src/xenia/cpu/hir/value.cc b/src/xenia/cpu/hir/value.cc index 998ee7514..9703eb631 100644 --- a/src/xenia/cpu/hir/value.cc +++ b/src/xenia/cpu/hir/value.cc @@ -629,6 +629,25 @@ void Value::RSqrt() { } } +void Value::Recip() { + switch (type) { + case FLOAT32_TYPE: + constant.f32 = 1.0f / constant.f32; + break; + case FLOAT64_TYPE: + constant.f64 = 1.0f / constant.f64; + break; + case VEC128_TYPE: + for (int i = 0; i < 4; i++) { + constant.v128.f32[i] = 1.0f / constant.v128.f32[i]; + } + break; + default: + assert_unhandled_case(type); + break; + } +} + void Value::And(Value* other) { assert_true(type == other->type); switch (type) { diff --git a/src/xenia/cpu/hir/value.h b/src/xenia/cpu/hir/value.h index 6b152896f..39188f223 100644 --- a/src/xenia/cpu/hir/value.h +++ b/src/xenia/cpu/hir/value.h @@ -487,6 +487,7 @@ class Value { void Abs(); void Sqrt(); void RSqrt(); + void Recip(); void And(Value* other); void Or(Value* other); void Xor(Value* other); diff --git a/src/xenia/cpu/ppc/ppc_emit_altivec.cc b/src/xenia/cpu/ppc/ppc_emit_altivec.cc index f2fc1330f..b562ffbab 100644 --- a/src/xenia/cpu/ppc/ppc_emit_altivec.cc +++ b/src/xenia/cpu/ppc/ppc_emit_altivec.cc @@ -1210,8 +1210,7 @@ int InstrEmit_vpermwi128(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_vrefp_(PPCHIRBuilder& f, uint32_t vd, uint32_t vb) { // (VD) <- 1/(VB) - vec128_t one = vec128f(1.0f); - Value* v = f.Div(f.LoadConstantVec128(one), f.LoadVR(vb)); + Value* v = f.Recip(f.LoadVR(vb)); f.StoreVR(vd, v); return 0; }