https://gcc.gnu.org/g:f3f8bb6afbcdc8a9dc5e63343f2826492a448c79

commit r17-891-gf3f8bb6afbcdc8a9dc5e63343f2826492a448c79
Author: Georg-Johann Lay <[email protected]>
Date:   Thu May 28 11:30:23 2026 +0200

    AVR: ad target/121343 - Use hard-reg constraints in [u]divmod insns.
    
            PR target/121343
    gcc/
            * config/avr/avr.md (divmod<mode>4, udivmod<mode>4): Use
            hard-reg constraints instead of explicit hard-regs.
            (*divmodqi4_call_split, *udivmodqi4_call_split): Remove.
            (*divmodhi4_call_split, *udivmodhi4_call_split): Remove.
            (*divmodpsi4_call_split, *udivmodpsi4_call_split): Remove.
            (*divmodsi4_call_split, *udivmodsi4_call_split): Remove.

Diff:
---
 gcc/config/avr/avr.md | 277 ++++++++++++--------------------------------------
 1 file changed, 65 insertions(+), 212 deletions(-)

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 2110f36febf5..81722e1dbf07 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -3737,39 +3737,18 @@
 ; divmod
 
 ;; Generate lib1funcs.S calls ourselves, because:
-;;  - we know exactly which registers are clobbered (for QI and HI
-;;    modes, some of the call-used registers are preserved)
-;;  - we get both the quotient and the remainder at no extra cost
-;;  - we split the patterns only after the first CSE passes because
-;;    CSE has problems to operate on hard regs.
-;;
-(define_insn_and_split "divmodqi4"
-  [(set (match_operand:QI 0 "pseudo_register_operand")
-        (div:QI (match_operand:QI 1 "pseudo_register_operand")
-                (match_operand:QI 2 "pseudo_register_operand")))
-   (set (match_operand:QI 3 "pseudo_register_operand")
-        (mod:QI (match_dup 1) (match_dup 2)))
-   (clobber (reg:QI 22))
-   (clobber (reg:QI 23))
-   (clobber (reg:QI 24))
-   (clobber (reg:QI 25))]
-  ""
-  { gcc_unreachable(); }
-  ""
-  [(set (reg:QI 24) (match_dup 1))
-   (set (reg:QI 22) (match_dup 2))
-   (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
-              (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
-              (clobber (reg:QI 22))
-              (clobber (reg:QI 23))])
-   (set (match_dup 0) (reg:QI 24))
-   (set (match_dup 3) (reg:QI 25))])
+;; - We know exactly which registers are clobbered, and for QI, HI
+;;   and PSI modes, some of the call-used registers are preserved.
+;; - We get both the quotient and the remainder at no extra cost.
 
-(define_insn_and_split "*divmodqi4_call_split"
-  [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
-   (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
-   (clobber (reg:QI 22))
-   (clobber (reg:QI 23))]
+(define_insn_and_split "divmodqi4"
+  [(set (match_operand:QI 0 "register_operand"        "={r24}")
+        (div:QI (match_operand:QI 1 "register_operand" "{r24}")
+                (match_operand:QI 2 "register_operand" "{r22}")))
+   (set (match_operand:QI 3 "register_operand"        "={r25}")
+        (mod:QI (match_dup 1)
+                (match_dup 2)))
+   (clobber (match_scratch:HI 4                       "={r22}"))]
   ""
   "#"
   "&& reload_completed"
@@ -3779,38 +3758,20 @@
 (define_insn "*divmodqi4_call"
   [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
    (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
-   (clobber (reg:QI 22))
-   (clobber (reg:QI 23))
+   (clobber (reg:HI 22))
    (clobber (reg:CC REG_CC))]
   "reload_completed"
   "%~call __divmodqi4"
   [(set_attr "type" "xcall")])
 
 (define_insn_and_split "udivmodqi4"
- [(set (match_operand:QI 0 "pseudo_register_operand")
-       (udiv:QI (match_operand:QI 1 "pseudo_register_operand")
-                (match_operand:QI 2 "pseudo_register_operand")))
-  (set (match_operand:QI 3 "pseudo_register_operand")
-       (umod:QI (match_dup 1) (match_dup 2)))
-  (clobber (reg:QI 22))
-  (clobber (reg:QI 23))
-  (clobber (reg:QI 24))
-  (clobber (reg:QI 25))]
-  ""
-  { gcc_unreachable(); }
-  ""
-  [(set (reg:QI 24) (match_dup 1))
-   (set (reg:QI 22) (match_dup 2))
-   (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
-              (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
-              (clobber (reg:QI 23))])
-   (set (match_dup 0) (reg:QI 24))
-   (set (match_dup 3) (reg:QI 25))])
-
-(define_insn_and_split "*udivmodqi4_call_split"
-  [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
-   (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
-   (clobber (reg:QI 23))]
+  [(set (match_operand:QI 0 "register_operand"         "={r24}")
+        (udiv:QI (match_operand:QI 1 "register_operand" "{r24}")
+                 (match_operand:QI 2 "register_operand" "{r22}")))
+   (set (match_operand:QI 3 "register_operand"         "={r25}")
+        (umod:QI (match_dup 1)
+                 (match_dup 2)))
+   (clobber (match_scratch:QI 4                        "={r23}"))]
   ""
   "#"
   "&& reload_completed"
@@ -3826,33 +3787,18 @@
   "%~call __udivmodqi4"
   [(set_attr "type" "xcall")])
 
-(define_insn_and_split "divmodhi4"
-  [(set (match_operand:HI 0 "pseudo_register_operand")
-        (div:HI (match_operand:HI 1 "pseudo_register_operand")
-                (match_operand:HI 2 "pseudo_register_operand")))
-   (set (match_operand:HI 3 "pseudo_register_operand")
-        (mod:HI (match_dup 1) (match_dup 2)))
-   (clobber (reg:QI 21))
-   (clobber (reg:HI 22))
-   (clobber (reg:HI 24))
-   (clobber (reg:HI 26))]
-  ""
-  { gcc_unreachable(); }
-  ""
-  [(set (reg:HI 24) (match_dup 1))
-   (set (reg:HI 22) (match_dup 2))
-   (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
-              (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
-              (clobber (reg:HI 26))
-              (clobber (reg:QI 21))])
-   (set (match_dup 0) (reg:HI 22))
-   (set (match_dup 3) (reg:HI 24))])
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 16-bit divmod
 
-(define_insn_and_split "*divmodhi4_call_split"
-  [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
-   (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
-   (clobber (reg:HI 26))
-   (clobber (reg:QI 21))]
+(define_insn_and_split "divmodhi4"
+  [(set (match_operand:HI 0 "register_operand"        "={r22}")
+        (div:HI (match_operand:HI 1 "register_operand" "{r24}")
+                (match_operand:HI 2 "register_operand" "{r22}")))
+   (set (match_operand:HI 3 "register_operand"        "={r24}")
+        (mod:HI (match_dup 1)
+                (match_dup 2)))
+   (clobber (match_scratch:HI 4                       "={r26}"))
+   (clobber (match_scratch:QI 5                       "={r21}"))]
   ""
   "#"
   "&& reload_completed"
@@ -3870,32 +3816,14 @@
   [(set_attr "type" "xcall")])
 
 (define_insn_and_split "udivmodhi4"
-  [(set (match_operand:HI 0 "pseudo_register_operand")
-        (udiv:HI (match_operand:HI 1 "pseudo_register_operand")
-                 (match_operand:HI 2 "pseudo_register_operand")))
-   (set (match_operand:HI 3 "pseudo_register_operand")
-        (umod:HI (match_dup 1) (match_dup 2)))
-   (clobber (reg:QI 21))
-   (clobber (reg:HI 22))
-   (clobber (reg:HI 24))
-   (clobber (reg:HI 26))]
-  ""
-  { gcc_unreachable(); }
-  ""
-  [(set (reg:HI 24) (match_dup 1))
-   (set (reg:HI 22) (match_dup 2))
-   (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
-              (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
-              (clobber (reg:HI 26))
-              (clobber (reg:QI 21))])
-   (set (match_dup 0) (reg:HI 22))
-   (set (match_dup 3) (reg:HI 24))])
-
-(define_insn_and_split "*udivmodhi4_call_split"
-  [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
-   (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
-   (clobber (reg:HI 26))
-   (clobber (reg:QI 21))]
+  [(set (match_operand:HI 0 "register_operand"         "={r22}")
+        (udiv:HI (match_operand:HI 1 "register_operand" "{r24}")
+                 (match_operand:HI 2 "register_operand" "{r22}")))
+   (set (match_operand:HI 3 "register_operand"         "={r24}")
+        (umod:HI (match_dup 1)
+                 (match_dup 2)))
+   (clobber (match_scratch:HI 4                        "={r26}"))
+   (clobber (match_scratch:QI 5                        "={r21}"))]
   ""
   "#"
   "&& reload_completed"
@@ -3907,8 +3835,7 @@
    (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
    (clobber (reg:HI 26))
    (clobber (reg:QI 21))
-   (clobber (reg:CC REG_CC))
-   ]
+   (clobber (reg:CC REG_CC))]
   "reload_completed"
   "%~call __udivmodhi4"
   [(set_attr "type" "xcall")])
@@ -4148,33 +4075,15 @@
 ;; implementation works the other way round.
 
 (define_insn_and_split "divmodpsi4"
-  [(set (match_operand:PSI 0 "pseudo_register_operand")
-        (div:PSI (match_operand:PSI 1 "pseudo_register_operand")
-                 (match_operand:PSI 2 "pseudo_register_operand")))
-   (set (match_operand:PSI 3 "pseudo_register_operand")
+  [(set (match_operand:PSI 0 "register_operand"         "={r22}")
+        (div:PSI (match_operand:PSI 1 "register_operand" "{r22}")
+                 (match_operand:PSI 2 "register_operand" "{r18}")))
+   (set (match_operand:PSI 3 "register_operand"         "={r18}")
         (mod:PSI (match_dup 1)
                  (match_dup 2)))
-   (clobber (reg:DI 18))
-   (clobber (reg:QI 26))]
-  ""
-  { gcc_unreachable(); }
-  ""
-  [(set (reg:PSI 22) (match_dup 1))
-   (set (reg:PSI 18) (match_dup 2))
-   (parallel [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
-              (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
-              (clobber (reg:QI 21))
-              (clobber (reg:QI 25))
-              (clobber (reg:QI 26))])
-   (set (match_dup 0) (reg:PSI 22))
-   (set (match_dup 3) (reg:PSI 18))])
-
-(define_insn_and_split "*divmodpsi4_call_split"
-  [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
-   (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
-   (clobber (reg:QI 21))
-   (clobber (reg:QI 25))
-   (clobber (reg:QI 26))]
+   (clobber (match_scratch:QI 4                         "={r21}"))
+   (clobber (match_scratch:QI 5                         "={r25}"))
+   (clobber (match_scratch:QI 6                         "={r26}"))]
   ""
   "#"
   "&& reload_completed"
@@ -4193,33 +4102,15 @@
   [(set_attr "type" "xcall")])
 
 (define_insn_and_split "udivmodpsi4"
-  [(set (match_operand:PSI 0 "pseudo_register_operand")
-        (udiv:PSI (match_operand:PSI 1 "pseudo_register_operand")
-                  (match_operand:PSI 2 "pseudo_register_operand")))
-   (set (match_operand:PSI 3 "pseudo_register_operand")
+  [(set (match_operand:PSI 0 "register_operand"          "={r22}")
+        (udiv:PSI (match_operand:PSI 1 "register_operand" "{r22}")
+                  (match_operand:PSI 2 "register_operand" "{r18}")))
+   (set (match_operand:PSI 3 "register_operand"          "={r18}")
         (umod:PSI (match_dup 1)
                   (match_dup 2)))
-   (clobber (reg:DI 18))
-   (clobber (reg:QI 26))]
-  ""
-  { gcc_unreachable(); }
-  ""
-  [(set (reg:PSI 22) (match_dup 1))
-   (set (reg:PSI 18) (match_dup 2))
-   (parallel [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
-              (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
-              (clobber (reg:QI 21))
-              (clobber (reg:QI 25))
-              (clobber (reg:QI 26))])
-   (set (match_dup 0) (reg:PSI 22))
-   (set (match_dup 3) (reg:PSI 18))])
-
-(define_insn_and_split "*udivmodpsi4_call_split"
-  [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
-   (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
-   (clobber (reg:QI 21))
-   (clobber (reg:QI 25))
-   (clobber (reg:QI 26))]
+   (clobber (match_scratch:QI 4                          "={r21}"))
+   (clobber (match_scratch:QI 5                          "={r25}"))
+   (clobber (match_scratch:QI 6                          "={r26}"))]
   ""
   "#"
   "&& reload_completed"
@@ -4240,33 +4131,14 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define_insn_and_split "divmodsi4"
-  [(set (match_operand:SI 0 "pseudo_register_operand")
-        (div:SI (match_operand:SI 1 "pseudo_register_operand")
-                (match_operand:SI 2 "pseudo_register_operand")))
-   (set (match_operand:SI 3 "pseudo_register_operand")
+  [(set (match_operand:SI 0 "register_operand"        "={r18}")
+        (div:SI (match_operand:SI 1 "register_operand" "{r22}")
+                (match_operand:SI 2 "register_operand" "{r18}")))
+   (set (match_operand:SI 3 "register_operand"        "={r22}")
         (mod:SI (match_dup 1)
                 (match_dup 2)))
-   (clobber (reg:SI 18))
-   (clobber (reg:SI 22))
-   (clobber (reg:HI 26))
-   (clobber (reg:HI 30))]
-  ""
-  { gcc_unreachable(); }
-  ""
-  [(set (reg:SI 22) (match_dup 1))
-   (set (reg:SI 18) (match_dup 2))
-   (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
-              (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
-              (clobber (reg:HI 26))
-              (clobber (reg:HI 30))])
-   (set (match_dup 0) (reg:SI 18))
-   (set (match_dup 3) (reg:SI 22))])
-
-(define_insn_and_split "*divmodsi4_call_split"
-  [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
-   (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
-   (clobber (reg:HI 26))
-   (clobber (reg:HI 30))]
+   (clobber (match_scratch:HI 4                       "=x"))
+   (clobber (match_scratch:HI 5                       "=z"))]
   ""
   "#"
   "&& reload_completed"
@@ -4284,33 +4156,14 @@
   [(set_attr "type" "xcall")])
 
 (define_insn_and_split "udivmodsi4"
-  [(set (match_operand:SI 0 "pseudo_register_operand")
-        (udiv:SI (match_operand:SI 1 "pseudo_register_operand")
-                 (match_operand:SI 2 "pseudo_register_operand")))
-   (set (match_operand:SI 3 "pseudo_register_operand")
+  [(set (match_operand:SI 0 "register_operand"         "={r18}")
+        (udiv:SI (match_operand:SI 1 "register_operand" "{r22}")
+                 (match_operand:SI 2 "register_operand" "{r18}")))
+   (set (match_operand:SI 3 "register_operand"         "={r22}")
         (umod:SI (match_dup 1)
                  (match_dup 2)))
-   (clobber (reg:SI 18))
-   (clobber (reg:SI 22))
-   (clobber (reg:HI 26))
-   (clobber (reg:HI 30))]
-  ""
-  { gcc_unreachable(); }
-  ""
-  [(set (reg:SI 22) (match_dup 1))
-   (set (reg:SI 18) (match_dup 2))
-   (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
-              (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
-              (clobber (reg:HI 26))
-              (clobber (reg:HI 30))])
-   (set (match_dup 0) (reg:SI 18))
-   (set (match_dup 3) (reg:SI 22))])
-
-(define_insn_and_split "*udivmodsi4_call_split"
-  [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
-   (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
-   (clobber (reg:HI 26))
-   (clobber (reg:HI 30))]
+   (clobber (match_scratch:HI 4                        "=x"))
+   (clobber (match_scratch:HI 5                        "=z"))]
   ""
   "#"
   "&& reload_completed"

Reply via email to