This patch deals with consequences but not the root cause though.

There are 5 cases which are subjects to rewrite:
case #1:
  mov ip, r1
  add r2, ip
  # ip is dead here
can be rewritten as:
  adds r2, r1

case #2:
  add ip, r1
  mov r1, ip
  # ip is dead here
can be rewritten as:
  add r1, ip

case #3:
  mov ip, r1
  add r2, ip
  add r3, ip
  # ip is dead here
can be rewritten as:
  adds r2, r1
  adds r3, r1

case #4:
  mov ip, r1
  add ip, r2
  mov r1, ip
can be rewritten as:
  adds r1, r2
  mov  ip, r1 <- might be eliminated too, if ip is dead

case #5 (arbitrary):
  mov  r1, ip
  subs r2, r1, r2
  mov  ip, r2
  # r1 is dead here
can be rewritten as:
  rsbs r1, r2, #0
  add  ip, r1
  movs r2, ip <- might be eliminated, if r2 is dead

Speed profit wasn't checked but size changes are the following:
   libgcc:  -132 bytes / -0.25%
     libc: -1262 bytes / -0.55%
     libm:  -384 bytes / -0.42%
libstdc++: -2258 bytes / -0.30%

No tests provided because its hard to force GCC to emit HI_REGS
in a small and straightforward function.

Signed-off-by: Siarhei Volkau <lis8...@gmail.com>
---
 gcc/config/arm/thumb1.md | 93 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 92 insertions(+), 1 deletion(-)

diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index d7074b43f60..9da4af9eccd 100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -2055,4 +2055,95 @@ (define_insn "thumb1_stack_protect_test_insn"
    (set_attr "conds" "clob")
    (set_attr "type" "multiple")]
 )
-
+
+;; bad code emitted when HI_REGS involved in addition
+;; subtract also might happen rarely
+
+;; case #1:
+;; mov ip, r1
+;; add r2, ip # ip is dead after that
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "register_operand" ""))
+   (set (match_operand:SI 2 "register_operand" "")
+       (plus:SI (match_dup 2) (match_dup 0)))]
+  "TARGET_THUMB1
+    && peep2_reg_dead_p (2, operands[0])
+    && REGNO_REG_CLASS (REGNO (operands[0])) == HI_REGS"
+  [(set (match_dup 2)
+       (plus:SI (match_dup 2) (match_dup 1)))]
+  "")
+
+;; case #2:
+;; add ip, r1
+;; mov r1, ip # ip is dead after that
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "")))
+   (set (match_dup 1) (match_dup 0))]
+  "TARGET_THUMB1
+    && peep2_reg_dead_p (2, operands[0])
+    && REGNO_REG_CLASS (REGNO (operands[0])) == HI_REGS"
+  [(set (match_dup 1)
+       (plus:SI (match_dup 1) (match_dup 0)))]
+  "")
+
+;; case #3:
+;; mov ip, r1
+;; add r2, ip
+;; add r3, ip # ip is dead after that
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "register_operand" ""))
+   (set (match_operand:SI 2 "register_operand" "")
+       (plus:SI (match_dup 2) (match_dup 0)))
+   (set (match_operand:SI 3 "register_operand" "")
+       (plus:SI (match_dup 3) (match_dup 0)))]
+  "TARGET_THUMB1
+    && peep2_reg_dead_p (3, operands[0])
+    && REGNO_REG_CLASS (REGNO (operands[0])) == HI_REGS"
+  [(set (match_dup 2)
+       (plus:SI (match_dup 2) (match_dup 1)))
+   (set (match_dup 3)
+       (plus:SI (match_dup 3) (match_dup 1)))]
+  "")
+
+;; case #4:
+;; mov ip, r1
+;; add ip, r2
+;; mov r1, ip
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+       (match_operand:SI 1 "register_operand" ""))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))
+   (set (match_dup 1)
+       (match_dup 0))]
+  "TARGET_THUMB1
+    && REGNO_REG_CLASS (REGNO (operands[0])) == HI_REGS"
+  [(set (match_dup 1)
+       (plus:SI (match_dup 1) (match_dup 2)))
+   (set (match_dup 0) (match_dup 1))]  ;; likely will be eliminated
+  "")
+
+;; case #5:
+;; mov  r1, ip
+;; subs r2, r1, r2
+;; mov  ip, r2      # r1 is dead after
+(define_peephole2
+  [(set (match_operand:SI 1 "register_operand" "")
+       (match_operand:SI 0 "register_operand" ""))
+   (set (match_operand:SI 2 "register_operand" "")
+        (minus:SI (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (match_dup 2))]
+  "TARGET_THUMB1
+    && peep2_reg_dead_p (3, operands[1])
+    && REGNO_REG_CLASS (REGNO (operands[0])) == HI_REGS"
+  [(set (match_dup 1)
+       (neg:SI (match_dup 2)))
+   (set (match_dup 0)
+        (plus:SI (match_dup 0) (match_dup 1)))
+   (set (match_dup 2)                  ;; likely will be eliminated
+        (match_dup 0))]
+  "")
-- 
2.45.2

Reply via email to