public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug middle-end/107709] New: IVOPTs is introducing a non-zero assumption
@ 2022-11-15 21:12 amacleod at redhat dot com
2022-11-16 14:52 ` [Bug middle-end/107709] " rguenth at gcc dot gnu.org
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: amacleod at redhat dot com @ 2022-11-15 21:12 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107709
Bug ID: 107709
Summary: IVOPTs is introducing a non-zero assumption
Product: gcc
Version: 13.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: amacleod at redhat dot com
Target Milestone: ---
Ive been working on fixing https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78655 ,
which basically adds an inferred range to
ptr1 = ptr2 + non-zero-const
such that ptr2 will be non-zero after this statement. Ive spent the last
couple of days trying to figure out why fortran is failing in a bootstrap, and
I think I finally have it figured out. fortran/scanner.c is being miscompiled
at -O2, and it boils down to the following testcase:
char *nextc;
void huh ()
{
int i;
char c;
for (i = 0; i < 5; i++)
{
c = (nextc == 0) ? '\n' : *nextc++;
if (c != ' ')
break;
}
}
The very beginning of this function, just before going into ivopts, looks like:
char * prephitmp_3;
char * pretmp_4;
unsigned int ivtmp_14;
unsigned int ivtmp_15;
<bb 2> [local count: 243289824]:
pretmp_4 = nextc;
<bb 3> [local count: 894749065]:
# prephitmp_3 = PHI <_2(7), pretmp_4(2)>
# ivtmp_14 = PHI <ivtmp_15(7), 5(2)>
if (prephitmp_3 != 0B)
goto <bb 5>; [96.34%]
else
goto <bb 8>; [3.66%]
<bb 8> [local count: 32747817]:
<bb 4> [local count: 243289824]:
return;
note that prephitmp_3 will be pretmp4 to start the loop (edge 2->3), and then
it is checked against 0 (NULL) and processing only continues to BB5 if it isnt
NULL.
After IVOPTS runs, this is transformed into:
<bb 2> [local count: 243289824]:
pretmp_4 = nextc;
_12 = pretmp_4 + 5; <-- New introduction
<bb 3> [local count: 894749065]:
# prephitmp_3 = PHI <_2(7), pretmp_4(2)>
if (prephitmp_3 != 0B)
goto <bb 5>; [96.34%]
else
goto <bb 8>; [3.66%]
<bb 8> [local count: 32747817]:
<bb 4> [local count: 243289824]:
return;
Note it has added
_12 = pretmp_4 + 5
to basic block 2.
With the new code to instruct VRP that ptr1 = ptr2 + const means ptr2 is
non-null, it now propagates a range of [+1, +INF] for pretmp_4 on the edge
2->3, and that allows the condition which checks prephitmp_3 != 0 to be folded,
as _2 is always non-zero as well.
It seems that IVOPTS should not be adding that statement into BB2? It is
introducing a non-zero assumption that is not there before.
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Bug middle-end/107709] IVOPTs is introducing a non-zero assumption
2022-11-15 21:12 [Bug middle-end/107709] New: IVOPTs is introducing a non-zero assumption amacleod at redhat dot com
@ 2022-11-16 14:52 ` rguenth at gcc dot gnu.org
2022-11-16 15:10 ` amacleod at redhat dot com
2022-11-16 16:14 ` amacleod at redhat dot com
2 siblings, 0 replies; 4+ messages in thread
From: rguenth at gcc dot gnu.org @ 2022-11-16 14:52 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107709
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jakub at gcc dot gnu.org
--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
IVOPTs is usually quite careful with this and the infer of non-NULL from
ptr + CST is new - that introduced a new undefinedness in GIMPLE. The
workaround would be to avoid the POINTER_PLUS_EXPR here and perform the
increment in an unsigned type.
You can see it creates
<Invariant Expressions>:
inv_expr 1: (signed int) (unsigned long) (pretmp_4 + 1) + 5
inv_expr 2: (signed int) (unsigned long) pretmp_4 + 5
inv_expr 3: (signed int) pretmp_4 + 5
inv_expr 4: (signed long) pretmp_4 + 1
and only the pretmp_4 + 1 somehow slips through here.
This is built in aff_combination_to_tree via
may_eliminate_iv and there cand_value_at which adds
iv->base as pointer. IIRC that was done on purpose to help
association and optimization. So this new undefined behavior hurts here.
The following fixes this
diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc
index a6f926a68ef..0f180f70ff6 100644
--- a/gcc/tree-ssa-loop-ivopts.cc
+++ b/gcc/tree-ssa-loop-ivopts.cc
@@ -5233,7 +5233,7 @@ cand_value_at (class loop *loop, struct iv_cand *cand,
gimple *at,
aff_combination_add (&delta, &step);
tree_to_aff_combination (iv->base, type, val);
- if (!POINTER_TYPE_P (type))
+ //if (!POINTER_TYPE_P (type))
aff_combination_convert (val, steptype);
aff_combination_add (val, &delta);
}
but we for example still see pretmp_4 + 1 in the SCEV analysis result:
(get_scalar_evolution
(scalar = _2)
(scalar_evolution = {pretmp_4 + 1, +, 1}_1))
it basically means the compiler can nowhere build a POINTER_PLUS_EXPR
without being sure the pointer is not NULL. There same issue is already
existing for building signed arithmetic (that may not overflow).
I was last changing the above code to fix the signed arithmetic issue with
r0-129164-gd6adff07f12460 but exempted pointer types there.
Now, do we really want to introduce this new undefined behavior without
seriously auditing the code base?
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Bug middle-end/107709] IVOPTs is introducing a non-zero assumption
2022-11-15 21:12 [Bug middle-end/107709] New: IVOPTs is introducing a non-zero assumption amacleod at redhat dot com
2022-11-16 14:52 ` [Bug middle-end/107709] " rguenth at gcc dot gnu.org
@ 2022-11-16 15:10 ` amacleod at redhat dot com
2022-11-16 16:14 ` amacleod at redhat dot com
2 siblings, 0 replies; 4+ messages in thread
From: amacleod at redhat dot com @ 2022-11-16 15:10 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107709
--- Comment #2 from Andrew Macleod <amacleod at redhat dot com> ---
(In reply to Richard Biener from comment #1)
> IVOPTs is usually quite careful with this and the infer of non-NULL from
> ptr + CST is new - that introduced a new undefinedness in GIMPLE. The
> workaround would be to avoid the POINTER_PLUS_EXPR here and perform the
> increment in an unsigned type.
>
>
> Now, do we really want to introduce this new undefined behavior without
> seriously auditing the code base?
I think not. I will defer the inferred range code until next release to give us
a chance to sort this kind of thing out. I will attach the patch to PR 78655,
which when it is applied triggers the bug. That way it is easy to at least
find this one.. I can probably even attach an executable test to this PR that,
when combined with that patch, will fail. I think :-)
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Bug middle-end/107709] IVOPTs is introducing a non-zero assumption
2022-11-15 21:12 [Bug middle-end/107709] New: IVOPTs is introducing a non-zero assumption amacleod at redhat dot com
2022-11-16 14:52 ` [Bug middle-end/107709] " rguenth at gcc dot gnu.org
2022-11-16 15:10 ` amacleod at redhat dot com
@ 2022-11-16 16:14 ` amacleod at redhat dot com
2 siblings, 0 replies; 4+ messages in thread
From: amacleod at redhat dot com @ 2022-11-16 16:14 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107709
--- Comment #3 from Andrew Macleod <amacleod at redhat dot com> ---
we might be able to provide a lightweight ranger based query to determine if an
ssa_name is non-null in a block.. in fact.. we may not need anything special.
/* Create a new ranger instance and associate it with a function.
Each call must be paired with a call to disable_ranger to release
resources. If USE_IMM_USES is true, pre-calculate sideffects like
non-null uses as required using the immediate use chains. */
extern gimple_ranger *enable_ranger (struct function *m,
bool use_imm_uses = true);
simply using the on-demand default which sets use_imm_uses to true is probably
enough, When a pointer is queried, if it hasn't been done yet, all immediate
uses are scanned and if there is an inferred range, those blocks are tagged
with an on-exit range on non-zero.
simply querying get_range_query->range_of_expr (r, name, stmt) will then walk
the dom tree and tell you through r if name is non-zero or not.
If we end up needing something more efficient for this purpose, we could
harvest that code and produce a module which much more efficiently processes
inferred ranges simply looking for whether a specific property is true or not
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-11-16 16:14 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-15 21:12 [Bug middle-end/107709] New: IVOPTs is introducing a non-zero assumption amacleod at redhat dot com
2022-11-16 14:52 ` [Bug middle-end/107709] " rguenth at gcc dot gnu.org
2022-11-16 15:10 ` amacleod at redhat dot com
2022-11-16 16:14 ` amacleod at redhat dot com
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).