This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[3.4-BIB] find_split_point tweek
- From: Jan Hubicka <jh at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com
- Date: Sun, 10 Nov 2002 20:31:09 +0100
- Subject: [3.4-BIB] find_split_point tweek
Hi,
this patch teach combine how to split read-modify-write instruction into
read-modify that is needed for proper combining of some instructions dealing
with memory operands.
The testcase requires previous patch to work but it should help even
without it in some cases.
Honza
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -msse2 -mfpmath=sse -march=athlon" } */
/* { dg-final { scan-assembler "sqrtss" } } */
float a;
t()
{
double b=a;
a=sqrt(b);
}
Sun Nov 10 22:41:29 CET 2002 Jan Hubicka <jh@suse.cz>
* combine.c (find_split_point): Accept extra argument dest;
split away the store from instruction when profitable; split away
memory operands.
(different_mem): New function.
(try_combine): Handle reversal when find_split_point splits away set
destination.
*** combine.c.old Sun Nov 10 20:03:37 2002
--- combine.c Sun Nov 10 22:36:33 2002
*************** static int contains_muldiv PARAMS ((rtx)
*** 345,351 ****
static rtx try_combine PARAMS ((rtx, rtx, rtx, int *));
static void undo_all PARAMS ((void));
static void undo_commit PARAMS ((void));
! static rtx *find_split_point PARAMS ((rtx *, rtx));
static rtx subst PARAMS ((rtx, rtx, rtx, int, int));
static rtx combine_simplify_rtx PARAMS ((rtx, enum machine_mode, int, int));
static rtx simplify_if_then_else PARAMS ((rtx));
--- 345,351 ----
static rtx try_combine PARAMS ((rtx, rtx, rtx, int *));
static void undo_all PARAMS ((void));
static void undo_commit PARAMS ((void));
! static rtx *find_split_point PARAMS ((rtx *, rtx, int *));
static rtx subst PARAMS ((rtx, rtx, rtx, int, int));
static rtx combine_simplify_rtx PARAMS ((rtx, enum machine_mode, int, int));
static rtx simplify_if_then_else PARAMS ((rtx));
*************** static int insn_cuid PARAMS ((rtx));
*** 400,405 ****
--- 400,406 ----
static void record_promoted_value PARAMS ((rtx, rtx));
static rtx reversed_comparison PARAMS ((rtx, enum machine_mode, rtx, rtx));
static enum rtx_code combine_reversed_comparison_code PARAMS ((rtx));
+ static int different_mem PARAMS ((rtx *, void *));
/* Substitute NEWVAL, an rtx expression, into INTO, a place in some
insn. The substitution can be undone by undo_all. If INTO is already
*************** try_combine (i3, i2, i1, new_direct_jump
*** 1527,1532 ****
--- 1528,1534 ----
rtx temp;
rtx link;
int i;
+ int dest;
/* Exit early if one of the insns involved can't be used for
combinations. */
*************** try_combine (i3, i2, i1, new_direct_jump
*** 2217,2227 ****
REG_N_SETS (REGNO (new_i2_dest))++;
}
}
/* If we can split it and use I2DEST, go ahead and see if that
helps things be recognized. Verify that none of the registers
are set between I2 and I3. */
! if (insn_code_number < 0 && (split = find_split_point (&newpat, i3)) != 0
#ifdef HAVE_cc0
&& GET_CODE (i2dest) == REG
#endif
--- 2219,2230 ----
REG_N_SETS (REGNO (new_i2_dest))++;
}
}
+ dest = 0;
/* If we can split it and use I2DEST, go ahead and see if that
helps things be recognized. Verify that none of the registers
are set between I2 and I3. */
! if (insn_code_number < 0 && (split = find_split_point (&newpat, i3, &dest)) != 0
#ifdef HAVE_cc0
&& GET_CODE (i2dest) == REG
#endif
*************** try_combine (i3, i2, i1, new_direct_jump
*** 2286,2292 ****
}
#endif
! newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
SUBST (*split, newdest);
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
--- 2289,2298 ----
}
#endif
! if (!dest)
! newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
! else
! newi2pat = gen_rtx_SET (VOIDmode, *split, newdest);
SUBST (*split, newdest);
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
*************** try_combine (i3, i2, i1, new_direct_jump
*** 2294,2299 ****
--- 2300,2314 ----
don't use one now. */
if (i2_code_number >= 0 && ! (split_code == MULT && ! have_mult))
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+ if (dest && insn_code_number >=0)
+ {
+ rtx t = newpat;
+ int t2 = insn_code_number;
+ newpat = newi2pat;
+ newi2pat = t;
+ insn_code_number = i2_code_number;
+ i2_code_number = t2;
+ }
}
}
*************** undo_commit ()
*** 2894,2912 ****
}
undobuf.undos = 0;
}
-
/* Find the innermost point within the rtx at LOC, possibly LOC itself,
where we have an arithmetic expression and return that point. LOC will
! be inside INSN.
try_combine will call this function to see if an insn can be split into
two insns. */
static rtx *
! find_split_point (loc, insn)
rtx *loc;
rtx insn;
{
rtx x = *loc;
enum rtx_code code = GET_CODE (x);
--- 2909,2948 ----
}
undobuf.undos = 0;
}
+ /* Subroutine of find_split_point; called through for_each_rtx.
+ Look for MEM expression different from one pointed to by data.
+ On sucess rewrite data and return 1 */
+ static int
+ different_mem (xp, data)
+ rtx *xp;
+ void *data;
+ {
+ if (GET_CODE (*xp) == MEM)
+ {
+ rtx **store = (rtx **)data;
+ if (!rtx_equal_p (**store, *xp))
+ {
+ *store = xp;
+ return 1;
+ }
+ }
+ return 0;
+ }
+
/* Find the innermost point within the rtx at LOC, possibly LOC itself,
where we have an arithmetic expression and return that point. LOC will
! be inside INSN. Set DEST to 1 when LOC is the destination of SET so
! we need to emit instructions in reversed order.
try_combine will call this function to see if an insn can be split into
two insns. */
static rtx *
! find_split_point (loc, insn, dest)
rtx *loc;
rtx insn;
+ int *dest;
{
rtx x = *loc;
enum rtx_code code = GET_CODE (x);
*************** find_split_point (loc, insn)
*** 2926,2932 ****
if (GET_CODE (SUBREG_REG (x)) == MEM)
return loc;
#endif
! return find_split_point (&SUBREG_REG (x), insn);
case MEM:
#ifdef HAVE_lo_sum
--- 2962,2968 ----
if (GET_CODE (SUBREG_REG (x)) == MEM)
return loc;
#endif
! return find_split_point (&SUBREG_REG (x), insn, dest);
case MEM:
#ifdef HAVE_lo_sum
*************** find_split_point (loc, insn)
*** 3008,3014 ****
&& (GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (XEXP (x, 0), 0))))
== 'o')))
return &XEXP (XEXP (x, 0), 0);
! }
break;
case SET:
--- 3044,3052 ----
&& (GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (XEXP (x, 0), 0))))
== 'o')))
return &XEXP (XEXP (x, 0), 0);
! } /* Otherwise try to split away the MEM operand itself. */
! else
! return loc;
break;
case SET:
*************** find_split_point (loc, insn)
*** 3028,3039 ****
#endif
/* See if we can split SET_SRC as it stands. */
! split = find_split_point (&SET_SRC (x), insn);
if (split && split != &SET_SRC (x))
! return split;
/* See if we can split SET_DEST as it stands. */
! split = find_split_point (&SET_DEST (x), insn);
if (split && split != &SET_DEST (x))
return split;
--- 3066,3095 ----
#endif
/* See if we can split SET_SRC as it stands. */
! split = find_split_point (&SET_SRC (x), insn, dest);
if (split && split != &SET_SRC (x))
! {
! /* Some architectures (i386) do have load-execute instructions, but
! it is probably uncommong to have execute-store instructions, so
! it is better to split load-execute-store instruction into
! load followed by execute-write.
! Exception may be the case where two different MEM input operands
! are present. Then we should split load-load-execute-store into
! load followed by load-execute-store. */
! if (GET_CODE (*split) == MEM
! && GET_CODE (SET_DEST (x)) == MEM)
! {
! rtx *sp = &SET_DEST (x);
!
! if (!for_each_rtx (&SET_SRC (x), different_mem, &sp))
! *dest = 1;
! return sp;
! }
! return split;
! }
/* See if we can split SET_DEST as it stands. */
! split = find_split_point (&SET_DEST (x), insn, dest);
if (split && split != &SET_DEST (x))
return split;
*************** find_split_point (loc, insn)
*** 3053,3060 ****
HOST_WIDE_INT pos = INTVAL (XEXP (SET_DEST (x), 2));
unsigned HOST_WIDE_INT len = INTVAL (XEXP (SET_DEST (x), 1));
unsigned HOST_WIDE_INT src = INTVAL (SET_SRC (x));
! rtx dest = XEXP (SET_DEST (x), 0);
! enum machine_mode mode = GET_MODE (dest);
unsigned HOST_WIDE_INT mask = ((HOST_WIDE_INT) 1 << len) - 1;
if (BITS_BIG_ENDIAN)
--- 3109,3116 ----
HOST_WIDE_INT pos = INTVAL (XEXP (SET_DEST (x), 2));
unsigned HOST_WIDE_INT len = INTVAL (XEXP (SET_DEST (x), 1));
unsigned HOST_WIDE_INT src = INTVAL (SET_SRC (x));
! rtx destexp = XEXP (SET_DEST (x), 0);
! enum machine_mode mode = GET_MODE (destexp);
unsigned HOST_WIDE_INT mask = ((HOST_WIDE_INT) 1 << len) - 1;
if (BITS_BIG_ENDIAN)
*************** find_split_point (loc, insn)
*** 3062,3079 ****
if (src == mask)
SUBST (SET_SRC (x),
! gen_binary (IOR, mode, dest, GEN_INT (src << pos)));
else
SUBST (SET_SRC (x),
gen_binary (IOR, mode,
! gen_binary (AND, mode, dest,
gen_int_mode (~(mask << pos),
mode)),
GEN_INT (src << pos)));
! SUBST (SET_DEST (x), dest);
! split = find_split_point (&SET_SRC (x), insn);
if (split && split != &SET_SRC (x))
return split;
}
--- 3118,3135 ----
if (src == mask)
SUBST (SET_SRC (x),
! gen_binary (IOR, mode, destexp, GEN_INT (src << pos)));
else
SUBST (SET_SRC (x),
gen_binary (IOR, mode,
! gen_binary (AND, mode, destexp,
gen_int_mode (~(mask << pos),
mode)),
GEN_INT (src << pos)));
! SUBST (SET_DEST (x), destexp);
! split = find_split_point (&SET_SRC (x), insn, dest);
if (split && split != &SET_SRC (x))
return split;
}
*************** find_split_point (loc, insn)
*** 3109,3115 ****
if (extraction != 0)
{
SUBST (SET_SRC (x), extraction);
! return find_split_point (loc, insn);
}
}
break;
--- 3165,3171 ----
if (extraction != 0)
{
SUBST (SET_SRC (x), extraction);
! return find_split_point (loc, insn, dest);
}
}
break;
*************** find_split_point (loc, insn)
*** 3131,3137 ****
XEXP (SET_SRC (x), 0),
GEN_INT (pos))));
! split = find_split_point (&SET_SRC (x), insn);
if (split && split != &SET_SRC (x))
return split;
}
--- 3187,3193 ----
XEXP (SET_SRC (x), 0),
GEN_INT (pos))));
! split = find_split_point (&SET_SRC (x), insn, dest);
if (split && split != &SET_SRC (x))
return split;
}
*************** find_split_point (loc, insn)
*** 3190,3196 ****
GEN_INT (pos)),
GEN_INT (((HOST_WIDE_INT) 1 << len) - 1)));
! split = find_split_point (&SET_SRC (x), insn);
if (split && split != &SET_SRC (x))
return split;
}
--- 3246,3252 ----
GEN_INT (pos)),
GEN_INT (((HOST_WIDE_INT) 1 << len) - 1)));
! split = find_split_point (&SET_SRC (x), insn, dest);
if (split && split != &SET_SRC (x))
return split;
}
*************** find_split_point (loc, insn)
*** 3205,3211 ****
- len - pos)),
GEN_INT (GET_MODE_BITSIZE (mode) - len)));
! split = find_split_point (&SET_SRC (x), insn);
if (split && split != &SET_SRC (x))
return split;
}
--- 3261,3267 ----
- len - pos)),
GEN_INT (GET_MODE_BITSIZE (mode) - len)));
! split = find_split_point (&SET_SRC (x), insn, dest);
if (split && split != &SET_SRC (x))
return split;
}
*************** find_split_point (loc, insn)
*** 3251,3257 ****
GET_MODE (x),
XEXP (XEXP (x, 0), 0),
XEXP (XEXP (x, 1), 0))));
! return find_split_point (loc, insn);
}
/* Many RISC machines have a large set of logical insns. If the
--- 3307,3313 ----
GET_MODE (x),
XEXP (XEXP (x, 0), 0),
XEXP (XEXP (x, 1), 0))));
! return find_split_point (loc, insn, dest);
}
/* Many RISC machines have a large set of logical insns. If the
*************** find_split_point (loc, insn)
*** 3274,3287 ****
{
case 'b': /* This is ZERO_EXTRACT and SIGN_EXTRACT. */
case '3':
! split = find_split_point (&XEXP (x, 2), insn);
if (split)
return split;
/* ... fall through ... */
case '2':
case 'c':
case '<':
! split = find_split_point (&XEXP (x, 1), insn);
if (split)
return split;
/* ... fall through ... */
--- 3330,3343 ----
{
case 'b': /* This is ZERO_EXTRACT and SIGN_EXTRACT. */
case '3':
! split = find_split_point (&XEXP (x, 2), insn, dest);
if (split)
return split;
/* ... fall through ... */
case '2':
case 'c':
case '<':
! split = find_split_point (&XEXP (x, 1), insn, dest);
if (split)
return split;
/* ... fall through ... */
*************** find_split_point (loc, insn)
*** 3291,3297 ****
if (GET_CODE (x) != AND && GET_CODE (XEXP (x, 0)) == AND)
return &XEXP (x, 0);
! split = find_split_point (&XEXP (x, 0), insn);
if (split)
return split;
return loc;
--- 3347,3353 ----
if (GET_CODE (x) != AND && GET_CODE (XEXP (x, 0)) == AND)
return &XEXP (x, 0);
! split = find_split_point (&XEXP (x, 0), insn, dest);
if (split)
return split;
return loc;