usethesource / flybytes

Flybytes is an intermediate language between JVM bytecode and software languages (DSLs, PLs), for compilation and decompilation.
BSD 2-Clause "Simplified" License
16 stars 6 forks source link

could use a simple peephole optimizer #13

Open jurgenvinju opened 4 years ago

jurgenvinju commented 4 years ago

If you look at what we generate for the FuncFactorial demo:

class(
  object("FuncFactorial"),
  methods=[
    method(
      methodDesc(
        integer(),
        "fact",
        [integer()]),
      [var(
          integer(),
          "n")],
      [asm([
            LABEL("L554752372"),
            LINENUMBER(1,"L554752372"),
            ILOAD(0),
            ICONST_1(),
            IF_ICMPGT("L82634714"),
            LABEL("L1444851469"),
            LINENUMBER(2,"L1444851469"),
            ICONST_1(),
            GOTO("L1932743161"),
            LABEL("L82634714"),
            LINENUMBER(4,"L82634714"),
            ILOAD(0),
            ILOAD(0),
            ICONST_1(),
            ISUB(),
            INVOKESTATIC(
              object("FuncFactorial"),
              methodDesc(
                integer(),
                "fact",
                [integer()]),
              false),
            IMUL(),
            LABEL("L1932743161"),
            LINENUMBER(1,"L1932743161"),
            IRETURN(),
            LABEL("L1422917010"),
            LOCALVARIABLE(
              "n",
              integer(),
              "L554752372",
              "L1422917010",
              0)
          ])]),
    method(
      methodDesc(
        integer(),
        "main",
        []),
      [],
      [asm([
            LABEL("L939397862"),
            LINENUMBER(7,"L939397862"),
            ICONST_4(),
            INVOKESTATIC(
              object("FuncFactorial"),
              methodDesc(
                integer(),
                "fact",
                [integer()]),
              false),
            IRETURN()
          ])]),
    method(
      methodDesc(
        void(),
        "main",
        [array(string())]),
      [var(
          array(string()),
          "args")],
      [asm([
            LABEL("L339453395"),
            LINENUMBER(1,"L339453395"),
            GETSTATIC(
              object("java.lang.System"),
              "out",
              object("java.io.PrintStream")),
            INVOKESTATIC(
              object("FuncFactorial"),
              methodDesc(
                integer(),
                "main",
                []),
              false),
            INVOKESTATIC(
              object("java.lang.Integer"),
              methodDesc(
                string(),
                "toString",
                [integer()]),
              false),
            INVOKEVIRTUAL(
              object("java.io.PrintStream"),
              methodDesc(
                void(),
                "println",
                [object("java.lang.Object")]),
              false),
            RETURN(),
            LABEL("L2104394292"),
            LOCALVARIABLE(
              "args",
              array(string()),
              "L339453395",
              "L2104394292",
              0)
          ])]),
    method(
      constructorDesc([]),
      [],
      [asm([
            LABEL("L1449579366"),
            ALOAD(0),
            INVOKESPECIAL(
              object("java.lang.Object"),
              constructorDesc([]),
              false),
            RETURN(),
            LABEL("L289964654"),
            LOCALVARIABLE(
              "this",
              object("FuncFactorial"),
              "L1449579366",
              "L289964654",
              0)
          ])])
  ],
  fields=[],
  interfaces=[],
  super=object("java.lang.Object"),
  modifiers={public()})

You see the consecutive ILOAD(0), ILOAD(0) which is much faster as ILOAD(0), DUP. A simple peephole optimizer in the back-end, written as a ASM visitor wrapper could do the trick.

jurgenvinju commented 4 years ago

https://github.com/cwi-swat/flybytes/blob/master/src/lang/flybytes/demo/func/fac.func

PaulKlint commented 4 years ago

As you know I have good experience writing peephole optimizers directly in Rascal. One could give that a try.

jurgenvinju commented 4 years ago

I know. Unfortunately I have not made an intermediate step between flybytes asts and the ASM library on the way to bytecode. The reason is performance of the compiler. I think the disassembled example made you think otherwise. Got ya! 😇

On the way back I did use the above data type for bytecode instructions, because I really needed list matching for the decompiler and because some people only need a disassembler.

So we would have to implement the peephole optimizer against the ASM library.