This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Handle STRICT_LOW_PART in ifcvt
- To: rth at redhat dot com
- Subject: [PATCH] Handle STRICT_LOW_PART in ifcvt
- From: Jakub Jelinek <jakub at redhat dot com>
- Date: Thu, 29 Mar 2001 18:32:50 +0200
- Cc: gcc-patches at gcc dot gnu dot org
- Reply-To: Jakub Jelinek <jakub at redhat dot com>
Hi!
The testcase below ICEs on ia32 with -O (while it worked just fine with
2.95.x). The issue is:
a) If the conditionally assigned destination is STRICT_LOW_PART, ifcvt
used to get mode from STRICT_LOW_PART (=VOIDmode), generated pseudo
of that mode and used it - bad
b) once that was fixed, I found that it is trying later on to emit_move_insn
this pseudo into the STRICT_LOW_PART. Unfortunately, emit_move_insn
requires that the modes are the same etc. As apparently ifcvt is the only
code which attempts something like that, I have tried not to bloat
emit_move_insn and instead created an ifcvt variant of emit_move_insn
which handles this by calling store_bit_field.
Or should I rather hack up emit_move_insn so that it handles this case?
Note that for SUBREG_BYTE, bitpos is SUBREG_BYTE (outer) * BITS_PER_UNIT
instead of the 4 lines setting it below.
Ok to commit?
2001-03-29 Jakub Jelinek <jakub@redhat.com>
* ifcvt.c (noce_emit_move_insn): New.
(noce_try_store_flag, noce_try_store_flag_constants,
noce_try_store_flag_inc, noce_try_store_flag_mask,
noce_try_cmove, noce_try_cmove_arith, noce_try_minmax,
noce_try_abs): Use it.
(noce_process_if_block): Likewise.
For STRICT_LOW_PART, take mode from its SUBREG.
* gcc.c-torture/compile/20010329-1.c: New test.
--- gcc/ifcvt.c.jj Thu Mar 22 12:10:33 2001
+++ gcc/ifcvt.c Thu Mar 29 19:15:02 2001
@@ -96,6 +96,7 @@ static int find_if_case_2 PARAMS ((basi
static int find_memory PARAMS ((rtx *, void *));
static int dead_or_predicable PARAMS ((basic_block, basic_block,
basic_block, rtx, int));
+static void noce_emit_move_insn PARAMS ((rtx, rtx));
/* Abuse the basic_block AUX field to store the original block index,
as well as a flag indicating that the block should be rescaned for
@@ -537,6 +538,34 @@ noce_emit_store_flag (if_info, x, revers
|| code == GEU || code == GTU), normalize);
}
+/* Emit instruction to move a rtx into STRICT_LOW_PART. */
+static void
+noce_emit_move_insn (x, y)
+ rtx x, y;
+{
+ enum machine_mode outmode, inmode;
+ rtx outer, inner;
+ int bitpos;
+
+ if (GET_CODE (x) != STRICT_LOW_PART)
+ {
+ emit_move_insn (x, y);
+ return;
+ }
+
+ outer = XEXP (x, 0);
+ inner = XEXP (outer, 0);
+ outmode = GET_MODE (outer);
+ inmode = GET_MODE (inner);
+ bitpos = SUBREG_WORD (outer) * BITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN)
+ bitpos += (GET_MODE_BITSIZE (inmode) - GET_MODE_BITSIZE (outmode))
+ % BITS_PER_WORD;
+ store_bit_field (inner, GET_MODE_BITSIZE (outmode),
+ bitpos, outmode, y, GET_MODE_BITSIZE (inmode),
+ GET_MODE_BITSIZE (inmode));
+}
+
/* Convert "if (test) x = 1; else x = 0".
Only try 0 and STORE_FLAG_VALUE here. Other combinations will be
@@ -569,7 +598,7 @@ noce_try_store_flag (if_info)
if (target)
{
if (target != if_info->x)
- emit_move_insn (if_info->x, target);
+ noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
end_sequence ();
@@ -692,7 +721,7 @@ noce_try_store_flag_constants (if_info)
}
if (target != if_info->x)
- emit_move_insn (if_info->x, target);
+ noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
end_sequence ();
@@ -751,7 +780,7 @@ noce_try_store_flag_inc (if_info)
if (target)
{
if (target != if_info->x)
- emit_move_insn (if_info->x, target);
+ noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
end_sequence ();
@@ -803,7 +832,7 @@ noce_try_store_flag_mask (if_info)
if (target)
{
if (target != if_info->x)
- emit_move_insn (if_info->x, target);
+ noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
end_sequence ();
@@ -902,7 +931,7 @@ noce_try_cmove (if_info)
if (target)
{
if (target != if_info->x)
- emit_move_insn (if_info->x, target);
+ noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
end_sequence ();
@@ -1059,10 +1088,10 @@ noce_try_cmove_arith (if_info)
if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
MEM_ALIAS_SET (tmp) = MEM_ALIAS_SET (if_info->a);
- emit_move_insn (if_info->x, tmp);
+ noce_emit_move_insn (if_info->x, tmp);
}
else if (target != x)
- emit_move_insn (x, target);
+ noce_emit_move_insn (x, target);
tmp = get_insns ();
end_sequence ();
@@ -1209,7 +1238,7 @@ noce_try_minmax (if_info)
return FALSE;
}
if (target != if_info->x)
- emit_move_insn (if_info->x, target);
+ noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
end_sequence ();
@@ -1327,7 +1356,7 @@ noce_try_abs (if_info)
}
if (target != if_info->x)
- emit_move_insn (if_info->x, target);
+ noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
end_sequence ();
@@ -1532,7 +1561,8 @@ noce_process_if_block (test_bb, then_bb,
{
if (no_new_pseudos)
return FALSE;
- x = gen_reg_rtx (GET_MODE (x));
+ x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
+ ? XEXP (x, 0) : x));
}
/* Don't operate on sources that may trap or are volatile. */
@@ -1638,7 +1668,7 @@ noce_process_if_block (test_bb, then_bb,
if (orig_x != x)
{
start_sequence ();
- emit_move_insn (orig_x, x);
+ noce_emit_move_insn (orig_x, x);
insn_b = gen_sequence ();
end_sequence ();
--- gcc/testsuite/gcc.c-torture/compile/20010329-1.c.jj Thu Mar 29 17:38:02 2001
+++ gcc/testsuite/gcc.c-torture/compile/20010329-1.c Thu Mar 29 19:18:06 2001
@@ -0,0 +1,17 @@
+union u {
+ unsigned char a;
+ double b;
+};
+
+int a;
+
+union u foo (void)
+{
+ union u b;
+
+ if (a)
+ b.a = 1;
+ else
+ b.a = 0;
+ return b;
+}
Jakub