From 72a4ddf2b5f8167dd49a483888f14d34c3da582f Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Mon, 24 Mar 2014 17:38:09 +0000 Subject: re PR rtl-optimization/60501 (LRA emits add patterns which might clobber cc) 2014-03-24 Andreas Krebbel PR rtl-optimization/60501 * optabs.def (addptr3_optab): New optab. * optabs.c (gen_addptr3_insn, have_addptr3_insn): New function. * doc/md.texi ("addptrm3"): Document new RTL standard expander. * expr.h (gen_addptr3_insn, have_addptr3_insn): Add prototypes. * lra.c (emit_add3_insn): Use the addptr pattern if available. * config/s390/s390.md ("addptrdi3", "addptrsi3"): New expanders. From-SVN: r208796 --- gcc/ChangeLog | 12 ++++++++++++ gcc/config/s390/s390.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ gcc/doc/md.texi | 11 +++++++++++ gcc/expr.h | 2 ++ gcc/lra.c | 13 +++++++++++++ gcc/optabs.c | 37 +++++++++++++++++++++++++++++++++++ gcc/optabs.def | 1 + 7 files changed, 127 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e24b5fa..d904fc0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2014-03-24 Andreas Krebbel + + PR rtl-optimization/60501 + * optabs.def (addptr3_optab): New optab. + * optabs.c (gen_addptr3_insn, have_addptr3_insn): New function. + * doc/md.texi ("addptrm3"): Document new RTL standard expander. + * expr.h (gen_addptr3_insn, have_addptr3_insn): Add prototypes. + + * lra.c (emit_add3_insn): Use the addptr pattern if available. + + * config/s390/s390.md ("addptrdi3", "addptrsi3"): New expanders. + 2014-03-24 Ulrich Drepper * config/i386/avx512fintrin.h: Define _mm512_set1_ps and diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 76902b5..7d9d1ad 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -5034,6 +5034,57 @@ [(set_attr "op_type" ",RXE") (set_attr "type" "fsimp")]) +; +; Pointer add instruction patterns +; + +; This will match "*la_64" +(define_expand "addptrdi3" + [(set (match_operand:DI 0 "register_operand" "") + (plus:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "nonmemory_operand" "")))] + "TARGET_64BIT" +{ + HOST_WIDE_INT c = INTVAL (operands[2]); + + if (GET_CODE (operands[2]) == CONST_INT) + { + if (!CONST_OK_FOR_CONSTRAINT_P (c, 'K', "K") + && !CONST_OK_FOR_CONSTRAINT_P (c, 'O', "Os")) + { + operands[2] = force_const_mem (DImode, operands[2]); + operands[2] = force_reg (DImode, operands[2]); + } + else if (!DISP_IN_RANGE (INTVAL (operands[2]))) + operands[2] = force_reg (DImode, operands[2]); + } +}) + +; For 31 bit we have to prevent the generated pattern from matching +; normal ADDs since la only does a 31 bit add. This is supposed to +; match "force_la_31". +(define_expand "addptrsi3" + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nonmemory_operand" ""))) + (use (const_int 0))])] + "!TARGET_64BIT" +{ + HOST_WIDE_INT c = INTVAL (operands[2]); + + if (GET_CODE (operands[2]) == CONST_INT) + { + if (!CONST_OK_FOR_CONSTRAINT_P (c, 'K', "K") + && !CONST_OK_FOR_CONSTRAINT_P (c, 'O', "Os")) + { + operands[2] = force_const_mem (SImode, operands[2]); + operands[2] = force_reg (SImode, operands[2]); + } + else if (!DISP_IN_RANGE (INTVAL (operands[2]))) + operands[2] = force_reg (SImode, operands[2]); + } +}) ;; ;;- Subtract instructions. diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 746acc2..85fd4b9 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -4720,6 +4720,17 @@ Add operand 2 and operand 1, storing the result in operand 0. All operands must have mode @var{m}. This can be used even on two-address machines, by means of constraints requiring operands 1 and 0 to be the same location. +@cindex @code{addptr@var{m}3} instruction pattern +@item @samp{addptr@var{m}3} +Like @code{add@var{m}3} but is guaranteed to only be used for address +calculations. The expanded code is not allowed to clobber the +condition code. It only needs to be defined if @code{add@var{m}3} +sets the condition code. If adds used for address calculations and +normal adds are not compatible it is required to expand a distinct +pattern (e.g. using an unspec). The pattern is used by LRA to emit +address calculations. @code{add@var{m}3} is used if +@code{addptr@var{m}3} is not defined. + @cindex @code{ssadd@var{m}3} instruction pattern @cindex @code{usadd@var{m}3} instruction pattern @cindex @code{sub@var{m}3} instruction pattern diff --git a/gcc/expr.h b/gcc/expr.h index 5111f06..524da67 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -180,10 +180,12 @@ extern void emit_libcall_block (rtx, rtx, rtx, rtx); Likewise for subtraction and for just copying. */ extern rtx gen_add2_insn (rtx, rtx); extern rtx gen_add3_insn (rtx, rtx, rtx); +extern rtx gen_addptr3_insn (rtx, rtx, rtx); extern rtx gen_sub2_insn (rtx, rtx); extern rtx gen_sub3_insn (rtx, rtx, rtx); extern rtx gen_move_insn (rtx, rtx); extern int have_add2_insn (rtx, rtx); +extern int have_addptr3_insn (rtx, rtx, rtx); extern int have_sub2_insn (rtx, rtx); /* Emit a pair of rtl insns to compare two rtx's and to jump diff --git a/gcc/lra.c b/gcc/lra.c index 77074e2..c1b92d8 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -254,6 +254,19 @@ emit_add3_insn (rtx x, rtx y, rtx z) rtx insn, last; last = get_last_insn (); + + if (have_addptr3_insn (x, y, z)) + { + insn = gen_addptr3_insn (x, y, z); + + /* If the target provides an "addptr" pattern it hopefully does + for a reason. So falling back to the normal add would be + a bug. */ + lra_assert (insn != NULL_RTX); + emit_insn (insn); + return insn; + } + insn = emit_insn (gen_rtx_SET (VOIDmode, x, gen_rtx_PLUS (GET_MODE (y), y, z))); if (recog_memoized (insn) < 0) diff --git a/gcc/optabs.c b/gcc/optabs.c index cec25a4..c4540f8 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4755,6 +4755,43 @@ have_add2_insn (rtx x, rtx y) return 1; } +/* Generate and return an insn body to add Y to X. */ + +rtx +gen_addptr3_insn (rtx x, rtx y, rtx z) +{ + enum insn_code icode = optab_handler (addptr3_optab, GET_MODE (x)); + + gcc_assert (insn_operand_matches (icode, 0, x)); + gcc_assert (insn_operand_matches (icode, 1, y)); + gcc_assert (insn_operand_matches (icode, 2, z)); + + return GEN_FCN (icode) (x, y, z); +} + +/* Return true if the target implements an addptr pattern and X, Y, + and Z are valid for the pattern predicates. */ + +int +have_addptr3_insn (rtx x, rtx y, rtx z) +{ + enum insn_code icode; + + gcc_assert (GET_MODE (x) != VOIDmode); + + icode = optab_handler (addptr3_optab, GET_MODE (x)); + + if (icode == CODE_FOR_nothing) + return 0; + + if (!insn_operand_matches (icode, 0, x) + || !insn_operand_matches (icode, 1, y) + || !insn_operand_matches (icode, 2, z)) + return 0; + + return 1; +} + /* Generate and return an insn body to subtract Y from X. */ rtx diff --git a/gcc/optabs.def b/gcc/optabs.def index decdaf3..9b89740 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -191,6 +191,7 @@ OPTAB_D (addv4_optab, "addv$I$a4") OPTAB_D (subv4_optab, "subv$I$a4") OPTAB_D (mulv4_optab, "mulv$I$a4") OPTAB_D (negv3_optab, "negv$I$a3") +OPTAB_D (addptr3_optab, "addptr$a3") OPTAB_D (smul_highpart_optab, "smul$a3_highpart") OPTAB_D (umul_highpart_optab, "umul$a3_highpart") -- cgit v1.1