aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/ifcvt.c113
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20060419-1.c21
4 files changed, 106 insertions, 39 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5ab45848029..c80626aef5e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2006-04-19 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.
+ (noce_process_if_block): Don't optimize if the destination is a
+ ZERO_EXTRACT which can't be handled by noce_emit_move_insn.
+
+2006-04-19 Andreas Krebbel <krebbel1@de.ibm.com>
+
* config/s390/s390.md: Add comments with the instructions emitted
by an insn pattern if macros are used.
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 23a9b3c7c36..4787a246b05 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -702,47 +702,76 @@ noce_emit_move_insn (rtx x, rtx y)
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;
+ {
+ 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 expects START to be relative to
+ BYTES_BIG_ENDIAN and adjusts this value for machines with
+ BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN. In order to be able to
+ invoke store_bit_field again it is necessary to have the START
+ value from the first call. */
+ if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
+ {
+ if (MEM_P (op))
+ start = BITS_PER_UNIT - start - size;
+ else
+ {
+ gcc_assert (REG_P (op));
+ start = BITS_PER_WORD - start - size;
+ }
+ }
- default:
- break;
- }
+ gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD));
+ 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;
}
@@ -2231,6 +2260,12 @@ noce_process_if_block (struct ce_if_block * ce_info)
{
if (no_new_pseudos || GET_MODE (x) == BLKmode)
return FALSE;
+
+ if (GET_MODE (x) == ZERO_EXTRACT
+ && (GET_CODE (XEXP (x, 1)) != CONST_INT
+ || GET_CODE (XEXP (x, 2)) != CONST_INT))
+ return FALSE;
+
x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
? XEXP (x, 0) : x));
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e48bc78add3..49fa80c9c9f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2006-04-19 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * gcc.c-torture/compile/20060419-1.c: Added.
+
2006-04-18 Bernhard Fischer <aldot@gcc.gnu.org>
* gfortran.dg/label_1.f90: Adjust dg-error.
diff --git a/gcc/testsuite/gcc.c-torture/compile/20060419-1.c b/gcc/testsuite/gcc.c-torture/compile/20060419-1.c
new file mode 100644
index 00000000000..dc346ae02a1
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20060419-1.c
@@ -0,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);
+}