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

Segher Boessenkool segher@kernel.crashing.org
Mon Sep 1 19:56:00 GMT 2014


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(-)

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")
-- 
1.8.1.4



More information about the Gcc-patches mailing list