[patch] MIPS/gcc: Revert removal of DImode shifts for 32-bit targets

Maciej W. Rozycki macro@linux-mips.org
Mon Jul 19 20:10:00 GMT 2004


Hello Richard,

 Your change to gcc 3.5:

2004-05-17  Richard Sandiford  <rsandifo@redhat.com>

	* config/mips/mips.h (MASK_DEBUG_G, TARGET_DEBUG_G_MODE): Delete.
	(TARGET_SWITCHES): Remove debugg.
	* config/mips/mips.md (adddi3, ashldi3, ashrdi3, lshrdi3): Only handle
	TARGET_64BIT.
	(subdi3): Replace the define_expand with a define_insn, the latter
	renamed from subdi3_internal_3.
	(negdi2): Likewise negdi2_internal_2.
	(adddi3_internal_[12], subdi3_internal, ashldi3_internal{,2,3})
	(ashrdi3_internal{,2,3}, lshrdi3_internal{,2,3}): Remove patterns
	and associated define_splits.
	(adddi3_internal): Renamed from adddi3_internal_3.
	(ashldi3_internal): Likewise ashldi3_internal4.
	(ashrdi3_internal): Likewise ashrdi3_internal4.
	(lshrdi3_internal): Likewise lshrdi3_internal4.

breaks 32-bit Linux builds.  Linux relies on simple operations
(addition/subtraction and shifts) on "long long" variables being
implemented inline without a call to libgcc, which isn't linked in.  
After your change Linux has unresolved references to external __ashldi3(),
__ashrdi3() and __lshrdi3() functions at the final link.

 Here is a complete revert of the relevant changes that works for me, but
please feel free to provide a replacement.  Either way, please make
ashldi3, ashrdi3 and lshrdi3 available for 32-bit targets again.

2004-07-19  Maciej W. Rozycki  <macro@linux-mips.org>

	* config/mips/mips.md (ashldi3, ashrdi3, lshrdi3): Handle 
	!TARGET_64BIT again, partially reverting the change from 
	2004-05-17.
	(ashldi3_internal{,2,3}, ashrdi3_internal{,2,3}, 
	lshrdi3_internal{,2,3}): Restore patterns and associated 
	define_splits.
	(ashldi3_internal4): Rename from ashldi3_internal.
	(ashrdi3_internal4): Likewise ashrdi3_internal.
	(lshrdi3_internal4): Likewise lshrdi3_internal.

  Maciej

