re PR target/49687 ([avr] Missed optimization for widening MUL)
authorGeorg-Johann Lay <avr@gjlay.de>
Thu, 11 Aug 2011 07:50:37 +0000 (07:50 +0000)
committerGeorg-Johann Lay <gjl@gcc.gnu.org>
Thu, 11 Aug 2011 07:50:37 +0000 (07:50 +0000)
PR target/49687
* config/avr/avr.md (smulqi3_highpart): New insn.
(umulqi3_highpart): New insn.
(*subqi3.ashiftrt7): New insn.
(smulhi3_highpart): New expander.
(umulhi3_highpart): Nex expander.
(*smulhi3_highpart_call): New insn.
(*umulhi3_highpart_call): New insn.
(extend_u): New code attribute.
(extend_prefix): Rename code attribute to extend_su.
* config/avr/avr.c (avr_rtx_costs): Report costs of highpart of
widening QI/HI multiply.

From-SVN: r177648

gcc/ChangeLog
gcc/config/avr/avr.c
gcc/config/avr/avr.md

index f85d349b8e1cd3fbe662087d92c911a363bb3ce2..0220752fed5cea178683178ca235bff3e55355f4 100644 (file)
@@ -1,3 +1,18 @@
+2011-08-11  Georg-Johann Lay  <avr@gjlay.de>
+       
+       PR target/49687
+       * config/avr/avr.md (smulqi3_highpart): New insn.
+       (umulqi3_highpart): New insn.
+       (*subqi3.ashiftrt7): New insn.
+       (smulhi3_highpart): New expander.
+       (umulhi3_highpart): Nex expander.
+       (*smulhi3_highpart_call): New insn.
+       (*umulhi3_highpart_call): New insn.
+       (extend_u): New code attribute.
+       (extend_prefix): Rename code attribute to extend_su.
+       * config/avr/avr.c (avr_rtx_costs): Report costs of highpart of
+       widening QI/HI multiply.
+
 2011-08-11  Ira Rosen  <ira.rosen@linaro.org>
 
        PR tree-optimization/50039
index d9ed22489479355f9067472c390b022c0b803c38..76542a87dc047a196174c5b03fc7bfbd0929e1fb 100644 (file)
@@ -5954,6 +5954,20 @@ avr_rtx_costs (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED, int *total,
       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, speed);
       return true;
 
+    case TRUNCATE:
+      if (AVR_HAVE_MUL
+          && LSHIFTRT == GET_CODE (XEXP (x, 0))
+          && MULT == GET_CODE (XEXP (XEXP (x, 0), 0))
+          && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
+        {
+          if (QImode == mode || HImode == mode)
+            {
+              *total = COSTS_N_INSNS (2);
+              return true;
+            }
+        }
+      break;
+
     default:
       break;
     }
index 8293ba7558e75f9ffd24951f4ffef8c6d34164e4..356b5095438043cabef60180e8efd8cec4cca853 100644 (file)
 (define_code_iterator any_extend2 [sign_extend zero_extend])
 
 ;; Define code attributes
-(define_code_attr extend_prefix
+(define_code_attr extend_su
   [(sign_extend "s")
    (zero_extend "u")])
 
+(define_code_attr extend_u
+  [(sign_extend "")
+   (zero_extend "u")])
+
 
 ;;========================================================================
 ;; The following is used by nonlocal_goto and setjmp.
   [(set_attr "type" "xcall")
    (set_attr "cc" "clobber")])
 
