aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch')
-rw-r--r--toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch2985
1 files changed, 0 insertions, 2985 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch
deleted file mode 100644
index b7b6d88a04..0000000000
--- a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99380.patch
+++ /dev/null
@@ -1,2985 +0,0 @@
-2010-08-31 Chung-Lin Tang <cltang@codesourcery.com>
-
- Backport from mainline:
-
- 2010-04-14 Bernd Schmidt <bernds@codesourcery.com>
-
- PR target/21803
- gcc/
- * ifcvt.c (cond_exec_process_if_block): Look for identical sequences
- at the start and end of the then/else blocks, and omit them from the
- conversion.
- * cfgcleanup.c (flow_find_cross_jump): No longer static. Remove MODE
- argument; all callers changed. Pass zero to old_insns_match_p instead.
- (flow_find_head_matching_sequence): New function.
- (old_insns_match_p): Check REG_EH_REGION notes for calls.
- * basic-block.h (flow_find_cross_jump,
- flow_find_head_matching_sequence): Declare functions.
-
- gcc/testsuite/
- * gcc.target/arm/pr42496.c: New test.
-
- 2010-04-22 Bernd Schmidt <bernds@codesourcery.com>
-
- PR middle-end/29274
- gcc/
- * tree-pass.h (pass_optimize_widening_mul): Declare.
- * tree-ssa-math-opts.c (execute_optimize_widening_mul,
- gate_optimize_widening_mul): New static functions.
- (pass_optimize_widening_mul): New.
- * expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: New case.
- <case MULT_EXPR>: Remove support for widening multiplies.
- * tree.def (WIDEN_MULT_EXPR): Tweak comment.
- * cfgexpand.c (expand_debug_expr) <case WIDEN_MULT_EXPR>: Use
- simplify_gen_unary rather than directly building extensions.
- * tree-cfg.c (verify_gimple_assign_binary): Add tests for
- WIDEN_MULT_EXPR.
- * expmed.c (expand_widening_mult): New function.
- * passes.c (init_optimization_passes): Add pass_optimize_widening_mul.
- * optabs.h (expand_widening_mult): Declare.
-
- gcc/testsuite/
- * gcc.target/i386/wmul-1.c: New test.
- * gcc.target/i386/wmul-2.c: New test.
- * gcc.target/bfin/wmul-1.c: New test.
- * gcc.target/bfin/wmul-2.c: New test.
- * gcc.target/arm/wmul-1.c: New test.
- * gcc.target/arm/wmul-2.c: New test.
-
- 2010-04-24 Bernd Schmidt <bernds@codesourcery.com>
-
- PR tree-optimization/41442
- gcc/
- * fold-const.c (merge_truthop_with_opposite_arm): New function.
- (fold_binary_loc): Call it.
-
- gcc/testsuite/
- * gcc.target/i386/pr41442.c: New test.
-
- 2010-04-29 Bernd Schmidt <bernds@codesourcery.com>
-
- PR target/42895
- gcc/
- * doc/tm.texi (ADJUST_REG_ALLOC_ORDER): Renamed from
- ORDER_REGS_FOR_LOCAL_ALLOC. All instances of this macro changed.
- (HONOR_REG_ALLOC_ORDER): Describe new macro.
- * ira.c (setup_alloc_regs): Use ADJUST_REG_ALLOC_ORDER if defined.
- * ira-color.c (assign_hard_reg): Take prologue/epilogue costs into
- account only if HONOR_REG_ALLOC_ORDER is not defined.
- * config/arm/arm.h (HONOR_REG_ALLOC_ORDER): Define.
- * system.h (ORDER_REGS_FOR_LOCAL_ALLOC): Poison.
-
- 2010-05-04 Mikael Pettersson <mikpe@it.uu.se>
-
- PR bootstrap/43964
- gcc/
- * ira-color.c (assign_hard_reg): Declare rclass and add_cost
- only if HONOR_REG_ALLOC_ORDER is not defined.
-
- 2010-06-04 Bernd Schmidt <bernds@codesourcery.com>
-
- PR rtl-optimization/39871
- PR rtl-optimization/40615
- PR rtl-optimization/42500
- PR rtl-optimization/42502
- gcc/
- * ira.c (init_reg_equiv_memory_loc: New function.
- (ira): Call it twice.
- * reload.h (calculate_elim_costs_all_insns): Declare.
- * ira-costs.c: Include "reload.h".
- (regno_equiv_gains): New static variable.
- (init_costs): Allocate it.
- (finish_costs): Free it.
- (ira_costs): Call calculate_elim_costs_all_insns.
- (find_costs_and_classes): Take estimated elimination costs
- into account.
- (ira_adjust_equiv_reg_cost): New function.
- * ira.h (ira_adjust_equiv_reg_cost): Declare it.
- * reload1.c (init_eliminable_invariants, free_reg_equiv,
- elimination_costs_in_insn, note_reg_elim_costly): New static functions.
- (elim_bb): New static variable.
- (reload): Move code out of here into init_eliminable_invariants and
- free_reg_equiv. Call them.
- (calculate_elim_costs_all_insns): New function.
- (eliminate_regs_1): Declare. Add extra arg FOR_COSTS;
- all callers changed. If FOR_COSTS is true, don't call alter_reg,
- but call note_reg_elim_costly if we turned a valid memory address
- into an invalid one.
- * Makefile.in (ira-costs.o): Depend on reload.h.
-
- gcc/testsuite/
- * gcc.target/arm/eliminate.c: New test.
-
- 2010-06-09 Bernd Schmidt <bernds@codesourcery.com>
-
- gcc/
- * config/arm/arm.c (thumb2_reorg): New function.
- (arm_reorg): Call it.
- * config/arm/thumb2.md (define_peephole2 for flag clobbering
- arithmetic operations): Delete.
-
- 2010-06-12 Bernd Schmidt <bernds@codesourcery.com>
-
- gcc/
- * config/arm/arm.c (thumb2_reorg): Fix errors in previous change.
-
- 2010-06-17 Bernd Schmidt <bernds@codesourcery.com>
-
- PR rtl-optimization/39871
- gcc/
- * reload1.c (init_eliminable_invariants): For flag_pic, disable
- equivalences only for constants that aren't LEGITIMATE_PIC_OPERAND_P.
- (function_invariant_p): Rule out a plus of frame or arg pointer with
- a SYMBOL_REF.
- * ira.c (find_reg_equiv_invariant_const): Likewise.
-
- 2010-06-18 Eric Botcazou <ebotcazou@adacore.com>
-
- PR rtl-optimization/40900
- gcc/
- * expr.c (expand_expr_real_1) <SSA_NAME>: Fix long line. Save the
- original expression for later reuse.
- <expand_decl_rtl>: Use promote_function_mode to compute the signedness
- of the promoted RTL for a SSA_NAME on the LHS of a call statement.
-
- 2010-06-18 Bernd Schmidt <bernds@codesourcery.com>
- gcc/testsuite/
- * gcc.target/arm/pr40900.c: New test.
-
- 2010-06-30 Bernd Schmidt <bernds@codesourcery.com>
-
- PR tree-optimization/39799
- gcc/
- * tree-inline.c (remap_ssa_name): Initialize variable only if
- SSA_NAME_OCCURS_IN_ABNORMAL_PHI.
- * tree-ssa.c (warn_uninit): Avoid emitting an unnecessary message.
-
- gcc/testsuite/
- * c-c++-common/uninit-17.c: New test.
-
- 2010-07-25 Eric Botcazou <ebotcazou@adacore.com>
-
- PR target/44484
- gcc/
- * config/sparc/predicates.md (memory_reg_operand): Delete.
- * config/sparc/sync.md (sync_compare_and_swap): Minor tweaks.
- (*sync_compare_and_swap): Encode the address form in the pattern.
- (*sync_compare_and_swapdi_v8plus): Likewise.
-
- 2010-08-29 Chung-Lin Tang <cltang@codesourcery.com>
-
- Backport from mainline:
-
-=== modified file 'gcc/Makefile.in'
-Index: gcc-4_5-branch/gcc/Makefile.in
-===================================================================
---- gcc-4_5-branch.orig/gcc/Makefile.in 2012-03-06 12:11:29.000000000 -0800
-+++ gcc-4_5-branch/gcc/Makefile.in 2012-03-06 12:14:01.024439210 -0800
-@@ -3197,7 +3197,7 @@
- ira-costs.o: ira-costs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- hard-reg-set.h $(RTL_H) $(EXPR_H) $(TM_P_H) $(FLAGS_H) $(BASIC_BLOCK_H) \
- $(REGS_H) addresses.h insn-config.h $(RECOG_H) $(TOPLEV_H) $(TARGET_H) \
-- $(PARAMS_H) $(IRA_INT_H)
-+ $(PARAMS_H) $(IRA_INT_H) reload.h
- ira-conflicts.o: ira-conflicts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TARGET_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
- insn-config.h $(RECOG_H) $(BASIC_BLOCK_H) $(TOPLEV_H) $(TM_P_H) $(PARAMS_H) \
-Index: gcc-4_5-branch/gcc/basic-block.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/basic-block.h 2012-03-06 12:11:33.000000000 -0800
-+++ gcc-4_5-branch/gcc/basic-block.h 2012-03-06 12:14:01.024439210 -0800
-@@ -894,6 +894,10 @@
-
- /* In cfgcleanup.c. */
- extern bool cleanup_cfg (int);
-+extern int flow_find_cross_jump (basic_block, basic_block, rtx *, rtx *);
-+extern int flow_find_head_matching_sequence (basic_block, basic_block,
-+ rtx *, rtx *, int);
-+
- extern bool delete_unreachable_blocks (void);
-
- extern bool mark_dfs_back_edges (void);
-Index: gcc-4_5-branch/gcc/cfgcleanup.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/cfgcleanup.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/cfgcleanup.c 2012-03-06 12:14:01.028439167 -0800
-@@ -68,7 +68,6 @@
- static bool try_crossjump_to_edge (int, edge, edge);
- static bool try_crossjump_bb (int, basic_block);
- static bool outgoing_edges_match (int, basic_block, basic_block);
--static int flow_find_cross_jump (int, basic_block, basic_block, rtx *, rtx *);
- static bool old_insns_match_p (int, rtx, rtx);
-
- static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block);
-@@ -977,13 +976,27 @@
- be filled that clobbers a parameter expected by the subroutine.
-
- ??? We take the simple route for now and assume that if they're
-- equal, they were constructed identically. */
-+ equal, they were constructed identically.
-
-- if (CALL_P (i1)
-- && (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
-+ Also check for identical exception regions. */
-+
-+ if (CALL_P (i1))
-+ {
-+ /* Ensure the same EH region. */
-+ rtx n1 = find_reg_note (i1, REG_EH_REGION, 0);
-+ rtx n2 = find_reg_note (i2, REG_EH_REGION, 0);
-+
-+ if (!n1 && n2)
-+ return false;
-+
-+ if (n1 && (!n2 || XEXP (n1, 0) != XEXP (n2, 0)))
-+ return false;
-+
-+ if (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
- CALL_INSN_FUNCTION_USAGE (i2))
-- || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)))
-- return false;
-+ || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2))
-+ return false;
-+ }
-
- #ifdef STACK_REGS
- /* If cross_jump_death_matters is not 0, the insn's mode
-@@ -1022,6 +1035,29 @@
- return false;
- }
-
-+/* When comparing insns I1 and I2 in flow_find_cross_jump or
-+ flow_find_head_matching_sequence, ensure the notes match. */
-+
-+static void
-+merge_notes (rtx i1, rtx i2)
-+{
-+ /* If the merged insns have different REG_EQUAL notes, then
-+ remove them. */
-+ rtx equiv1 = find_reg_equal_equiv_note (i1);
-+ rtx equiv2 = find_reg_equal_equiv_note (i2);
-+
-+ if (equiv1 && !equiv2)
-+ remove_note (i1, equiv1);
-+ else if (!equiv1 && equiv2)
-+ remove_note (i2, equiv2);
-+ else if (equiv1 && equiv2
-+ && !rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0)))
-+ {
-+ remove_note (i1, equiv1);
-+ remove_note (i2, equiv2);
-+ }
-+}
-+
- /* Look through the insns at the end of BB1 and BB2 and find the longest
- sequence that are equivalent. Store the first insns for that sequence
- in *F1 and *F2 and return the sequence length.
-@@ -1029,9 +1065,8 @@
- To simplify callers of this function, if the blocks match exactly,
- store the head of the blocks in *F1 and *F2. */
-
--static int
--flow_find_cross_jump (int mode ATTRIBUTE_UNUSED, basic_block bb1,
-- basic_block bb2, rtx *f1, rtx *f2)
-+int
-+flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2)
- {
- rtx i1, i2, last1, last2, afterlast1, afterlast2;
- int ninsns = 0;
-@@ -1071,7 +1106,7 @@
- if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2))
- break;
-
-- if (!old_insns_match_p (mode, i1, i2))
-+ if (!old_insns_match_p (0, i1, i2))
- break;
-
- merge_memattrs (i1, i2);
-@@ -1079,21 +1114,7 @@
- /* Don't begin a cross-jump with a NOTE insn. */
- if (INSN_P (i1))
- {
-- /* If the merged insns have different REG_EQUAL notes, then
-- remove them. */
-- rtx equiv1 = find_reg_equal_equiv_note (i1);
-- rtx equiv2 = find_reg_equal_equiv_note (i2);
--
-- if (equiv1 && !equiv2)
-- remove_note (i1, equiv1);
-- else if (!equiv1 && equiv2)
-- remove_note (i2, equiv2);
-- else if (equiv1 && equiv2
-- && !rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0)))
-- {
-- remove_note (i1, equiv1);
-- remove_note (i2, equiv2);
-- }
-+ merge_notes (i1, i2);
-
- afterlast1 = last1, afterlast2 = last2;
- last1 = i1, last2 = i2;
-@@ -1135,6 +1156,97 @@
- return ninsns;
- }
-
-+/* Like flow_find_cross_jump, except start looking for a matching sequence from
-+ the head of the two blocks. Do not include jumps at the end.
-+ If STOP_AFTER is nonzero, stop after finding that many matching
-+ instructions. */
-+
-+int
-+flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1,
-+ rtx *f2, int stop_after)
-+{
-+ rtx i1, i2, last1, last2, beforelast1, beforelast2;
-+ int ninsns = 0;
-+ edge e;
-+ edge_iterator ei;
-+ int nehedges1 = 0, nehedges2 = 0;
-+
-+ FOR_EACH_EDGE (e, ei, bb1->succs)
-+ if (e->flags & EDGE_EH)
-+ nehedges1++;
-+ FOR_EACH_EDGE (e, ei, bb2->succs)
-+ if (e->flags & EDGE_EH)
-+ nehedges2++;
-+
-+ i1 = BB_HEAD (bb1);
-+ i2 = BB_HEAD (bb2);
-+ last1 = beforelast1 = last2 = beforelast2 = NULL_RTX;
-+
-+ while (true)
-+ {
-+
-+ /* Ignore notes. */
-+ while (!NONDEBUG_INSN_P (i1) && i1 != BB_END (bb1))
-+ i1 = NEXT_INSN (i1);
-+
-+ while (!NONDEBUG_INSN_P (i2) && i2 != BB_END (bb2))
-+ i2 = NEXT_INSN (i2);
-+
-+ if (NOTE_P (i1) || NOTE_P (i2)
-+ || JUMP_P (i1) || JUMP_P (i2))
-+ break;
-+
-+ /* A sanity check to make sure we're not merging insns with different
-+ effects on EH. If only one of them ends a basic block, it shouldn't
-+ have an EH edge; if both end a basic block, there should be the same
-+ number of EH edges. */
-+ if ((i1 == BB_END (bb1) && i2 != BB_END (bb2)
-+ && nehedges1 > 0)
-+ || (i2 == BB_END (bb2) && i1 != BB_END (bb1)
-+ && nehedges2 > 0)
-+ || (i1 == BB_END (bb1) && i2 == BB_END (bb2)
-+ && nehedges1 != nehedges2))
-+ break;
-+
-+ if (!old_insns_match_p (0, i1, i2))
-+ break;
-+
-+ merge_memattrs (i1, i2);
-+
-+ /* Don't begin a cross-jump with a NOTE insn. */
-+ if (INSN_P (i1))
-+ {
-+ merge_notes (i1, i2);
-+
-+ beforelast1 = last1, beforelast2 = last2;
-+ last1 = i1, last2 = i2;
-+ ninsns++;
-+ }
-+
-+ if (i1 == BB_END (bb1) || i2 == BB_END (bb2)
-+ || (stop_after > 0 && ninsns == stop_after))
-+ break;
-+
-+ i1 = NEXT_INSN (i1);
-+ i2 = NEXT_INSN (i2);
-+ }
-+
-+#ifdef HAVE_cc0
-+ /* Don't allow a compare to be shared by cross-jumping unless the insn
-+ after the compare is also shared. */
-+ if (ninsns && reg_mentioned_p (cc0_rtx, last1) && sets_cc0_p (last1))
-+ last1 = beforelast1, last2 = beforelast2, ninsns--;
-+#endif
-+
-+ if (ninsns)
-+ {
-+ *f1 = last1;
-+ *f2 = last2;
-+ }
-+
-+ return ninsns;
-+}
-+
- /* Return true iff outgoing edges of BB1 and BB2 match, together with
- the branch instruction. This means that if we commonize the control
- flow before end of the basic block, the semantic remains unchanged.
-@@ -1503,7 +1615,7 @@
- return false;
-
- /* ... and part the second. */
-- nmatch = flow_find_cross_jump (mode, src1, src2, &newpos1, &newpos2);
-+ nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2);
-
- /* Don't proceed with the crossjump unless we found a sufficient number
- of matching instructions or the 'from' block was totally matched
-Index: gcc-4_5-branch/gcc/cfgexpand.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/cfgexpand.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/cfgexpand.c 2012-03-06 12:14:01.028439167 -0800
-@@ -3033,14 +3033,15 @@
- if (SCALAR_INT_MODE_P (GET_MODE (op0))
- && SCALAR_INT_MODE_P (mode))
- {
-+ enum machine_mode inner_mode = GET_MODE (op0);
- if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))))
-- op0 = gen_rtx_ZERO_EXTEND (mode, op0);
-+ op0 = simplify_gen_unary (ZERO_EXTEND, mode, op0, inner_mode);
- else
-- op0 = gen_rtx_SIGN_EXTEND (mode, op0);
-+ op0 = simplify_gen_unary (SIGN_EXTEND, mode, op0, inner_mode);
- if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))))
-- op1 = gen_rtx_ZERO_EXTEND (mode, op1);
-+ op1 = simplify_gen_unary (ZERO_EXTEND, mode, op1, inner_mode);
- else
-- op1 = gen_rtx_SIGN_EXTEND (mode, op1);
-+ op1 = simplify_gen_unary (SIGN_EXTEND, mode, op1, inner_mode);
- return gen_rtx_MULT (mode, op0, op1);
- }
- return NULL;
-Index: gcc-4_5-branch/gcc/config/arm/arm.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/arm/arm.c 2012-03-06 12:11:35.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/arm/arm.c 2012-03-06 12:14:01.032439183 -0800
-@@ -8096,8 +8096,6 @@
- static bool
- xscale_sched_adjust_cost (rtx insn, rtx link, rtx dep, int * cost)
- {
-- rtx i_pat, d_pat;
--
- /* Some true dependencies can have a higher cost depending
- on precisely how certain input operands are used. */
- if (REG_NOTE_KIND (link) == 0
-@@ -12146,6 +12144,60 @@
- return result;
- }
-
-+/* Convert instructions to their cc-clobbering variant if possible, since
-+ that allows us to use smaller encodings. */
-+
-+static void
-+thumb2_reorg (void)
-+{
-+ basic_block bb;
-+ regset_head live;
-+
-+ INIT_REG_SET (&live);
-+
-+ /* We are freeing block_for_insn in the toplev to keep compatibility
-+ with old MDEP_REORGS that are not CFG based. Recompute it now. */
-+ compute_bb_for_insn ();
-+ df_analyze ();
-+
-+ FOR_EACH_BB (bb)
-+ {
-+ rtx insn;
-+ COPY_REG_SET (&live, DF_LR_OUT (bb));
-+ df_simulate_initialize_backwards (bb, &live);
-+ FOR_BB_INSNS_REVERSE (bb, insn)
-+ {
-+ if (NONJUMP_INSN_P (insn)
-+ && !REGNO_REG_SET_P (&live, CC_REGNUM))
-+ {
-+ rtx pat = PATTERN (insn);
-+ if (GET_CODE (pat) == SET
-+ && low_register_operand (XEXP (pat, 0), SImode)
-+ && thumb_16bit_operator (XEXP (pat, 1), SImode)
-+ && low_register_operand (XEXP (XEXP (pat, 1), 0), SImode)
-+ && low_register_operand (XEXP (XEXP (pat, 1), 1), SImode))
-+ {
-+ rtx dst = XEXP (pat, 0);
-+ rtx src = XEXP (pat, 1);
-+ rtx op0 = XEXP (src, 0);
-+ if (rtx_equal_p (dst, op0)
-+ || GET_CODE (src) == PLUS || GET_CODE (src) == MINUS)
-+ {
-+ rtx ccreg = gen_rtx_REG (CCmode, CC_REGNUM);
-+ rtx clobber = gen_rtx_CLOBBER (VOIDmode, ccreg);
-+ rtvec vec = gen_rtvec (2, pat, clobber);
-+ PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode, vec);
-+ INSN_CODE (insn) = -1;
-+ }
-+ }
-+ }
-+ if (NONDEBUG_INSN_P (insn))
-+ df_simulate_one_insn_backwards (bb, insn, &live);
-+ }
-+ }
-+ CLEAR_REG_SET (&live);
-+}
-+
- /* Gcc puts the pool in the wrong place for ARM, since we can only
- load addresses a limited distance around the pc. We do some
- special munging to move the constant pool values to the correct
-@@ -12157,6 +12209,9 @@
- HOST_WIDE_INT address = 0;
- Mfix * fix;
-
-+ if (TARGET_THUMB2)
-+ thumb2_reorg ();
-+
- minipool_fix_head = minipool_fix_tail = NULL;
-
- /* The first insn must always be a note, or the code below won't
-Index: gcc-4_5-branch/gcc/config/arm/arm.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/arm/arm.h 2012-03-06 12:11:33.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/arm/arm.h 2012-03-06 12:14:01.032439183 -0800
-@@ -1133,7 +1133,11 @@
- }
-
- /* Use different register alloc ordering for Thumb. */
--#define ORDER_REGS_FOR_LOCAL_ALLOC arm_order_regs_for_local_alloc ()
-+#define ADJUST_REG_ALLOC_ORDER arm_order_regs_for_local_alloc ()
-+
-+/* Tell IRA to use the order we define rather than messing it up with its
-+ own cost calculations. */
-+#define HONOR_REG_ALLOC_ORDER
-
- /* Interrupt functions can only use registers that have already been
- saved by the prologue, even if they would normally be
-Index: gcc-4_5-branch/gcc/config/arm/arm.md
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/arm/arm.md 2012-03-06 12:11:35.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/arm/arm.md 2012-03-06 12:14:01.036439231 -0800
-@@ -4074,7 +4074,7 @@
-
- (define_split
- [(set (match_operand:SI 0 "register_operand" "")
-- (zero_extend:SI (match_operand:HI 1 "register_operand" "l,m")))]
-+ (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
- "!TARGET_THUMB2 && !arm_arch6"
- [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
- (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
-Index: gcc-4_5-branch/gcc/config/arm/thumb2.md
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/arm/thumb2.md 2012-03-06 12:11:35.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/arm/thumb2.md 2012-03-06 12:14:01.036439231 -0800
-@@ -1046,29 +1046,6 @@
- }"
- )
-
--;; Peepholes and insns for 16-bit flag clobbering instructions.
--;; The conditional forms of these instructions do not clobber CC.
--;; However by the time peepholes are run it is probably too late to do
--;; anything useful with this information.
--(define_peephole2
-- [(set (match_operand:SI 0 "low_register_operand" "")
-- (match_operator:SI 3 "thumb_16bit_operator"
-- [(match_operand:SI 1 "low_register_operand" "")
-- (match_operand:SI 2 "low_register_operand" "")]))]
-- "TARGET_THUMB2
-- && (rtx_equal_p(operands[0], operands[1])
-- || GET_CODE(operands[3]) == PLUS
-- || GET_CODE(operands[3]) == MINUS)
-- && peep2_regno_dead_p(0, CC_REGNUM)"
-- [(parallel
-- [(set (match_dup 0)
-- (match_op_dup 3
-- [(match_dup 1)
-- (match_dup 2)]))
-- (clobber (reg:CC CC_REGNUM))])]
-- ""
--)
--
- (define_insn "*thumb2_alusi3_short"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (match_operator:SI 3 "thumb_16bit_operator"
-Index: gcc-4_5-branch/gcc/config/avr/avr.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/avr/avr.h 2012-03-06 11:53:21.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/avr/avr.h 2012-03-06 12:14:01.036439231 -0800
-@@ -232,7 +232,7 @@
- 32,33,34,35 \
- }
-
--#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
-+#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc ()
-
-
- #define HARD_REGNO_NREGS(REGNO, MODE) ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-Index: gcc-4_5-branch/gcc/config/i386/i386.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/i386/i386.h 2012-03-06 11:53:19.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/i386/i386.h 2012-03-06 12:14:01.036439231 -0800
-@@ -955,7 +955,7 @@
- registers listed in CALL_USED_REGISTERS, keeping the others
- available for storage of persistent values.
-
-- The ORDER_REGS_FOR_LOCAL_ALLOC actually overwrite the order,
-+ The ADJUST_REG_ALLOC_ORDER actually overwrite the order,
- so this is just empty initializer for array. */
-
- #define REG_ALLOC_ORDER \
-@@ -964,11 +964,11 @@
- 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
- 48, 49, 50, 51, 52 }
-
--/* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order
-+/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order
- to be rearranged based on a particular function. When using sse math,
- we want to allocate SSE before x87 registers and vice versa. */
-
--#define ORDER_REGS_FOR_LOCAL_ALLOC x86_order_regs_for_local_alloc ()
-+#define ADJUST_REG_ALLOC_ORDER x86_order_regs_for_local_alloc ()
-
-
- #define OVERRIDE_ABI_FORMAT(FNDECL) ix86_call_abi_override (FNDECL)
-Index: gcc-4_5-branch/gcc/config/mips/mips.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/mips/mips.h 2012-03-06 11:53:28.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/mips/mips.h 2012-03-06 12:14:01.040439261 -0800
-@@ -2059,12 +2059,12 @@
- 182,183,184,185,186,187 \
- }
-
--/* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order
-+/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order
- to be rearranged based on a particular function. On the mips16, we
- want to allocate $24 (T_REG) before other registers for
- instructions for which it is possible. */
-
--#define ORDER_REGS_FOR_LOCAL_ALLOC mips_order_regs_for_local_alloc ()
-+#define ADJUST_REG_ALLOC_ORDER mips_order_regs_for_local_alloc ()
-
- /* True if VALUE is an unsigned 6-bit number. */
-
-Index: gcc-4_5-branch/gcc/config/picochip/picochip.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/picochip/picochip.h 2012-03-06 11:53:26.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/picochip/picochip.h 2012-03-06 12:14:01.040439261 -0800
-@@ -261,7 +261,7 @@
- /* We can dynamically change the REG_ALLOC_ORDER using the following hook.
- It would be desirable to change it for leaf functions so we can put
- r12 at the end of this list.*/
--#define ORDER_REGS_FOR_LOCAL_ALLOC picochip_order_regs_for_local_alloc ()
-+#define ADJUST_REG_ALLOC_ORDER picochip_order_regs_for_local_alloc ()
-
- /* How Values Fit in Registers */
-
-Index: gcc-4_5-branch/gcc/config/sparc/predicates.md
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/sparc/predicates.md 2012-03-06 11:53:17.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/sparc/predicates.md 2012-03-06 12:14:01.040439261 -0800
-@@ -1,5 +1,5 @@
- ;; Predicate definitions for SPARC.
--;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
-+;; Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
- ;;
- ;; This file is part of GCC.
- ;;
-@@ -473,9 +473,3 @@
- ;; and (xor ... (not ...)) to (not (xor ...)). */
- (define_predicate "cc_arith_not_operator"
- (match_code "and,ior"))
--
--;; Return true if OP is memory operand with just [%reg] addressing mode.
--(define_predicate "memory_reg_operand"
-- (and (match_code "mem")
-- (and (match_operand 0 "memory_operand")
-- (match_test "REG_P (XEXP (op, 0))"))))
-Index: gcc-4_5-branch/gcc/config/sparc/sparc.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/sparc/sparc.h 2012-03-06 11:53:17.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/sparc/sparc.h 2012-03-06 12:14:01.040439261 -0800
-@@ -1188,7 +1188,7 @@
- 96, 97, 98, 99, /* %fcc0-3 */ \
- 100, 0, 14, 30, 31, 101} /* %icc, %g0, %o6, %i6, %i7, %sfp */
-
--#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
-+#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc ()
-
- extern char sparc_leaf_regs[];
- #define LEAF_REGISTERS sparc_leaf_regs
-Index: gcc-4_5-branch/gcc/config/sparc/sync.md
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/sparc/sync.md 2012-03-06 11:53:17.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/sparc/sync.md 2012-03-06 12:14:01.040439261 -0800
-@@ -1,5 +1,5 @@
- ;; GCC machine description for SPARC synchronization instructions.
--;; Copyright (C) 2005, 2007, 2009
-+;; Copyright (C) 2005, 2007, 2009, 2010
- ;; Free Software Foundation, Inc.
- ;;
- ;; This file is part of GCC.
-@@ -62,7 +62,7 @@
-
- (define_expand "sync_compare_and_swap<mode>"
- [(parallel
-- [(set (match_operand:I48MODE 0 "register_operand" "=r")
-+ [(set (match_operand:I48MODE 0 "register_operand" "")
- (match_operand:I48MODE 1 "memory_operand" ""))
- (set (match_dup 1)
- (unspec_volatile:I48MODE
-@@ -71,7 +71,7 @@
- UNSPECV_CAS))])]
- "TARGET_V9"
- {
-- if (! REG_P (XEXP (operands[1], 0)))
-+ if (!REG_P (XEXP (operands[1], 0)))
- {
- rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
- operands[1] = replace_equiv_address (operands[1], addr);
-@@ -81,20 +81,20 @@
-
- (define_insn "*sync_compare_and_swap<mode>"
- [(set (match_operand:I48MODE 0 "register_operand" "=r")
-- (match_operand:I48MODE 1 "memory_reg_operand" "+m"))
-- (set (match_dup 1)
-+ (mem:I48MODE (match_operand 1 "register_operand" "r")))
-+ (set (mem:I48MODE (match_dup 1))
- (unspec_volatile:I48MODE
- [(match_operand:I48MODE 2 "register_operand" "r")
- (match_operand:I48MODE 3 "register_operand" "0")]
- UNSPECV_CAS))]
- "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
-- "cas<modesuffix>\t%1, %2, %0"
-+ "cas<modesuffix>\t[%1], %2, %0"
- [(set_attr "type" "multi")])
-
- (define_insn "*sync_compare_and_swapdi_v8plus"
- [(set (match_operand:DI 0 "register_operand" "=h")
-- (match_operand:DI 1 "memory_reg_operand" "+m"))
-- (set (match_dup 1)
-+ (mem:DI (match_operand 1 "register_operand" "r")))
-+ (set (mem:DI (match_dup 1))
- (unspec_volatile:DI
- [(match_operand:DI 2 "register_operand" "h")
- (match_operand:DI 3 "register_operand" "0")]
-@@ -109,7 +109,7 @@
- output_asm_insn ("srl\t%L2, 0, %L2", operands);
- output_asm_insn ("sllx\t%H2, 32, %H3", operands);
- output_asm_insn ("or\t%L2, %H3, %H3", operands);
-- output_asm_insn ("casx\t%1, %H3, %L3", operands);
-+ output_asm_insn ("casx\t[%1], %H3, %L3", operands);
- return "srlx\t%L3, 32, %H3";
- }
- [(set_attr "type" "multi")
-Index: gcc-4_5-branch/gcc/config/xtensa/xtensa.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/xtensa/xtensa.h 2012-03-06 11:53:21.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/xtensa/xtensa.h 2012-03-06 12:14:01.040439261 -0800
-@@ -286,7 +286,7 @@
- incoming argument in a2 is live throughout the function and
- local-alloc decides to use a2, then the incoming argument must
- either be spilled or copied to another register. To get around
-- this, we define ORDER_REGS_FOR_LOCAL_ALLOC to redefine
-+ this, we define ADJUST_REG_ALLOC_ORDER to redefine
- reg_alloc_order for leaf functions such that lowest numbered
- registers are used first with the exception that the incoming
- argument registers are not used until after other register choices
-@@ -300,7 +300,7 @@
- 35, \
- }
-
--#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
-+#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc ()
-
- /* For Xtensa, the only point of this is to prevent GCC from otherwise
- giving preference to call-used registers. To minimize window
-Index: gcc-4_5-branch/gcc/doc/tm.texi
-===================================================================
---- gcc-4_5-branch.orig/gcc/doc/tm.texi 2012-03-06 12:11:33.000000000 -0800
-+++ gcc-4_5-branch/gcc/doc/tm.texi 2012-03-06 12:14:01.044439265 -0800
-@@ -2093,7 +2093,7 @@
- the highest numbered allocable register first.
- @end defmac
-
--@defmac ORDER_REGS_FOR_LOCAL_ALLOC
-+@defmac ADJUST_REG_ALLOC_ORDER
- A C statement (sans semicolon) to choose the order in which to allocate
- hard registers for pseudo-registers local to a basic block.
-
-@@ -2107,6 +2107,15 @@
- On most machines, it is not necessary to define this macro.
- @end defmac
-
-+@defmac HONOR_REG_ALLOC_ORDER
-+Normally, IRA tries to estimate the costs for saving a register in the
-+prologue and restoring it in the epilogue. This discourages it from
-+using call-saved registers. If a machine wants to ensure that IRA
-+allocates registers in the order given by REG_ALLOC_ORDER even if some
-+call-saved registers appear earlier than call-used ones, this macro
-+should be defined.
-+@end defmac
-+
- @defmac IRA_HARD_REGNO_ADD_COST_MULTIPLIER (@var{regno})
- In some case register allocation order is not enough for the
- Integrated Register Allocator (@acronym{IRA}) to generate a good code.
-Index: gcc-4_5-branch/gcc/expmed.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/expmed.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/expmed.c 2012-03-06 12:14:01.044439265 -0800
-@@ -3255,6 +3255,55 @@
- gcc_assert (op0);
- return op0;
- }
-+
-+/* Perform a widening multiplication and return an rtx for the result.
-+ MODE is mode of value; OP0 and OP1 are what to multiply (rtx's);
-+ TARGET is a suggestion for where to store the result (an rtx).
-+ THIS_OPTAB is the optab we should use, it must be either umul_widen_optab
-+ or smul_widen_optab.
-+
-+ We check specially for a constant integer as OP1, comparing the
-+ cost of a widening multiply against the cost of a sequence of shifts
-+ and adds. */
-+
-+rtx
-+expand_widening_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
-+ int unsignedp, optab this_optab)
-+{
-+ bool speed = optimize_insn_for_speed_p ();
-+
-+ if (CONST_INT_P (op1)
-+ && (INTVAL (op1) >= 0
-+ || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT))
-+ {
-+ HOST_WIDE_INT coeff = INTVAL (op1);
-+ int max_cost;
-+ enum mult_variant variant;
-+ struct algorithm algorithm;
-+
-+ /* Special case powers of two. */
-+ if (EXACT_POWER_OF_2_OR_ZERO_P (coeff))
-+ {
-+ op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab);
-+ return expand_shift (LSHIFT_EXPR, mode, op0,
-+ build_int_cst (NULL_TREE, floor_log2 (coeff)),
-+ target, unsignedp);
-+ }
-+
-+ /* Exclude cost of op0 from max_cost to match the cost
-+ calculation of the synth_mult. */
-+ max_cost = mul_widen_cost[speed][mode];
-+ if (choose_mult_variant (mode, coeff, &algorithm, &variant,
-+ max_cost))
-+ {
-+ op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab);
-+ return expand_mult_const (mode, op0, coeff, target,
-+ &algorithm, variant);
-+ }
-+ }
-+ return expand_binop (mode, this_optab, op0, op1, target,
-+ unsignedp, OPTAB_LIB_WIDEN);
-+}
-
- /* Return the smallest n such that 2**n >= X. */
-
-Index: gcc-4_5-branch/gcc/expr.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/expr.c 2012-03-06 12:11:34.000000000 -0800
-+++ gcc-4_5-branch/gcc/expr.c 2012-03-06 12:46:21.548533151 -0800
-@@ -7345,7 +7345,6 @@
- optab this_optab;
- rtx subtarget, original_target;
- int ignore;
-- tree subexp0, subexp1;
- bool reduce_bit_field;
- gimple subexp0_def, subexp1_def;
- tree top0, top1;
-@@ -7800,13 +7799,7 @@
-
- goto binop2;
-
-- case MULT_EXPR:
-- /* If this is a fixed-point operation, then we cannot use the code
-- below because "expand_mult" doesn't support sat/no-sat fixed-point
-- multiplications. */
-- if (ALL_FIXED_POINT_MODE_P (mode))
-- goto binop;
--
-+ case WIDEN_MULT_EXPR:
- /* If first operand is constant, swap them.
- Thus the following special case checks need only
- check the second operand. */
-@@ -7817,96 +7810,35 @@
- treeop1 = t1;
- }
-
-- /* Attempt to return something suitable for generating an
-- indexed address, for machines that support that. */
--
-- if (modifier == EXPAND_SUM && mode == ptr_mode
-- && host_integerp (treeop1, 0))
-- {
-- tree exp1 = treeop1;
--
-- op0 = expand_expr (treeop0, subtarget, VOIDmode,
-- EXPAND_SUM);
--
-- if (!REG_P (op0))
-- op0 = force_operand (op0, NULL_RTX);
-- if (!REG_P (op0))
-- op0 = copy_to_mode_reg (mode, op0);
--
-- return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
-- gen_int_mode (tree_low_cst (exp1, 0),
-- TYPE_MODE (TREE_TYPE (exp1)))));
-- }
--
-- if (modifier == EXPAND_STACK_PARM)
-- target = 0;
--
-- /* Check for multiplying things that have been extended
-- from a narrower type. If this machine supports multiplying
-- in that narrower type with a result in the desired type,
-- do it that way, and avoid the explicit type-conversion. */
--
-- subexp0 = treeop0;
-- subexp1 = treeop1;
-- subexp0_def = get_def_for_expr (subexp0, NOP_EXPR);
-- subexp1_def = get_def_for_expr (subexp1, NOP_EXPR);
-- top0 = top1 = NULL_TREE;
--
- /* First, check if we have a multiplication of one signed and one
- unsigned operand. */
-- if (subexp0_def
-- && (top0 = gimple_assign_rhs1 (subexp0_def))
-- && subexp1_def
-- && (top1 = gimple_assign_rhs1 (subexp1_def))
-- && TREE_CODE (type) == INTEGER_TYPE
-- && (TYPE_PRECISION (TREE_TYPE (top0))
-- < TYPE_PRECISION (TREE_TYPE (subexp0)))
-- && (TYPE_PRECISION (TREE_TYPE (top0))
-- == TYPE_PRECISION (TREE_TYPE (top1)))
-- && (TYPE_UNSIGNED (TREE_TYPE (top0))
-- != TYPE_UNSIGNED (TREE_TYPE (top1))))
-+ if (TREE_CODE (treeop1) != INTEGER_CST
-+ && (TYPE_UNSIGNED (TREE_TYPE (treeop0))
-+ != TYPE_UNSIGNED (TREE_TYPE (treeop1))))
- {
-- enum machine_mode innermode
-- = TYPE_MODE (TREE_TYPE (top0));
-+ enum machine_mode innermode = TYPE_MODE (TREE_TYPE (treeop0));
- this_optab = usmul_widen_optab;
-- if (mode == GET_MODE_WIDER_MODE (innermode))
-+ if (mode == GET_MODE_2XWIDER_MODE (innermode))
- {
- if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
- {
-- if (TYPE_UNSIGNED (TREE_TYPE (top0)))
-- expand_operands (top0, top1, NULL_RTX, &op0, &op1,
-+ if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))
-+ expand_operands (treeop0, treeop1, subtarget, &op0, &op1,
- EXPAND_NORMAL);
- else
-- expand_operands (top0, top1, NULL_RTX, &op1, &op0,
-+ expand_operands (treeop0, treeop1, subtarget, &op1, &op0,
- EXPAND_NORMAL);
--
- goto binop3;
- }
- }
- }
-- /* Check for a multiplication with matching signedness. If
-- valid, TOP0 and TOP1 were set in the previous if
-- condition. */
-- else if (top0
-- && TREE_CODE (type) == INTEGER_TYPE
-- && (TYPE_PRECISION (TREE_TYPE (top0))
-- < TYPE_PRECISION (TREE_TYPE (subexp0)))
-- && ((TREE_CODE (subexp1) == INTEGER_CST
-- && int_fits_type_p (subexp1, TREE_TYPE (top0))
-- /* Don't use a widening multiply if a shift will do. */
-- && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (subexp1)))
-- > HOST_BITS_PER_WIDE_INT)
-- || exact_log2 (TREE_INT_CST_LOW (subexp1)) < 0))
-- ||
-- (top1
-- && (TYPE_PRECISION (TREE_TYPE (top1))
-- == TYPE_PRECISION (TREE_TYPE (top0))
-- /* If both operands are extended, they must either both
-- be zero-extended or both be sign-extended. */
-- && (TYPE_UNSIGNED (TREE_TYPE (top1))
-- == TYPE_UNSIGNED (TREE_TYPE (top0)))))))
-+ /* Check for a multiplication with matching signedness. */
-+ else if ((TREE_CODE (treeop1) == INTEGER_CST
-+ && int_fits_type_p (treeop1, TREE_TYPE (treeop0)))
-+ || (TYPE_UNSIGNED (TREE_TYPE (treeop1))
-+ == TYPE_UNSIGNED (TREE_TYPE (treeop0))))
- {
-- tree op0type = TREE_TYPE (top0);
-+ tree op0type = TREE_TYPE (treeop0);
- enum machine_mode innermode = TYPE_MODE (op0type);
- bool zextend_p = TYPE_UNSIGNED (op0type);
- optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
-@@ -7916,24 +7848,22 @@
- {
- if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
- {
-- if (TREE_CODE (subexp1) == INTEGER_CST)
-- expand_operands (top0, subexp1, NULL_RTX, &op0, &op1,
-- EXPAND_NORMAL);
-- else
-- expand_operands (top0, top1, NULL_RTX, &op0, &op1,
-- EXPAND_NORMAL);
-- goto binop3;
-+ expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
-+ EXPAND_NORMAL);
-+ temp = expand_widening_mult (mode, op0, op1, target,
-+ unsignedp, this_optab);
-+ return REDUCE_BIT_FIELD (temp);
- }
-- else if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
-- && innermode == word_mode)
-+ if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
-+ && innermode == word_mode)
- {
- rtx htem, hipart;
-- op0 = expand_normal (top0);
-- if (TREE_CODE (subexp1) == INTEGER_CST)
-+ op0 = expand_normal (treeop0);
-+ if (TREE_CODE (treeop1) == INTEGER_CST)
- op1 = convert_modes (innermode, mode,
-- expand_normal (subexp1), unsignedp);
-+ expand_normal (treeop1), unsignedp);
- else
-- op1 = expand_normal (top1);
-+ op1 = expand_normal (treeop1);
- temp = expand_binop (mode, other_optab, op0, op1, target,
- unsignedp, OPTAB_LIB_WIDEN);
- hipart = gen_highpart (innermode, temp);
-@@ -7946,7 +7876,53 @@
- }
- }
- }
-- expand_operands (subexp0, subexp1, subtarget, &op0, &op1, EXPAND_NORMAL);
-+ treeop0 = fold_build1 (CONVERT_EXPR, type, treeop0);
-+ treeop1 = fold_build1 (CONVERT_EXPR, type, treeop1);
-+ expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL);
-+ return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
-+
-+ case MULT_EXPR:
-+ /* If this is a fixed-point operation, then we cannot use the code
-+ below because "expand_mult" doesn't support sat/no-sat fixed-point
-+ multiplications. */
-+ if (ALL_FIXED_POINT_MODE_P (mode))
-+ goto binop;
-+
-+ /* If first operand is constant, swap them.
-+ Thus the following special case checks need only
-+ check the second operand. */
-+ if (TREE_CODE (treeop0) == INTEGER_CST)
-+ {
-+ tree t1 = treeop0;
-+ treeop0 = treeop1;
-+ treeop1 = t1;
-+ }
-+
-+ /* Attempt to return something suitable for generating an
-+ indexed address, for machines that support that. */
-+
-+ if (modifier == EXPAND_SUM && mode == ptr_mode
-+ && host_integerp (treeop1, 0))
-+ {
-+ tree exp1 = treeop1;
-+
-+ op0 = expand_expr (treeop0, subtarget, VOIDmode,
-+ EXPAND_SUM);
-+
-+ if (!REG_P (op0))
-+ op0 = force_operand (op0, NULL_RTX);
-+ if (!REG_P (op0))
-+ op0 = copy_to_mode_reg (mode, op0);
-+
-+ return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
-+ gen_int_mode (tree_low_cst (exp1, 0),
-+ TYPE_MODE (TREE_TYPE (exp1)))));
-+ }
-+
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+
-+ expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL);
- return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
-
- case TRUNC_DIV_EXPR:
-@@ -8435,6 +8411,8 @@
- location_t loc = EXPR_LOCATION (exp);
- struct separate_ops ops;
- tree treeop0, treeop1, treeop2;
-+ tree ssa_name = NULL_TREE;
-+ gimple g;
-
- type = TREE_TYPE (exp);
- mode = TYPE_MODE (type);
-@@ -8547,15 +8525,17 @@
- base variable. This unnecessarily allocates a pseudo, see how we can
- reuse it, if partition base vars have it set already. */
- if (!currently_expanding_to_rtl)
-- return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier, NULL);
-- {
-- gimple g = get_gimple_for_ssa_name (exp);
-- if (g)
-- return expand_expr_real (gimple_assign_rhs_to_tree (g), target,
-- tmode, modifier, NULL);
-- }
-- decl_rtl = get_rtx_for_ssa_name (exp);
-- exp = SSA_NAME_VAR (exp);
-+ return expand_expr_real_1 (SSA_NAME_VAR (exp), target, tmode, modifier,
-+ NULL);
-+
-+ g = get_gimple_for_ssa_name (exp);
-+ if (g)
-+ return expand_expr_real (gimple_assign_rhs_to_tree (g), target, tmode,
-+ modifier, NULL);
-+
-+ ssa_name = exp;
-+ decl_rtl = get_rtx_for_ssa_name (ssa_name);
-+ exp = SSA_NAME_VAR (ssa_name);
- goto expand_decl_rtl;
-
- case PARM_DECL:
-@@ -8669,7 +8649,15 @@
-
- /* Get the signedness used for this variable. Ensure we get the
- same mode we got when the variable was declared. */
-- pmode = promote_decl_mode (exp, &unsignedp);
-+ if (code == SSA_NAME
-+ && (g = SSA_NAME_DEF_STMT (ssa_name))
-+ && gimple_code (g) == GIMPLE_CALL)
-+ pmode = promote_function_mode (type, mode, &unsignedp,
-+ TREE_TYPE
-+ (TREE_TYPE (gimple_call_fn (g))),
-+ 2);
-+ else
-+ pmode = promote_decl_mode (exp, &unsignedp);
- gcc_assert (GET_MODE (decl_rtl) == pmode);
-
- temp = gen_lowpart_SUBREG (mode, decl_rtl);
-Index: gcc-4_5-branch/gcc/fold-const.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/fold-const.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/fold-const.c 2012-03-06 12:14:01.052439240 -0800
-@@ -5749,6 +5749,76 @@
- const_binop (BIT_XOR_EXPR, c, temp, 0));
- }
-
-+/* For an expression that has the form
-+ (A && B) || ~B
-+ or
-+ (A || B) && ~B,
-+ we can drop one of the inner expressions and simplify to
-+ A || ~B
-+ or
-+ A && ~B
-+ LOC is the location of the resulting expression. OP is the inner
-+ logical operation; the left-hand side in the examples above, while CMPOP
-+ is the right-hand side. RHS_ONLY is used to prevent us from accidentally
-+ removing a condition that guards another, as in
-+ (A != NULL && A->...) || A == NULL
-+ which we must not transform. If RHS_ONLY is true, only eliminate the
-+ right-most operand of the inner logical operation. */
-+
-+static tree
-+merge_truthop_with_opposite_arm (location_t loc, tree op, tree cmpop,
-+ bool rhs_only)
-+{
-+ tree type = TREE_TYPE (cmpop);
-+ enum tree_code code = TREE_CODE (cmpop);
-+ enum tree_code truthop_code = TREE_CODE (op);
-+ tree lhs = TREE_OPERAND (op, 0);
-+ tree rhs = TREE_OPERAND (op, 1);
-+ tree orig_lhs = lhs, orig_rhs = rhs;
-+ enum tree_code rhs_code = TREE_CODE (rhs);
-+ enum tree_code lhs_code = TREE_CODE (lhs);
-+ enum tree_code inv_code;
-+
-+ if (TREE_SIDE_EFFECTS (op) || TREE_SIDE_EFFECTS (cmpop))
-+ return NULL_TREE;
-+
-+ if (TREE_CODE_CLASS (code) != tcc_comparison)
-+ return NULL_TREE;
-+
-+ if (rhs_code == truthop_code)
-+ {
-+ tree newrhs = merge_truthop_with_opposite_arm (loc, rhs, cmpop, rhs_only);
-+ if (newrhs != NULL_TREE)
-+ {
-+ rhs = newrhs;
-+ rhs_code = TREE_CODE (rhs);
-+ }
-+ }
-+ if (lhs_code == truthop_code && !rhs_only)
-+ {
-+ tree newlhs = merge_truthop_with_opposite_arm (loc, lhs, cmpop, false);
-+ if (newlhs != NULL_TREE)
-+ {
-+ lhs = newlhs;
-+ lhs_code = TREE_CODE (lhs);
-+ }
-+ }
-+
-+ inv_code = invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type)));
-+ if (inv_code == rhs_code
-+ && operand_equal_p (TREE_OPERAND (rhs, 0), TREE_OPERAND (cmpop, 0), 0)
-+ && operand_equal_p (TREE_OPERAND (rhs, 1), TREE_OPERAND (cmpop, 1), 0))
-+ return lhs;
-+ if (!rhs_only && inv_code == lhs_code
-+ && operand_equal_p (TREE_OPERAND (lhs, 0), TREE_OPERAND (cmpop, 0), 0)
-+ && operand_equal_p (TREE_OPERAND (lhs, 1), TREE_OPERAND (cmpop, 1), 0))
-+ return rhs;
-+ if (rhs != orig_rhs || lhs != orig_lhs)
-+ return fold_build2_loc (loc, truthop_code, TREE_TYPE (cmpop),
-+ lhs, rhs);
-+ return NULL_TREE;
-+}
-+
- /* Find ways of folding logical expressions of LHS and RHS:
- Try to merge two comparisons to the same innermost item.
- Look for range tests like "ch >= '0' && ch <= '9'".
-@@ -12553,6 +12623,22 @@
- if (0 != (tem = fold_range_test (loc, code, type, op0, op1)))
- return tem;
-
-+ if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg0) == TRUTH_ORIF_EXPR)
-+ || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg0) == TRUTH_ANDIF_EXPR))
-+ {
-+ tem = merge_truthop_with_opposite_arm (loc, arg0, arg1, true);
-+ if (tem)
-+ return fold_build2_loc (loc, code, type, tem, arg1);
-+ }
-+
-+ if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg1) == TRUTH_ORIF_EXPR)
-+ || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg1) == TRUTH_ANDIF_EXPR))
-+ {
-+ tem = merge_truthop_with_opposite_arm (loc, arg1, arg0, false);
-+ if (tem)
-+ return fold_build2_loc (loc, code, type, arg0, tem);
-+ }
-+
- /* Check for the possibility of merging component references. If our
- lhs is another similar operation, try to merge its rhs with our
- rhs. Then try to merge our lhs and rhs. */
-Index: gcc-4_5-branch/gcc/ifcvt.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/ifcvt.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/ifcvt.c 2012-03-06 12:14:01.052439240 -0800
-@@ -385,7 +385,11 @@
- rtx false_expr; /* test for then block insns */
- rtx true_prob_val; /* probability of else block */
- rtx false_prob_val; /* probability of then block */
-- int n_insns;
-+ rtx then_last_head = NULL_RTX; /* Last match at the head of THEN */
-+ rtx else_last_head = NULL_RTX; /* Last match at the head of ELSE */
-+ rtx then_first_tail = NULL_RTX; /* First match at the tail of THEN */
-+ rtx else_first_tail = NULL_RTX; /* First match at the tail of ELSE */
-+ int then_n_insns, else_n_insns, n_insns;
- enum rtx_code false_code;
-
- /* If test is comprised of && or || elements, and we've failed at handling
-@@ -418,15 +422,78 @@
- number of insns and see if it is small enough to convert. */
- then_start = first_active_insn (then_bb);
- then_end = last_active_insn (then_bb, TRUE);
-- n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
-+ then_n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
-+ n_insns = then_n_insns;
- max = MAX_CONDITIONAL_EXECUTE;
-
- if (else_bb)
- {
-+ int n_matching;
-+
- max *= 2;
- else_start = first_active_insn (else_bb);
- else_end = last_active_insn (else_bb, TRUE);
-- n_insns += ce_info->num_else_insns = count_bb_insns (else_bb);
-+ else_n_insns = ce_info->num_else_insns = count_bb_insns (else_bb);
-+ n_insns += else_n_insns;
-+
-+ /* Look for matching sequences at the head and tail of the two blocks,
-+ and limit the range of insns to be converted if possible. */
-+ n_matching = flow_find_cross_jump (then_bb, else_bb,
-+ &then_first_tail, &else_first_tail);
-+ if (then_first_tail == BB_HEAD (then_bb))
-+ then_start = then_end = NULL_RTX;
-+ if (else_first_tail == BB_HEAD (else_bb))
-+ else_start = else_end = NULL_RTX;
-+
-+ if (n_matching > 0)
-+ {
-+ if (then_end)
-+ then_end = prev_active_insn (then_first_tail);
-+ if (else_end)
-+ else_end = prev_active_insn (else_first_tail);
-+ n_insns -= 2 * n_matching;
-+ }
-+
-+ if (then_start && else_start)
-+ {
-+ int longest_match = MIN (then_n_insns - n_matching,
-+ else_n_insns - n_matching);
-+ n_matching
-+ = flow_find_head_matching_sequence (then_bb, else_bb,
-+ &then_last_head,
-+ &else_last_head,
-+ longest_match);
-+
-+ if (n_matching > 0)
-+ {
-+ rtx insn;
-+
-+ /* We won't pass the insns in the head sequence to
-+ cond_exec_process_insns, so we need to test them here
-+ to make sure that they don't clobber the condition. */
-+ for (insn = BB_HEAD (then_bb);
-+ insn != NEXT_INSN (then_last_head);
-+ insn = NEXT_INSN (insn))
-+ if (!LABEL_P (insn) && !NOTE_P (insn)
-+ && !DEBUG_INSN_P (insn)
-+ && modified_in_p (test_expr, insn))
-+ return FALSE;
-+ }
-+
-+ if (then_last_head == then_end)
-+ then_start = then_end = NULL_RTX;
-+ if (else_last_head == else_end)
-+ else_start = else_end = NULL_RTX;
-+
-+ if (n_matching > 0)
-+ {
-+ if (then_start)
-+ then_start = next_active_insn (then_last_head);
-+ if (else_start)
-+ else_start = next_active_insn (else_last_head);
-+ n_insns -= 2 * n_matching;
-+ }
-+ }
- }
-
- if (n_insns > max)
-@@ -570,7 +637,21 @@
- fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
- n_insns, (n_insns == 1) ? " was" : "s were");
-
-- /* Merge the blocks! */
-+ /* Merge the blocks! If we had matching sequences, make sure to delete one
-+ copy at the appropriate location first: delete the copy in the THEN branch
-+ for a tail sequence so that the remaining one is executed last for both
-+ branches, and delete the copy in the ELSE branch for a head sequence so
-+ that the remaining one is executed first for both branches. */
-+ if (then_first_tail)
-+ {
-+ rtx from = then_first_tail;
-+ if (!INSN_P (from))
-+ from = next_active_insn (from);
-+ delete_insn_chain (from, BB_END (then_bb), false);
-+ }
-+ if (else_last_head)
-+ delete_insn_chain (first_active_insn (else_bb), else_last_head, false);
-+
- merge_if_block (ce_info);
- cond_exec_changed_p = TRUE;
- return TRUE;
-Index: gcc-4_5-branch/gcc/ira-color.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/ira-color.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/ira-color.c 2012-03-06 12:14:01.056439222 -0800
-@@ -447,14 +447,18 @@
- {
- HARD_REG_SET conflicting_regs;
- int i, j, k, hard_regno, best_hard_regno, class_size;
-- int cost, mem_cost, min_cost, full_cost, min_full_cost, add_cost;
-+ int cost, mem_cost, min_cost, full_cost, min_full_cost;
- int *a_costs;
- int *conflict_costs;
-- enum reg_class cover_class, rclass, conflict_cover_class;
-+ enum reg_class cover_class, conflict_cover_class;
- enum machine_mode mode;
- ira_allocno_t a, conflict_allocno;
- ira_allocno_conflict_iterator aci;
- static int costs[FIRST_PSEUDO_REGISTER], full_costs[FIRST_PSEUDO_REGISTER];
-+#ifndef HONOR_REG_ALLOC_ORDER
-+ enum reg_class rclass;
-+ int add_cost;
-+#endif
- #ifdef STACK_REGS
- bool no_stack_reg_p;
- #endif
-@@ -592,6 +596,7 @@
- continue;
- cost = costs[i];
- full_cost = full_costs[i];
-+#ifndef HONOR_REG_ALLOC_ORDER
- if (! allocated_hardreg_p[hard_regno]
- && ira_hard_reg_not_in_set_p (hard_regno, mode, call_used_reg_set))
- /* We need to save/restore the hard register in
-@@ -604,6 +609,7 @@
- cost += add_cost;
- full_cost += add_cost;
- }
-+#endif
- if (min_cost > cost)
- min_cost = cost;
- if (min_full_cost > full_cost)
-Index: gcc-4_5-branch/gcc/ira-costs.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/ira-costs.c 2012-03-06 12:11:33.000000000 -0800
-+++ gcc-4_5-branch/gcc/ira-costs.c 2012-03-06 12:14:01.056439222 -0800
-@@ -33,6 +33,7 @@
- #include "addresses.h"
- #include "insn-config.h"
- #include "recog.h"
-+#include "reload.h"
- #include "toplev.h"
- #include "target.h"
- #include "params.h"
-@@ -123,6 +124,10 @@
- /* Record cover register class of each allocno with the same regno. */
- static enum reg_class *regno_cover_class;
-
-+/* Record cost gains for not allocating a register with an invariant
-+ equivalence. */
-+static int *regno_equiv_gains;
-+
- /* Execution frequency of the current insn. */
- static int frequency;
-
-@@ -1263,6 +1268,7 @@
- #ifdef FORBIDDEN_INC_DEC_CLASSES
- int inc_dec_p = false;
- #endif
-+ int equiv_savings = regno_equiv_gains[i];
-
- if (! allocno_p)
- {
-@@ -1311,6 +1317,15 @@
- #endif
- }
- }
-+ if (equiv_savings < 0)
-+ temp_costs->mem_cost = -equiv_savings;
-+ else if (equiv_savings > 0)
-+ {
-+ temp_costs->mem_cost = 0;
-+ for (k = 0; k < cost_classes_num; k++)
-+ temp_costs->cost[k] += equiv_savings;
-+ }
-+
- best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
- best = ALL_REGS;
- alt_class = NO_REGS;
-@@ -1680,6 +1695,8 @@
- regno_cover_class
- = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
- * max_reg_num ());
-+ regno_equiv_gains = (int *) ira_allocate (sizeof (int) * max_reg_num ());
-+ memset (regno_equiv_gains, 0, sizeof (int) * max_reg_num ());
- }
-
- /* Common finalization function for ira_costs and
-@@ -1687,6 +1704,7 @@
- static void
- finish_costs (void)
- {
-+ ira_free (regno_equiv_gains);
- ira_free (regno_cover_class);
- ira_free (pref_buffer);
- ira_free (costs);
-@@ -1702,6 +1720,7 @@
- init_costs ();
- total_allocno_costs = (struct costs *) ira_allocate (max_struct_costs_size
- * ira_allocnos_num);
-+ calculate_elim_costs_all_insns ();
- find_costs_and_classes (ira_dump_file);
- setup_allocno_cover_class_and_costs ();
- finish_costs ();
-@@ -1775,3 +1794,16 @@
- ALLOCNO_COVER_CLASS_COST (a) = min_cost;
- }
- }
-+
-+/* Add COST to the estimated gain for eliminating REGNO with its
-+ equivalence. If COST is zero, record that no such elimination is
-+ possible. */
-+
-+void
-+ira_adjust_equiv_reg_cost (unsigned regno, int cost)
-+{
-+ if (cost == 0)
-+ regno_equiv_gains[regno] = 0;
-+ else
-+ regno_equiv_gains[regno] += cost;
-+}
-Index: gcc-4_5-branch/gcc/ira.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/ira.c 2012-03-06 12:11:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/ira.c 2012-03-06 12:14:01.056439222 -0800
-@@ -431,9 +431,6 @@
- HARD_REG_SET processed_hard_reg_set;
-
- ira_assert (SHRT_MAX >= FIRST_PSEUDO_REGISTER);
-- /* We could call ORDER_REGS_FOR_LOCAL_ALLOC here (it is usually
-- putting hard callee-used hard registers first). But our
-- heuristics work better. */
- for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--)
- {
- COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
-@@ -490,6 +487,9 @@
- static void
- setup_alloc_regs (bool use_hard_frame_p)
- {
-+#ifdef ADJUST_REG_ALLOC_ORDER
-+ ADJUST_REG_ALLOC_ORDER;
-+#endif
- COPY_HARD_REG_SET (no_unit_alloc_regs, fixed_reg_set);
- if (! use_hard_frame_p)
- SET_HARD_REG_BIT (no_unit_alloc_regs, HARD_FRAME_POINTER_REGNUM);
-@@ -1533,12 +1533,8 @@
-
- x = XEXP (note, 0);
-
-- if (! function_invariant_p (x)
-- || ! flag_pic
-- /* A function invariant is often CONSTANT_P but may
-- include a register. We promise to only pass CONSTANT_P
-- objects to LEGITIMATE_PIC_OPERAND_P. */
-- || (CONSTANT_P (x) && LEGITIMATE_PIC_OPERAND_P (x)))
-+ if (! CONSTANT_P (x)
-+ || ! flag_pic || LEGITIMATE_PIC_OPERAND_P (x))
- {
- /* It can happen that a REG_EQUIV note contains a MEM
- that is not a legitimate memory operand. As later
-@@ -3096,8 +3092,19 @@
- if (dump_file)
- print_insn_chains (dump_file);
- }
--
-
-+/* Allocate memory for reg_equiv_memory_loc. */
-+static void
-+init_reg_equiv_memory_loc (void)
-+{
-+ max_regno = max_reg_num ();
-+
-+ /* And the reg_equiv_memory_loc array. */
-+ VEC_safe_grow (rtx, gc, reg_equiv_memory_loc_vec, max_regno);
-+ memset (VEC_address (rtx, reg_equiv_memory_loc_vec), 0,
-+ sizeof (rtx) * max_regno);
-+ reg_equiv_memory_loc = VEC_address (rtx, reg_equiv_memory_loc_vec);
-+}
-
- /* All natural loops. */
- struct loops ira_loops;
-@@ -3202,6 +3209,8 @@
- record_loop_exits ();
- current_loops = &ira_loops;
-
-+ init_reg_equiv_memory_loc ();
-+
- if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
- fprintf (ira_dump_file, "Building IRA IR\n");
- loops_p = ira_build (optimize
-@@ -3265,13 +3274,8 @@
- #endif
-
- delete_trivially_dead_insns (get_insns (), max_reg_num ());
-- max_regno = max_reg_num ();
-
-- /* And the reg_equiv_memory_loc array. */
-- VEC_safe_grow (rtx, gc, reg_equiv_memory_loc_vec, max_regno);
-- memset (VEC_address (rtx, reg_equiv_memory_loc_vec), 0,
-- sizeof (rtx) * max_regno);
-- reg_equiv_memory_loc = VEC_address (rtx, reg_equiv_memory_loc_vec);
-+ init_reg_equiv_memory_loc ();
-
- if (max_regno != max_regno_before_ira)
- {
-Index: gcc-4_5-branch/gcc/ira.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/ira.h 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/ira.h 2012-03-06 12:14:01.056439222 -0800
-@@ -87,3 +87,4 @@
- extern void ira_mark_new_stack_slot (rtx, int, unsigned int);
- extern bool ira_better_spill_reload_regno_p (int *, int *, rtx, rtx, rtx);
-
-+extern void ira_adjust_equiv_reg_cost (unsigned, int);
-Index: gcc-4_5-branch/gcc/optabs.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/optabs.h 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/optabs.h 2012-03-06 12:14:01.056439222 -0800
-@@ -771,6 +771,9 @@
- /* Generate code for float to integral conversion. */
- extern bool expand_sfix_optab (rtx, rtx, convert_optab);
-
-+/* Generate code for a widening multiply. */
-+extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
-+
- /* Return tree if target supports vector operations for COND_EXPR. */
- bool expand_vec_cond_expr_p (tree, enum machine_mode);
-
-Index: gcc-4_5-branch/gcc/passes.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/passes.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/passes.c 2012-03-06 12:14:01.056439222 -0800
-@@ -944,6 +944,7 @@
- NEXT_PASS (pass_forwprop);
- NEXT_PASS (pass_phiopt);
- NEXT_PASS (pass_fold_builtins);
-+ NEXT_PASS (pass_optimize_widening_mul);
- NEXT_PASS (pass_tail_calls);
- NEXT_PASS (pass_rename_ssa_copies);
- NEXT_PASS (pass_uncprop);
-Index: gcc-4_5-branch/gcc/reload.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/reload.h 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/reload.h 2012-03-06 12:14:01.056439222 -0800
-@@ -347,6 +347,10 @@
- extern rtx eliminate_regs (rtx, enum machine_mode, rtx);
- extern bool elimination_target_reg_p (rtx);
-
-+/* Called from the register allocator to estimate costs of eliminating
-+ invariant registers. */
-+extern void calculate_elim_costs_all_insns (void);
-+
- /* Deallocate the reload register used by reload number R. */
- extern void deallocate_reload_reg (int r);
-
-Index: gcc-4_5-branch/gcc/reload1.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/reload1.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/reload1.c 2012-03-06 12:14:01.060439213 -0800
-@@ -413,6 +413,7 @@
- static void set_label_offsets (rtx, rtx, int);
- static void check_eliminable_occurrences (rtx);
- static void elimination_effects (rtx, enum machine_mode);
-+static rtx eliminate_regs_1 (rtx, enum machine_mode, rtx, bool, bool);
- static int eliminate_regs_in_insn (rtx, int);
- static void update_eliminable_offsets (void);
- static void mark_not_eliminable (rtx, const_rtx, void *);
-@@ -420,8 +421,11 @@
- static bool verify_initial_elim_offsets (void);
- static void set_initial_label_offsets (void);
- static void set_offsets_for_label (rtx);
-+static void init_eliminable_invariants (rtx, bool);
- static void init_elim_table (void);
-+static void free_reg_equiv (void);
- static void update_eliminables (HARD_REG_SET *);
-+static void elimination_costs_in_insn (rtx);
- static void spill_hard_reg (unsigned int, int);
- static int finish_spills (int);
- static void scan_paradoxical_subregs (rtx);
-@@ -697,6 +701,9 @@
-
- /* Global variables used by reload and its subroutines. */
-
-+/* The current basic block while in calculate_elim_costs_all_insns. */
-+static basic_block elim_bb;
-+
- /* Set during calculate_needs if an insn needs register elimination. */
- static int something_needs_elimination;
- /* Set during calculate_needs if an insn needs an operand changed. */
-@@ -775,22 +782,6 @@
- if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
- df_set_regs_ever_live (i, true);
-
-- /* Find all the pseudo registers that didn't get hard regs
-- but do have known equivalent constants or memory slots.
-- These include parameters (known equivalent to parameter slots)
-- and cse'd or loop-moved constant memory addresses.
--
-- Record constant equivalents in reg_equiv_constant
-- so they will be substituted by find_reloads.
-- Record memory equivalents in reg_mem_equiv so they can
-- be substituted eventually by altering the REG-rtx's. */
--
-- reg_equiv_constant = XCNEWVEC (rtx, max_regno);
-- reg_equiv_invariant = XCNEWVEC (rtx, max_regno);
-- reg_equiv_mem = XCNEWVEC (rtx, max_regno);
-- reg_equiv_alt_mem_list = XCNEWVEC (rtx, max_regno);
-- reg_equiv_address = XCNEWVEC (rtx, max_regno);
-- reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
- reg_old_renumber = XCNEWVEC (short, max_regno);
- memcpy (reg_old_renumber, reg_renumber, max_regno * sizeof (short));
- pseudo_forbidden_regs = XNEWVEC (HARD_REG_SET, max_regno);
-@@ -798,115 +789,9 @@
-
- CLEAR_HARD_REG_SET (bad_spill_regs_global);
-
-- /* Look for REG_EQUIV notes; record what each pseudo is equivalent
-- to. Also find all paradoxical subregs and find largest such for
-- each pseudo. */
--
-- num_eliminable_invariants = 0;
-- for (insn = first; insn; insn = NEXT_INSN (insn))
-- {
-- rtx set = single_set (insn);
--
-- /* We may introduce USEs that we want to remove at the end, so
-- we'll mark them with QImode. Make sure there are no
-- previously-marked insns left by say regmove. */
-- if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
-- && GET_MODE (insn) != VOIDmode)
-- PUT_MODE (insn, VOIDmode);
--
-- if (NONDEBUG_INSN_P (insn))
-- scan_paradoxical_subregs (PATTERN (insn));
--
-- if (set != 0 && REG_P (SET_DEST (set)))
-- {
-- rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
-- rtx x;
--
-- if (! note)
-- continue;
--
-- i = REGNO (SET_DEST (set));
-- x = XEXP (note, 0);
--
-- if (i <= LAST_VIRTUAL_REGISTER)
-- continue;
--
-- if (! function_invariant_p (x)
-- || ! flag_pic
-- /* A function invariant is often CONSTANT_P but may
-- include a register. We promise to only pass
-- CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P. */
-- || (CONSTANT_P (x)
-- && LEGITIMATE_PIC_OPERAND_P (x)))
-- {
-- /* It can happen that a REG_EQUIV note contains a MEM
-- that is not a legitimate memory operand. As later
-- stages of reload assume that all addresses found
-- in the reg_equiv_* arrays were originally legitimate,
-- we ignore such REG_EQUIV notes. */
-- if (memory_operand (x, VOIDmode))
-- {
-- /* Always unshare the equivalence, so we can
-- substitute into this insn without touching the
-- equivalence. */
-- reg_equiv_memory_loc[i] = copy_rtx (x);
-- }
-- else if (function_invariant_p (x))
-- {
-- if (GET_CODE (x) == PLUS)
-- {
-- /* This is PLUS of frame pointer and a constant,
-- and might be shared. Unshare it. */
-- reg_equiv_invariant[i] = copy_rtx (x);
-- num_eliminable_invariants++;
-- }
-- else if (x == frame_pointer_rtx || x == arg_pointer_rtx)
-- {
-- reg_equiv_invariant[i] = x;
-- num_eliminable_invariants++;
-- }
-- else if (LEGITIMATE_CONSTANT_P (x))
-- reg_equiv_constant[i] = x;
-- else
-- {
-- reg_equiv_memory_loc[i]
-- = force_const_mem (GET_MODE (SET_DEST (set)), x);
-- if (! reg_equiv_memory_loc[i])
-- reg_equiv_init[i] = NULL_RTX;
-- }
-- }
-- else
-- {
-- reg_equiv_init[i] = NULL_RTX;
-- continue;
-- }
-- }
-- else
-- reg_equiv_init[i] = NULL_RTX;
-- }
-- }
--
-- if (dump_file)
-- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-- if (reg_equiv_init[i])
-- {
-- fprintf (dump_file, "init_insns for %u: ", i);
-- print_inline_rtx (dump_file, reg_equiv_init[i], 20);
-- fprintf (dump_file, "\n");
-- }
--
-+ init_eliminable_invariants (first, true);
- init_elim_table ();
-
-- first_label_num = get_first_label_num ();
-- num_labels = max_label_num () - first_label_num;
--
-- /* Allocate the tables used to store offset information at labels. */
-- /* We used to use alloca here, but the size of what it would try to
-- allocate would occasionally cause it to exceed the stack limit and
-- cause a core dump. */
-- offsets_known_at = XNEWVEC (char, num_labels);
-- offsets_at = (HOST_WIDE_INT (*)[NUM_ELIMINABLE_REGS]) xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT));
--
- /* Alter each pseudo-reg rtx to contain its hard reg number. Assign
- stack slots to the pseudos that lack hard regs or equivalents.
- Do not touch virtual registers. */
-@@ -1410,31 +1295,11 @@
- }
- }
-
-- /* Indicate that we no longer have known memory locations or constants. */
-- if (reg_equiv_constant)
-- free (reg_equiv_constant);
-- if (reg_equiv_invariant)
-- free (reg_equiv_invariant);
-- reg_equiv_constant = 0;
-- reg_equiv_invariant = 0;
-- VEC_free (rtx, gc, reg_equiv_memory_loc_vec);
-- reg_equiv_memory_loc = 0;
--
- free (temp_pseudo_reg_arr);
-
-- if (offsets_known_at)
-- free (offsets_known_at);
-- if (offsets_at)
-- free (offsets_at);
--
-- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-- if (reg_equiv_alt_mem_list[i])
-- free_EXPR_LIST_list (&reg_equiv_alt_mem_list[i]);
-- free (reg_equiv_alt_mem_list);
--
-- free (reg_equiv_mem);
-+ /* Indicate that we no longer have known memory locations or constants. */
-+ free_reg_equiv ();
- reg_equiv_init = 0;
-- free (reg_equiv_address);
- free (reg_max_ref_width);
- free (reg_old_renumber);
- free (pseudo_previous_regs);
-@@ -1727,6 +1592,100 @@
- *pprev_reload = 0;
- }
-
-+/* This function is called from the register allocator to set up estimates
-+ for the cost of eliminating pseudos which have REG_EQUIV equivalences to
-+ an invariant. The structure is similar to calculate_needs_all_insns. */
-+
-+void
-+calculate_elim_costs_all_insns (void)
-+{
-+ int *reg_equiv_init_cost;
-+ basic_block bb;
-+ int i;
-+
-+ reg_equiv_init_cost = XCNEWVEC (int, max_regno);
-+ init_elim_table ();
-+ init_eliminable_invariants (get_insns (), false);
-+
-+ set_initial_elim_offsets ();
-+ set_initial_label_offsets ();
-+
-+ FOR_EACH_BB (bb)
-+ {
-+ rtx insn;
-+ elim_bb = bb;
-+
-+ FOR_BB_INSNS (bb, insn)
-+ {
-+ /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
-+ include REG_LABEL_OPERAND and REG_LABEL_TARGET), we need to see
-+ what effects this has on the known offsets at labels. */
-+
-+ if (LABEL_P (insn) || JUMP_P (insn)
-+ || (INSN_P (insn) && REG_NOTES (insn) != 0))
-+ set_label_offsets (insn, insn, 0);
-+
-+ if (INSN_P (insn))
-+ {
-+ rtx set = single_set (insn);
-+
-+ /* Skip insns that only set an equivalence. */
-+ if (set && REG_P (SET_DEST (set))
-+ && reg_renumber[REGNO (SET_DEST (set))] < 0
-+ && (reg_equiv_constant[REGNO (SET_DEST (set))]
-+ || (reg_equiv_invariant[REGNO (SET_DEST (set))])))
-+ {
-+ unsigned regno = REGNO (SET_DEST (set));
-+ rtx init = reg_equiv_init[regno];
-+ if (init)
-+ {
-+ rtx t = eliminate_regs_1 (SET_SRC (set), VOIDmode, insn,
-+ false, true);
-+ int cost = rtx_cost (t, SET,
-+ optimize_bb_for_speed_p (bb));
-+ int freq = REG_FREQ_FROM_BB (bb);
-+
-+ reg_equiv_init_cost[regno] = cost * freq;
-+ continue;
-+ }
-+ }
-+ /* If needed, eliminate any eliminable registers. */
-+ if (num_eliminable || num_eliminable_invariants)
-+ elimination_costs_in_insn (insn);
-+
-+ if (num_eliminable)
-+ update_eliminable_offsets ();
-+ }
-+ }
-+ }
-+ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-+ {
-+ if (reg_equiv_invariant[i])
-+ {
-+ if (reg_equiv_init[i])
-+ {
-+ int cost = reg_equiv_init_cost[i];
-+ if (dump_file)
-+ fprintf (dump_file,
-+ "Reg %d has equivalence, initial gains %d\n", i, cost);
-+ if (cost != 0)
-+ ira_adjust_equiv_reg_cost (i, cost);
-+ }
-+ else
-+ {
-+ if (dump_file)
-+ fprintf (dump_file,
-+ "Reg %d had equivalence, but can't be eliminated\n",
-+ i);
-+ ira_adjust_equiv_reg_cost (i, 0);
-+ }
-+ }
-+ }
-+
-+ free_reg_equiv ();
-+ free (reg_equiv_init_cost);
-+}
-+
- /* Comparison function for qsort to decide which of two reloads
- should be handled first. *P1 and *P2 are the reload numbers. */
-
-@@ -2513,6 +2472,36 @@
- }
- }
-
-+/* Called through for_each_rtx, this function examines every reg that occurs
-+ in PX and adjusts the costs for its elimination which are gathered by IRA.
-+ DATA is the insn in which PX occurs. We do not recurse into MEM
-+ expressions. */
-+
-+static int
-+note_reg_elim_costly (rtx *px, void *data)
-+{
-+ rtx insn = (rtx)data;
-+ rtx x = *px;
-+
-+ if (MEM_P (x))
-+ return -1;
-+
-+ if (REG_P (x)
-+ && REGNO (x) >= FIRST_PSEUDO_REGISTER
-+ && reg_equiv_init[REGNO (x)]
-+ && reg_equiv_invariant[REGNO (x)])
-+ {
-+ rtx t = reg_equiv_invariant[REGNO (x)];
-+ rtx new_rtx = eliminate_regs_1 (t, Pmode, insn, true, true);
-+ int cost = rtx_cost (new_rtx, SET, optimize_bb_for_speed_p (elim_bb));
-+ int freq = REG_FREQ_FROM_BB (elim_bb);
-+
-+ if (cost != 0)
-+ ira_adjust_equiv_reg_cost (REGNO (x), -cost * freq);
-+ }
-+ return 0;
-+}
-+
- /* Scan X and replace any eliminable registers (such as fp) with a
- replacement (such as sp), plus an offset.
-
-@@ -2532,6 +2521,9 @@
- This means, do not set ref_outside_mem even if the reference
- is outside of MEMs.
-
-+ If FOR_COSTS is true, we are being called before reload in order to
-+ estimate the costs of keeping registers with an equivalence unallocated.
-+
- REG_EQUIV_MEM and REG_EQUIV_ADDRESS contain address that have had
- replacements done assuming all offsets are at their initial values. If
- they are not, or if REG_EQUIV_ADDRESS is nonzero for a pseudo we
-@@ -2540,7 +2532,7 @@
-
- static rtx
- eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
-- bool may_use_invariant)
-+ bool may_use_invariant, bool for_costs)
- {
- enum rtx_code code = GET_CODE (x);
- struct elim_table *ep;
-@@ -2588,11 +2580,12 @@
- {
- if (may_use_invariant || (insn && DEBUG_INSN_P (insn)))
- return eliminate_regs_1 (copy_rtx (reg_equiv_invariant[regno]),
-- mem_mode, insn, true);
-+ mem_mode, insn, true, for_costs);
- /* There exists at least one use of REGNO that cannot be
- eliminated. Prevent the defining insn from being deleted. */
- reg_equiv_init[regno] = NULL_RTX;
-- alter_reg (regno, -1, true);
-+ if (!for_costs)
-+ alter_reg (regno, -1, true);
- }
- return x;
-
-@@ -2653,8 +2646,10 @@
- operand of a load-address insn. */
-
- {
-- rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true);
-- rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true);
-+ rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true,
-+ for_costs);
-+ rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
-+ for_costs);
-
- if (reg_renumber && (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)))
- {
-@@ -2728,9 +2723,11 @@
- case GE: case GT: case GEU: case GTU:
- case LE: case LT: case LEU: case LTU:
- {
-- rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false);
-+ rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false,
-+ for_costs);
- rtx new1 = XEXP (x, 1)
-- ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false) : 0;
-+ ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false,
-+ for_costs) : 0;
-
- if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
- return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
-@@ -2741,7 +2738,8 @@
- /* If we have something in XEXP (x, 0), the usual case, eliminate it. */
- if (XEXP (x, 0))
- {
-- new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true);
-+ new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true,
-+ for_costs);
- if (new_rtx != XEXP (x, 0))
- {
- /* If this is a REG_DEAD note, it is not valid anymore.
-@@ -2749,7 +2747,8 @@
- REG_DEAD note for the stack or frame pointer. */
- if (REG_NOTE_KIND (x) == REG_DEAD)
- return (XEXP (x, 1)
-- ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true)
-+ ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
-+ for_costs)
- : NULL_RTX);
-
- x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
-@@ -2764,7 +2763,8 @@
- strictly needed, but it simplifies the code. */
- if (XEXP (x, 1))
- {
-- new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true);
-+ new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
-+ for_costs);
- if (new_rtx != XEXP (x, 1))
- return
- gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new_rtx);
-@@ -2790,7 +2790,7 @@
- && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
- {
- rtx new_rtx = eliminate_regs_1 (XEXP (XEXP (x, 1), 1), mem_mode,
-- insn, true);
-+ insn, true, for_costs);
-
- if (new_rtx != XEXP (XEXP (x, 1), 1))
- return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
-@@ -2813,7 +2813,8 @@
- case POPCOUNT:
- case PARITY:
- case BSWAP:
-- new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false);
-+ new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false,
-+ for_costs);
- if (new_rtx != XEXP (x, 0))
- return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
- return x;
-@@ -2834,7 +2835,8 @@
- new_rtx = SUBREG_REG (x);
- }
- else
-- new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false);
-+ new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false,
-+ for_costs);
-
- if (new_rtx != SUBREG_REG (x))
- {
-@@ -2868,14 +2870,20 @@
- /* Our only special processing is to pass the mode of the MEM to our
- recursive call and copy the flags. While we are here, handle this
- case more efficiently. */
-- return
-- replace_equiv_address_nv (x,
-- eliminate_regs_1 (XEXP (x, 0), GET_MODE (x),
-- insn, true));
-+
-+ new_rtx = eliminate_regs_1 (XEXP (x, 0), GET_MODE (x), insn, true,
-+ for_costs);
-+ if (for_costs
-+ && memory_address_p (GET_MODE (x), XEXP (x, 0))
-+ && !memory_address_p (GET_MODE (x), new_rtx))
-+ for_each_rtx (&XEXP (x, 0), note_reg_elim_costly, insn);
-+
-+ return replace_equiv_address_nv (x, new_rtx);
-
- case USE:
- /* Handle insn_list USE that a call to a pure function may generate. */
-- new_rtx = eliminate_regs_1 (XEXP (x, 0), VOIDmode, insn, false);
-+ new_rtx = eliminate_regs_1 (XEXP (x, 0), VOIDmode, insn, false,
-+ for_costs);
- if (new_rtx != XEXP (x, 0))
- return gen_rtx_USE (GET_MODE (x), new_rtx);
- return x;
-@@ -2899,7 +2907,8 @@
- {
- if (*fmt == 'e')
- {
-- new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false);
-+ new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false,
-+ for_costs);
- if (new_rtx != XEXP (x, i) && ! copied)
- {
- x = shallow_copy_rtx (x);
-@@ -2912,7 +2921,8 @@
- int copied_vec = 0;
- for (j = 0; j < XVECLEN (x, i); j++)
- {
-- new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false);
-+ new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false,
-+ for_costs);
- if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
- {
- rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
-@@ -2936,7 +2946,7 @@
- rtx
- eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
- {
-- return eliminate_regs_1 (x, mem_mode, insn, false);
-+ return eliminate_regs_1 (x, mem_mode, insn, false, false);
- }
-
- /* Scan rtx X for modifications of elimination target registers. Update
-@@ -3454,7 +3464,8 @@
- /* Companion to the above plus substitution, we can allow
- invariants as the source of a plain move. */
- is_set_src = false;
-- if (old_set && recog_data.operand_loc[i] == &SET_SRC (old_set))
-+ if (old_set
-+ && recog_data.operand_loc[i] == &SET_SRC (old_set))
- is_set_src = true;
- in_plus = false;
- if (plus_src
-@@ -3465,7 +3476,7 @@
- substed_operand[i]
- = eliminate_regs_1 (recog_data.operand[i], VOIDmode,
- replace ? insn : NULL_RTX,
-- is_set_src || in_plus);
-+ is_set_src || in_plus, false);
- if (substed_operand[i] != orig_operand[i])
- val = 1;
- /* Terminate the search in check_eliminable_occurrences at
-@@ -3593,11 +3604,167 @@
- the pre-passes. */
- if (val && REG_NOTES (insn) != 0)
- REG_NOTES (insn)
-- = eliminate_regs_1 (REG_NOTES (insn), VOIDmode, REG_NOTES (insn), true);
-+ = eliminate_regs_1 (REG_NOTES (insn), VOIDmode, REG_NOTES (insn), true,
-+ false);
-
- return val;
- }
-
-+/* Like eliminate_regs_in_insn, but only estimate costs for the use of the
-+ register allocator. INSN is the instruction we need to examine, we perform
-+ eliminations in its operands and record cases where eliminating a reg with
-+ an invariant equivalence would add extra cost. */
-+
-+static void
-+elimination_costs_in_insn (rtx insn)
-+{
-+ int icode = recog_memoized (insn);
-+ rtx old_body = PATTERN (insn);
-+ int insn_is_asm = asm_noperands (old_body) >= 0;
-+ rtx old_set = single_set (insn);
-+ int i;
-+ rtx orig_operand[MAX_RECOG_OPERANDS];
-+ rtx orig_dup[MAX_RECOG_OPERANDS];
-+ struct elim_table *ep;
-+ rtx plus_src, plus_cst_src;
-+ bool sets_reg_p;
-+
-+ if (! insn_is_asm && icode < 0)
-+ {
-+ gcc_assert (GET_CODE (PATTERN (insn)) == USE
-+ || GET_CODE (PATTERN (insn)) == CLOBBER
-+ || GET_CODE (PATTERN (insn)) == ADDR_VEC
-+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
-+ || GET_CODE (PATTERN (insn)) == ASM_INPUT
-+ || DEBUG_INSN_P (insn));
-+ return;
-+ }
-+
-+ if (old_set != 0 && REG_P (SET_DEST (old_set))
-+ && REGNO (SET_DEST (old_set)) < FIRST_PSEUDO_REGISTER)
-+ {
-+ /* Check for setting an eliminable register. */
-+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-+ if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
-+ return;
-+ }
-+
-+ /* We allow one special case which happens to work on all machines we
-+ currently support: a single set with the source or a REG_EQUAL
-+ note being a PLUS of an eliminable register and a constant. */
-+ plus_src = plus_cst_src = 0;
-+ sets_reg_p = false;
-+ if (old_set && REG_P (SET_DEST (old_set)))
-+ {
-+ sets_reg_p = true;
-+ if (GET_CODE (SET_SRC (old_set)) == PLUS)
-+ plus_src = SET_SRC (old_set);
-+ /* First see if the source is of the form (plus (...) CST). */
-+ if (plus_src
-+ && CONST_INT_P (XEXP (plus_src, 1)))
-+ plus_cst_src = plus_src;
-+ else if (REG_P (SET_SRC (old_set))
-+ || plus_src)
-+ {
-+ /* Otherwise, see if we have a REG_EQUAL note of the form
-+ (plus (...) CST). */
-+ rtx links;
-+ for (links = REG_NOTES (insn); links; links = XEXP (links, 1))
-+ {
-+ if ((REG_NOTE_KIND (links) == REG_EQUAL
-+ || REG_NOTE_KIND (links) == REG_EQUIV)
-+ && GET_CODE (XEXP (links, 0)) == PLUS
-+ && CONST_INT_P (XEXP (XEXP (links, 0), 1)))
-+ {
-+ plus_cst_src = XEXP (links, 0);
-+ break;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* Determine the effects of this insn on elimination offsets. */
-+ elimination_effects (old_body, VOIDmode);
-+
-+ /* Eliminate all eliminable registers occurring in operands that
-+ can be handled by reload. */
-+ extract_insn (insn);
-+ for (i = 0; i < recog_data.n_dups; i++)
-+ orig_dup[i] = *recog_data.dup_loc[i];
-+
-+ for (i = 0; i < recog_data.n_operands; i++)
-+ {
-+ orig_operand[i] = recog_data.operand[i];
-+
-+ /* For an asm statement, every operand is eliminable. */
-+ if (insn_is_asm || insn_data[icode].operand[i].eliminable)
-+ {
-+ bool is_set_src, in_plus;
-+
-+ /* Check for setting a register that we know about. */
-+ if (recog_data.operand_type[i] != OP_IN
-+ && REG_P (orig_operand[i]))
-+ {
-+ /* If we are assigning to a register that can be eliminated, it
-+ must be as part of a PARALLEL, since the code above handles
-+ single SETs. We must indicate that we can no longer
-+ eliminate this reg. */
-+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
-+ ep++)
-+ if (ep->from_rtx == orig_operand[i])
-+ ep->can_eliminate = 0;
-+ }
-+
-+ /* Companion to the above plus substitution, we can allow
-+ invariants as the source of a plain move. */
-+ is_set_src = false;
-+ if (old_set && recog_data.operand_loc[i] == &SET_SRC (old_set))
-+ is_set_src = true;
-+ if (is_set_src && !sets_reg_p)
-+ note_reg_elim_costly (&SET_SRC (old_set), insn);
-+ in_plus = false;
-+ if (plus_src && sets_reg_p
-+ && (recog_data.operand_loc[i] == &XEXP (plus_src, 0)
-+ || recog_data.operand_loc[i] == &XEXP (plus_src, 1)))
-+ in_plus = true;
-+
-+ eliminate_regs_1 (recog_data.operand[i], VOIDmode,
-+ NULL_RTX,
-+ is_set_src || in_plus, true);
-+ /* Terminate the search in check_eliminable_occurrences at
-+ this point. */
-+ *recog_data.operand_loc[i] = 0;
-+ }
-+ }
-+
-+ for (i = 0; i < recog_data.n_dups; i++)
-+ *recog_data.dup_loc[i]
-+ = *recog_data.operand_loc[(int) recog_data.dup_num[i]];
-+
-+ /* If any eliminable remain, they aren't eliminable anymore. */
-+ check_eliminable_occurrences (old_body);
-+
-+ /* Restore the old body. */
-+ for (i = 0; i < recog_data.n_operands; i++)
-+ *recog_data.operand_loc[i] = orig_operand[i];
-+ for (i = 0; i < recog_data.n_dups; i++)
-+ *recog_data.dup_loc[i] = orig_dup[i];
-+
-+ /* Update all elimination pairs to reflect the status after the current
-+ insn. The changes we make were determined by the earlier call to
-+ elimination_effects. */
-+
-+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-+ {
-+ if (ep->previous_offset != ep->offset && ep->ref_outside_mem)
-+ ep->can_eliminate = 0;
-+
-+ ep->ref_outside_mem = 0;
-+ }
-+
-+ return;
-+}
-+
- /* Loop through all elimination pairs.
- Recalculate the number not at initial offset.
-
-@@ -3907,6 +4074,168 @@
- ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
- }
- }
-+
-+/* Find all the pseudo registers that didn't get hard regs
-+ but do have known equivalent constants or memory slots.
-+ These include parameters (known equivalent to parameter slots)
-+ and cse'd or loop-moved constant memory addresses.
-+
-+ Record constant equivalents in reg_equiv_constant
-+ so they will be substituted by find_reloads.
-+ Record memory equivalents in reg_mem_equiv so they can
-+ be substituted eventually by altering the REG-rtx's. */
-+
-+static void
-+init_eliminable_invariants (rtx first, bool do_subregs)
-+{
-+ int i;
-+ rtx insn;
-+
-+ reg_equiv_constant = XCNEWVEC (rtx, max_regno);
-+ reg_equiv_invariant = XCNEWVEC (rtx, max_regno);
-+ reg_equiv_mem = XCNEWVEC (rtx, max_regno);
-+ reg_equiv_alt_mem_list = XCNEWVEC (rtx, max_regno);
-+ reg_equiv_address = XCNEWVEC (rtx, max_regno);
-+ if (do_subregs)
-+ reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
-+ else
-+ reg_max_ref_width = NULL;
-+
-+ num_eliminable_invariants = 0;
-+
-+ first_label_num = get_first_label_num ();
-+ num_labels = max_label_num () - first_label_num;
-+
-+ /* Allocate the tables used to store offset information at labels. */
-+ offsets_known_at = XNEWVEC (char, num_labels);
-+ offsets_at = (HOST_WIDE_INT (*)[NUM_ELIMINABLE_REGS]) xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT));
-+
-+/* Look for REG_EQUIV notes; record what each pseudo is equivalent
-+ to. If DO_SUBREGS is true, also find all paradoxical subregs and
-+ find largest such for each pseudo. FIRST is the head of the insn
-+ list. */
-+
-+ for (insn = first; insn; insn = NEXT_INSN (insn))
-+ {
-+ rtx set = single_set (insn);
-+
-+ /* We may introduce USEs that we want to remove at the end, so
-+ we'll mark them with QImode. Make sure there are no
-+ previously-marked insns left by say regmove. */
-+ if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
-+ && GET_MODE (insn) != VOIDmode)
-+ PUT_MODE (insn, VOIDmode);
-+
-+ if (do_subregs && NONDEBUG_INSN_P (insn))
-+ scan_paradoxical_subregs (PATTERN (insn));
-+
-+ if (set != 0 && REG_P (SET_DEST (set)))
-+ {
-+ rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
-+ rtx x;
-+
-+ if (! note)
-+ continue;
-+
-+ i = REGNO (SET_DEST (set));
-+ x = XEXP (note, 0);
-+
-+ if (i <= LAST_VIRTUAL_REGISTER)
-+ continue;
-+
-+ /* If flag_pic and we have constant, verify it's legitimate. */
-+ if (!CONSTANT_P (x)
-+ || !flag_pic || LEGITIMATE_PIC_OPERAND_P (x))
-+ {
-+ /* It can happen that a REG_EQUIV note contains a MEM
-+ that is not a legitimate memory operand. As later
-+ stages of reload assume that all addresses found
-+ in the reg_equiv_* arrays were originally legitimate,
-+ we ignore such REG_EQUIV notes. */
-+ if (memory_operand (x, VOIDmode))
-+ {
-+ /* Always unshare the equivalence, so we can
-+ substitute into this insn without touching the
-+ equivalence. */
-+ reg_equiv_memory_loc[i] = copy_rtx (x);
-+ }
-+ else if (function_invariant_p (x))
-+ {
-+ if (GET_CODE (x) == PLUS)
-+ {
-+ /* This is PLUS of frame pointer and a constant,
-+ and might be shared. Unshare it. */
-+ reg_equiv_invariant[i] = copy_rtx (x);
-+ num_eliminable_invariants++;
-+ }
-+ else if (x == frame_pointer_rtx || x == arg_pointer_rtx)
-+ {
-+ reg_equiv_invariant[i] = x;
-+ num_eliminable_invariants++;
-+ }
-+ else if (LEGITIMATE_CONSTANT_P (x))
-+ reg_equiv_constant[i] = x;
-+ else
-+ {
-+ reg_equiv_memory_loc[i]
-+ = force_const_mem (GET_MODE (SET_DEST (set)), x);
-+ if (! reg_equiv_memory_loc[i])
-+ reg_equiv_init[i] = NULL_RTX;
-+ }
-+ }
-+ else
-+ {
-+ reg_equiv_init[i] = NULL_RTX;
-+ continue;
-+ }
-+ }
-+ else
-+ reg_equiv_init[i] = NULL_RTX;
-+ }
-+ }
-+
-+ if (dump_file)
-+ for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-+ if (reg_equiv_init[i])
-+ {
-+ fprintf (dump_file, "init_insns for %u: ", i);
-+ print_inline_rtx (dump_file, reg_equiv_init[i], 20);
-+ fprintf (dump_file, "\n");
-+ }
-+}
-+
-+/* Indicate that we no longer have known memory locations or constants.
-+ Free all data involved in tracking these. */
-+
-+static void
-+free_reg_equiv (void)
-+{
-+ int i;
-+
-+ if (reg_equiv_constant)
-+ free (reg_equiv_constant);
-+ if (reg_equiv_invariant)
-+ free (reg_equiv_invariant);
-+ reg_equiv_constant = 0;
-+ reg_equiv_invariant = 0;
-+ VEC_free (rtx, gc, reg_equiv_memory_loc_vec);
-+ reg_equiv_memory_loc = 0;
-+
-+ if (offsets_known_at)
-+ free (offsets_known_at);
-+ if (offsets_at)
-+ free (offsets_at);
-+ offsets_at = 0;
-+ offsets_known_at = 0;
-+
-+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-+ if (reg_equiv_alt_mem_list[i])
-+ free_EXPR_LIST_list (&reg_equiv_alt_mem_list[i]);
-+ free (reg_equiv_alt_mem_list);
-+
-+ free (reg_equiv_mem);
-+ free (reg_equiv_address);
-+}
-
- /* Kick all pseudos out of hard register REGNO.
-
-@@ -5664,7 +5993,7 @@
- return 1;
- if (GET_CODE (x) == PLUS
- && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
-- && CONSTANT_P (XEXP (x, 1)))
-+ && GET_CODE (XEXP (x, 1)) == CONST_INT)
- return 1;
- return 0;
- }
-Index: gcc-4_5-branch/gcc/system.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/system.h 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/system.h 2012-03-06 12:14:01.060439213 -0800
-@@ -761,7 +761,8 @@
- TARGET_ASM_EXCEPTION_SECTION TARGET_ASM_EH_FRAME_SECTION \
- SMALL_ARG_MAX ASM_OUTPUT_SHARED_BSS ASM_OUTPUT_SHARED_COMMON \
- ASM_OUTPUT_SHARED_LOCAL ASM_MAKE_LABEL_LINKONCE \
-- STACK_CHECK_PROBE_INTERVAL STACK_CHECK_PROBE_LOAD
-+ STACK_CHECK_PROBE_INTERVAL STACK_CHECK_PROBE_LOAD \
-+ ORDER_REGS_FOR_LOCAL_ALLOC
-
- /* Hooks that are no longer used. */
- #pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \
-Index: gcc-4_5-branch/gcc/testsuite/c-c++-common/uninit-17.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/c-c++-common/uninit-17.c 2012-03-06 12:14:01.060439213 -0800
-@@ -0,0 +1,25 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2 -Wuninitialized" } */
-+
-+inline int foo(int x)
-+{
-+ return x;
-+}
-+static void bar(int a, int *ptr)
-+{
-+ do
-+ {
-+ int b; /* { dg-warning "is used uninitialized" } */
-+ if (b < 40) {
-+ ptr[0] = b;
-+ }
-+ b += 1;
-+ ptr++;
-+ }
-+ while (--a != 0);
-+}
-+void foobar(int a, int *ptr)
-+{
-+ bar(foo(a), ptr);
-+}
-+
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/arm/eliminate.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/arm/eliminate.c 2012-03-06 12:14:01.060439213 -0800
-@@ -0,0 +1,19 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2" } */
-+
-+struct X
-+{
-+ int c;
-+};
-+
-+extern void bar(struct X *);
-+
-+void foo ()
-+{
-+ struct X x;
-+ bar (&x);
-+ bar (&x);
-+ bar (&x);
-+}
-+
-+/* { dg-final { scan-assembler-times "r0,\[\\t \]*sp" 3 } } */
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/arm/pr40900.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/arm/pr40900.c 2012-03-06 12:14:01.060439213 -0800
-@@ -0,0 +1,12 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2 -fno-optimize-sibling-calls" } */
-+
-+extern short shortv2();
-+short shortv1()
-+{
-+ return shortv2();
-+}
-+
-+/* { dg-final { scan-assembler-not "lsl" } } */
-+/* { dg-final { scan-assembler-not "asr" } } */
-+/* { dg-final { scan-assembler-not "sxth" } } */
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/arm/pr42496.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/arm/pr42496.c 2012-03-06 12:14:01.060439213 -0800
-@@ -0,0 +1,16 @@
-+/* { dg-options "-O2" } */
-+
-+void foo(int i)
-+{
-+ extern int j;
-+
-+ if (i) {
-+ j = 10;
-+ }
-+ else {
-+ j = 20;
-+ }
-+}
-+
-+/* { dg-final { scan-assembler-not "strne" } } */
-+/* { dg-final { scan-assembler-not "streq" } } */
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/arm/wmul-1.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/arm/wmul-1.c 2012-03-06 12:14:01.060439213 -0800
-@@ -0,0 +1,18 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2 -march=armv6t2 -fno-unroll-loops" } */
-+
-+int mac(const short *a, const short *b, int sqr, int *sum)
-+{
-+ int i;
-+ int dotp = *sum;
-+
-+ for (i = 0; i < 150; i++) {
-+ dotp += b[i] * a[i];
-+ sqr += b[i] * b[i];
-+ }
-+
-+ *sum = dotp;
-+ return sqr;
-+}
-+
-+/* { dg-final { scan-assembler-times "smulbb" 2 } } */
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/arm/wmul-2.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/arm/wmul-2.c 2012-03-06 12:14:01.064439219 -0800
-@@ -0,0 +1,12 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2 -march=armv6t2 -fno-unroll-loops" } */
-+
-+void vec_mpy(int y[], const short x[], short scaler)
-+{
-+ int i;
-+
-+ for (i = 0; i < 150; i++)
-+ y[i] += ((scaler * x[i]) >> 31);
-+}
-+
-+/* { dg-final { scan-assembler-times "smulbb" 1 } } */
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/bfin/wmul-1.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/bfin/wmul-1.c 2012-03-06 12:14:01.064439219 -0800
-@@ -0,0 +1,18 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2" } */
-+
-+int mac(const short *a, const short *b, int sqr, int *sum)
-+{
-+ int i;
-+ int dotp = *sum;
-+
-+ for (i = 0; i < 150; i++) {
-+ dotp += b[i] * a[i];
-+ sqr += b[i] * b[i];
-+ }
-+
-+ *sum = dotp;
-+ return sqr;
-+}
-+
-+/* { dg-final { scan-assembler-times "\\(IS\\)" 2 } } */
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/bfin/wmul-2.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/bfin/wmul-2.c 2012-03-06 12:14:01.064439219 -0800
-@@ -0,0 +1,12 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2" } */
-+
-+void vec_mpy(int y[], const short x[], short scaler)
-+{
-+ int i;
-+
-+ for (i = 0; i < 150; i++)
-+ y[i] += ((scaler * x[i]) >> 31);
-+}
-+
-+/* { dg-final { scan-assembler-times "\\(IS\\)" 1 } } */
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/i386/pr41442.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/i386/pr41442.c 2012-03-06 12:14:01.064439219 -0800
-@@ -0,0 +1,18 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2" } */
-+
-+typedef struct LINK link;
-+struct LINK
-+{
-+ link* next;
-+};
-+
-+int haha(link* p1, link* p2)
-+{
-+ if ((p1->next && !p2->next) || p2->next)
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/* { dg-final { scan-assembler-times "test|cmp" 2 } } */
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/i386/wmul-1.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/i386/wmul-1.c 2012-03-06 12:14:01.064439219 -0800
-@@ -0,0 +1,18 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2" } */
-+
-+long long mac(const int *a, const int *b, long long sqr, long long *sum)
-+{
-+ int i;
-+ long long dotp = *sum;
-+
-+ for (i = 0; i < 150; i++) {
-+ dotp += (long long)b[i] * a[i];
-+ sqr += (long long)b[i] * b[i];
-+ }
-+
-+ *sum = dotp;
-+ return sqr;
-+}
-+
-+/* { dg-final { scan-assembler-times "imull" 2 } } */
-Index: gcc-4_5-branch/gcc/testsuite/gcc.target/i386/wmul-2.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/testsuite/gcc.target/i386/wmul-2.c 2012-03-06 12:14:01.064439219 -0800
-@@ -0,0 +1,12 @@
-+/* { dg-do compile } */
-+/* { dg-options "-O2" } */
-+
-+void vec_mpy(int y[], const int x[], int scaler)
-+{
-+ int i;
-+
-+ for (i = 0; i < 150; i++)
-+ y[i] += (((long long)scaler * x[i]) >> 31);
-+}
-+
-+/* { dg-final { scan-assembler-times "imull" 1 } } */
-Index: gcc-4_5-branch/gcc/tree-cfg.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/tree-cfg.c 2012-03-06 12:11:30.000000000 -0800
-+++ gcc-4_5-branch/gcc/tree-cfg.c 2012-03-06 12:14:01.064439219 -0800
-@@ -3429,8 +3429,13 @@
- connected to the operand types. */
- return verify_gimple_comparison (lhs_type, rhs1, rhs2);
-
-- case WIDEN_SUM_EXPR:
- case WIDEN_MULT_EXPR:
-+ if (TREE_CODE (lhs_type) != INTEGER_TYPE)
-+ return true;
-+ return ((2 * TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (lhs_type))
-+ || (TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type)));
-+
-+ case WIDEN_SUM_EXPR:
- case VEC_WIDEN_MULT_HI_EXPR:
- case VEC_WIDEN_MULT_LO_EXPR:
- case VEC_PACK_TRUNC_EXPR:
-Index: gcc-4_5-branch/gcc/tree-inline.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/tree-inline.c 2012-03-06 12:11:30.000000000 -0800
-+++ gcc-4_5-branch/gcc/tree-inline.c 2012-03-06 12:14:01.064439219 -0800
-@@ -229,6 +229,7 @@
- regions of the CFG, but this is expensive to test. */
- if (id->entry_bb
- && is_gimple_reg (SSA_NAME_VAR (name))
-+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name)
- && TREE_CODE (SSA_NAME_VAR (name)) != PARM_DECL
- && (id->entry_bb != EDGE_SUCC (ENTRY_BLOCK_PTR, 0)->dest
- || EDGE_COUNT (id->entry_bb->preds) != 1))
-Index: gcc-4_5-branch/gcc/tree-pass.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/tree-pass.h 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/tree-pass.h 2012-03-06 12:14:01.068439233 -0800
-@@ -407,6 +407,7 @@
- extern struct gimple_opt_pass pass_cse_reciprocals;
- extern struct gimple_opt_pass pass_cse_sincos;
- extern struct gimple_opt_pass pass_optimize_bswap;
-+extern struct gimple_opt_pass pass_optimize_widening_mul;
- extern struct gimple_opt_pass pass_warn_function_return;
- extern struct gimple_opt_pass pass_warn_function_noreturn;
- extern struct gimple_opt_pass pass_cselim;
-Index: gcc-4_5-branch/gcc/tree-ssa-math-opts.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/tree-ssa-math-opts.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/tree-ssa-math-opts.c 2012-03-06 12:14:01.068439233 -0800
-@@ -1269,3 +1269,137 @@
- 0 /* todo_flags_finish */
- }
- };
-+
-+/* Find integer multiplications where the operands are extended from
-+ smaller types, and replace the MULT_EXPR with a WIDEN_MULT_EXPR
-+ where appropriate. */
-+
-+static unsigned int
-+execute_optimize_widening_mul (void)
-+{
-+ bool changed = false;
-+ basic_block bb;
-+
-+ FOR_EACH_BB (bb)
-+ {
-+ gimple_stmt_iterator gsi;
-+
-+ for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-+ {
-+ gimple stmt = gsi_stmt (gsi);
-+ gimple rhs1_stmt = NULL, rhs2_stmt = NULL;
-+ tree type, type1 = NULL, type2 = NULL;
-+ tree rhs1, rhs2, rhs1_convop = NULL, rhs2_convop = NULL;
-+ enum tree_code rhs1_code, rhs2_code;
-+
-+ if (!is_gimple_assign (stmt)
-+ || gimple_assign_rhs_code (stmt) != MULT_EXPR)
-+ continue;
-+
-+ type = TREE_TYPE (gimple_assign_lhs (stmt));
-+
-+ if (TREE_CODE (type) != INTEGER_TYPE)
-+ continue;
-+
-+ rhs1 = gimple_assign_rhs1 (stmt);
-+ rhs2 = gimple_assign_rhs2 (stmt);
-+
-+ if (TREE_CODE (rhs1) == SSA_NAME)
-+ {
-+ rhs1_stmt = SSA_NAME_DEF_STMT (rhs1);
-+ if (!is_gimple_assign (rhs1_stmt))
-+ continue;
-+ rhs1_code = gimple_assign_rhs_code (rhs1_stmt);
-+ if (!CONVERT_EXPR_CODE_P (rhs1_code))
-+ continue;
-+ rhs1_convop = gimple_assign_rhs1 (rhs1_stmt);
-+ type1 = TREE_TYPE (rhs1_convop);
-+ if (TYPE_PRECISION (type1) * 2 != TYPE_PRECISION (type))
-+ continue;
-+ }
-+ else if (TREE_CODE (rhs1) != INTEGER_CST)
-+ continue;
-+
-+ if (TREE_CODE (rhs2) == SSA_NAME)
-+ {
-+ rhs2_stmt = SSA_NAME_DEF_STMT (rhs2);
-+ if (!is_gimple_assign (rhs2_stmt))
-+ continue;
-+ rhs2_code = gimple_assign_rhs_code (rhs2_stmt);
-+ if (!CONVERT_EXPR_CODE_P (rhs2_code))
-+ continue;
-+ rhs2_convop = gimple_assign_rhs1 (rhs2_stmt);
-+ type2 = TREE_TYPE (rhs2_convop);
-+ if (TYPE_PRECISION (type2) * 2 != TYPE_PRECISION (type))
-+ continue;
-+ }
-+ else if (TREE_CODE (rhs2) != INTEGER_CST)
-+ continue;
-+
-+ if (rhs1_stmt == NULL && rhs2_stmt == NULL)
-+ continue;
-+
-+ /* Verify that the machine can perform a widening multiply in this
-+ mode/signedness combination, otherwise this transformation is
-+ likely to pessimize code. */
-+ if ((rhs1_stmt == NULL || TYPE_UNSIGNED (type1))
-+ && (rhs2_stmt == NULL || TYPE_UNSIGNED (type2))
-+ && (optab_handler (umul_widen_optab, TYPE_MODE (type))
-+ ->insn_code == CODE_FOR_nothing))
-+ continue;
-+ else if ((rhs1_stmt == NULL || !TYPE_UNSIGNED (type1))
-+ && (rhs2_stmt == NULL || !TYPE_UNSIGNED (type2))
-+ && (optab_handler (smul_widen_optab, TYPE_MODE (type))
-+ ->insn_code == CODE_FOR_nothing))
-+ continue;
-+ else if (rhs1_stmt != NULL && rhs2_stmt != 0
-+ && (TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2))
-+ && (optab_handler (usmul_widen_optab, TYPE_MODE (type))
-+ ->insn_code == CODE_FOR_nothing))
-+ continue;
-+
-+ if ((rhs1_stmt == NULL && !int_fits_type_p (rhs1, type2))
-+ || (rhs2_stmt == NULL && !int_fits_type_p (rhs2, type1)))
-+ continue;
-+
-+ if (rhs1_stmt == NULL)
-+ gimple_assign_set_rhs1 (stmt, fold_convert (type2, rhs1));
-+ else
-+ gimple_assign_set_rhs1 (stmt, rhs1_convop);
-+ if (rhs2_stmt == NULL)
-+ gimple_assign_set_rhs2 (stmt, fold_convert (type1, rhs2));
-+ else
-+ gimple_assign_set_rhs2 (stmt, rhs2_convop);
-+ gimple_assign_set_rhs_code (stmt, WIDEN_MULT_EXPR);
-+ update_stmt (stmt);
-+ changed = true;
-+ }
-+ }
-+ return (changed ? TODO_dump_func | TODO_update_ssa | TODO_verify_ssa
-+ | TODO_verify_stmts : 0);
-+}
-+
-+static bool
-+gate_optimize_widening_mul (void)
-+{
-+ return flag_expensive_optimizations && optimize;
-+}
-+
-+struct gimple_opt_pass pass_optimize_widening_mul =
-+{
-+ {
-+ GIMPLE_PASS,
-+ "widening_mul", /* name */
-+ gate_optimize_widening_mul, /* gate */
-+ execute_optimize_widening_mul, /* execute */
-+ NULL, /* sub */
-+ NULL, /* next */
-+ 0, /* static_pass_number */
-+ TV_NONE, /* tv_id */
-+ PROP_ssa, /* properties_required */
-+ 0, /* properties_provided */
-+ 0, /* properties_destroyed */
-+ 0, /* todo_flags_start */
-+ 0 /* todo_flags_finish */
-+ }
-+};
-Index: gcc-4_5-branch/gcc/tree-ssa.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/tree-ssa.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/tree-ssa.c 2012-03-06 12:14:01.068439233 -0800
-@@ -1671,6 +1671,8 @@
- {
- TREE_NO_WARNING (var) = 1;
-
-+ if (location == DECL_SOURCE_LOCATION (var))
-+ return;
- if (xloc.file != floc.file
- || xloc.line < floc.line
- || xloc.line > LOCATION_LINE (cfun->function_end_locus))