diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d9a0bf89569..1f108e7339a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2015-12-04 Segher Boessenkool + + * (cstore4_signed): New expander. + (cstore4): Call it. + 2015-12-04 Jakub Jelinek * tree-tailcall.c (find_tail_calls): Ignore GIMPLE_NOPs. diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 26b0962ae7d..f346cba8e08 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -10525,6 +10525,47 @@ DONE; }") +(define_expand "cstore4_signed" + [(use (match_operator 1 "signed_comparison_operator" + [(match_operand:P 2 "gpc_reg_operand") + (match_operand:P 3 "gpc_reg_operand")])) + (clobber (match_operand:P 0 "gpc_reg_operand"))] + "" +{ + enum rtx_code cond_code = GET_CODE (operands[1]); + + rtx op0 = operands[0]; + rtx op1 = operands[2]; + rtx op2 = operands[3]; + + if (cond_code == GE || cond_code == LT) + { + cond_code = swap_condition (cond_code); + std::swap (op1, op2); + } + + rtx tmp1 = gen_reg_rtx (mode); + rtx tmp2 = gen_reg_rtx (mode); + rtx tmp3 = gen_reg_rtx (mode); + + int sh = GET_MODE_BITSIZE (mode) - 1; + emit_insn (gen_lshr3 (tmp1, op1, GEN_INT (sh))); + emit_insn (gen_ashr3 (tmp2, op2, GEN_INT (sh))); + + emit_insn (gen_subf3_carry (tmp3, op1, op2)); + + if (cond_code == LE) + emit_insn (gen_add3_carry_in (op0, tmp1, tmp2)); + else + { + rtx tmp4 = gen_reg_rtx (mode); + emit_insn (gen_add3_carry_in (tmp4, tmp1, tmp2)); + emit_insn (gen_xor3 (op0, tmp4, const1_rtx)); + } + + DONE; +}) + (define_expand "cstore4_unsigned" [(use (match_operator 1 "unsigned_comparison_operator" [(match_operand:P 2 "gpc_reg_operand" "") @@ -10751,6 +10792,12 @@ emit_insn (gen_cstore4_unsigned_imm (operands[0], operands[1], operands[2], operands[3])); + /* We also do not want to use mfcr for signed comparisons. */ + else if (mode == Pmode + && signed_comparison_operator (operands[1], VOIDmode)) + emit_insn (gen_cstore4_signed (operands[0], operands[1], + operands[2], operands[3])); + /* Everything else, use the mfcr brute force. */ else rs6000_emit_sCOND (mode, operands);