This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR34099, wrong-code with CCP
On Fri, 16 Nov 2007, Richard Guenther wrote:
> On Fri, 16 Nov 2007, Joseph S. Myers wrote:
>
> > On Fri, 16 Nov 2007, Richard Guenther wrote:
> >
> > > + case MULT_EXPR:
> > > + case TRUNC_DIV_EXPR:
> > > + case CEIL_DIV_EXPR:
> > > + case FLOOR_DIV_EXPR:
> > > + case ROUND_DIV_EXPR:
> > > + case TRUNC_MOD_EXPR:
> > > + case CEIL_MOD_EXPR:
> > > + case FLOOR_MOD_EXPR:
> > > + case ROUND_MOD_EXPR:
> > > + case EQ_EXPR:
> > > + case NE_EXPR:
> > > + case LT_EXPR:
> > > + case GT_EXPR:
> > > + /* Not MIN_EXPR, MAX_EXPR. One VARYING operand may be selected.
> > > + Not bitwise operators, one VARYING operand may specify the
> > > + result completely. Not logical operators for the same reason.
> > > + Not LE/GE comparisons or unordered comparisons. Not
> > > + COMPLEX_EXPR as one VARYING operand makes the result partly
> > > + not UNDEFINED. */
> >
> > x * 0 and x % 1 are always 0 (for integer x). Comparisons may be always 0
> > or always 1 for one operand outside the range of the unsigned char from
> > which the original operand was promoted; likewise the results of
> > divisions, or shifts.
>
> Right. That'll shrink down the list to nearly zero operands. Unless
> we start to tell apart which of the operands is undefined. I'll do a
> followup patch.
Like this one. Bootstrap / regtest in progress.
Richard.
2007-11-18 Richard Guenther <rguenther@suse.de>
PR tree-optimization/34
* tree-ssa-ccp.c (likely_value): Exclude all but PLUS_EXPR,
MINUS_EXPR and POINTER_PLUS_EXPR from handling as UNDEFINED
if only one operand is undefined.
* gcc.c-torture/execute/pr34099-2.c: New testcase.
Index: tree-ssa-ccp.c
===================================================================
*** tree-ssa-ccp.c (revision 130268)
--- tree-ssa-ccp.c (working copy)
*************** likely_value (tree stmt)
*** 582,613 ****
/* Unary operators are handled with all_undefined_operands. */
case PLUS_EXPR:
case MINUS_EXPR:
- case MULT_EXPR:
case POINTER_PLUS_EXPR:
- case TRUNC_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case TRUNC_MOD_EXPR:
- case CEIL_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case ROUND_MOD_EXPR:
- case RDIV_EXPR:
- case EXACT_DIV_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case LROTATE_EXPR:
- case RROTATE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- case LT_EXPR:
- case GT_EXPR:
/* Not MIN_EXPR, MAX_EXPR. One VARYING operand may be selected.
Not bitwise operators, one VARYING operand may specify the
result completely. Not logical operators for the same reason.
! Not LE/GE comparisons or unordered comparisons. Not
! COMPLEX_EXPR as one VARYING operand makes the result partly
! not UNDEFINED. */
return UNDEFINED;
default:
--- 582,594 ----
/* Unary operators are handled with all_undefined_operands. */
case PLUS_EXPR:
case MINUS_EXPR:
case POINTER_PLUS_EXPR:
/* Not MIN_EXPR, MAX_EXPR. One VARYING operand may be selected.
Not bitwise operators, one VARYING operand may specify the
result completely. Not logical operators for the same reason.
! Not COMPLEX_EXPR as one VARYING operand makes the result partly
! not UNDEFINED. Not *DIV_EXPR, comparisons and shifts because
! the undefined operand may be promoted. */
return UNDEFINED;
default:
Index: testsuite/gcc.c-torture/execute/pr34099-2.c
===================================================================
*** testsuite/gcc.c-torture/execute/pr34099-2.c (revision 0)
--- testsuite/gcc.c-torture/execute/pr34099-2.c (revision 0)
***************
*** 0 ****
--- 1,47 ----
+ int test1 (int b, int c)
+ {
+ char x;
+ if (b)
+ return x / c;
+ else
+ return 1;
+ }
+ int test2 (int b, int c)
+ {
+ int x;
+ if (b)
+ return x * c;
+ else
+ return 1;
+ }
+ int test3 (int b, int c)
+ {
+ int x;
+ if (b)
+ return x % c;
+ else
+ return 1;
+ }
+ int test4 (int b, int c)
+ {
+ char x;
+ if (b)
+ return x == c;
+ else
+ return 1;
+ }
+
+ extern void abort (void);
+ int main()
+ {
+ if (test1(1, 1000) != 0)
+ abort ();
+ if (test2(1, 0) != 0)
+ abort ();
+ if (test3(1, 1) != 0)
+ abort ();
+ if (test4(1, 1000) != 0)
+ abort ();
+ return 0;
+ }
+