From caff53db41781c14605bdbf1c6d38f2d59694c54 Mon Sep 17 00:00:00 2001 From: froydnj Date: Wed, 20 Oct 2010 20:15:07 +0000 Subject: [PATCH] * ifcvt.c (noce_emit_cmove): If both of the values are SUBREGs, try emitting the conditional move in the inner mode of the SUBREG. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165735 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 +++++ gcc/ifcvt.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3ec4112..beed454 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2010-10-20 Nathan Froyd + + * ifcvt.c (noce_emit_cmove): If both of the values are SUBREGs, try + emitting the conditional move in the inner mode of the SUBREG. + 2010-10-20 Anatoly Sokolov * config/ia64/ia64.h (PREFERRED_RELOAD_CLASS): Remove macros. diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index eb96182..15f76e3 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -1337,6 +1337,9 @@ static rtx noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue) { + rtx target; + int unsignedp; + /* If earliest == jump, try to build the cmove insn directly. This is helpful when combine has created some complex condition (like for alpha's cmovlbs) that we can't hope to regenerate @@ -1371,10 +1374,62 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, return NULL_RTX; #if HAVE_conditional_move - return emit_conditional_move (x, code, cmp_a, cmp_b, VOIDmode, - vtrue, vfalse, GET_MODE (x), - (code == LTU || code == GEU - || code == LEU || code == GTU)); + unsignedp = (code == LTU || code == GEU + || code == LEU || code == GTU); + + target = emit_conditional_move (x, code, cmp_a, cmp_b, VOIDmode, + vtrue, vfalse, GET_MODE (x), + unsignedp); + if (target) + return target; + + /* We might be faced with a situation like: + + x = (reg:M TARGET) + vtrue = (subreg:M (reg:N VTRUE) BYTE) + vfalse = (subreg:M (reg:N VFALSE) BYTE) + + We can't do a conditional move in mode M, but it's possible that we + could do a conditional move in mode N instead and take a subreg of + the result. + + If we can't create new pseudos, though, don't bother. */ + if (reload_completed) + return NULL_RTX; + + if (GET_CODE (vtrue) == SUBREG && GET_CODE (vfalse) == SUBREG) + { + rtx reg_vtrue = SUBREG_REG (vtrue); + rtx reg_vfalse = SUBREG_REG (vfalse); + unsigned int byte_vtrue = SUBREG_BYTE (vtrue); + unsigned int byte_vfalse = SUBREG_BYTE (vfalse); + rtx promoted_target; + + if (GET_MODE (reg_vtrue) != GET_MODE (reg_vfalse) + || byte_vtrue != byte_vfalse + || (SUBREG_PROMOTED_VAR_P (vtrue) + != SUBREG_PROMOTED_VAR_P (vfalse)) + || (SUBREG_PROMOTED_UNSIGNED_P (vtrue) + != SUBREG_PROMOTED_UNSIGNED_P (vfalse))) + return NULL_RTX; + + promoted_target = gen_reg_rtx (GET_MODE (reg_vtrue)); + + target = emit_conditional_move (promoted_target, code, cmp_a, cmp_b, + VOIDmode, reg_vtrue, reg_vfalse, + GET_MODE (reg_vtrue), unsignedp); + /* Nope, couldn't do it in that mode either. */ + if (!target) + return NULL_RTX; + + target = gen_rtx_SUBREG (GET_MODE (vtrue), promoted_target, byte_vtrue); + SUBREG_PROMOTED_VAR_P (target) = SUBREG_PROMOTED_VAR_P (vtrue); + SUBREG_PROMOTED_UNSIGNED_SET (target, SUBREG_PROMOTED_UNSIGNED_P (vtrue)); + emit_move_insn (x, target); + return x; + } + else + return NULL_RTX; #else /* We'll never get here, as noce_process_if_block doesn't call the functions involved. Ifdef code, however, should be discouraged -- 2.7.4