This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix inconsistent pruning of aliases
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Daniel Berlin <dberlin at dberlin dot org>, dnovillo at google dot com
- Date: Tue, 20 Nov 2007 11:37:34 +0100 (CET)
- Subject: [PATCH] Fix inconsistent pruning of aliases
This fixes an inconsistency in alias pruning. The situation is as
follows. Consider two pointers, p_1 and p_2, p_1 has a NMT which aliases
a global integer var X and SMT.1, p_2 points to anything (no NMT). The
SMT.1 has X as its only alias.
p_1->x = 0;
p_2->x = 0;
at the moment we prune X and so use SMT.1 for p_1->x because
access_can_touch_variable correctly figures that p_1->x cannot access
a bare global integer variable.
for p_2->x we add SMT.1s aliases, but do not prune X here because as we
don't know what p_2 points to, we disregard base/offset information and
do not ask access_can_touch_variable:
/* If we do not know the full reference tree or if the access is
unspecified [0, -1], we cannot prune it. Otherwise try doing
so using access_can_touch_variable. */
if (full_ref
&& !(offset == 0 && size == -1)
&& !access_can_touch_variable (full_ref, al, offset, size))
continue;
the fix is to make the behavior consistent and let access_can_touch_variable
prune also in the case of offset == 0 && size == -1 where it will now
prune the alias to X and cause the SMT itself to be added to the VOPs.
[It looks like one still could construct a case where we point to the SMT
but otoh use SMTs aliases for when we have a pt_anything pointer, which
would result in a missing link between both memory accesses -- don't we
want to add the SMT itself in any case in get_addr_dereference_operands:
/* If we don't know what this pointer points to then we have
to make sure to not prune virtual operands based on offset
and size. */
if (v_ann->symbol_mem_tag)
add_virtual_operand (v_ann->symbol_mem_tag, s_ann, flags,
full_ref, 0, -1, false);
? That is, not only add the aliases of the SMT, but the SMT itself?]
Bootstrap / regtest on x86_64-unknown-linux-gnu in progress, I'll apply
this if that succeeds.
Thanks,
Richard.
2007-11-20 Richard Guenther <rguenther@suse.de>
* tree-ssa-operands.c (add_virtual_operand): Consistently prune
accesses.
* gcc.c-torture/execute/20071120-1.c: New testcase.
Index: tree-ssa-operands.c
===================================================================
*** tree-ssa-operands.c (revision 130288)
--- tree-ssa-operands.c (working copy)
*************** add_virtual_operand (tree var, stmt_ann_
*** 1531,1537 ****
unspecified [0, -1], we cannot prune it. Otherwise try doing
so using access_can_touch_variable. */
if (full_ref
- && !(offset == 0 && size == -1)
&& !access_can_touch_variable (full_ref, al, offset, size))
continue;
--- 1531,1536 ----
Index: testsuite/gcc.c-torture/execute/20071120-1.c
===================================================================
*** testsuite/gcc.c-torture/execute/20071120-1.c (revision 0)
--- testsuite/gcc.c-torture/execute/20071120-1.c (revision 0)
***************
*** 0 ****
--- 1,81 ----
+ extern void abort (void);
+
+ void __attribute__((noinline,noreturn))
+ vec_assert_fail (void)
+ {
+ abort ();
+ }
+
+ struct ggc_root_tab {
+ void *base;
+ };
+
+ typedef struct deferred_access_check {} VEC_deferred_access_check_gc;
+
+ typedef struct deferred_access {
+ VEC_deferred_access_check_gc* deferred_access_checks;
+ int deferring_access_checks_kind;
+ } deferred_access;
+
+ typedef struct VEC_deferred_access_base {
+ unsigned num;
+ deferred_access vec[1];
+ } VEC_deferred_access_base;
+
+ static __inline__ deferred_access *
+ VEC_deferred_access_base_last (VEC_deferred_access_base *vec_)
+ {
+ (void)((vec_ && vec_->num) ? 0 : (vec_assert_fail (), 0));
+ return &vec_->vec[vec_->num - 1];
+ }
+
+ static __inline__ void
+ VEC_deferred_access_base_pop (VEC_deferred_access_base *vec_)
+ {
+ (void)((vec_->num) ? 0 : (vec_assert_fail (), 0));
+ --vec_->num;
+ }
+
+ void __attribute__((noinline))
+ perform_access_checks (VEC_deferred_access_check_gc* p)
+ {
+ abort ();
+ }
+
+ typedef struct VEC_deferred_access_gc {
+ VEC_deferred_access_base base;
+ } VEC_deferred_access_gc;
+
+ static VEC_deferred_access_gc *deferred_access_stack;
+ static unsigned deferred_access_no_check;
+
+ const struct ggc_root_tab gt_pch_rs_gt_cp_semantics_h[] = {
+ {
+ &deferred_access_no_check
+ }
+ };
+
+ void __attribute__((noinline)) pop_to_parent_deferring_access_checks (void)
+ {
+ if (deferred_access_no_check)
+ deferred_access_no_check--;
+ else
+ {
+ VEC_deferred_access_check_gc *checks;
+ deferred_access *ptr;
+ checks = (VEC_deferred_access_base_last(deferred_access_stack ? &deferred_access_stack->base : 0))->deferred_access_checks;
+ VEC_deferred_access_base_pop(deferred_access_stack ? &deferred_access_stack->base : 0);
+ ptr = VEC_deferred_access_base_last(deferred_access_stack ? &deferred_access_stack->base : 0);
+ if (ptr->deferring_access_checks_kind == 0)
+ perform_access_checks (checks);
+ }
+ }
+
+ int main()
+ {
+ deferred_access_stack = __builtin_malloc (sizeof(VEC_deferred_access_gc) + sizeof(deferred_access) * 8);
+ deferred_access_stack->base.num = 2;
+ deferred_access_stack->base.vec[0].deferring_access_checks_kind = 1;
+ pop_to_parent_deferring_access_checks ();
+ return 0;
+ }