+ Construct a CFG and run life analysis. Then convert each insn one
+ by one. Run a last cleanup_cfg pass, if optimizing, to eliminate
+ code duplication created when the converter inserts pop insns on
+ the edges. */
+
+static bool
+reg_to_stack (void)
+{
+ basic_block bb;
+ int i;
+ int max_uid;
+
+ /* Clean up previous run. */
+ if (stack_regs_mentioned_data != NULL)
+ VEC_free (char, heap, stack_regs_mentioned_data);
+
+ /* See if there is something to do. Flow analysis is quite
+ expensive so we might save some compilation time. */
+ for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
+ if (regs_ever_live[i])
+ break;
+ if (i > LAST_STACK_REG)
+ return false;
+
+ /* Ok, floating point instructions exist. If not optimizing,
+ build the CFG and run life analysis.
+ Also need to rebuild life when superblock scheduling is done
+ as it don't update liveness yet. */
+ if (!optimize
+ || ((flag_sched2_use_superblocks || flag_sched2_use_traces)
+ && flag_schedule_insns_after_reload))
+ {
+ count_or_remove_death_notes (NULL, 1);
+ life_analysis (PROP_DEATH_NOTES);
+ }
+ mark_dfs_back_edges ();
+
+ /* Set up block info for each basic block. */
+ alloc_aux_for_blocks (sizeof (struct block_info_def));
+ FOR_EACH_BB (bb)
+ {
+ block_info bi = BLOCK_INFO (bb);
+ edge_iterator ei;
+ edge e;
+ int reg;
+
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!(e->flags & EDGE_DFS_BACK)
+ && e->src != ENTRY_BLOCK_PTR)
+ bi->predecessors++;
+
+ /* Set current register status at last instruction `uninitialized'. */
+ bi->stack_in.top = -2;
+
+ /* Copy live_at_end and live_at_start into temporaries. */
+ for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
+ {
+ if (REGNO_REG_SET_P (bb->il.rtl->global_live_at_end, reg))
+ SET_HARD_REG_BIT (bi->out_reg_set, reg);
+ if (REGNO_REG_SET_P (bb->il.rtl->global_live_at_start, reg))
+ SET_HARD_REG_BIT (bi->stack_in.reg_set, reg);
+ }
+ }
+
+ /* Create the replacement registers up front. */
+ for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
+ {
+ enum machine_mode mode;
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
+ }
+
+ ix86_flags_rtx = gen_rtx_REG (CCmode, FLAGS_REG);
+
+ /* A QNaN for initializing uninitialized variables.
+
+ ??? We can't load from constant memory in PIC mode, because
+ we're inserting these instructions before the prologue and
+ the PIC register hasn't been set up. In that case, fall back
+ on zero, which we can get from `ldz'. */
+
+ if ((flag_pic && !TARGET_64BIT)
+ || ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
+ not_a_num = CONST0_RTX (SFmode);
+ else
+ {
+ not_a_num = gen_lowpart (SFmode, GEN_INT (0x7fc00000));
+ not_a_num = force_const_mem (SFmode, not_a_num);
+ }
+
+ /* Allocate a cache for stack_regs_mentioned. */
+ max_uid = get_max_uid ();
+ stack_regs_mentioned_data = VEC_alloc (char, heap, max_uid + 1);
+ memset (VEC_address (char, stack_regs_mentioned_data),
+ 0, sizeof (char) * max_uid + 1);
+
+ convert_regs ();
+
+ free_aux_for_blocks ();
+ return true;