diff options
author | Segher Boessenkool <segher@kernel.crashing.org> | 2015-05-06 17:55:10 +0200 |
---|---|---|
committer | Segher Boessenkool <segher@gcc.gnu.org> | 2015-05-06 17:55:10 +0200 |
commit | 29e597d0e6c853b1487ee86357df704a5e0ab618 (patch) | |
tree | f9babee25f5605f87d2df60a8e17cafe17462c8d | |
parent | 93e956161e843aecdd9ad07574132efb3616d549 (diff) | |
download | gcc-29e597d0e6c853b1487ee86357df704a5e0ab618.tar.gz |
rs6000.md (cstore<mode>4_signed_imm): New expander.
* config/rs6000/rs6000.md (cstore<mode>4_signed_imm): New expander.
(cstore<mode>4_unsigned_imm): New expander.
(cstore<mode>4): Remove empty constraint strings. Use the new
expanders.
From-SVN: r222855
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 113 |
2 files changed, 113 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f7188b26496..3b267c8d3a3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-05-06 Segher Boessenkool <segher@kernel.crashing.org> + + * config/rs6000/rs6000.md (cstore<mode>4_signed_imm): New expander. + (cstore<mode>4_unsigned_imm): New expander. + (cstore<mode>4): Remove empty constraint strings. Use the new + expanders. + 2015-05-06 Yvan Roux <yvan.roux@linaro.org> PR target/64208 diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 2d15d71cc88..7fc2bb1b4ad 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -11787,10 +11787,102 @@ DONE; }) +(define_expand "cstore<mode>4_signed_imm" + [(use (match_operator 1 "signed_comparison_operator" + [(match_operand:GPR 2 "gpc_reg_operand") + (match_operand:GPR 3 "immediate_operand")])) + (clobber (match_operand:GPR 0 "register_operand"))] + "" +{ + bool invert = false; + + enum rtx_code cond_code = GET_CODE (operands[1]); + + rtx op0 = operands[0]; + rtx op1 = operands[2]; + HOST_WIDE_INT val = INTVAL (operands[3]); + + if (cond_code == GE || cond_code == GT) + { + cond_code = reverse_condition (cond_code); + invert = true; + } + + if (cond_code == LE) + val++; + + rtx tmp = gen_reg_rtx (<MODE>mode); + emit_insn (gen_add<mode>3 (tmp, op1, GEN_INT (-val))); + rtx x = gen_reg_rtx (<MODE>mode); + if (val < 0) + emit_insn (gen_and<mode>3 (x, op1, tmp)); + else + emit_insn (gen_ior<mode>3 (x, op1, tmp)); + + if (invert) + { + rtx tmp = gen_reg_rtx (<MODE>mode); + emit_insn (gen_one_cmpl<mode>2 (tmp, x)); + x = tmp; + } + + int sh = GET_MODE_BITSIZE (<MODE>mode) - 1; + emit_insn (gen_lshr<mode>3 (op0, x, GEN_INT (sh))); + + DONE; +}) + +(define_expand "cstore<mode>4_unsigned_imm" + [(use (match_operator 1 "unsigned_comparison_operator" + [(match_operand:GPR 2 "gpc_reg_operand") + (match_operand:GPR 3 "immediate_operand")])) + (clobber (match_operand:GPR 0 "register_operand"))] + "" +{ + bool invert = false; + + enum rtx_code cond_code = GET_CODE (operands[1]); + + rtx op0 = operands[0]; + rtx op1 = operands[2]; + HOST_WIDE_INT val = INTVAL (operands[3]); + + if (cond_code == GEU || cond_code == GTU) + { + cond_code = reverse_condition (cond_code); + invert = true; + } + + if (cond_code == LEU) + val++; + + rtx tmp = gen_reg_rtx (<MODE>mode); + rtx tmp2 = gen_reg_rtx (<MODE>mode); + emit_insn (gen_add<mode>3 (tmp, op1, GEN_INT (-val))); + emit_insn (gen_one_cmpl<mode>2 (tmp2, op1)); + rtx x = gen_reg_rtx (<MODE>mode); + if (val < 0) + emit_insn (gen_ior<mode>3 (x, tmp, tmp2)); + else + emit_insn (gen_and<mode>3 (x, tmp, tmp2)); + + if (invert) + { + rtx tmp = gen_reg_rtx (<MODE>mode); + emit_insn (gen_one_cmpl<mode>2 (tmp, x)); + x = tmp; + } + + int sh = GET_MODE_BITSIZE (<MODE>mode) - 1; + emit_insn (gen_lshr<mode>3 (op0, x, GEN_INT (sh))); + + DONE; +}) + (define_expand "cstore<mode>4" [(use (match_operator 1 "rs6000_cbranch_operator" - [(match_operand:GPR 2 "gpc_reg_operand" "") - (match_operand:GPR 3 "reg_or_short_operand" "")])) + [(match_operand:GPR 2 "gpc_reg_operand") + (match_operand:GPR 3 "reg_or_short_operand")])) (clobber (match_operand:GPR 0 "register_operand"))] "" { @@ -11819,11 +11911,18 @@ emit_insn (gen_cstore<mode>4_unsigned (operands[0], operands[1], operands[2], operands[3])); - /* The generic code knows tricks to compute signed comparisons against - zero. Let it do its thing. */ - else if (operands[3] == const0_rtx - && signed_comparison_operator (operands[1], VOIDmode)) - FAIL; + /* For signed comparisons against a constant, we can do some simple + bit-twiddling. */ + else if (signed_comparison_operator (operands[1], VOIDmode) + && CONST_INT_P (operands[3])) + emit_insn (gen_cstore<mode>4_signed_imm (operands[0], operands[1], + operands[2], operands[3])); + + /* And similarly for unsigned comparisons. */ + else if (unsigned_comparison_operator (operands[1], VOIDmode) + && CONST_INT_P (operands[3])) + emit_insn (gen_cstore<mode>4_unsigned_imm (operands[0], operands[1], + operands[2], operands[3])); /* Everything else, use the mfcr brute force. */ else |