[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