rs6000.md (any_extend): New code iterator.
authorSegher Boessenkool <segher@kernel.crashing.org>
Tue, 2 Sep 2014 11:21:09 +0000 (13:21 +0200)
committerSegher Boessenkool <segher@gcc.gnu.org>
Tue, 2 Sep 2014 11:21:09 +0000 (13:21 +0200)
2014-09-02  Segher Boessenkool  <segher@kernel.crashing.org>

* config/rs6000/rs6000.md (any_extend): New code iterator.
(u, su): New code attributes.
(dmode, DMODE): New mode attributes.
(<su>mul<mode>3_highpart): New.
(*<su>mul<mode>3_highpart): New.
(<su>mulsi3_highpart_le): New.
(<su>muldi3_highpart_le): New.
(<su>mulsi3_highpart_64): New.
(<u>mul<mode><dmode>3): New.
(mulsidi3, umulsidi3, smulsi3_highpart, umulsi3_highpart, and two
splitters): Delete.
(mulditi3, umulditi3, smuldi3_highpart, umuldi3_highpart, and two
splitters): Delete.

From-SVN: r214814

gcc/ChangeLog
gcc/config/rs6000/rs6000.md

index 10c3554..79fb3f8 100644 (file)
@@ -1,5 +1,21 @@
 2014-09-02  Segher Boessenkool  <segher@kernel.crashing.org>
 
+       * config/rs6000/rs6000.md (any_extend): New code iterator.
+       (u, su): New code attributes.
+       (dmode, DMODE): New mode attributes.
+       (<su>mul<mode>3_highpart): New.
+       (*<su>mul<mode>3_highpart): New.
+       (<su>mulsi3_highpart_le): New.
+       (<su>muldi3_highpart_le): New.
+       (<su>mulsi3_highpart_64): New.
+       (<u>mul<mode><dmode>3): New.
+       (mulsidi3, umulsidi3, smulsi3_highpart, umulsi3_highpart, and two
+       splitters): Delete.
+       (mulditi3, umulditi3, smuldi3_highpart, umuldi3_highpart, and two
+       splitters): Delete.
+
+2014-09-02  Segher Boessenkool  <segher@kernel.crashing.org>
+
        * config/rs6000/rs6000.md (mulsi3, *mulsi3_internal1,
        *mulsi3_internal2, and two splitters): Delete.
        (muldi3, *muldi3_internal1, *muldi3_internal2, and two splitters):
index d903e4a..f9e1eba 100644 (file)
                               (simple_return "1")])
 (define_code_attr return_str [(return "") (simple_return "simple_")])
 
+; Signed/unsigned variants of ops.
+(define_code_iterator any_extend [sign_extend zero_extend])
+(define_code_attr u [(sign_extend "") (zero_extend "u")])
+(define_code_attr su [(sign_extend "s") (zero_extend "u")])
+
 ; Various instructions that come in SI and DI forms.
 ; A generic w/d attribute, for things like cmpw/cmpd.
 (define_mode_attr wd [(QI    "b")
 ;; Bitmask for shift instructions
 (define_mode_attr hH [(SI "h") (DI "H")])
 
+;; A mode twice the size of the given mode
+(define_mode_attr dmode [(SI "di") (DI "ti")])
+(define_mode_attr DMODE [(SI "DI") (DI "TI")])
+
 ;; Suffix for reload patterns
 (define_mode_attr ptrsize [(SI "32bit")
                           (DI "64bit")])
    (set_attr "length" "4,8")])
 
 
