This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] ifcvt: Handle INSV patterns properly when a temp reg is needed
- From: Andreas Krebbel <krebbel1 at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 31 Mar 2006 13:43:14 +0200
- Subject: [PATCH] ifcvt: Handle INSV patterns properly when a temp reg is needed
Hi,
when the if conversion step optimizes something like:
if (x)
y = c1;
else
y = c2;
it introduces a temporary register for calculating the value for y without jumps.
Even if y = c1 is an INSV pattern ifcvt replaces c1 with the temporary register without asking
recog whether the insn stays valid. On S/390 we allow only MEMs or immediates as
source in INSV patterns. Hence we get an "unrecognizable insn" in such cases.
ifcvt uses the noce_emit_move function for moving the temporary to the target
location. This function performs several checks for the structure of the source rtx
if the resulting insn couldn't be recognized but doesn't care about 'unusual'
destinations. The attached patch adds a check for ZERO_EXTRACT as destination and
calls store_bit_field to emit the move instruction. This fixes the failure on s390x.
As it seems due to this patch store_bit_field encounters rtxs which it didn't had to
deal with before. This revealed a store_bit_field bug when handling paradoxical subregs.
I've fixed this with another patch which is a prerequisite for this one:
http://gcc.gnu.org/ml/gcc-patches/2006-03/msg01793.html
Bootstrapped on s390 and s390x with gcc 4.1 and gcc 4.2.
No testsuite regressions.
I will bootstrap and test this patch on i686 as well.
OK for mainline and 4.1?
Bye,
-Andreas-
2006-03-31 Andreas Krebbel <krebbel1@de.ibm.com>
* ifcvt.c (noce_emit_move_insn): Call store_bit_field if the resulting
move would be an INSV insn.
2006-03-31 Andreas Krebbel <krebbel1@de.ibm.com>
* gcc.c-torture/compile/20060331-1.c: Added.
Index: gcc/ifcvt.c
===================================================================
*** gcc/ifcvt.c.orig 2006-03-31 13:10:17.000000000 +0200
--- gcc/ifcvt.c 2006-03-31 13:10:31.000000000 +0200
*************** noce_emit_move_insn (rtx x, rtx y)
*** 702,748 ****
end_sequence();
if (recog_memoized (insn) <= 0)
! switch (GET_RTX_CLASS (GET_CODE (y)))
! {
! case RTX_UNARY:
! ot = code_to_optab[GET_CODE (y)];
! if (ot)
! {
! start_sequence ();
! target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
! if (target != NULL_RTX)
! {
! if (target != x)
! emit_move_insn (x, target);
! seq = get_insns ();
! }
! end_sequence ();
! }
! break;
!
! case RTX_BIN_ARITH:
! case RTX_COMM_ARITH:
! ot = code_to_optab[GET_CODE (y)];
! if (ot)
! {
! start_sequence ();
! target = expand_binop (GET_MODE (y), ot,
! XEXP (y, 0), XEXP (y, 1),
! x, 0, OPTAB_DIRECT);
! if (target != NULL_RTX)
! {
! if (target != x)
! emit_move_insn (x, target);
! seq = get_insns ();
! }
! end_sequence ();
! }
! break;
! default:
! break;
! }
emit_insn (seq);
return;
}
--- 702,760 ----
end_sequence();
if (recog_memoized (insn) <= 0)
! {
! if (GET_CODE (x) == ZERO_EXTRACT)
! {
! rtx op = XEXP (x, 0);
! unsigned HOST_WIDE_INT size = INTVAL (XEXP (x, 1));
! unsigned HOST_WIDE_INT start = INTVAL (XEXP (x, 2));
! store_bit_field (op, size, start, GET_MODE (x), y);
! return;
! }
+ switch (GET_RTX_CLASS (GET_CODE (y)))
+ {
+ case RTX_UNARY:
+ ot = code_to_optab[GET_CODE (y)];
+ if (ot)
+ {
+ start_sequence ();
+ target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
+ if (target != NULL_RTX)
+ {
+ if (target != x)
+ emit_move_insn (x, target);
+ seq = get_insns ();
+ }
+ end_sequence ();
+ }
+ break;
+
+ case RTX_BIN_ARITH:
+ case RTX_COMM_ARITH:
+ ot = code_to_optab[GET_CODE (y)];
+ if (ot)
+ {
+ start_sequence ();
+ target = expand_binop (GET_MODE (y), ot,
+ XEXP (y, 0), XEXP (y, 1),
+ x, 0, OPTAB_DIRECT);
+ if (target != NULL_RTX)
+ {
+ if (target != x)
+ emit_move_insn (x, target);
+ seq = get_insns ();
+ }
+ end_sequence ();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
emit_insn (seq);
return;
}
Index: gcc/testsuite/gcc.c-torture/compile/20060331-1.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/20060331-1.c 2006-03-31 13:10:31.000000000 +0200
***************
*** 0 ****
--- 1,21 ----
+ /* This failed because if conversion didn't handle insv patterns properly. */
+
+ union y
+ {
+ int a;
+ unsigned short b;
+ };
+
+ extern void bar (unsigned short u, union y v);
+
+ void
+ foo (int check)
+ {
+ union y x;
+
+ if (check != 0)
+ x.b = 1;
+ else
+ x.b = 2;
+ bar (x.b, x);
+ }