From 39bdddb30f6d2bebe0c27a0ea865ea46c50ec969 Mon Sep 17 00:00:00 2001 From: ishland Date: Sun, 17 Nov 2024 19:13:33 +0800 Subject: [PATCH] perf: use batched codegen for Max/MinShortNode and MulNode Cherry-picked from 3aa5e549760218f7d3a6f2696841f7b37d10dd4e --- .../dfc/common/ast/binary/MaxShortNode.java | 48 ++++++++++++++++++- .../dfc/common/ast/binary/MinShortNode.java | 46 +++++++++++++++++- .../opts/dfc/common/ast/binary/MulNode.java | 43 ++++++++++++++++- 3 files changed, 134 insertions(+), 3 deletions(-) diff --git a/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MaxShortNode.java b/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MaxShortNode.java index 8f5f584b..0556d45a 100644 --- a/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MaxShortNode.java +++ b/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MaxShortNode.java @@ -62,7 +62,53 @@ public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter @Override public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) { - context.delegateToSingle(m, localVarConsumer, this); + String leftMethod = context.newMultiMethod(this.left); + String rightMethodSingle = context.newSingleMethod(this.right); + context.callDelegateMulti(m, leftMethod); + + context.doCountedLoop(m, localVarConsumer, idx -> { + Label minLabel = new Label(); + Label end = new Label(); + + m.load(1, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + + m.load(1, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.DOUBLE_TYPE); + + m.dup2(); + m.dconst(this.rightMax); + m.cmpl(Type.DOUBLE_TYPE); + m.iflt(minLabel); + m.goTo(end); + + m.visitLabel(minLabel); + + m.load(0, InstructionAdapter.OBJECT_TYPE); + m.load(2, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.INT_TYPE); + m.load(3, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.INT_TYPE); + m.load(4, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.INT_TYPE); + m.load(5, InstructionAdapter.OBJECT_TYPE); + m.invokevirtual(context.className, rightMethodSingle, BytecodeGen.Context.SINGLE_DESC, false); + + m.invokestatic( + Type.getInternalName(Math.class), + "max", + Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE), + false + ); + + m.visitLabel(end); + m.astore(Type.DOUBLE_TYPE); + }); + m.areturn(Type.VOID_TYPE); } diff --git a/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MinShortNode.java b/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MinShortNode.java index 348d58d8..50729215 100644 --- a/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MinShortNode.java +++ b/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MinShortNode.java @@ -62,7 +62,51 @@ public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter @Override public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) { - context.delegateToSingle(m, localVarConsumer, this); + String leftMethod = context.newMultiMethod(this.left); + String rightMethodSingle = context.newSingleMethod(this.right); + context.callDelegateMulti(m, leftMethod); + + context.doCountedLoop(m, localVarConsumer, idx -> { + Label minLabel = new Label(); + Label end = new Label(); + + m.load(1, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + + m.load(1, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.DOUBLE_TYPE); + + m.dup2(); + m.dconst(this.rightMin); + m.cmpg(Type.DOUBLE_TYPE); + m.ifgt(minLabel); + m.goTo(end); + + m.visitLabel(minLabel); + m.load(0, InstructionAdapter.OBJECT_TYPE); + m.load(2, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.INT_TYPE); + m.load(3, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.INT_TYPE); + m.load(4, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.INT_TYPE); + m.load(5, InstructionAdapter.OBJECT_TYPE); + m.invokevirtual(context.className, rightMethodSingle, BytecodeGen.Context.SINGLE_DESC, false); + m.invokestatic( + Type.getInternalName(Math.class), + "min", + Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE), + false + ); + + m.visitLabel(end); + m.astore(Type.DOUBLE_TYPE); + }); + m.areturn(Type.VOID_TYPE); } diff --git a/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MulNode.java b/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MulNode.java index d3ba863b..e6259e79 100644 --- a/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MulNode.java +++ b/c2me-opts-dfc/src/main/java/com/ishland/c2me/opts/dfc/common/ast/binary/MulNode.java @@ -55,7 +55,48 @@ public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter @Override public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) { - context.delegateToSingle(m, localVarConsumer, this); + String leftMethod = context.newMultiMethod(this.left); + String rightMethodSingle = context.newSingleMethod(this.right); + context.callDelegateMulti(m, leftMethod); + + context.doCountedLoop(m, localVarConsumer, idx -> { + Label minLabel = new Label(); + Label end = new Label(); + + m.load(1, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + + m.load(1, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.DOUBLE_TYPE); + + m.dup2(); + m.dconst(0.0); + m.cmpl(Type.DOUBLE_TYPE); + m.ifne(minLabel); + m.pop2(); + m.dconst(0.0); + m.goTo(end); + + m.visitLabel(minLabel); + m.load(0, InstructionAdapter.OBJECT_TYPE); + m.load(2, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.INT_TYPE); + m.load(3, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.INT_TYPE); + m.load(4, InstructionAdapter.OBJECT_TYPE); + m.load(idx, Type.INT_TYPE); + m.aload(Type.INT_TYPE); + m.load(5, InstructionAdapter.OBJECT_TYPE); + m.invokevirtual(context.className, rightMethodSingle, BytecodeGen.Context.SINGLE_DESC, false); + m.mul(Type.DOUBLE_TYPE); + + m.visitLabel(end); + m.astore(Type.DOUBLE_TYPE); + }); + m.areturn(Type.VOID_TYPE); }