From ff66dc3189bb4fd5941d37affbca5a11587180af Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 2 Nov 2016 15:46:15 +0100 Subject: [PATCH] - flatten FxBinaryLogical chains into a single node for more efficient processing. --- src/scripting/codegeneration/codegen.cpp | 100 ++++++++++++----------- src/scripting/codegeneration/codegen.h | 2 + 2 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index d3923b2317..620d9feed7 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3583,9 +3583,47 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx) return x; } } + Flatten(); return this; } +//========================================================================== +// +// flatten a list of the same operator into a single node. +// +//========================================================================== + +void FxBinaryLogical::Flatten() +{ + if (left->ExprType == EFX_BinaryLogical && static_cast(left)->Operator == Operator) + { + list = std::move(static_cast(left)->list); + delete left; + } + else + { + list.Push(left); + } + + if (right->ExprType == EFX_BinaryLogical && static_cast(right)->Operator == Operator) + { + auto &rlist = static_cast(right)->list; + auto cnt = rlist.Size(); + auto v = list.Reserve(cnt); + for (unsigned i = 0; i < cnt; i++) + { + list[v + i] = rlist[i]; + rlist[i] = nullptr; + } + delete right; + } + else + { + list.Push(right); + } + left = right = nullptr; +} + //========================================================================== // // @@ -3594,56 +3632,24 @@ FxExpression *FxBinaryLogical::Resolve(FCompileContext& ctx) ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build) { - // This is not the "right" way to do these, but it works for now. - // (Problem: No information sharing is done between nodes to reduce the - // code size if you have something like a1 && a2 && a3 && ... && an.) - assert(left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT); - ExpEmit op1 = left->Emit(build); - assert(!op1.Konst); + TArray patchspots; + int zero = build->GetConstantInt(0); - op1.Free(build); - - if (Operator == TK_AndAnd) + for (unsigned i = 0; i < list.Size(); i++) { - build->Emit(OP_EQ_K, 1, op1.RegNum, zero); - // If op1 is 0, skip evaluation of op2. - size_t patchspot = build->Emit(OP_JMP, 0, 0, 0); - - // Evaluate op2. - ExpEmit op2 = right->Emit(build); - assert(!op2.Konst); - op2.Free(build); - - ExpEmit to(build, REGT_INT); - build->Emit(OP_EQ_K, 1, op2.RegNum, zero); - build->Emit(OP_JMP, 2); - build->Emit(OP_LI, to.RegNum, 1); - build->Emit(OP_JMP, 1); - size_t target = build->Emit(OP_LI, to.RegNum, 0); - build->Backpatch(patchspot, target); - return to; - } - else - { - assert(Operator == TK_OrOr); - build->Emit(OP_EQ_K, 0, op1.RegNum, zero); - // If op1 is not 0, skip evaluation of op2. - size_t patchspot = build->Emit(OP_JMP, 0, 0, 0); - - // Evaluate op2. - ExpEmit op2 = right->Emit(build); - assert(!op2.Konst); - op2.Free(build); - - ExpEmit to(build, REGT_INT); - build->Emit(OP_EQ_K, 0, op2.RegNum, zero); - build->Emit(OP_JMP, 2); - build->Emit(OP_LI, to.RegNum, 0); - build->Emit(OP_JMP, 1); - size_t target = build->Emit(OP_LI, to.RegNum, 1); - build->Backpatch(patchspot, target); - return to; + assert(list[i]->ValueType->GetRegType() == REGT_INT); + ExpEmit op1 = list[i]->Emit(build); + assert(!op1.Konst); + op1.Free(build); + build->Emit(OP_EQ_K, (Operator == TK_AndAnd) ? 1 : 0, op1.RegNum, zero); + patchspots.Push(build->Emit(OP_JMP, 0, 0, 0)); } + ExpEmit to(build, REGT_INT); + build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 1 : 0); + build->Emit(OP_JMP, 1); + auto ctarget = build->Emit(OP_LI, to.RegNum, (Operator == TK_AndAnd) ? 0 : 1); + for (auto addr : patchspots) build->Backpatch(addr, ctarget); + return to; } //========================================================================== diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index cfe261b39b..ee792e5bfd 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -910,9 +910,11 @@ public: int Operator; FxExpression *left; FxExpression *right; + TDeletingArray list; FxBinaryLogical(int, FxExpression*, FxExpression*); ~FxBinaryLogical(); + void Flatten(); FxExpression *Resolve(FCompileContext&); ExpEmit Emit(VMFunctionBuilder *build);