+(define_insn "smulqi3_highpart"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (truncate:QI
+         (lshiftrt:HI (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
+                               (sign_extend:HI (match_operand:QI 2 "register_operand" "d")))
+                      (const_int 8))))]
+  "AVR_HAVE_MUL"
+  "muls %1,%2
+       mov %0,r1
+       clr __zero_reg__"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+  
+(define_insn "umulqi3_highpart"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (truncate:QI
+         (lshiftrt:HI (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+                               (zero_extend:HI (match_operand:QI 2 "register_operand" "r")))
+                      (const_int 8))))]
+  "AVR_HAVE_MUL"
+  "mul %1,%2
+       mov %0,r1
+       clr __zero_reg__"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+
+;; Used when expanding div or mod inline for some special values
+(define_insn "*subqi3.ashiftrt7"
+  [(set (match_operand:QI 0 "register_operand"                       "=r")
+        (minus:QI (match_operand:QI 1 "register_operand"              "0")
+                  (ashiftrt:QI (match_operand:QI 2 "register_operand" "r")
+                               (const_int 7))))]
+  ""
+  "sbrc %2,7\;inc %0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")])
+
 (define_insn "mulqihi3"
   [(set (match_operand:HI 0 "register_operand" "=r")
        (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
   [(set_attr "type" "xcall")
    (set_attr "cc" "clobber")])
 
-;; Operand 2 (reg:SI 18) not clobbered on the enhanced core.
-;; All call-used registers clobbered otherwise - normal library call.
-;;    To support widening multiplicatioon with constant we postpone
+;; To support widening multiplicatioon with constant we postpone
 ;; expanding to the implicit library call until post combine and
 ;; prior to register allocation.  Clobber all hard registers that
 ;; might be used by the (widening) multiply until it is split and
         (reg:SI 22))]
   "")
 
-(define_expand "mulhisi3"
+;; "mulhisi3"
+;; "umulhisi3"
+(define_expand "<extend_u>mulhisi3"
   [(parallel [(set (match_operand:SI 0 "register_operand" "")
-                   (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" ""))
-                            (sign_extend:SI (match_operand:HI 2 "register_operand" ""))))
-              (clobber (reg:HI 26))
-              (clobber (reg:DI 18))])]
-  "AVR_HAVE_MUL"
-  "")
-
-(define_expand "umulhisi3"
-  [(parallel [(set (match_operand:SI 0 "register_operand" "")
-                   (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" ""))
-                            (zero_extend:SI (match_operand:HI 2 "register_operand" ""))))
+                   (mult:SI (any_extend:SI (match_operand:HI 1 "register_operand" ""))
+                            (any_extend:SI (match_operand:HI 2 "register_operand" ""))))
               (clobber (reg:HI 26))
               (clobber (reg:DI 18))])]
   "AVR_HAVE_MUL"
 ;; "*sumulqihisi3" "*sumulhiqisi3" "*sumulhihisi3" "*sumulqiqisi3"
 ;; "*ssmulqihisi3" "*ssmulhiqisi3" "*ssmulhihisi3" "*ssmulqiqisi3"
 (define_insn_and_split
-  "*<any_extend:extend_prefix><any_extend2:extend_prefix>mul<QIHI:mode><QIHI2:mode>si3"
+  "*<any_extend:extend_su><any_extend2:extend_su>mul<QIHI:mode><QIHI2:mode>si3"
   [(set (match_operand:SI 0 "pseudo_register_operand"                            "=r")
         (mult:SI (any_extend:SI (match_operand:QIHI 1 "pseudo_register_operand"   "r"))
                  (any_extend2:SI (match_operand:QIHI2 2 "pseudo_register_operand" "r"))))
       }
   })
 
