diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 153 |
1 files changed, 61 insertions, 92 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 8e24769..2d34b14 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -190,11 +190,6 @@ int rs6000_darwin64_abi; /* Set to nonzero once AIX common-mode calls have been defined. */ static GTY(()) int common_mode_defined; -/* Save information from a "cmpxx" operation until the branch or scc is - emitted. */ -rtx rs6000_compare_op0, rs6000_compare_op1; -int rs6000_compare_fp_p; - /* Label number of label created for -mrelocatable, to call to so we can get the address of the GOT section */ int rs6000_pic_labelno; @@ -752,7 +747,7 @@ struct processor_costs power6_cost = { static bool rs6000_function_ok_for_sibcall (tree, tree); static const char *rs6000_invalid_within_doloop (const_rtx); -static rtx rs6000_generate_compare (enum rtx_code); +static rtx rs6000_generate_compare (rtx, enum machine_mode); static void rs6000_emit_stack_tie (void); static void rs6000_frame_related (rtx, rtx, HOST_WIDE_INT, rtx, rtx); static bool spe_func_has_64bit_regs_p (void); @@ -12788,21 +12783,24 @@ rs6000_reverse_condition (enum machine_mode mode, enum rtx_code code) represents the result of the compare. */ static rtx -rs6000_generate_compare (enum rtx_code code) +rs6000_generate_compare (rtx cmp, enum machine_mode mode) { enum machine_mode comp_mode; rtx compare_result; + enum rtx_code code = GET_CODE (cmp); + rtx op0 = XEXP (cmp, 0); + rtx op1 = XEXP (cmp, 1); - if (rs6000_compare_fp_p) + if (FLOAT_MODE_P (mode)) comp_mode = CCFPmode; else if (code == GTU || code == LTU || code == GEU || code == LEU) comp_mode = CCUNSmode; else if ((code == EQ || code == NE) - && GET_CODE (rs6000_compare_op0) == SUBREG - && GET_CODE (rs6000_compare_op1) == SUBREG - && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op0) - && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op1)) + && GET_CODE (op0) == SUBREG + && GET_CODE (op1) == SUBREG + && SUBREG_PROMOTED_UNSIGNED_P (op0) + && SUBREG_PROMOTED_UNSIGNED_P (op1)) /* These are unsigned values, perhaps there will be a later ordering compare that can be shared with this one. Unfortunately we cannot detect the signedness of the operands @@ -12816,13 +12814,13 @@ rs6000_generate_compare (enum rtx_code code) /* E500 FP compare instructions on the GPRs. Yuck! */ if ((!TARGET_FPRS && TARGET_HARD_FLOAT) - && rs6000_compare_fp_p) + && FLOAT_MODE_P (mode)) { rtx cmp, or_result, compare_result2; - enum machine_mode op_mode = GET_MODE (rs6000_compare_op0); + enum machine_mode op_mode = GET_MODE (op0); if (op_mode == VOIDmode) - op_mode = GET_MODE (rs6000_compare_op1); + op_mode = GET_MODE (op1); /* The E500 FP compare instructions toggle the GT bit (CR bit 1) only. This explains the following mess. */ @@ -12834,26 +12832,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsfeq_gpr (compare_result, op0, op1) + : gen_cmpsfeq_gpr (compare_result, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdfeq_gpr (compare_result, op0, op1) + : gen_cmpdfeq_gpr (compare_result, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttfeq_gpr (compare_result, op0, op1) + : gen_cmptfeq_gpr (compare_result, op0, op1); break; default: @@ -12866,26 +12858,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsfgt_gpr (compare_result, op0, op1) + : gen_cmpsfgt_gpr (compare_result, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdfgt_gpr (compare_result, op0, op1) + : gen_cmpdfgt_gpr (compare_result, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttfgt_gpr (compare_result, op0, op1) + : gen_cmptfgt_gpr (compare_result, op0, op1); break; default: @@ -12898,26 +12884,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsflt_gpr (compare_result, op0, op1) + : gen_cmpsflt_gpr (compare_result, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdflt_gpr (compare_result, op0, op1) + : gen_cmpdflt_gpr (compare_result, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttflt_gpr (compare_result, op0, op1) + : gen_cmptflt_gpr (compare_result, op0, op1); break; default: @@ -12949,26 +12929,20 @@ rs6000_generate_compare (enum rtx_code code) { case SFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstsfeq_gpr (compare_result2, op0, op1) + : gen_cmpsfeq_gpr (compare_result2, op0, op1); break; case DFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tstdfeq_gpr (compare_result2, op0, op1) + : gen_cmpdfeq_gpr (compare_result2, op0, op1); break; case TFmode: cmp = (flag_finite_math_only && !flag_trapping_math) - ? gen_tsttfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmptfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + ? gen_tsttfeq_gpr (compare_result2, op0, op1) + : gen_cmptfeq_gpr (compare_result2, op0, op1); break; default: @@ -12998,16 +12972,14 @@ rs6000_generate_compare (enum rtx_code code) /* Generate XLC-compatible TFmode compare as PARALLEL with extra CLOBBERs to match cmptf_internal2 pattern. */ if (comp_mode == CCFPmode && TARGET_XL_COMPAT - && GET_MODE (rs6000_compare_op0) == TFmode + && GET_MODE (op0) == TFmode && !TARGET_IEEEQUAD && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128) emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (9, gen_rtx_SET (VOIDmode, compare_result, - gen_rtx_COMPARE (comp_mode, - rs6000_compare_op0, - rs6000_compare_op1)), + gen_rtx_COMPARE (comp_mode, op0, op1)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), @@ -13016,29 +12988,25 @@ rs6000_generate_compare (enum rtx_code code) gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)), gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode))))); - else if (GET_CODE (rs6000_compare_op1) == UNSPEC - && XINT (rs6000_compare_op1, 1) == UNSPEC_SP_TEST) + else if (GET_CODE (op1) == UNSPEC + && XINT (op1, 1) == UNSPEC_SP_TEST) { - rtx op1 = XVECEXP (rs6000_compare_op1, 0, 0); + rtx op1 = XVECEXP (op1, 0, 0); comp_mode = CCEQmode; compare_result = gen_reg_rtx (CCEQmode); if (TARGET_64BIT) - emit_insn (gen_stack_protect_testdi (compare_result, - rs6000_compare_op0, op1)); + emit_insn (gen_stack_protect_testdi (compare_result, op0, op1)); else - emit_insn (gen_stack_protect_testsi (compare_result, - rs6000_compare_op0, op1)); + emit_insn (gen_stack_protect_testsi (compare_result, op0, op1)); } else emit_insn (gen_rtx_SET (VOIDmode, compare_result, - gen_rtx_COMPARE (comp_mode, - rs6000_compare_op0, - rs6000_compare_op1))); + gen_rtx_COMPARE (comp_mode, op0, op1))); } /* Some kinds of FP comparisons need an OR operation; under flag_finite_math_only we don't bother. */ - if (rs6000_compare_fp_p + if (FLOAT_MODE_P (mode) && !flag_finite_math_only && !(TARGET_HARD_FLOAT && !TARGET_FPRS) && (code == LE || code == GE @@ -13081,16 +13049,17 @@ rs6000_generate_compare (enum rtx_code code) /* Emit the RTL for an sCOND pattern. */ void -rs6000_emit_sCOND (enum rtx_code code, rtx result) +rs6000_emit_sCOND (enum machine_mode mode, rtx operands[]) { rtx condition_rtx; enum machine_mode op_mode; enum rtx_code cond_code; + rtx result = operands[0]; - condition_rtx = rs6000_generate_compare (code); + condition_rtx = rs6000_generate_compare (operands[1], mode); cond_code = GET_CODE (condition_rtx); - if (rs6000_compare_fp_p + if (FLOAT_MODE_P (mode) && !TARGET_FPRS && TARGET_HARD_FLOAT) { rtx t; @@ -13125,11 +13094,11 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result) condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx); } - op_mode = GET_MODE (rs6000_compare_op0); + op_mode = GET_MODE (XEXP (operands[1], 0)); if (op_mode == VOIDmode) - op_mode = GET_MODE (rs6000_compare_op1); + op_mode = GET_MODE (XEXP (operands[1], 1)); - if (TARGET_POWERPC64 && (op_mode == DImode || rs6000_compare_fp_p)) + if (TARGET_POWERPC64 && (op_mode == DImode || FLOAT_MODE_P (mode))) { PUT_MODE (condition_rtx, DImode); convert_move (result, condition_rtx, 0); @@ -13144,12 +13113,12 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result) /* Emit a branch of kind CODE to location LOC. */ void -rs6000_emit_cbranch (enum rtx_code code, rtx loc) +rs6000_emit_cbranch (enum machine_mode mode, rtx operands[]) { rtx condition_rtx, loc_ref; - condition_rtx = rs6000_generate_compare (code); - loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc); + condition_rtx = rs6000_generate_compare (operands[0], mode); + loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx, loc_ref, pc_rtx))); @@ -13595,8 +13564,8 @@ int rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) { enum rtx_code code = GET_CODE (op); - rtx op0 = rs6000_compare_op0; - rtx op1 = rs6000_compare_op1; + rtx op0 = XEXP (op, 0); + rtx op1 = XEXP (op, 1); REAL_VALUE_TYPE c1; enum machine_mode compare_mode = GET_MODE (op0); enum machine_mode result_mode = GET_MODE (dest); @@ -13616,7 +13585,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) /* First, work out if the hardware can do this at all, or if it's too slow.... */ - if (! rs6000_compare_fp_p) + if (!FLOAT_MODE_P (compare_mode)) { if (TARGET_ISEL) return rs6000_emit_int_cmove (dest, op, true_cond, false_cond); @@ -13781,13 +13750,13 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) rtx condition_rtx, cr; /* All isel implementations thus far are 32-bits. */ - if (GET_MODE (rs6000_compare_op0) != SImode) + if (GET_MODE (XEXP (op, 0)) != SImode) return 0; /* We still have to do the compare, because isel doesn't do a compare, it just looks at the CRx bits set by a previous compare instruction. */ - condition_rtx = rs6000_generate_compare (GET_CODE (op)); + condition_rtx = rs6000_generate_compare (op, SImode); cr = XEXP (condition_rtx, 0); if (GET_MODE (cr) == CCmode) |