diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-26 18:56:14 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-26 18:56:14 +0000 |
commit | abe2d6dd80e07fc55a69dd3da361d78436222044 (patch) | |
tree | 88e469cfb5350bf8f7f8f1d7c548232a4a4050f4 /gcc/fwprop.c | |
parent | a1d07e97417fb905496f727f3a78b89e2eaf6397 (diff) | |
download | gcc-abe2d6dd80e07fc55a69dd3da361d78436222044.tar.gz |
PR inline-asm/39543
* fwprop.c (forward_propagate_asm): New function.
(forward_propagate_and_simplify): Propagate also into __asm, if it
doesn't increase the number of referenced registers.
* gcc.target/i386/pr39543-1.c: New test.
* gcc.target/i386/pr39543-2.c: New test.
* gcc.target/i386/pr39543-3.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146813 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fwprop.c')
-rw-r--r-- | gcc/fwprop.c | 89 |
1 files changed, 85 insertions, 4 deletions
diff --git a/gcc/fwprop.c b/gcc/fwprop.c index 2f78cd49f82..a01de13e3c7 100644 --- a/gcc/fwprop.c +++ b/gcc/fwprop.c @@ -1,5 +1,5 @@ /* RTL-based forward propagation pass for GNU compiler. - Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Paolo Bonzini and Steven Bosscher. This file is part of GCC. @@ -852,6 +852,80 @@ forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set) return false; } +/* Try to replace USE with SRC (defined in DEF_INSN) in __asm. */ + +static bool +forward_propagate_asm (df_ref use, rtx def_insn, rtx def_set, rtx reg) +{ + rtx use_insn = DF_REF_INSN (use), src, use_pat, asm_operands, new_rtx, *loc; + int speed_p, i; + df_ref *use_vec; + + gcc_assert ((DF_REF_FLAGS (use) & DF_REF_IN_NOTE) == 0); + + src = SET_SRC (def_set); + use_pat = PATTERN (use_insn); + + /* In __asm don't replace if src might need more registers than + reg, as that could increase register pressure on the __asm. */ + use_vec = DF_INSN_USES (def_insn); + if (use_vec[0] && use_vec[1]) + return false; + + speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn)); + asm_operands = NULL_RTX; + switch (GET_CODE (use_pat)) + { + case ASM_OPERANDS: + asm_operands = use_pat; + break; + case SET: + if (MEM_P (SET_DEST (use_pat))) + { + loc = &SET_DEST (use_pat); + new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p); + if (new_rtx) + validate_unshare_change (use_insn, loc, new_rtx, true); + } + asm_operands = SET_SRC (use_pat); + break; + case PARALLEL: + for (i = 0; i < XVECLEN (use_pat, 0); i++) + if (GET_CODE (XVECEXP (use_pat, 0, i)) == SET) + { + if (MEM_P (SET_DEST (XVECEXP (use_pat, 0, i)))) + { + loc = &SET_DEST (XVECEXP (use_pat, 0, i)); + new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, + src, speed_p); + if (new_rtx) + validate_unshare_change (use_insn, loc, new_rtx, true); + } + asm_operands = SET_SRC (XVECEXP (use_pat, 0, i)); + } + else if (GET_CODE (XVECEXP (use_pat, 0, i)) == ASM_OPERANDS) + asm_operands = XVECEXP (use_pat, 0, i); + break; + default: + gcc_unreachable (); + } + + gcc_assert (asm_operands && GET_CODE (asm_operands) == ASM_OPERANDS); + for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (asm_operands); i++) + { + loc = &ASM_OPERANDS_INPUT (asm_operands, i); + new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p); + if (new_rtx) + validate_unshare_change (use_insn, loc, new_rtx, true); + } + + if (num_changes_pending () == 0 || !apply_change_group ()) + return false; + + num_changes++; + return true; +} + /* Try to replace USE with SRC (defined in DEF_INSN) and simplify the result. */ @@ -863,12 +937,16 @@ forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set) rtx src, reg, new_rtx, *loc; bool set_reg_equal; enum machine_mode mode; + int asm_use = -1; + + if (INSN_CODE (use_insn) < 0) + asm_use = asm_noperands (PATTERN (use_insn)); - if (!use_set) + if (!use_set && asm_use < 0) return false; /* Do not propagate into PC, CC0, etc. */ - if (GET_MODE (SET_DEST (use_set)) == VOIDmode) + if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode) return false; /* If def and use are subreg, check if they match. */ @@ -900,7 +978,7 @@ forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set) if (MEM_P (src) && MEM_READONLY_P (src)) { rtx x = avoid_constant_pool_reference (src); - if (x != src) + if (x != src && use_set) { rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX); rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (use_set); @@ -911,6 +989,9 @@ forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set) return false; } + if (asm_use >= 0) + return forward_propagate_asm (use, def_insn, def_set, reg); + /* Else try simplifying. */ if (DF_REF_TYPE (use) == DF_REF_REG_MEM_STORE) |