+;; "smulhi3_highpart"
+;; "umulhi3_highpart"
+(define_expand "<extend_su>mulhi3_highpart"
+  [(set (reg:HI 18)
+        (match_operand:HI 1 "nonmemory_operand" ""))
+   (set (reg:HI 26)
+        (match_operand:HI 2 "nonmemory_operand" ""))
+   (parallel [(set (reg:HI 24)
+                   (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
+                                                      (any_extend:SI (reg:HI 26)))
+                                             (const_int 16))))
+              (clobber (reg:HI 22))])
+   (set (match_operand:HI 0 "register_operand" "")
+        (reg:HI 24))]
+  "AVR_HAVE_MUL"
+  "")
+
+
 (define_insn "*mulsi3_call"
   [(set (reg:SI 22)
         (mult:SI (reg:SI 22)
   [(set_attr "type" "xcall")
    (set_attr "cc" "clobber")])
 
-(define_insn "*mulhisi3_call"
+;; "*mulhisi3_call"
+;; "*umulhisi3_call"
+(define_insn "*<extend_u>mulhisi3_call"
   [(set (reg:SI 22)
-        (mult:SI (sign_extend:SI (reg:HI 18))
-                 (sign_extend:SI (reg:HI 26))))]
+        (mult:SI (any_extend:SI (reg:HI 18))
+                 (any_extend:SI (reg:HI 26))))]
   "AVR_HAVE_MUL"
-  "%~call __mulhisi3"
+  "%~call __<extend_u>mulhisi3"
   [(set_attr "type" "xcall")
    (set_attr "cc" "clobber")])
 
-(define_insn "*umulhisi3_call"
-  [(set (reg:SI 22)
-        (mult:SI (zero_extend:SI (reg:HI 18))
-                 (zero_extend:SI (reg:HI 26))))]
+;; "*umulhi3_highpart_call"
+;; "*smulhi3_highpart_call"
+(define_insn "*<extend_su>mulhi3_highpart_call"
+  [(set (reg:HI 24)
+        (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
+                                           (any_extend:SI (reg:HI 26)))
+                                  (const_int 16))))
+   (clobber (reg:HI 22))]
   "AVR_HAVE_MUL"
-  "%~call __umulhisi3"
+  "%~call __<extend_u>mulhisi3"
   [(set_attr "type" "xcall")
    (set_attr "cc" "clobber")])
 
   [(set_attr "type" "xcall")
    (set_attr "cc" "clobber")])
 
-(define_insn "*muluhisi3_call"
-  [(set (reg:SI 22)
-        (mult:SI (zero_extend:SI (reg:HI 26))
-                 (reg:SI 18)))]
-  "AVR_HAVE_MUL"
-  "%~call __muluhisi3"
-  [(set_attr "type" "xcall")
-   (set_attr "cc" "clobber")])
-
-(define_insn "*mulshisi3_call"
+(define_insn "*mul<extend_su>hisi3_call"
   [(set (reg:SI 22)
-        (mult:SI (sign_extend:SI (reg:HI 26))
+        (mult:SI (any_extend:SI (reg:HI 26))
                  (reg:SI 18)))]
   "AVR_HAVE_MUL"
-  "%~call __mulshisi3"
+  "%~call __mul<extend_su>hisi3"
   [(set_attr "type" "xcall")
    (set_attr "cc" "clobber")])
 
 
 ;; "*ashluqihiqi3"
 ;; "*ashlsqihiqi3"
-(define_insn_and_split "*ashl<extend_prefix>qihiqi3"
+(define_insn_and_split "*ashl<extend_su>qihiqi3"
   [(set (match_operand:QI 0 "register_operand"                                     "=r")
         (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "0"))
                               (match_operand:QI 2 "register_operand"                "r"))
 
 ;; "*ashluqihiqi3.mem"
 ;; "*ashlsqihiqi3.mem"
-(define_insn_and_split "*ashl<extend_prefix>qihiqi3.mem"
+(define_insn_and_split "*ashl<extend_su>qihiqi3.mem"
   [(set (match_operand:QI 0 "memory_operand" "=m")
         (subreg:QI (ashift:HI (any_extend:HI (match_operand:QI 1 "register_operand" "r"))
                               (match_operand:QI 2 "register_operand" "r"))
    (set (match_dup 0)
         (match_dup 3))]
   {
-    operands[3] = force_reg (QImode, operands[0]);
+    operands[3] = gen_reg_rtx (QImode);
   })
 
 ;; Similar.
         (match_dup 4))]
   {
     operands[3] = simplify_gen_subreg (QImode, operands[1], HImode, 0);
-    operands[4] = force_reg (QImode, operands[0]);
+    operands[4] = gen_reg_rtx (QImode);
   })
 
 ;; High part of 16-bit shift is unused after the instruction: