From da56e5908d9f2e2ac3c94ecc56d07f2daad91dd8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 23 Oct 2016 15:30:58 +0200 Subject: [PATCH] - added an optimization to FxBoolCast that it doesn't force the source value to a 0/1 integer if not explicitly needed. When doing comparisons we do not care about actual values, we only want to know if it is 0 or not. - added the above for the 'if' condition. It works for integers, floats and pointers and will save 3 instructions if the condition is a non-boolean that can be implicitly casted to bool. --- src/scripting/codegeneration/codegen.cpp | 72 ++++++++++++++++-------- src/scripting/codegeneration/codegen.h | 3 +- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 9568c34a5..f882b8b2b 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -434,11 +434,12 @@ ExpEmit FxConstant::Emit(VMFunctionBuilder *build) // //========================================================================== -FxBoolCast::FxBoolCast(FxExpression *x) +FxBoolCast::FxBoolCast(FxExpression *x, bool needvalue) : FxExpression(EFX_BoolCast, x->ScriptPosition) { basex = x; ValueType = TypeBool; + NeedValue = needvalue; } //========================================================================== @@ -499,31 +500,37 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build) ExpEmit from = basex->Emit(build); assert(!from.Konst); assert(basex->ValueType->GetRegType() == REGT_INT || basex->ValueType->GetRegType() == REGT_FLOAT || basex->ValueType->GetRegType() == REGT_POINTER); - ExpEmit to(build, REGT_INT); - from.Free(build); - // Preload result with 0. - build->Emit(OP_LI, to.RegNum, 0); - - // Check source against 0. - if (from.RegType == REGT_INT) + if (NeedValue) { - build->Emit(OP_EQ_R, 1, from.RegNum, to.RegNum); - } - else if (from.RegType == REGT_FLOAT) - { - build->Emit(OP_EQF_K, 1, from.RegNum, build->GetConstantFloat(0.)); - } - else if (from.RegType == REGT_POINTER) - { - build->Emit(OP_EQA_K, 1, from.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC)); - } - build->Emit(OP_JMP, 1); + ExpEmit to(build, REGT_INT); + from.Free(build); + // Preload result with 0. + build->Emit(OP_LI, to.RegNum, 0); - // Reload result with 1 if the comparison fell through. - build->Emit(OP_LI, to.RegNum, 1); + // Check source against 0. + if (from.RegType == REGT_INT) + { + build->Emit(OP_EQ_R, 1, from.RegNum, to.RegNum); + } + else if (from.RegType == REGT_FLOAT) + { + build->Emit(OP_EQF_K, 1, from.RegNum, build->GetConstantFloat(0.)); + } + else if (from.RegType == REGT_POINTER) + { + build->Emit(OP_EQA_K, 1, from.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC)); + } + build->Emit(OP_JMP, 1); - return to; + // Reload result with 1 if the comparison fell through. + build->Emit(OP_LI, to.RegNum, 1); + return to; + } + else + { + return from; + } } //========================================================================== @@ -5871,7 +5878,7 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) if (Condition->ValueType != TypeBool) { - Condition = new FxBoolCast(Condition); + Condition = new FxBoolCast(Condition, false); SAFE_RESOLVE(Condition, ctx); } @@ -5914,7 +5921,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) // This is pretty much copied from FxConditional, except we don't // keep any results. ExpEmit cond = Condition->Emit(build); - assert(cond.RegType == REGT_INT && !cond.Konst); + assert(cond.RegType != REGT_STRING && !cond.Konst); if (WhenTrue != NULL) { @@ -5933,7 +5940,22 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) } // Test condition. - build->Emit(OP_EQ_K, condcheck, cond.RegNum, build->GetConstantInt(0)); + + switch (cond.RegType) + { + default: + case REGT_INT: + build->Emit(OP_EQ_K, condcheck, cond.RegNum, build->GetConstantInt(0)); + break; + + case REGT_FLOAT: + build->Emit(OP_EQF_K, condcheck, cond.RegNum, build->GetConstantFloat(0)); + break; + + case REGT_POINTER: + build->Emit(OP_EQA_K, condcheck, cond.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC)); + break; + } jumpspot = build->Emit(OP_JMP, 0); cond.Free(build); diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 3ea97ba66..9125d5d8c 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -457,10 +457,11 @@ public: class FxBoolCast : public FxExpression { FxExpression *basex; + bool NeedValue; public: - FxBoolCast(FxExpression *x); + FxBoolCast(FxExpression *x, bool needvalue = true); ~FxBoolCast(); FxExpression *Resolve(FCompileContext&);