diff mbox

[2/4] rs6000: Merge and improve highpart and widening muls

Message ID 4787074296dde2e3c21416541f78ee475c588df6.1409581755.git.segher@kernel.crashing.org
State New
Headers show

Commit Message

Segher Boessenkool Sept. 1, 2014, 7:49 p.m. UTC
This is a little more complex.  The highpart muls generate a "truncate
lshiftrt" pattern that is not canonical when widening to two registers,
so this doesn't optimise well with combine.  This patch changes it to use
the canonical subreg patterns instead, which means we need separate patterns
for LE mode.  Oh well.

Tested as usual.  This regresses gcc.dg/sms-8.c with -m32: SMS now _does_
succeed, from my shallow investigation because there now are subregs and
SMS explicitly looks for that.  I didn't look further because other SMS
tests are failing (without the patch) as well.

Is this okay to apply?


Segher


2014-09-01  Segher Boessenkool  <segher@kernel.crashing.org>

gcc/
	* 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.

---
 gcc/config/rs6000/rs6000.md | 247 ++++++++++++++++++--------------------------
 1 file changed, 103 insertions(+), 144 deletions(-)

Comments

David Edelsohn Sept. 2, 2014, 12:30 a.m. UTC | #1
On Mon, Sep 1, 2014 at 3:49 PM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> This is a little more complex.  The highpart muls generate a "truncate
> lshiftrt" pattern that is not canonical when widening to two registers,
> so this doesn't optimise well with combine.  This patch changes it to use
> the canonical subreg patterns instead, which means we need separate patterns
> for LE mode.  Oh well.
>
> Tested as usual.  This regresses gcc.dg/sms-8.c with -m32: SMS now _does_
> succeed, from my shallow investigation because there now are subregs and
> SMS explicitly looks for that.  I didn't look further because other SMS
> tests are failing (without the patch) as well.
>
> Is this okay to apply?
>
>
> Segher
>
>
> 2014-09-01  Segher Boessenkool  <segher@kernel.crashing.org>
>
> gcc/
>         * 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.

Okay.

Thanks, David
diff mbox

Patch

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index d903e4a..f9e1eba 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -431,6 +431,11 @@  (define_code_attr return_pred [(return "direct_return ()")
 			       (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")
@@ -454,6 +459,10 @@  (define_mode_attr sel [(SI "") (DI "64")])
 ;; 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")])
@@ -2767,6 +2776,100 @@  (define_insn_and_split "*mul<mode>3_dot2"
    (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")
@@ -6622,96 +6725,6 @@  (define_insn "*negdi2_noppc64"
   [(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.
@@ -6758,60 +6771,6 @@  (define_insn "*ashrdisi3_noppc64be"
 
 ;; 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")