This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]