static bool transform_ifelse (ext_cand *cand, rtx def_insn) { rtx set_insn = PATTERN (def_insn); rtx srcreg, dstreg, srcreg2; rtx map_srcreg, map_dstreg, map_srcreg2; rtx ifexpr; rtx cond; rtx new_set; gcc_assert (GET_CODE (set_insn) == SET); cond = XEXP (SET_SRC (set_insn), 0); dstreg = SET_DEST (set_insn); srcreg = XEXP (SET_SRC (set_insn), 1); srcreg2 = XEXP (SET_SRC (set_insn), 2); /* If the conditional move already has the right or wider mode, there is nothing to do. */ if (GET_MODE_SIZE (GET_MODE (dstreg)) >= GET_MODE_SIZE (cand->mode)) return true; map_srcreg = gen_rtx_REG (cand->mode, REGNO (srcreg)); map_srcreg2 = gen_rtx_REG (cand->mode, REGNO (srcreg2)); map_dstreg = gen_rtx_REG (cand->mode, REGNO (dstreg)); ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2); new_set = gen_rtx_SET (VOIDmode, map_dstreg, ifexpr); if (validate_change (def_insn, &PATTERN (def_insn), new_set, true) && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg), cand->code)) { if (dump_file) { fprintf (dump_file, "Mode of conditional move instruction extended:\n"); print_rtl_single (dump_file, def_insn); } return true; } return false; }
static bool combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set) { rtx orig_src = SET_SRC (*orig_set); enum machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set)); rtx new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set))); rtx new_set; /* Merge constants by directly moving the constant into the register under some conditions. Recall that RTL constants are sign-extended. */ if (GET_CODE (orig_src) == CONST_INT && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (cand->mode)) { if (INTVAL (orig_src) >= 0 || cand->code == SIGN_EXTEND) new_set = gen_rtx_SET (VOIDmode, new_reg, orig_src); else { /* Zero-extend the negative constant by masking out the bits outside the source mode. */ rtx new_const_int = GEN_INT (INTVAL (orig_src) & GET_MODE_MASK (orig_mode)); new_set = gen_rtx_SET (VOIDmode, new_reg, new_const_int); } } else if (GET_MODE (orig_src) == VOIDmode) { /* This is mostly due to a call insn that should not be optimized. */ return false; } else if (GET_CODE (orig_src) == cand->code) { /* Here is a sequence of two extensions. Try to merge them. */ rtx temp_extension = gen_rtx_fmt_e (cand->code, cand->mode, XEXP (orig_src, 0)); rtx simplified_temp_extension = simplify_rtx (temp_extension); if (simplified_temp_extension) temp_extension = simplified_temp_extension; new_set = gen_rtx_SET (VOIDmode, new_reg, temp_extension); } else if (GET_CODE (orig_src) == IF_THEN_ELSE) { /* Only IF_THEN_ELSE of phi-type copies are combined. Otherwise, in general, IF_THEN_ELSE should not be combined. */ return false; } else { /* This is the normal case. */ rtx temp_extension = gen_rtx_fmt_e (cand->code, cand->mode, orig_src); rtx simplified_temp_extension = simplify_rtx (temp_extension); if (simplified_temp_extension) temp_extension = simplified_temp_extension; new_set = gen_rtx_SET (VOIDmode, new_reg, temp_extension); } /* This change is a part of a group of changes. Hence, validate_change will not try to commit the change. */ if (validate_change (curr_insn, orig_set, new_set, true) && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode, cand->code)) { if (dump_file) { fprintf (dump_file, "Tentatively merged extension with definition:\n"); print_rtl_single (dump_file, curr_insn); } return true; } return false; }
static bool combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set) { rtx orig_src = SET_SRC (*orig_set); machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set)); rtx new_set; rtx cand_pat = PATTERN (cand->insn); /* If the extension's source/destination registers are not the same then we need to change the original load to reference the destination of the extension. Then we need to emit a copy from that destination to the original destination of the load. */ rtx new_reg; bool copy_needed = (REGNO (SET_DEST (cand_pat)) != REGNO (XEXP (SET_SRC (cand_pat), 0))); if (copy_needed) new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (cand_pat))); else new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set))); #if 0 /* Rethinking test. Temporarily disabled. */ /* We're going to be widening the result of DEF_INSN, ensure that doing so doesn't change the number of hard registers needed for the result. */ if (HARD_REGNO_NREGS (REGNO (new_reg), cand->mode) != HARD_REGNO_NREGS (REGNO (SET_DEST (*orig_set)), GET_MODE (SET_DEST (*orig_set)))) return false; #endif /* Merge constants by directly moving the constant into the register under some conditions. Recall that RTL constants are sign-extended. */ if (GET_CODE (orig_src) == CONST_INT && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (cand->mode)) { if (INTVAL (orig_src) >= 0 || cand->code == SIGN_EXTEND) new_set = gen_rtx_SET (new_reg, orig_src); else { /* Zero-extend the negative constant by masking out the bits outside the source mode. */ rtx new_const_int = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (orig_mode), GET_MODE (new_reg)); new_set = gen_rtx_SET (new_reg, new_const_int); } } else if (GET_MODE (orig_src) == VOIDmode) { /* This is mostly due to a call insn that should not be optimized. */ return false; } else if (GET_CODE (orig_src) == cand->code) { /* Here is a sequence of two extensions. Try to merge them. */ rtx temp_extension = gen_rtx_fmt_e (cand->code, cand->mode, XEXP (orig_src, 0)); rtx simplified_temp_extension = simplify_rtx (temp_extension); if (simplified_temp_extension) temp_extension = simplified_temp_extension; new_set = gen_rtx_SET (new_reg, temp_extension); } else if (GET_CODE (orig_src) == IF_THEN_ELSE) { /* Only IF_THEN_ELSE of phi-type copies are combined. Otherwise, in general, IF_THEN_ELSE should not be combined. */ return false; } else { /* This is the normal case. */ rtx temp_extension = gen_rtx_fmt_e (cand->code, cand->mode, orig_src); rtx simplified_temp_extension = simplify_rtx (temp_extension); if (simplified_temp_extension) temp_extension = simplified_temp_extension; new_set = gen_rtx_SET (new_reg, temp_extension); } /* This change is a part of a group of changes. Hence, validate_change will not try to commit the change. */ if (validate_change (curr_insn, orig_set, new_set, true) && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode, cand->code)) { if (dump_file) { fprintf (dump_file, "Tentatively merged extension with definition %s:\n", (copy_needed) ? "(copy needed)" : ""); print_rtl_single (dump_file, curr_insn); } return true; } return false; }