gcc-3.5.0-20040714-mips-xshxdi32.patch
diff -up --recursive --new-file gcc-3.5.0-20040714.macro/gcc/config/mips/mips.md gcc-3.5.0-20040714/gcc/config/mips/mips.md
--- gcc-3.5.0-20040714.macro/gcc/config/mips/mips.md	2004-07-13 04:59:54.000000000 +0000
+++ gcc-3.5.0-20040714/gcc/config/mips/mips.md	2004-07-17 19:00:14.000000000 +0000
@@ -4997,37 +4997,213 @@ dsrl\t%3,%3,1\n\
   { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); })
 
 (define_expand "ashldi3"
-  [(set (match_operand:DI 0 "register_operand")
-	(ashift:DI (match_operand:DI 1 "register_operand")
-		   (match_operand:SI 2 "arith_operand")))]
-  "TARGET_64BIT"
+  [(parallel [(set (match_operand:DI 0 "register_operand")
+		   (ashift:DI (match_operand:DI 1 "register_operand")
+			      (match_operand:SI 2 "arith_operand")))
+	      (clobber (match_dup  3))])]
+  "TARGET_64BIT || !TARGET_MIPS16"
 {
-  /* On the mips16, a shift of more than 8 is a four byte
-     instruction, so, for a shift between 8 and 16, it is just as
-     fast to do two shifts of 8 or less.  If there is a lot of
-     shifting going on, we may win in CSE.  Otherwise combine will
-     put the shifts back together again.  This can be called by
-     function_arg, so we must be careful not to allocate a new
-     register if we've reached the reload pass.  */
-  if (TARGET_MIPS16
-      && optimize
-      && GET_CODE (operands[2]) == CONST_INT
-      && INTVAL (operands[2]) > 8
-      && INTVAL (operands[2]) <= 16
-      && ! reload_in_progress
-      && ! reload_completed)
+  if (TARGET_64BIT)
     {
-      rtx temp = gen_reg_rtx (DImode);
+      /* On the mips16, a shift of more than 8 is a four byte
+	 instruction, so, for a shift between 8 and 16, it is just as
+	 fast to do two shifts of 8 or less.  If there is a lot of
+	 shifting going on, we may win in CSE.  Otherwise combine will
+	 put the shifts back together again.  This can be called by
+	 function_arg, so we must be careful not to allocate a new
+	 register if we've reached the reload pass.  */
+      if (TARGET_MIPS16
+	  && optimize
+	  && GET_CODE (operands[2]) == CONST_INT
+	  && INTVAL (operands[2]) > 8
+	  && INTVAL (operands[2]) <= 16
+	  && ! reload_in_progress
+	  && ! reload_completed)
+	{
+	  rtx temp = gen_reg_rtx (DImode);
 
-      emit_insn (gen_ashldi3_internal (temp, operands[1], GEN_INT (8)));
-      emit_insn (gen_ashldi3_internal (operands[0], temp,
-				       GEN_INT (INTVAL (operands[2]) - 8)));
+	  emit_insn (gen_ashldi3_internal4 (temp, operands[1], GEN_INT (8)));
+	  emit_insn (gen_ashldi3_internal4 (operands[0], temp,
+					    GEN_INT (INTVAL (operands[2]) - 8)));
+	  DONE;
+	}
+
+      emit_insn (gen_ashldi3_internal4 (operands[0], operands[1],
+					operands[2]));
       DONE;
     }
+
+  operands[3] = gen_reg_rtx (SImode);
 })
 
 
 (define_insn "ashldi3_internal"
+  [(set (match_operand:DI 0 "register_operand" "=&d")
+	(ashift:DI (match_operand:DI 1 "register_operand" "d")
+		   (match_operand:SI 2 "register_operand" "d")))
+   (clobber (match_operand:SI 3 "register_operand" "=d"))]
+  "!TARGET_64BIT && !TARGET_MIPS16"
+  "sll\t%3,%2,26\;\
+bgez\t%3,1f%#\;\
+sll\t%M0,%L1,%2\;\
+%(b\t3f\;\
+move\t%L0,%.%)\
+\n\n\
+%~1:\;\
+%(beq\t%3,%.,2f\;\
+sll\t%M0,%M1,%2%)\
+\n\;\
+subu\t%3,%.,%2\;\
+srl\t%3,%L1,%3\;\
+or\t%M0,%M0,%3\n\
+%~2:\;\
+sll\t%L0,%L1,%2\n\
+%~3:"
+  [(set_attr "type"	"multi")
+   (set_attr "mode"	"SI")
+   (set_attr "length"	"48")])
+
+
+(define_insn "ashldi3_internal2"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(ashift:DI (match_operand:DI 1 "register_operand" "d")
+		   (match_operand:SI 2 "small_int" "IJK")))
+   (clobber (match_operand:SI 3 "register_operand" "=d"))]
+  "!TARGET_64BIT && !TARGET_MIPS16
+   && (INTVAL (operands[2]) & 32) != 0"
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+  return "sll\t%M0,%L1,%2\;move\t%L0,%.";
+}
+  [(set_attr "type"	"multi")
+   (set_attr "mode"	"DI")
+   (set_attr "length"	"8")])
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(ashift:DI (match_operand:DI 1 "register_operand")
+		   (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 32) != 0"
+
+  [(set (subreg:SI (match_dup 0) 4) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
+   (set (subreg:SI (match_dup 0) 0) (const_int 0))]
+
+  "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(ashift:DI (match_operand:DI 1 "register_operand")
+		   (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 32) != 0"
+
+  [(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 4) (match_dup 2)))
+   (set (subreg:SI (match_dup 0) 4) (const_int 0))]
+
+  "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
+
+
+(define_insn "ashldi3_internal3"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(ashift:DI (match_operand:DI 1 "register_operand" "d")
+		   (match_operand:SI 2 "small_int" "IJK")))
+   (clobber (match_operand:SI 3 "register_operand" "=d"))]
+  "!TARGET_64BIT && !TARGET_MIPS16
+   && (INTVAL (operands[2]) & 63) < 32
+   && (INTVAL (operands[2]) & 63) != 0"
+{
+  int amount = INTVAL (operands[2]);
+
+  operands[2] = GEN_INT (amount & 31);
+  operands[4] = GEN_INT ((-amount) & 31);
+
+  return "sll\t%M0,%M1,%2\;srl\t%3,%L1,%4\;or\t%M0,%M0,%3\;sll\t%L0,%L1,%2";
+}
+  [(set_attr "type"	"multi")
+   (set_attr "mode"	"DI")
+   (set_attr "length"	"16")])
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(ashift:DI (match_operand:DI 1 "register_operand")
+		   (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 63) < 32
+   && (INTVAL (operands[2]) & 63) != 0"
+
+  [(set (subreg:SI (match_dup 0) 4)
+	(ashift:SI (subreg:SI (match_dup 1) 4)
+		   (match_dup 2)))
+
+   (set (match_dup 3)
+	(lshiftrt:SI (subreg:SI (match_dup 1) 0)
+		     (match_dup 4)))
+
+   (set (subreg:SI (match_dup 0) 4)
+	(ior:SI (subreg:SI (match_dup 0) 4)
+		(match_dup 3)))
+
+   (set (subreg:SI (match_dup 0) 0)
+	(ashift:SI (subreg:SI (match_dup 1) 0)
+		   (match_dup 2)))]
+{
+  int amount = INTVAL (operands[2]);
+  operands[2] = GEN_INT (amount & 31);
+  operands[4] = GEN_INT ((-amount) & 31);
+})
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(ashift:DI (match_operand:DI 1 "register_operand")
+		   (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 63) < 32
+   && (INTVAL (operands[2]) & 63) != 0"
+
+  [(set (subreg:SI (match_dup 0) 0)
+	(ashift:SI (subreg:SI (match_dup 1) 0)
+		   (match_dup 2)))
+
+   (set (match_dup 3)
+	(lshiftrt:SI (subreg:SI (match_dup 1) 4)
+		     (match_dup 4)))
+
+   (set (subreg:SI (match_dup 0) 0)
+	(ior:SI (subreg:SI (match_dup 0) 0)
+		(match_dup 3)))
+
+   (set (subreg:SI (match_dup 0) 4)
+	(ashift:SI (subreg:SI (match_dup 1) 4)
+		   (match_dup 2)))]
+{
+  int amount = INTVAL (operands[2]);
+  operands[2] = GEN_INT (amount & 31);
+  operands[4] = GEN_INT ((-amount) & 31);
+})
+
+
+(define_insn "ashldi3_internal4"
   [(set (match_operand:DI 0 "register_operand" "=d")
 	(ashift:DI (match_operand:DI 1 "register_operand" "d")
 		   (match_operand:SI 2 "arith_operand" "dI")))]
@@ -5157,33 +5333,208 @@ dsrl\t%3,%3,1\n\
   { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); })
 
 (define_expand "ashrdi3"
-  [(set (match_operand:DI 0 "register_operand")
-	(ashiftrt:DI (match_operand:DI 1 "register_operand")
-		     (match_operand:SI 2 "arith_operand")))]
-  "TARGET_64BIT"
+  [(parallel [(set (match_operand:DI 0 "register_operand")
+		   (ashiftrt:DI (match_operand:DI 1 "register_operand")
+				(match_operand:SI 2 "arith_operand")))
+	      (clobber (match_dup  3))])]
+  "TARGET_64BIT || !TARGET_MIPS16"
 {
-  /* On the mips16, a shift of more than 8 is a four byte
-     instruction, so, for a shift between 8 and 16, it is just as
-     fast to do two shifts of 8 or less.  If there is a lot of
-     shifting going on, we may win in CSE.  Otherwise combine will
-     put the shifts back together again.  */
-  if (TARGET_MIPS16
-      && optimize
-      && GET_CODE (operands[2]) == CONST_INT
-      && INTVAL (operands[2]) > 8
-      && INTVAL (operands[2]) <= 16)
+  if (TARGET_64BIT)
     {
-      rtx temp = gen_reg_rtx (DImode);
+      /* On the mips16, a shift of more than 8 is a four byte
+	 instruction, so, for a shift between 8 and 16, it is just as
+	 fast to do two shifts of 8 or less.  If there is a lot of
+	 shifting going on, we may win in CSE.  Otherwise combine will
+	 put the shifts back together again.  */
+      if (TARGET_MIPS16
+	  && optimize
+	  && GET_CODE (operands[2]) == CONST_INT
+	  && INTVAL (operands[2]) > 8
+	  && INTVAL (operands[2]) <= 16)
+	{
+	  rtx temp = gen_reg_rtx (DImode);
+
+	  emit_insn (gen_ashrdi3_internal4 (temp, operands[1], GEN_INT (8)));
+	  emit_insn (gen_ashrdi3_internal4 (operands[0], temp,
+					    GEN_INT (INTVAL (operands[2]) - 8)));
+	  DONE;
+	}
 
-      emit_insn (gen_ashrdi3_internal (temp, operands[1], GEN_INT (8)));
-      emit_insn (gen_ashrdi3_internal (operands[0], temp,
-				       GEN_INT (INTVAL (operands[2]) - 8)));
+      emit_insn (gen_ashrdi3_internal4 (operands[0], operands[1],
+					operands[2]));
       DONE;
     }
+
+  operands[3] = gen_reg_rtx (SImode);
 })
 
 
 (define_insn "ashrdi3_internal"
+  [(set (match_operand:DI 0 "register_operand" "=&d")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+		     (match_operand:SI 2 "register_operand" "d")))
+   (clobber (match_operand:SI 3 "register_operand" "=d"))]
+  "!TARGET_64BIT && !TARGET_MIPS16"
+  "sll\t%3,%2,26\;\
+bgez\t%3,1f%#\;\
+sra\t%L0,%M1,%2\;\
+%(b\t3f\;\
+sra\t%M0,%M1,31%)\
+\n\n\
+%~1:\;\
+%(beq\t%3,%.,2f\;\
+srl\t%L0,%L1,%2%)\
+\n\;\
+subu\t%3,%.,%2\;\
+sll\t%3,%M1,%3\;\
+or\t%L0,%L0,%3\n\
+%~2:\;\
+sra\t%M0,%M1,%2\n\
+%~3:"
+  [(set_attr "type"	"multi")
+   (set_attr "mode"	"DI")
+   (set_attr "length"	"48")])
+
+
+(define_insn "ashrdi3_internal2"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+		     (match_operand:SI 2 "small_int" "IJK")))
+   (clobber (match_operand:SI 3 "register_operand" "=d"))]
+  "!TARGET_64BIT && (INTVAL (operands[2]) & 32) != 0"
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+  return "sra\t%L0,%M1,%2\;sra\t%M0,%M1,31";
+}
+  [(set_attr "type"	"multi")
+   (set_attr "mode"	"DI")
+   (set_attr "length"	"8")])
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand")
+		     (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 32) != 0"
+
+  [(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2)))
+   (set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (const_int 31)))]
+
+  "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand")
+		     (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 32) != 0"
+
+  [(set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
+   (set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (const_int 31)))]
+
+  "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
+
+
+(define_insn "ashrdi3_internal3"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+		     (match_operand:SI 2 "small_int" "IJK")))
+   (clobber (match_operand:SI 3 "register_operand" "=d"))]
+  "!TARGET_64BIT && !TARGET_MIPS16
+   && (INTVAL (operands[2]) & 63) < 32
+   && (INTVAL (operands[2]) & 63) != 0"
+{
+  int amount = INTVAL (operands[2]);
+
+  operands[2] = GEN_INT (amount & 31);
+  operands[4] = GEN_INT ((-amount) & 31);
+
+  return "srl\t%L0,%L1,%2\;sll\t%3,%M1,%4\;or\t%L0,%L0,%3\;sra\t%M0,%M1,%2";
+}
+  [(set_attr "type"	"multi")
+   (set_attr "mode"	"DI")
+   (set_attr "length"	"16")])
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand")
+		     (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 63) < 32
+   && (INTVAL (operands[2]) & 63) != 0"
+
+  [(set (subreg:SI (match_dup 0) 0)
+	(lshiftrt:SI (subreg:SI (match_dup 1) 0)
+		     (match_dup 2)))
+
+   (set (match_dup 3)
+	(ashift:SI (subreg:SI (match_dup 1) 4)
+		   (match_dup 4)))
+
+   (set (subreg:SI (match_dup 0) 0)
+	(ior:SI (subreg:SI (match_dup 0) 0)
+		(match_dup 3)))
+
+   (set (subreg:SI (match_dup 0) 4)
+	(ashiftrt:SI (subreg:SI (match_dup 1) 4)
+		     (match_dup 2)))]
+{
+  int amount = INTVAL (operands[2]);
+  operands[2] = GEN_INT (amount & 31);
+  operands[4] = GEN_INT ((-amount) & 31);
+})
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand")
+		     (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 63) < 32
+   && (INTVAL (operands[2]) & 63) != 0"
+
+  [(set (subreg:SI (match_dup 0) 4)
+	(lshiftrt:SI (subreg:SI (match_dup 1) 4)
+		     (match_dup 2)))
+
+   (set (match_dup 3)
+	(ashift:SI (subreg:SI (match_dup 1) 0)
+		   (match_dup 4)))
+
+   (set (subreg:SI (match_dup 0) 4)
+	(ior:SI (subreg:SI (match_dup 0) 4)
+		(match_dup 3)))
+
+   (set (subreg:SI (match_dup 0) 0)
+	(ashiftrt:SI (subreg:SI (match_dup 1) 0)
+		     (match_dup 2)))]
+{
+  int amount = INTVAL (operands[2]);
+  operands[2] = GEN_INT (amount & 31);
+  operands[4] = GEN_INT ((-amount) & 31);
+})
+
+
+(define_insn "ashrdi3_internal4"
   [(set (match_operand:DI 0 "register_operand" "=d")
 	(ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
 		     (match_operand:SI 2 "arith_operand" "dI")))]
@@ -5332,33 +5683,209 @@ dsrl\t%3,%3,1\n\
    (set_attr "length"	"16")])
 
 (define_expand "lshrdi3"
-  [(set (match_operand:DI 0 "register_operand")
-	(lshiftrt:DI (match_operand:DI 1 "register_operand")
-		     (match_operand:SI 2 "arith_operand")))]
-  "TARGET_64BIT"
+  [(parallel [(set (match_operand:DI 0 "register_operand")
+		   (lshiftrt:DI (match_operand:DI 1 "register_operand")
+				(match_operand:SI 2 "arith_operand")))
+	      (clobber (match_dup  3))])]
+  "TARGET_64BIT || !TARGET_MIPS16"
 {
-  /* On the mips16, a shift of more than 8 is a four byte
-     instruction, so, for a shift between 8 and 16, it is just as
-     fast to do two shifts of 8 or less.  If there is a lot of
-     shifting going on, we may win in CSE.  Otherwise combine will
-     put the shifts back together again.  */
-  if (TARGET_MIPS16
-      && optimize
-      && GET_CODE (operands[2]) == CONST_INT
-      && INTVAL (operands[2]) > 8
-      && INTVAL (operands[2]) <= 16)
+  if (TARGET_64BIT)
     {
-      rtx temp = gen_reg_rtx (DImode);
+      /* On the mips16, a shift of more than 8 is a four byte
+	 instruction, so, for a shift between 8 and 16, it is just as
+	 fast to do two shifts of 8 or less.  If there is a lot of
+	 shifting going on, we may win in CSE.  Otherwise combine will
+	 put the shifts back together again.  */
+      if (TARGET_MIPS16
+	  && optimize
+	  && GET_CODE (operands[2]) == CONST_INT
+	  && INTVAL (operands[2]) > 8
+	  && INTVAL (operands[2]) <= 16)
+	{
+	  rtx temp = gen_reg_rtx (DImode);
 
-      emit_insn (gen_lshrdi3_internal (temp, operands[1], GEN_INT (8)));
-      emit_insn (gen_lshrdi3_internal (operands[0], temp,
-				       GEN_INT (INTVAL (operands[2]) - 8)));
+	  emit_insn (gen_lshrdi3_internal4 (temp, operands[1], GEN_INT (8)));
+	  emit_insn (gen_lshrdi3_internal4 (operands[0], temp,
+					    GEN_INT (INTVAL (operands[2]) - 8)));
+	  DONE;
+	}
+
+      emit_insn (gen_lshrdi3_internal4 (operands[0], operands[1],
+					operands[2]));
       DONE;
     }
+
+  operands[3] = gen_reg_rtx (SImode);
 })
 
 
 (define_insn "lshrdi3_internal"
+  [(set (match_operand:DI 0 "register_operand" "=&d")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
+		     (match_operand:SI 2 "register_operand" "d")))
+   (clobber (match_operand:SI 3 "register_operand" "=d"))]
+  "!TARGET_64BIT && !TARGET_MIPS16"
+  "sll\t%3,%2,26\;\
+bgez\t%3,1f%#\;\
+srl\t%L0,%M1,%2\;\
+%(b\t3f\;\
+move\t%M0,%.%)\
+\n\n\
+%~1:\;\
+%(beq\t%3,%.,2f\;\
+srl\t%L0,%L1,%2%)\
+\n\;\
+subu\t%3,%.,%2\;\
+sll\t%3,%M1,%3\;\
+or\t%L0,%L0,%3\n\
+%~2:\;\
+srl\t%M0,%M1,%2\n\
+%~3:"
+  [(set_attr "type"	"multi")
+   (set_attr "mode"	"DI")
+   (set_attr "length"	"48")])
+
+
+(define_insn "lshrdi3_internal2"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
+		     (match_operand:SI 2 "small_int" "IJK")))
+   (clobber (match_operand:SI 3 "register_operand" "=d"))]
+  "!TARGET_64BIT && !TARGET_MIPS16
+   && (INTVAL (operands[2]) & 32) != 0"
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+  return "srl\t%L0,%M1,%2\;move\t%M0,%.";
+}
+  [(set_attr "type"	"multi")
+   (set_attr "mode"	"DI")
+   (set_attr "length"	"8")])
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand")
+		     (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 32) != 0"
+
+  [(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2)))
+   (set (subreg:SI (match_dup 0) 4) (const_int 0))]
+
+  "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand")
+		     (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 32) != 0"
+
+  [(set (subreg:SI (match_dup 0) 4) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
+   (set (subreg:SI (match_dup 0) 0) (const_int 0))]
+
+  "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
+
+
+(define_insn "lshrdi3_internal3"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
+		   (match_operand:SI 2 "small_int" "IJK")))
+   (clobber (match_operand:SI 3 "register_operand" "=d"))]
+  "!TARGET_64BIT && !TARGET_MIPS16
+   && (INTVAL (operands[2]) & 63) < 32
+   && (INTVAL (operands[2]) & 63) != 0"
+{
+  int amount = INTVAL (operands[2]);
+
+  operands[2] = GEN_INT (amount & 31);
+  operands[4] = GEN_INT ((-amount) & 31);
+
+  return "srl\t%L0,%L1,%2\;sll\t%3,%M1,%4\;or\t%L0,%L0,%3\;srl\t%M0,%M1,%2";
+}
+  [(set_attr "type"	"multi")
+   (set_attr "mode"	"DI")
+   (set_attr "length"	"16")])
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand")
+		     (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 63) < 32
+   && (INTVAL (operands[2]) & 63) != 0"
+
+  [(set (subreg:SI (match_dup 0) 0)
+	(lshiftrt:SI (subreg:SI (match_dup 1) 0)
+		     (match_dup 2)))
+
+   (set (match_dup 3)
+	(ashift:SI (subreg:SI (match_dup 1) 4)
+		   (match_dup 4)))
+
+   (set (subreg:SI (match_dup 0) 0)
+	(ior:SI (subreg:SI (match_dup 0) 0)
+		(match_dup 3)))
+
+   (set (subreg:SI (match_dup 0) 4)
+	(lshiftrt:SI (subreg:SI (match_dup 1) 4)
+		     (match_dup 2)))]
+{
+  int amount = INTVAL (operands[2]);
+  operands[2] = GEN_INT (amount & 31);
+  operands[4] = GEN_INT ((-amount) & 31);
+})
+
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand")
+		     (match_operand:SI 2 "small_int")))
+   (clobber (match_operand:SI 3 "register_operand"))]
+  "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT
+   && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16
+   && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
+   && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
+   && (INTVAL (operands[2]) & 63) < 32
+   && (INTVAL (operands[2]) & 63) != 0"
+
+  [(set (subreg:SI (match_dup 0) 4)
+	(lshiftrt:SI (subreg:SI (match_dup 1) 4)
+		     (match_dup 2)))
+
+   (set (match_dup 3)
+	(ashift:SI (subreg:SI (match_dup 1) 0)
+		   (match_dup 4)))
+
+   (set (subreg:SI (match_dup 0) 4)
+	(ior:SI (subreg:SI (match_dup 0) 4)
+		(match_dup 3)))
+
+   (set (subreg:SI (match_dup 0) 0)
+	(lshiftrt:SI (subreg:SI (match_dup 1) 0)
+		     (match_dup 2)))]
+{
+  int amount = INTVAL (operands[2]);
+  operands[2] = GEN_INT (amount & 31);
+  operands[4] = GEN_INT ((-amount) & 31);
+})
+
+
+(define_insn "lshrdi3_internal4"
   [(set (match_operand:DI 0 "register_operand" "=d")
 	(lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
 		     (match_operand:SI 2 "arith_operand" "dI")))]



More information about the Gcc-patches mailing list