This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR 28402: Doubleword shifts use word_mode libcalls


This patch fixes 28402, which is an SH regression introduced by:

2004-09-04  Richard Sandiford  <rsandifo@redhat.com>

	* doc/md.texi (shift patterns): New anchor.  Add reference to
	TARGET_SHIFT_TRUNCATION_MASK.
	* doc/tm.texi (TARGET_SHIFT_TRUNCATION_MASK): Document.
	* target.h (shift_truncation_mask): New target hook.
	* targhook.h (default_shift_truncation_mask): Declare.
	* targhook.c (default_shift_truncation_mask): Define.
	* target-def.h (TARGET_SHIFT_TRUNCATION_MASK): Define.
	(TARGET_INITIALIZER): Include it.
	* simplify-rtx.c (simplify_binary_operation): Combine ASHIFT, ASHIFTRT
	and LSHIFTRT cases.  Truncate arg1 if SHIFT_COUNT_TRUNCATED, otherwise
	reject all out-of-range values.  Fix sign-extension code for modes
	whose width is smaller than HOST_BITS_PER_WIDE_INT.
	* optabs.c (simplify_expand_binop, force_expand_binop): New functions.
	(expand_superword_shift, expand_subword_shift): Likewise.
	(expand_doubleword_shift_condmove, expand_doubleword_shift): Likewise.
	(expand_binop): Use them to implement double-word shifts.
	* config/arm/arm.c (arm_shift_truncation_mask): New function.
	(TARGET_SHIFT_TRUNCATION_MASK): Define.

The problem is that expand_binop passes the original method type
("methods") rather than the nested type ("next_methods") to
expand_doubleword_shift.  The shifts can therefore use SImode
libcalls to implement a double-word shift, which is certainly
not what we want in general.

(There are probably cases where using SImode libcalls turns out to be
better, such as shifts by constants larger than 32.  However, we make no
attempt to distinguish those cases at the moment, and doing so would be
a separate change.  The current behaviour is unintentional and IMO an
out-and-out bug.)

Bootstrapped & regression-tested on x86_64-linux-gnu.  Also regression-
tested on sh-elf.  OK for trunk?  This is a 4.x regression from 3.4,
so OK for the branches too, once tested there?

Richard


gcc/
	PR middle-end/28402
	* optabs.c (expand_binop): Pass next_methods rather than methods
	to expand_doubleword_shift.

gcc/testsuite/
	PR middle-end/28402
	* gcc.dg/pr28402.c: New test.

Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(revision 115438)
+++ gcc/optabs.c	(working copy)
@@ -1558,7 +1560,7 @@ expand_binop (enum machine_mode mode, op
 	  if (expand_doubleword_shift (op1_mode, binoptab,
 				       outof_input, into_input, op1,
 				       outof_target, into_target,
-				       unsignedp, methods, shift_mask))
+				       unsignedp, next_methods, shift_mask))
 	    {
 	      insns = get_insns ();
 	      end_sequence ();
Index: gcc/testsuite/gcc.dg/pr28402.c
===================================================================
--- gcc/testsuite/gcc.dg/pr28402.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr28402.c	(revision 0)
@@ -0,0 +1,22 @@
+/* { dg-options "" } */
+typedef long long ll;
+typedef unsigned long long ull;
+
+int global;
+
+#define A(BASE, OP, AMT) \
+  ll BASE ## AMT (ll x) { return x OP AMT; } \
+  ull BASE ## AMT ## u (ull x) { return x OP AMT; }
+
+#define B(BASE, OP) \
+  A (BASE, OP, 1) \
+  A (BASE, OP, 10) \
+  A (BASE, OP, 31) \
+  A (BASE, OP, 33) \
+  A (BASE, OP, 61) \
+  A (BASE, OP, global)
+
+B (left, <<)
+B (right, >>)
+
+/* { dg-final { scan-assembler-not "__\[a-z\]*si3" } } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]