re PR rtl-optimization/60501 (LRA emits add patterns which might clobber cc)
2014-03-24 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> 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
This commit is contained in:
parent
2b2384e8c1
commit
72a4ddf2b5
7 changed files with 127 additions and 0 deletions
|
@ -1,3 +1,15 @@
|
|||
2014-03-24 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
|
||||
|
||||
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 <drepper@gmail.com>
|
||||
|
||||
* config/i386/avx512fintrin.h: Define _mm512_set1_ps and
|
||||
|
|
|
@ -5034,6 +5034,57 @@
|
|||
[(set_attr "op_type" "<RRer>,RXE")
|
||||
(set_attr "type" "fsimp<mode>")])
|
||||
|
||||
;
|
||||
; 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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
13
gcc/lra.c
13
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)
|
||||
|
|
37
gcc/optabs.c
37
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
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Reference in a new issue