diff --git a/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala b/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala index c1762d8e..ac960752 100644 --- a/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala +++ b/src/main/scala/millfork/assembly/mos/opt/AlwaysGoodOptimizations.scala @@ -1840,7 +1840,7 @@ object AlwaysGoodOptimizations { val ifSet = Elidable & HasOpcode(LDA) & HasImmediate(if (zeroIfSet) 0 else nonZero) val ifClear = Elidable & HasOpcode(LDA) & HasImmediate(if (zeroIfSet) nonZero else 0) val jump = Elidable & HasOpcodeIn(Set(JMP, if (firstSet) BCS else BCC, if (zeroIfSet) BEQ else BNE)) & MatchParameter(1) - val elseLabel = (Elidable & HasOpcode(LABEL) & MatchParameter(0)).capture(10) + val elseLabel = (Elidable & HasOpcode(LABEL) & MatchParameter(0) & IsNotALabelUsedManyTimes).capture(10) val afterLabel = Elidable & HasOpcode(LABEL) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z) & IsNotALabelUsedManyTimes val store = Elidable & (Not(ReadsC) & Linear | HasOpcodeIn(RTS, JSR, RTI, RTL, BSR)) val secondReturn = (Elidable & (HasOpcodeIn(RTS, RTI) | NoopDiscardsFlags)).*.capture(6) diff --git a/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala b/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala index b85b9d84..b0154f2a 100644 --- a/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala @@ -662,8 +662,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { MLine.shortBranch(BRA, label2), MLine.label(label), MLine.immediate(LDB, 0), - MLine.label(label2), - MLine.inherentB(ROL) + MLine.label(label2) ) } diff --git a/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala b/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala index a4c15e71..d66003ca 100644 --- a/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala @@ -53,7 +53,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] { // TODO: helper functions to convert flags to booleans, to make code smaller } } - if (ctx.options.flag(CompilationFlag.OptimizeForSpeed)) { + if (ctx.options.flag(CompilationFlag.OptimizeForSpeed) || !hasOnlyOneJump) { val skip = ctx.env.nextLabel("bo") condition ++ List( ZLine.ldImm8(ZRegister.A, 1), diff --git a/src/test/scala/millfork/test/BooleanSuite.scala b/src/test/scala/millfork/test/BooleanSuite.scala index 98aa1f0d..e9258d81 100644 --- a/src/test/scala/millfork/test/BooleanSuite.scala +++ b/src/test/scala/millfork/test/BooleanSuite.scala @@ -288,4 +288,56 @@ class BooleanSuite extends FunSuite with Matchers { |} |""".stripMargin) } + + test("Complex boolean expressions") { + for ((x,y,w,h) <- Seq( + (2,3,2,2), + (2,2,1,1), + (0,0,0,0), + (0,5,0,0), + (5,0,0,0), + (0,0,5,0), + (0,0,0,5), + )) { + + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)( + s""" + |const byte MAX_SIZE = 4 + | + |macro void is_room_within_bounds(byte x, byte y, byte width, byte height, bool output) { + | output = x < MAX_SIZE && y < MAX_SIZE && x + width < MAX_SIZE && y + height < MAX_SIZE + |} + | + |byte temp + | + |bool in_bounds + |bool output0 @0xc000 + | + |void main() { + | byte x + | byte y + | byte width + | byte height + | + | temp=$x + | x = temp + | temp=$y + | y = temp + | temp=$w + | width = temp + | temp=$h + | height = temp + | + | is_room_within_bounds(x, y, width, height, in_bounds) + | + | output0 = in_bounds + | + |} + |""".stripMargin) { m => + val MAX_SIZE = 4 + val bool = x < MAX_SIZE && y < MAX_SIZE && x + w < MAX_SIZE && y + h < MAX_SIZE + m.readByte(0xc000) should equal(if (bool) 1 else 0) + } + } + } }