diff options
author | Andreas Krebbel <krebbel1@de.ibm.com> | 2006-04-19 11:45:41 +0000 |
---|---|---|
committer | Andreas Krebbel <krebbel@gcc.gnu.org> | 2006-04-19 11:45:41 +0000 |
commit | e90cd8543a2684ec9757e47b52d9a4905a7b0874 (patch) | |
tree | 2260174418b14113abb50883007c90cf82b10d68 /gcc/ifcvt.c | |
parent | 43a09b63d42a5a1de8c4870b4a208cb84fa127d8 (diff) | |
download | gcc-e90cd8543a2684ec9757e47b52d9a4905a7b0874.zip gcc-e90cd8543a2684ec9757e47b52d9a4905a7b0874.tar.gz gcc-e90cd8543a2684ec9757e47b52d9a4905a7b0874.tar.bz2 |
ifcvt.c (noce_emit_move_insn): Call store_bit_field if the resulting move would be an INSV insn.
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>
* gcc.c-torture/compile/20060419-1.c: Added.
From-SVN: r113072
Diffstat (limited to 'gcc/ifcvt.c')
-rw-r--r-- | gcc/ifcvt.c | 113 |
1 files changed, 74 insertions, 39 deletions
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 23a9b3c..4787a24 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)); } |