diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-10-10 15:56:07 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-10-10 15:56:07 +0000 |
commit | 0c2d398f6f3c40afefe8f483171ba5e5121892d1 (patch) | |
tree | 98910f50ad06223df3a830870ec1d14aac86e59f | |
parent | 27d77081f4bdb9b33afc84879a1fae05530fb696 (diff) | |
download | gcc-0c2d398f6f3c40afefe8f483171ba5e5121892d1.tar.gz |
PR target/63404
* shrink-wrap.c (move_insn_for_shrink_wrap): Don't use single_set.
Restrict the set of expressions we're willing to move.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@216096 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/shrink-wrap.c | 89 |
2 files changed, 72 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 21863280459..d1086cfb182 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2014-10-10 Richard Henderson <rth@redhat.com> + + PR target/63404 + * shrink-wrap.c (move_insn_for_shrink_wrap): Don't use single_set. + Restrict the set of expressions we're willing to move. + 2014-10-10 Jeff Law <law@redhat.com> * ira.c (struct equivalence): Promote INIT_INSNs field to diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c index b1ff8a255f8..257812c02fb 100644 --- a/gcc/shrink-wrap.c +++ b/gcc/shrink-wrap.c @@ -176,17 +176,40 @@ move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn, basic_block next_block; edge live_edge; - /* Look for a simple register copy. */ - set = single_set (insn); - if (!set) + /* Look for a simple register assignment. We don't use single_set here + because we can't deal with any CLOBBERs, USEs, or REG_UNUSED secondary + destinations. */ + if (!INSN_P (insn)) + return false; + set = PATTERN (insn); + if (GET_CODE (set) != SET) return false; src = SET_SRC (set); dest = SET_DEST (set); - if (!REG_P (src)) + /* For the destination, we want only a register. Also disallow STACK + or FRAME related adjustments. They are likely part of the prologue, + so keep them in the entry block. */ + if (!REG_P (dest) + || dest == stack_pointer_rtx + || dest == frame_pointer_rtx + || dest == hard_frame_pointer_rtx) + return false; + + /* For the source, we want one of: + (1) A (non-overlapping) register + (2) A constant, + (3) An expression involving no more than one register. + + That last point comes from the code following, which was originally + written to handle only register move operations, and still only handles + a single source register when checking for overlaps. Happily, the + same checks can be applied to expressions like (plus reg const). */ + + if (CONSTANT_P (src)) + ; + else if (!REG_P (src)) { - unsigned int reg_num = 0; - unsigned int nonconstobj_num = 0; rtx src_inner = NULL_RTX; if (can_throw_internal (insn)) @@ -196,30 +219,50 @@ move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn, FOR_EACH_SUBRTX_VAR (iter, array, src, ALL) { rtx x = *iter; - if (REG_P (x)) + switch (GET_RTX_CLASS (GET_CODE (x))) { - reg_num++; - src_inner = x; + case RTX_CONST_OBJ: + case RTX_COMPARE: + case RTX_COMM_COMPARE: + case RTX_BIN_ARITH: + case RTX_COMM_ARITH: + case RTX_UNARY: + case RTX_TERNARY: + /* Constant or expression. Continue. */ + break; + + case RTX_OBJ: + case RTX_EXTRA: + switch (GET_CODE (x)) + { + case UNSPEC: + case SUBREG: + case STRICT_LOW_PART: + case PC: + /* Ok. Continue. */ + break; + + case REG: + /* Fail if we see a second inner register. */ + if (src_inner != NULL) + return false; + src_inner = x; + break; + + default: + return false; + } + break; + + default: + return false; } - else if (!CONSTANT_P (x) && OBJECT_P (x)) - nonconstobj_num++; } - if (nonconstobj_num > 0 - || reg_num > 1) - src = NULL_RTX; - else if (reg_num == 1) + if (src_inner != NULL) src = src_inner; } - if (!REG_P (dest) || src == NULL_RTX - /* STACK or FRAME related adjustment might be part of prologue. - So keep them in the entry block. */ - || dest == stack_pointer_rtx - || dest == frame_pointer_rtx - || dest == hard_frame_pointer_rtx) - return false; - /* Make sure that the source register isn't defined later in BB. */ if (REG_P (src)) { |