fold_truthop patch causes sparcv9 testsuite regressions

David S. Miller davem@redhat.com
Sun Jun 23 19:50:00 GMT 2002


   From: Roger Sayle <roger@eyesopen.com>
   Date: Sat, 22 Jun 2002 10:42:39 -0600 (MDT)
   
   I know nothing of machine descriptions, and don't have access to a
   sparc machine, but hopefully I've tracked down the problem far enough
   that Dave can take it from here.
   
We lack any "mod" patterns for any Sparc configuration.  But
that is OK, when you do have hardware divide patterns the
compiler is supposed to transform:

	result = x % y;

into:

	tmp1 = x / y;
	tmp1 = tmp1 * y;
	result = x - tmp1;

It should never have a need to emit a libcall for the modulo
operation.

It is not doing that properly for (x % 0) for some reason and we need
to figure that out.  There is a bunch of code in expand_divmod that
appears to handle all of this.  Aha, but for some reason in this case
it doesn't try to widen the mode of the operation to DImode.  A huge
block of code is disabled when op1 is const0_rtx and that is aparently
what leads to this code not trying a wider mode division to accomplish
the remainder operation.  Other constant values work just fine.
op1_is_pow2 determines whether the compute mode is determined by shift
operations or real division operations.  However, const0_rtx makes
op1_is_pow2 true but it should not because in that case we will not be
generating shift operations but rather div/sdiv ones.

The fix is to change the optab1/optab2 calculation to no use shift
optabs when op1 == const0_rtx.  I am testing this fix right now,
attached below as a patch.

I noticed some other things while working on this bug, here is my
brain dump for that in case someone wants to pursue these issues:

1. On Sparc we only provide a DImode hardware divison because that is
   what is available when we don't want to use the deprecated V8
   32-bit division instructions.  We might want to open code the
   SI-->DI mode conversions in these cases using expanders so that
   expand_divmod doesn't work as hard.

2. Strangely the Solaris config uses TARGET_DEPRECATED_V8_INSNS by
   default for -m64 and that is absolutely stupid.  The deprecated V8
   instructions are faster for SImode divisions on UltraSPARC which
   accounts for %99 of all Solaris2 64-bit Sparc systems (the rest are
   Fujitsu Hal and Sparc64, ie. nearly nobody).  And it's probably faster
   on Fujitsu's chips too.  I'm inclined to totally rip this option out
   from the sparc backend because any sane modern chip will do a 32-bit
   division more quickly than a 64-bit one.  And this Solaris2 config
   bogosity shows that very few people understand the implications of it.

   This setting severely pessimizes performance on Solaris2.x Sparc
   systems unless the user configures with a default cpu of ultrasparc.

Anyways, here is the patch.

2002-06-23  David S. Miller  <davem@redhat.com>

	* expmed.c (expand_divmod): Do not set optab1/optab2 to the shift
	optabs if op1 is const0_rtx.

--- expmed.c.~1~	Mon Jun 17 19:31:53 2002
+++ expmed.c	Sun Jun 23 18:07:46 2002
@@ -3049,9 +3049,12 @@ expand_divmod (rem_flag, code, mode, op0
      not straightforward to generalize this.  Maybe we should make an array
      of possible modes in init_expmed?  Save this for GCC 2.7.  */
 
-  optab1 = (op1_is_pow2 ? (unsignedp ? lshr_optab : ashr_optab)
+  optab1 = ((op1_is_pow2 && op1 != const0_rtx)
+	    ? (unsignedp ? lshr_optab : ashr_optab)
 	    : (unsignedp ? udiv_optab : sdiv_optab));
-  optab2 = (op1_is_pow2 ? optab1 : (unsignedp ? udivmod_optab : sdivmod_optab));
+  optab2 = ((op1_is_pow2 && op1 != const0_rtx)
+	    ? optab1
+	    : (unsignedp ? udivmod_optab : sdivmod_optab));
 
   for (compute_mode = mode; compute_mode != VOIDmode;
        compute_mode = GET_MODE_WIDER_MODE (compute_mode))



More information about the Gcc-bugs mailing list