This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Doloop transform resulting in extra code
Hello,
> Has anyone pointed out to you that the doloop transform in mainline results
> in extra code when compared to the 3.4 branch? Actually, that's not true
> for the -m64 case since 3.4 didn't generate a doloop for -m64 but I've
> included it anyway since it suffers from the same problem.
>
> Following is example source (trimmed down from bzip2.c) and generated code
> for PowerPC target. The extra tests (one for -m32, two for -m64) will
> never be true since the first test guarantees the loop count is > 0.
the code to handle this works just fine with lno/tree-ssa branches, and
I obviously forgot to check it before submitting the patch for mainline
(which apparently produces the conditions in the program in a somewhat
different shape).
The patch below should fix the problem.
Zdenek
Index: loop-iv.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-iv.c,v
retrieving revision 2.7
diff -c -3 -p -r2.7 loop-iv.c
*** loop-iv.c 18 Mar 2004 16:42:31 -0000 2.7
--- loop-iv.c 11 May 2004 22:29:02 -0000
*************** determine_max_iter (struct niter_desc *d
*** 1203,1209 ****
}
}
! get_mode_bounds (desc->mode, desc->signed_p, &mmin, &mmax);
nmax = INTVAL (mmax) - INTVAL (mmin);
if (GET_CODE (niter) == UDIV)
--- 1203,1209 ----
}
}
! get_mode_bounds (desc->mode, desc->signed_p, desc->mode, &mmin, &mmax);
nmax = INTVAL (mmax) - INTVAL (mmin);
if (GET_CODE (niter) == UDIV)
*************** simplify_using_assignment (rtx insn, rtx
*** 1354,1360 ****
static bool
implies_p (rtx a, rtx b)
{
! rtx op0, op1, r;
if (GET_CODE (a) == EQ)
{
--- 1354,1361 ----
static bool
implies_p (rtx a, rtx b)
{
! rtx op0, op1, opb0, opb1, r;
! enum machine_mode mode;
if (GET_CODE (a) == EQ)
{
*************** implies_p (rtx a, rtx b)
*** 1376,1381 ****
--- 1377,1423 ----
}
}
+ /* A < B implies A + 1 <= B. */
+ if ((GET_CODE (a) == GT || GET_CODE (a) == LT)
+ && (GET_CODE (b) == GE || GET_CODE (b) == LE))
+ {
+ op0 = XEXP (a, 0);
+ op1 = XEXP (a, 1);
+ opb0 = XEXP (b, 0);
+ opb1 = XEXP (b, 1);
+
+ if (GET_CODE (a) == GT)
+ {
+ r = op0;
+ op0 = op1;
+ op1 = r;
+ }
+
+ if (GET_CODE (b) == GE)
+ {
+ r = opb0;
+ opb0 = opb1;
+ opb1 = r;
+ }
+
+ mode = GET_MODE (op0);
+ if (mode != GET_MODE (opb0))
+ mode = VOIDmode;
+ else if (mode != VOIDmode)
+ ;
+ else
+ {
+ mode = GET_MODE (op1);
+ if (mode != GET_MODE (opb1))
+ mode = VOIDmode;
+ }
+
+ if (mode != VOIDmode
+ && rtx_equal_p (op1, opb1)
+ && simplify_gen_binary (MINUS, mode, opb0, op0) == const1_rtx)
+ return true;
+ }
+
return false;
}
*************** shorten_into_mode (struct rtx_iv *iv, en
*** 1696,1702 ****
{
rtx mmin, mmax, cond_over, cond_under;
! get_mode_bounds (mode, signed_p, &mmin, &mmax);
cond_under = simplify_gen_relational (LT, SImode, iv->extend_mode,
iv->base, mmin);
cond_over = simplify_gen_relational (GT, SImode, iv->extend_mode,
--- 1738,1744 ----
{
rtx mmin, mmax, cond_over, cond_under;
! get_mode_bounds (mode, signed_p, iv->extend_mode, &mmin, &mmax);
cond_under = simplify_gen_relational (LT, SImode, iv->extend_mode,
iv->base, mmin);
cond_over = simplify_gen_relational (GT, SImode, iv->extend_mode,
*************** iv_number_of_iterations (struct loop *lo
*** 1873,1879 ****
rtx assumption;
enum rtx_code cond;
enum machine_mode mode, comp_mode;
! rtx mmin, mmax;
unsigned HOST_WIDEST_INT s, size, d;
HOST_WIDEST_INT up, down, inc;
int was_sharp = false;
--- 1915,1921 ----
rtx assumption;
enum rtx_code cond;
enum machine_mode mode, comp_mode;
! rtx mmin, mmax, mode_mmin, mode_mmax;
unsigned HOST_WIDEST_INT s, size, d;
HOST_WIDEST_INT up, down, inc;
int was_sharp = false;
*************** iv_number_of_iterations (struct loop *lo
*** 1959,1965 ****
comp_mode = iv0.extend_mode;
mode = iv0.mode;
size = GET_MODE_BITSIZE (mode);
! get_mode_bounds (mode, (cond == LE || cond == LT), &mmin, &mmax);
if (GET_CODE (iv0.step) != CONST_INT || GET_CODE (iv1.step) != CONST_INT)
goto fail;
--- 2001,2009 ----
comp_mode = iv0.extend_mode;
mode = iv0.mode;
size = GET_MODE_BITSIZE (mode);
! get_mode_bounds (mode, (cond == LE || cond == LT), comp_mode, &mmin, &mmax);
! mode_mmin = lowpart_subreg (mode, mmin, comp_mode);
! mode_mmax = lowpart_subreg (mode, mmax, comp_mode);
if (GET_CODE (iv0.step) != CONST_INT || GET_CODE (iv1.step) != CONST_INT)
goto fail;
*************** iv_number_of_iterations (struct loop *lo
*** 2001,2007 ****
if (iv0.step == const0_rtx)
{
tmp = lowpart_subreg (mode, iv0.base, comp_mode);
! assumption = simplify_gen_relational (EQ, SImode, mode, tmp, mmax);
if (assumption == const_true_rtx)
goto zero_iter;
iv0.base = simplify_gen_binary (PLUS, comp_mode,
--- 2045,2052 ----
if (iv0.step == const0_rtx)
{
tmp = lowpart_subreg (mode, iv0.base, comp_mode);
! assumption = simplify_gen_relational (EQ, SImode, mode, tmp,
! mode_mmax);
if (assumption == const_true_rtx)
goto zero_iter;
iv0.base = simplify_gen_binary (PLUS, comp_mode,
*************** iv_number_of_iterations (struct loop *lo
*** 2010,2016 ****
else
{
tmp = lowpart_subreg (mode, iv1.base, comp_mode);
! assumption = simplify_gen_relational (EQ, SImode, mode, tmp, mmin);
if (assumption == const_true_rtx)
goto zero_iter;
iv1.base = simplify_gen_binary (PLUS, comp_mode,
--- 2055,2062 ----
else
{
tmp = lowpart_subreg (mode, iv1.base, comp_mode);
! assumption = simplify_gen_relational (EQ, SImode, mode, tmp,
! mode_mmin);
if (assumption == const_true_rtx)
goto zero_iter;
iv1.base = simplify_gen_binary (PLUS, comp_mode,
*************** iv_number_of_iterations (struct loop *lo
*** 2035,2041 ****
if (iv0.step == const0_rtx)
{
tmp = lowpart_subreg (mode, iv0.base, comp_mode);
! if (rtx_equal_p (tmp, mmin))
{
desc->infinite =
alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
--- 2081,2087 ----
if (iv0.step == const0_rtx)
{
tmp = lowpart_subreg (mode, iv0.base, comp_mode);
! if (rtx_equal_p (tmp, mode_mmin))
{
desc->infinite =
alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
*************** iv_number_of_iterations (struct loop *lo
*** 2045,2051 ****
else
{
tmp = lowpart_subreg (mode, iv1.base, comp_mode);
! if (rtx_equal_p (tmp, mmax))
{
desc->infinite =
alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
--- 2091,2097 ----
else
{
tmp = lowpart_subreg (mode, iv1.base, comp_mode);
! if (rtx_equal_p (tmp, mode_mmax))
{
desc->infinite =
alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
*************** iv_number_of_iterations (struct loop *lo
*** 2122,2129 ****
if (GET_CODE (iv1.base) == CONST_INT)
up = INTVAL (iv1.base);
else
! up = INTVAL (mmax) - inc;
! down = INTVAL (GET_CODE (iv0.base) == CONST_INT ? iv0.base : mmin);
desc->niter_max = (up - down) / inc + 1;
if (iv0.step == const0_rtx)
--- 2168,2177 ----
if (GET_CODE (iv1.base) == CONST_INT)
up = INTVAL (iv1.base);
else
! up = INTVAL (mode_mmax) - inc;
! down = INTVAL (GET_CODE (iv0.base) == CONST_INT
! ? iv0.base
! : mode_mmin);
desc->niter_max = (up - down) / inc + 1;
if (iv0.step == const0_rtx)
*************** iv_number_of_iterations (struct loop *lo
*** 2204,2210 ****
tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
! bound = simplify_gen_binary (MINUS, mode, mmax, step);
assumption = simplify_gen_relational (cond, SImode, mode,
tmp1, bound);
desc->assumptions =
--- 2252,2259 ----
tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
! bound = simplify_gen_binary (MINUS, mode, mode_mmax,
! lowpart_subreg (mode, step, comp_mode));
assumption = simplify_gen_relational (cond, SImode, mode,
tmp1, bound);
desc->assumptions =
*************** iv_number_of_iterations (struct loop *lo
*** 2227,2233 ****
tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
! bound = simplify_gen_binary (MINUS, mode, mmin, step);
assumption = simplify_gen_relational (cond, SImode, mode,
bound, tmp0);
desc->assumptions =
--- 2276,2283 ----
tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
! bound = simplify_gen_binary (MINUS, mode, mode_mmin,
! lowpart_subreg (mode, step, comp_mode));
assumption = simplify_gen_relational (cond, SImode, mode,
bound, tmp0);
desc->assumptions =
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.470
diff -c -3 -p -r1.470 rtl.h
*** rtl.h 3 May 2004 01:27:55 -0000 1.470
--- rtl.h 11 May 2004 22:29:02 -0000
*************** extern void tracer (void);
*** 2462,2468 ****
extern void variable_tracking_main (void);
/* In stor-layout.c. */
! extern void get_mode_bounds (enum machine_mode, int, rtx *, rtx *);
/* In loop-unswitch.c */
extern rtx reversed_condition (rtx);
--- 2462,2469 ----
extern void variable_tracking_main (void);
/* In stor-layout.c. */
! extern void get_mode_bounds (enum machine_mode, int, enum machine_mode,
! rtx *, rtx *);
/* In loop-unswitch.c */
extern rtx reversed_condition (rtx);
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.189
diff -c -3 -p -r1.189 simplify-rtx.c
*** simplify-rtx.c 1 May 2004 09:36:55 -0000 1.189
--- simplify-rtx.c 11 May 2004 22:29:02 -0000
*************** simplify_const_relational_operation (enu
*** 2892,2897 ****
--- 2892,2954 ----
/* Otherwise, there are some code-specific tests we can make. */
else
{
+ /* Optimize comparisons with upper and lower bounds. */
+ if (INTEGRAL_MODE_P (mode)
+ && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+ {
+ rtx mmin, mmax;
+ int sign;
+
+ if (code == GEU
+ || code == LEU
+ || code == GTU
+ || code == LTU)
+ sign = 0;
+ else
+ sign = 1;
+
+ get_mode_bounds (mode, sign, mode, &mmin, &mmax);
+
+ tem = NULL_RTX;
+ switch (code)
+ {
+ case GEU:
+ case GE:
+ /* x >= min is always true. */
+ if (rtx_equal_p (trueop1, mmin))
+ tem = const_true_rtx;
+ else
+ break;
+
+ case LEU:
+ case LE:
+ /* x <= max is always true. */
+ if (rtx_equal_p (trueop1, mmax))
+ tem = const_true_rtx;
+ break;
+
+ case GTU:
+ case GT:
+ /* x > max is always false. */
+ if (rtx_equal_p (trueop1, mmax))
+ tem = const0_rtx;
+ break;
+
+ case LTU:
+ case LT:
+ /* x < min is always false. */
+ if (rtx_equal_p (trueop1, mmin))
+ tem = const0_rtx;
+ break;
+
+ default:
+ break;
+ }
+ if (tem == const0_rtx
+ || tem == const_true_rtx)
+ return tem;
+ }
+
switch (code)
{
case EQ:
*************** simplify_const_relational_operation (enu
*** 2902,2934 ****
case NE:
if (trueop1 == const0_rtx && nonzero_address_p (op0))
return const_true_rtx;
- break;
-
- case GEU:
- /* Unsigned values are never negative. */
- if (trueop1 == const0_rtx)
- return const_true_rtx;
- break;
-
- case LTU:
- if (trueop1 == const0_rtx)
- return const0_rtx;
- break;
-
- case LEU:
- /* Unsigned values are never greater than the largest
- unsigned value. */
- if (GET_CODE (trueop1) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (trueop1) == GET_MODE_MASK (mode)
- && INTEGRAL_MODE_P (mode))
- return const_true_rtx;
- break;
-
- case GTU:
- if (GET_CODE (trueop1) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (trueop1) == GET_MODE_MASK (mode)
- && INTEGRAL_MODE_P (mode))
- return const0_rtx;
break;
case LT:
--- 2959,2964 ----
Index: stor-layout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stor-layout.c,v
retrieving revision 1.187
diff -c -3 -p -r1.187 stor-layout.c
*** stor-layout.c 19 Apr 2004 18:02:40 -0000 1.187
--- stor-layout.c 11 May 2004 22:29:02 -0000
*************** get_best_mode (int bitsize, int bitpos,
*** 2156,2181 ****
}
/* Gets minimal and maximal values for MODE (signed or unsigned depending on
! SIGN). */
void
! get_mode_bounds (enum machine_mode mode, int sign, rtx *mmin, rtx *mmax)
{
! int size = GET_MODE_BITSIZE (mode);
if (size > HOST_BITS_PER_WIDE_INT)
abort ();
if (sign)
{
! *mmin = GEN_INT (-((unsigned HOST_WIDE_INT) 1 << (size - 1)));
! *mmax = GEN_INT (((unsigned HOST_WIDE_INT) 1 << (size - 1)) - 1);
}
else
{
! *mmin = const0_rtx;
! *mmax = GEN_INT (((unsigned HOST_WIDE_INT) 1 << (size - 1) << 1) - 1);
}
}
#include "gt-stor-layout.h"
--- 2156,2187 ----
}
/* Gets minimal and maximal values for MODE (signed or unsigned depending on
! SIGN). The returned constants are made to be usable in TARGET_MODE. */
void
! get_mode_bounds (enum machine_mode mode, int sign,
! enum machine_mode target_mode,
! rtx *mmin, rtx *mmax)
{
! unsigned size = GET_MODE_BITSIZE (mode);
! unsigned HOST_WIDE_INT min_val, max_val;
if (size > HOST_BITS_PER_WIDE_INT)
abort ();
if (sign)
{
! min_val = -((unsigned HOST_WIDE_INT) 1 << (size - 1));
! max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1)) - 1;
}
else
{
! min_val = 0;
! max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1) << 1) - 1;
}
+
+ *mmin = GEN_INT (trunc_int_for_mode (min_val, target_mode));
+ *mmax = GEN_INT (trunc_int_for_mode (max_val, target_mode));
}
#include "gt-stor-layout.h"