[PATCH] Fix divdi3 on ppc64

Jakub Jelinek jakub@redhat.com
Thu Dec 14 14:57:00 GMT 2006


Hi!

The attached testcase broke between 4.0 and 4.1 due to the
http://gcc.gnu.org/ml/gcc-patches/2005-06/msg01044.html
macroization of rs6000.md patterns.
Before that patch divdi3 was

(define_expand "divdi3"
  [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
                (match_operand:DI 2 "reg_or_cint_operand" "")))]
  "TARGET_POWERPC64"
  "
{
  if (GET_CODE (operands[2]) == CONST_INT
      && INTVAL (operands[2]) > 0
      && exact_log2 (INTVAL (operands[2])) >= 0)
    ;
  else
    operands[2] = force_reg (DImode, operands[2]);
}")

now it is:

(define_expand "div<mode>3"
  [(set (match_operand:GPR 0 "gpc_reg_operand" "")
        (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
                 (match_operand:GPR 2 "reg_or_cint_operand" "")))]
  ""
  "
{
  if (GET_CODE (operands[2]) == CONST_INT
      && INTVAL (operands[2]) > 0
      && exact_log2 (INTVAL (operands[2])) >= 0)
    ;
  else if (TARGET_POWERPC)
    {
      operands[2] = force_reg (SImode, operands[2]);
      if (TARGET_POWER)
        {
          emit_insn (gen_divsi3_mq (operands[0], operands[1], operands[2]));
          DONE;
        }
    }
  else if (TARGET_POWER)
    FAIL;
  else
    {
      emit_move_insn (gen_rtx_REG (SImode, 3), operands[1]);
      emit_move_insn (gen_rtx_REG (SImode, 4), operands[2]);
      emit_insn (gen_quoss_call ());
      emit_move_insn (operands[0], gen_rtx_REG (SImode, 3));
      DONE;
    }
}")

This is not equivalent (we know TARGET_POWERPC64 != 0,
therefore also TARGET_POWERPC != 0 and TARGET_POWER == 0), but still
the mode argument passed to force_reg is different - used to be DImode
(correct), now is incorrectly SImode (code copied over from divsi3).
Usually operands[2] is already a register here and for REG_P
force_reg ignores the mode argument, but on the PR30185 testcase it is not.

Ok for 4.1/4.2/trunk?

2006-12-14  Jakub Jelinek  <jakub@redhat.com>

	PR target/30185
	* config/rs6000/rs6000.md (div<mode>3): Use correct mode in
	force_reg call.

	* gcc.c-torture/execute/pr30185.c: New test.

--- gcc/config/rs6000/rs6000.md.jj	2006-12-04 11:11:00.000000000 +0100
+++ gcc/config/rs6000/rs6000.md	2006-12-14 14:49:35.000000000 +0100
@@ -2443,7 +2443,7 @@
     ;
   else if (TARGET_POWERPC)
     {
-      operands[2] = force_reg (SImode, operands[2]);
+      operands[2] = force_reg (<MODE>mode, operands[2]);
       if (TARGET_POWER)
 	{
 	  emit_insn (gen_divsi3_mq (operands[0], operands[1], operands[2]));
--- gcc/testsuite/gcc.c-torture/execute/pr30185.c.jj	2006-12-14 15:38:16.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr30185.c	2006-12-14 15:31:16.000000000 +0100
@@ -0,0 +1,28 @@
+/* PR target/30185 */
+
+extern void abort (void);
+
+typedef struct S { char a; long long b; } S;
+
+S
+foo (S x, S y)
+{
+  S z;
+  z.b = x.b / y.b;
+  return z;
+}
+
+int
+main (void)
+{
+  S a, b;
+  a.b = 32LL;
+  b.b = 4LL;
+  if (foo ().b != 8LL)
+    abort ();
+  a.b = -8LL;
+  b.b = -2LL;
+  if (foo ().b != 4LL)
+    abort ();
+  return 0;
+}

	Jakub



More information about the Gcc-patches mailing list