On Tue, Dec 01, 2015 at 09:39:30PM -0600, Segher Boessenkool wrote: > On Wed, Dec 02, 2015 at 01:50:46PM +1030, Alan Modra wrote: > > On Wed, Dec 02, 2015 at 01:55:17AM +0000, Segher Boessenkool wrote: > > > + emit_insn (gen_subdi3 (tmp, op1, op2)); > > > + emit_insn (gen_lshrdi3 (tmp2, tmp, GEN_INT (63))); > > > + emit_insn (gen_anddi3 (tmp3, tmp2, const1_rtx)); > > > > Why the AND? The top 63 bits are already clear. > > Ha, yes. Thanks. In a previous version I shifted by less, in which > case GCC is smart enough to make it 63 anyway. 63 is always correct > as well, and simpler because you don't need the AND. But I forgot > to take it out :-)
For completeness, this is what I committed. Segher --- diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index a500d67..26b0962 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -10564,6 +10564,51 @@ (define_expand "cstore<mode>4_unsigned" DONE; }) +(define_expand "cstore_si_as_di" + [(use (match_operator 1 "unsigned_comparison_operator" + [(match_operand:SI 2 "gpc_reg_operand") + (match_operand:SI 3 "reg_or_short_operand")])) + (clobber (match_operand:SI 0 "register_operand"))] + "" +{ + int uns_flag = unsigned_comparison_operator (operands[1], VOIDmode) ? 1 : 0; + enum rtx_code cond_code = signed_condition (GET_CODE (operands[1])); + + rtx op1 = gen_reg_rtx (DImode); + rtx op2 = gen_reg_rtx (DImode); + convert_move (op1, operands[2], uns_flag); + convert_move (op2, operands[3], uns_flag); + + if (cond_code == GT || cond_code == LE) + { + cond_code = swap_condition (cond_code); + std::swap (op1, op2); + } + + rtx tmp = gen_reg_rtx (DImode); + rtx tmp2 = gen_reg_rtx (DImode); + emit_insn (gen_subdi3 (tmp, op1, op2)); + emit_insn (gen_lshrdi3 (tmp2, tmp, GEN_INT (63))); + + rtx tmp3; + switch (cond_code) + { + default: + gcc_unreachable (); + case LT: + tmp3 = tmp2; + break; + case GE: + tmp3 = gen_reg_rtx (DImode); + emit_insn (gen_xordi3 (tmp3, tmp2, const1_rtx)); + break; + } + + convert_move (operands[0], tmp3, 1); + + DONE; +}) + (define_expand "cstore<mode>4_signed_imm" [(use (match_operator 1 "signed_comparison_operator" [(match_operand:GPR 2 "gpc_reg_operand") @@ -10688,6 +10733,11 @@ (define_expand "cstore<mode>4" emit_insn (gen_cstore<mode>4_unsigned (operands[0], operands[1], operands[2], operands[3])); + /* For comparisons smaller than Pmode we can cheaply do things in Pmode. */ + else if (<MODE>mode == SImode && Pmode == DImode) + emit_insn (gen_cstore_si_as_di (operands[0], operands[1], + operands[2], operands[3])); + /* For signed comparisons against a constant, we can do some simple bit-twiddling. */ else if (signed_comparison_operator (operands[1], VOIDmode) -- 1.9.3