+(define_expand "<su>mul<mode>3_highpart"
+  [(set (match_operand:GPR 0 "gpc_reg_operand")
+       (subreg:GPR
+         (mult:<DMODE> (any_extend:<DMODE>
+                         (match_operand:GPR 1 "gpc_reg_operand"))
+                       (any_extend:<DMODE>
+                         (match_operand:GPR 2 "gpc_reg_operand")))
+        0))]
+  ""
+{
+  if (<MODE>mode == SImode && TARGET_POWERPC64)
+    {
+      emit_insn (gen_<su>mulsi3_highpart_64 (operands[0], operands[1],
+                                            operands[2]));
+      DONE;
+    }
+
+  if (!WORDS_BIG_ENDIAN)
+    {
+      emit_insn (gen_<su>mul<mode>3_highpart_le (operands[0], operands[1],
+                                                operands[2]));
+      DONE;
+    }
+})
+
+(define_insn "*<su>mul<mode>3_highpart"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (subreg:GPR
+         (mult:<DMODE> (any_extend:<DMODE>
+                         (match_operand:GPR 1 "gpc_reg_operand" "r"))
+                       (any_extend:<DMODE>
+                         (match_operand:GPR 2 "gpc_reg_operand" "r")))
+        0))]
+  "WORDS_BIG_ENDIAN && !(<MODE>mode == SImode && TARGET_POWERPC64)"
+  "mulh<wd><u> %0,%1,%2"
+  [(set_attr "type" "mul")
+   (set_attr "size" "<bits>")])
+
+(define_insn "<su>mulsi3_highpart_le"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (subreg:SI
+         (mult:DI (any_extend:DI
+                    (match_operand:SI 1 "gpc_reg_operand" "r"))
+                  (any_extend:DI
+                    (match_operand:SI 2 "gpc_reg_operand" "r")))
+        4))]
+  "!WORDS_BIG_ENDIAN && !TARGET_POWERPC64"
+  "mulhw<u> %0,%1,%2"
+  [(set_attr "type" "mul")])
+
+(define_insn "<su>muldi3_highpart_le"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+       (subreg:DI
+         (mult:TI (any_extend:TI
+                    (match_operand:DI 1 "gpc_reg_operand" "r"))
+                  (any_extend:TI
+                    (match_operand:DI 2 "gpc_reg_operand" "r")))
+        8))]
+  "!WORDS_BIG_ENDIAN && TARGET_POWERPC64"
+  "mulhd<u> %0,%1,%2"
+  [(set_attr "type" "mul")
+   (set_attr "size" "64")])
+
+(define_insn "<su>mulsi3_highpart_64"
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (truncate:SI
+         (lshiftrt:DI
+           (mult:DI (any_extend:DI
+                      (match_operand:SI 1 "gpc_reg_operand" "r"))
+                    (any_extend:DI
+                      (match_operand:SI 2 "gpc_reg_operand" "r")))
+           (const_int 32))))]
+  "TARGET_POWERPC64"
+  "mulhw<u> %0,%1,%2"
+  [(set_attr "type" "mul")])
+
+(define_expand "<u>mul<mode><dmode>3"
+  [(set (match_operand:<DMODE> 0 "gpc_reg_operand")
+       (mult:<DMODE> (any_extend:<DMODE>
+                       (match_operand:GPR 1 "gpc_reg_operand"))
+                     (any_extend:<DMODE>
+                       (match_operand:GPR 2 "gpc_reg_operand"))))]
+  "!(<MODE>mode == SImode && TARGET_POWERPC64)"
+{
+  rtx l = gen_reg_rtx (<MODE>mode);
+  rtx h = gen_reg_rtx (<MODE>mode);
+  emit_insn (gen_mul<mode>3 (l, operands[1], operands[2]));
+  emit_insn (gen_<su>mul<mode>3_highpart (h, operands[1], operands[2]));
+  emit_move_insn (gen_lowpart (<MODE>mode, operands[0]), l);
+  emit_move_insn (gen_highpart (<MODE>mode, operands[0]), h);
+  DONE;
+})
+
+
 (define_insn "udiv<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
         (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
   [(set_attr "type" "two")
    (set_attr "length" "8")])
 
-(define_insn "mulsidi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
-       (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r"))
-                (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
-  "! TARGET_POWERPC64"
-{
-  return (WORDS_BIG_ENDIAN)
-    ? \"mulhw %0,%1,%2\;mullw %L0,%1,%2\"
-    : \"mulhw %L0,%1,%2\;mullw %0,%1,%2\";
-}
-  [(set_attr "type" "mul")
-   (set_attr "length" "8")])
-
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
-                (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" ""))))]
-  "! TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (truncate:SI
-        (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
-                              (sign_extend:DI (match_dup 2)))
-                     (const_int 32))))
-   (set (match_dup 4)
-       (mult:SI (match_dup 1)
-                (match_dup 2)))]
-  "
-{
-  int endian = (WORDS_BIG_ENDIAN == 0);
-  operands[3] = operand_subword (operands[0], endian, 0, DImode);
-  operands[4] = operand_subword (operands[0], 1 - endian, 0, DImode);
-}")
-
-(define_insn "umulsidi3"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
-       (mult:DI (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r"))
-                (zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
-  "! TARGET_POWERPC64"
-  "*
-{
-  return (WORDS_BIG_ENDIAN)
-    ? \"mulhwu %0,%1,%2\;mullw %L0,%1,%2\"
-    : \"mulhwu %L0,%1,%2\;mullw %0,%1,%2\";
-}"
-  [(set_attr "type" "mul")
-   (set_attr "length" "8")])
-
-(define_split
-  [(set (match_operand:DI 0 "gpc_reg_operand" "")
-       (mult:DI (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
-                (zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" ""))))]
-  "! TARGET_POWERPC64 && reload_completed"
-  [(set (match_dup 3)
-       (truncate:SI
-        (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
-                              (zero_extend:DI (match_dup 2)))
-                     (const_int 32))))
-   (set (match_dup 4)
-       (mult:SI (match_dup 1)
-                (match_dup 2)))]
-  "
-{
-  int endian = (WORDS_BIG_ENDIAN == 0);
-  operands[3] = operand_subword (operands[0], endian, 0, DImode);
-  operands[4] = operand_subword (operands[0], 1 - endian, 0, DImode);
-}")
-
-(define_insn "smulsi3_highpart"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (truncate:SI
-        (lshiftrt:DI (mult:DI (sign_extend:DI
-                               (match_operand:SI 1 "gpc_reg_operand" "%r"))
-                              (sign_extend:DI
-                               (match_operand:SI 2 "gpc_reg_operand" "r")))
-                     (const_int 32))))]
-  ""
-  "mulhw %0,%1,%2"
-  [(set_attr "type" "mul")])
-
-(define_insn "umulsi3_highpart"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (truncate:SI
-        (lshiftrt:DI (mult:DI (zero_extend:DI
-                               (match_operand:SI 1 "gpc_reg_operand" "%r"))
-                              (zero_extend:DI
-                               (match_operand:SI 2 "gpc_reg_operand" "r")))
-                     (const_int 32))))]
-  ""
-  "mulhwu %0,%1,%2"
-  [(set_attr "type" "mul")])
 
 ;; Shift by a variable amount is too complex to be worth open-coding.  We
 ;; just handle shifts by constants.
 \f
 ;; PowerPC64 DImode operations.
 
-(define_insn "smuldi3_highpart"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (truncate:DI
-        (lshiftrt:TI (mult:TI (sign_extend:TI
-                               (match_operand:DI 1 "gpc_reg_operand" "%r"))
-                              (sign_extend:TI
-                               (match_operand:DI 2 "gpc_reg_operand" "r")))
-                     (const_int 64))))]
-  "TARGET_POWERPC64"
-  "mulhd %0,%1,%2"
-  [(set_attr "type" "mul")
-   (set_attr "size" "64")])
-
-(define_insn "umuldi3_highpart"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
-       (truncate:DI
-        (lshiftrt:TI (mult:TI (zero_extend:TI
-                               (match_operand:DI 1 "gpc_reg_operand" "%r"))
-                              (zero_extend:TI
-                               (match_operand:DI 2 "gpc_reg_operand" "r")))
-                     (const_int 64))))]
-  "TARGET_POWERPC64"
-  "mulhdu %0,%1,%2"
-  [(set_attr "type" "mul")
-   (set_attr "size" "64")])
-
-(define_expand "mulditi3"
-  [(set (match_operand:TI 0 "gpc_reg_operand")
-       (mult:TI (sign_extend:TI (match_operand:DI 1 "gpc_reg_operand"))
-                (sign_extend:TI (match_operand:DI 2 "gpc_reg_operand"))))]
-  "TARGET_POWERPC64"
-{
-  rtx l = gen_reg_rtx (DImode), h = gen_reg_rtx (DImode);
-  emit_insn (gen_muldi3 (l, operands[1], operands[2]));
-  emit_insn (gen_smuldi3_highpart (h, operands[1], operands[2]));
-  emit_move_insn (gen_lowpart (DImode, operands[0]), l);
-  emit_move_insn (gen_highpart (DImode, operands[0]), h);
-  DONE;
-})
-
-(define_expand "umulditi3"
-  [(set (match_operand:TI 0 "gpc_reg_operand")
-       (mult:TI (zero_extend:TI (match_operand:DI 1 "gpc_reg_operand"))
-                (zero_extend:TI (match_operand:DI 2 "gpc_reg_operand"))))]
-  "TARGET_POWERPC64"
-{
-  rtx l = gen_reg_rtx (DImode), h = gen_reg_rtx (DImode);
-  emit_insn (gen_muldi3 (l, operands[1], operands[2]));
-  emit_insn (gen_umuldi3_highpart (h, operands[1], operands[2]));
-  emit_move_insn (gen_lowpart (DImode, operands[0]), l);
-  emit_move_insn (gen_highpart (DImode, operands[0]), h);
-  DONE;
-})
-
 (define_insn "*rotldi3_internal4"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")