diff mbox series

[avr,applied] Tweak comparisons with constant

Message ID 4eaf3a6e-78be-4880-b972-46d5b321d335@gjlay.de
State New
Headers show
Series [avr,applied] Tweak comparisons with constant | expand

Commit Message

Georg-Johann Lay Aug. 1, 2024, 8:43 a.m. UTC
Applied this tweak to the 16-bit and 32-bit comparisons.

Johann

--

gcc/
         * config/avr/constraints.md (YMM): New constraint.
         * config/avr/avr.md (cmp<mode>3, *cmp<mode>3)
         (cbranch<mode>4_insn): Allow YMM where M is allowed.
         (cbranch<mode>4_insn): Split to a test of the
         high part against 0 if possible.
diff mbox series

Patch

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 91a306f2522..fce5349bbe5 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -6568,9 +6568,9 @@  (define_insn "*cmp<HISI:mode>.<code><QIPSI:mode>.1"
 ;; "cmpha3" "cmpuha3"
 (define_insn "cmp<mode>3"
   [(set (reg:CC REG_CC)
-        (compare:CC (match_operand:ALL2 0 "register_operand"  "!w  ,r  ,r,d ,r  ,d,r")
-                    (match_operand:ALL2 1 "nonmemory_operand"  "Y00,Y00,r,s ,s  ,M,n Ynn")))
-   (clobber (match_scratch:QI 2                               "=X  ,X  ,X,&d,&d ,X,&d"))]
+        (compare:CC (match_operand:ALL2 0 "register_operand"  "!w  ,r  ,r,d ,r ,d    ,r")
+                    (match_operand:ALL2 1 "nonmemory_operand"  "Y00,Y00,r,s ,s ,M YMM,n Ynn")))
+   (clobber (match_scratch:QI 2                               "=X  ,X  ,X,&d,&d,X    ,&d"))]
   "reload_completed"
   {
     switch (which_alternative)
@@ -6635,9 +6635,9 @@  (define_insn "*cmppsi"
 ;; "*cmpsa" "*cmpusa"
 (define_insn "*cmp<mode>"
   [(set (reg:CC REG_CC)
-        (compare:CC (match_operand:ALL4 0 "register_operand"  "r  ,r ,d,r ,r")
-                    (match_operand:ALL4 1 "nonmemory_operand" "Y00,r ,M,M ,n Ynn")))
-   (clobber (match_scratch:QI 2                              "=X  ,X ,X,&d,&d"))]
+        (compare:CC (match_operand:ALL4 0 "register_operand"  "r  ,r ,d    ,r")
+                    (match_operand:ALL4 1 "nonmemory_operand" "Y00,r ,M YMM,n Ynn")))
+   (clobber (match_scratch:QI 2                              "=X  ,X ,X    ,&d"))]
   "reload_completed"
   {
     if (0 == which_alternative)
@@ -6647,8 +6647,8 @@  (define_insn "*cmp<mode>"
 
     return avr_out_compare (insn, operands, NULL);
   }
-  [(set_attr "length" "4,4,4,5,8")
-   (set_attr "adjust_len" "tstsi,*,compare,compare,compare")])
+  [(set_attr "length" "4,4,4,8")
+   (set_attr "adjust_len" "tstsi,*,compare,compare")])
 
 
 ;; A helper for avr_pass_ifelse::avr_rest_of_handle_ifelse().
@@ -6727,11 +6727,11 @@  (define_insn_and_split "cbranch<mode>4_insn"
   [(set (pc)
         (if_then_else
          (match_operator 0 "ordered_comparison_operator"
-           [(match_operand:ALL4 1 "register_operand"  "r  ,r,d,r ,r")
-            (match_operand:ALL4 2 "nonmemory_operand" "Y00,r,M,M ,n Ynn")])
+           [(match_operand:ALL4 1 "register_operand"  "r  ,r,d     ,r")
+            (match_operand:ALL4 2 "nonmemory_operand" "Y00,r,M YMM ,n Ynn")])
          (label_ref (match_operand 3))
          (pc)))
-   (clobber (match_scratch:QI 4                      "=X  ,X,X,&d,&d"))]
+   (clobber (match_scratch:QI 4                      "=X  ,X,X     ,&d"))]
    ""
    "#"
    "reload_completed"
@@ -6742,7 +6742,23 @@  (define_insn_and_split "cbranch<mode>4_insn"
          (if_then_else (match_op_dup 0
                          [(reg:CC REG_CC) (const_int 0)])
                        (label_ref (match_dup 3))
-                       (pc)))])
+                       (pc)))]
+   {
+     // Unsigned >= 65536 and < 65536 can be performed by testing the
+     // high word against 0.
+     if ((GET_CODE (operands[0]) == LTU
+          || GET_CODE (operands[0]) == GEU)
+         && const_operand (operands[2], <MODE>mode)
+         && INTVAL (avr_to_int_mode (operands[2])) == 65536)
+       {
+         // "cmphi3" of the high word against 0.
+         operands[0] = copy_rtx (operands[0]);
+         PUT_CODE (operands[0], GET_CODE (operands[0]) == GEU ? NE : EQ);
+         operands[1] = simplify_gen_subreg (HImode, operands[1], <MODE>mode, 2);
+         operands[2] = const0_rtx;
+         operands[4] = gen_rtx_SCRATCH (QImode);
+       }
+   })
 
 ;; "cbranchpsi4_insn"
 (define_insn_and_split "cbranchpsi4_insn"
@@ -6772,11 +6788,11 @@  (define_insn_and_split "cbranch<mode>4_insn"
   [(set (pc)
         (if_then_else
          (match_operator 0 "ordered_comparison_operator"
-           [(match_operand:ALL2 1 "register_operand" "!w  ,r  ,r,d ,r ,d,r")
-            (match_operand:ALL2 2 "nonmemory_operand" "Y00,Y00,r,s ,s ,M,n Ynn")])
+           [(match_operand:ALL2 1 "register_operand" "!w  ,r  ,r,d ,r ,d    ,r")
+            (match_operand:ALL2 2 "nonmemory_operand" "Y00,Y00,r,s ,s ,M YMM,n Ynn")])
          (label_ref (match_operand 3))
          (pc)))
-   (clobber (match_scratch:QI 4                      "=X  ,X  ,X,&d,&d,X,&d"))]
+   (clobber (match_scratch:QI 4                      "=X  ,X  ,X,&d,&d,X    ,&d"))]
    ""
    "#"
    "reload_completed"
@@ -6787,7 +6803,23 @@  (define_insn_and_split "cbranch<mode>4_insn"
          (if_then_else (match_op_dup 0
                          [(reg:CC REG_CC) (const_int 0)])
                        (label_ref (match_dup 3))
-                       (pc)))])
+                       (pc)))]
+   {
+     // Unsigned >= 256 and < 256 can be performed by testing the
+     // high byte against 0.
+     if ((GET_CODE (operands[0]) == LTU
+          || GET_CODE (operands[0]) == GEU)
+         && const_operand (operands[2], <MODE>mode)
+         && INTVAL (avr_to_int_mode (operands[2])) == 256)
+       {
+         rtx_code code = GET_CODE (operands[0]) == GEU ? NE : EQ;
+         rtx hi8 = simplify_gen_subreg (QImode, operands[1], <MODE>mode, 1);
+         rtx cmp = gen_rtx_fmt_ee (code, VOIDmode, cc_reg_rtx, const0_rtx);
+         emit (gen_cmpqi3 (hi8, const0_rtx));
+         emit (gen_branch (operands[3], cmp));
+         DONE;
+       }
+   })
 
 ;; Combiner pattern to compare sign- or zero-extended register against
 ;; a wider register, like comparing uint8_t against uint16_t.
diff --git a/gcc/config/avr/constraints.md b/gcc/config/avr/constraints.md
index 35448614aa7..963e23a4d9e 100644
--- a/gcc/config/avr/constraints.md
+++ b/gcc/config/avr/constraints.md
@@ -313,6 +313,13 @@  (define_constraint "YIJ"
   (and (match_code "const_fixed")
        (match_test "IN_RANGE (INTVAL (avr_to_int_mode (op)), -63, 63)")))
 
+;; Similar to "M", but for CONST_FIXED.
+
+(define_constraint "YMM"
+  "Fixed-point constant in the range 0 @dots{} 0xff when viewed as CONST_INT."
+  (and (match_code "const_fixed")
+       (match_test "IN_RANGE (INTVAL (avr_to_int_mode (op)), 0, 0xff)")))
+
 (define_constraint "Yil"
   "Memory in the lower half of the I/O space."
   (and (match_code "mem")