Browse Source

* x86: MovAndTest2Test optimisation now accepts a smaller sub-regiser on the TEST instruction

J. Gareth "Curious Kit" Moreton 3 years ago
parent
commit
d7f1e56191
1 changed files with 40 additions and 6 deletions
  1. 40 6
      compiler/x86/aoptx86.pas

+ 40 - 6
compiler/x86/aoptx86.pas

@@ -3055,13 +3055,47 @@ unit aoptx86;
                   else
                     ;
                 end;
-                if ((taicpu(p).oper[0]^.typ=top_reg) or
-                  ((taicpu(p).oper[0]^.typ=top_ref) and (taicpu(p).oper[0]^.ref^.refaddr<>addr_full))) and
+                if (
+                    (taicpu(p).oper[0]^.typ=top_reg) or
+                    (
+                      (taicpu(p).oper[0]^.typ=top_ref) and
+                      (taicpu(p).oper[0]^.ref^.refaddr<>addr_full)
+                    )
+                  ) and
                   GetNextInstruction(hp1,hp2) and
-                  MatchInstruction(hp2,A_TEST,[taicpu(p).opsize]) and
-                  MatchOperand(taicpu(hp1).oper[1]^,taicpu(hp2).oper[1]^) and
-                  (MatchOperand(taicpu(hp2).oper[0]^,taicpu(hp2).oper[1]^) or
-                   MatchOperand(taicpu(hp2).oper[0]^,-1)) and
+                  MatchInstruction(hp2,A_TEST,[]) and
+                  (
+                    MatchOperand(taicpu(hp1).oper[1]^,taicpu(hp2).oper[1]^) or
+                    (
+                      { If the register being tested is smaller than the one
+                        that received a bitwise AND, permit it if the constant
+                        fits into the smaller size  }
+                      (taicpu(hp1).oper[1]^.typ = top_reg) and (taicpu(hp2).oper[1]^.typ = top_reg) and
+                      SuperRegistersEqual(taicpu(hp1).oper[1]^.reg,taicpu(hp2).oper[1]^.reg) and
+                      (taicpu(hp1).oper[0]^.typ = top_const) and (taicpu(hp1).oper[0]^.val >= 0) and
+                      (GetSubReg(taicpu(hp2).oper[1]^.reg) < GetSubReg(taicpu(hp1).oper[1]^.reg)) and
+                      (
+                        (
+                          (GetSubReg(taicpu(hp2).oper[1]^.reg) = R_SUBL) and
+                          (taicpu(hp1).oper[0]^.val <= $FF)
+                        ) or
+                        (
+                          (GetSubReg(taicpu(hp2).oper[1]^.reg) = R_SUBW) and
+                          (taicpu(hp1).oper[0]^.val <= $FFFF)
+{$ifdef x86_64}
+                        ) or
+                        (
+                          (GetSubReg(taicpu(hp2).oper[1]^.reg) = R_SUBD) and
+                          (taicpu(hp1).oper[0]^.val <= $FFFFFFFF)
+{$endif x86_64}
+                        )
+                      )
+                    )
+                  ) and
+                  (
+                    MatchOperand(taicpu(hp2).oper[0]^,taicpu(hp2).oper[1]^) or
+                    MatchOperand(taicpu(hp2).oper[0]^,-1)
+                  ) and
                   GetNextInstruction(hp2,hp3) and
                   MatchInstruction(hp3,A_Jcc,A_Setcc,[]) and
                   (taicpu(hp3).condition in [C_E,C_NE]) then