void func_fma_steering::analyze () { int i, n_blocks, *bb_dfs_preorder; basic_block bb; rtx_insn *insn; bb_dfs_preorder = XNEWVEC (int, last_basic_block_for_fn (cfun)); n_blocks = pre_and_rev_post_order_compute (bb_dfs_preorder, NULL, false); /* Browse the graph of basic blocks looking for FMUL or FMADD/FMSUB instructions. */ for (i = 0; i < n_blocks; i++) { bb = BASIC_BLOCK_FOR_FN (cfun, bb_dfs_preorder[i]); FOR_BB_INSNS (bb, insn) { operand_rr_info *dest_op_info; struct du_chain *chain; unsigned dest_regno; fma_forest *forest; du_head_p head; int i; if (!is_fmul_fmac_insn (insn, true)) continue; /* Search the chain where this instruction is (one of) the root. */ dest_op_info = insn_rr[INSN_UID (insn)].op_info; dest_regno = REGNO (SET_DEST (PATTERN (insn))); for (i = 0; i < dest_op_info->n_chains; i++) { /* The register tracked by this chain does not match the destination register of insn. */ if (dest_op_info->heads[i]->regno != dest_regno) continue; head = dest_op_info->heads[i]; /* The chain was merged in another, find the new head. */ if (!head->first) head = regrename_chain_from_id (head->id); /* Search the chain element for this instruction and, if another FMUL or FMADD/FMSUB instruction was already processed, note the forest of its tree. */ forest = NULL; for (chain = head->first; chain; chain = chain->next_use) { fma_node **fma_slot; if (!is_fmul_fmac_insn (chain->insn, true)) continue; /* This is a use, continue. */ if (chain->loc != &SET_DEST (PATTERN (chain->insn))) continue; if (chain->insn == insn) break; fma_slot = this->m_insn_fma_head_map->get (chain->insn); if (fma_slot && (*fma_slot)->get_children ()) forest = (*fma_slot)->get_forest (); } if (chain) break; } /* We didn't find a chain with a def for this instruction. */ gcc_assert (i < dest_op_info->n_chains); this->analyze_fma_fmul_insn (forest, chain, head); } }
void func_fma_steering::analyze () { int i, n_blocks, *bb_dfs_preorder; basic_block bb; rtx_insn *insn; bb_dfs_preorder = XNEWVEC (int, last_basic_block_for_fn (cfun)); n_blocks = pre_and_rev_post_order_compute (bb_dfs_preorder, NULL, false); /* Browse the graph of basic blocks looking for FMUL or FMADD/FMSUB instructions. */ for (i = 0; i < n_blocks; i++) { bb = BASIC_BLOCK_FOR_FN (cfun, bb_dfs_preorder[i]); FOR_BB_INSNS (bb, insn) { operand_rr_info *dest_op_info; struct du_chain *chain = NULL; unsigned dest_regno; fma_forest *forest = NULL; du_head_p head = NULL; int i; if (!is_fmul_fmac_insn (insn, true)) continue; /* Search the chain where this instruction is (one of) the root. */ dest_op_info = insn_rr[INSN_UID (insn)].op_info; dest_regno = REGNO (SET_DEST (PATTERN (insn))); for (i = 0; i < dest_op_info->n_chains; i++) { /* The register tracked by this chain does not match the destination register of insn. */ if (dest_op_info->heads[i]->regno != dest_regno) continue; head = dest_op_info->heads[i]; /* The chain was merged in another, find the new head. */ if (!head->first) head = regrename_chain_from_id (head->id); /* Search the chain element for this instruction and, if another FMUL or FMADD/FMSUB instruction was already processed, note the forest of its tree. */ forest = NULL; for (chain = head->first; chain; chain = chain->next_use) { fma_node **fma_slot; if (!is_fmul_fmac_insn (chain->insn, true)) continue; /* This is a use, continue. */ if (chain->loc != &SET_DEST (PATTERN (chain->insn))) continue; if (chain->insn == insn) break; fma_slot = this->m_insn_fma_head_map->get (chain->insn); if (fma_slot && (*fma_slot)->get_children ()) forest = (*fma_slot)->get_forest (); } if (chain) break; } /* Due to implementation of regrename, dest register can slip away from regrename's analysis. As a result, there is no chain for the destination register of insn. We simply skip the insn even it is a fmul/fmac instruction. This can happen when the dest register is also a source register of insn and one of the below conditions is satisfied: 1) the source reg is setup in larger mode than this insn; 2) the source reg is uninitialized; 3) the source reg is passed in as parameter. */ if (i < dest_op_info->n_chains) this->analyze_fma_fmul_insn (forest, chain, head); } }