Bug 58513 - *var and MEM[(const int &)var] (var has int* type) are not treated as the same data ref.
Summary: *var and MEM[(const int &)var] (var has int* type) are not treated as the sa...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on: 58521
Blocks:
  Show dependency treegraph
 
Reported: 2013-09-23 20:49 UTC by Cong Hou
Modified: 2013-09-26 01:36 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Cong Hou 2013-09-23 20:49:11 UTC
First look at the code below:


int op (const int& x, const int& y) { return x + y; }

void foo(int* a)
{
 for (int i = 0; i < 100000; ++i)
   a[i] = op(a[i], 1);
}


GCC will generate the following GIMPLE for this loop after inlining op():


  <bb 3>:
  # i_17 = PHI <0(2), i_23(4)>
  # ivtmp_13 = PHI <100000(2), ivtmp_24(4)>
  _12 = (long unsigned int) i_17;
  _2 = _12 * 4;
  _1 = a_6(D) + _2;
  _20 = MEM[(const int &)_1];
  _19 = _20 + 1;
  *_1 = _19;
  i_23 = i_17 + 1;
  ivtmp_24 = ivtmp_13 - 1;
  if (ivtmp_24 != 0)
    goto <bb 4>;
  else
    goto <bb 5>;


Here each element of the array a is loaded by MEM[(const int &)_1] and stored by *_1, which are the only two data refs in the loop body. The GCC vectorizer needs to check the possible aliasing between data refs with potential data dependence. Here those two data refs are actually the same one, but GCC could not recognize this fact. As a result, the aliasing checking predicate will always return false at runtime (GCC 4.9 could eliminate this generated branch at the end of the vectorization pass). 

The reason why GCC thinks that MEM[(const int &)_1] and *_1 are two different data refs is that there is a possible defect in the function operand_equal_p(), which is used to compare two data refs. The current implementation uses == to compare the types of the second argument of MEM_REF operator, which is too strict. Using types_compatible_p() instead can fix the issue above. I have produced a patch to fix it and the patch is shown below. Please give me the comment on this patch. (bootstrapping and "make check" passed).


thanks,
Cong

 

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 202662)
+++ gcc/fold-const.c	(working copy)
@@ -2693,8 +2693,9 @@ operand_equal_p (const_tree arg0, const_
 		       && operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)),
 					   TYPE_SIZE (TREE_TYPE (arg1)), flags)))
 		  && types_compatible_p (TREE_TYPE (arg0), TREE_TYPE (arg1))
-		  && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 1)))
-		      == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg1, 1))))
+		  && types_compatible_p (
+			TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg0, 1))),
+			TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg1, 1))))
 		  && OP_SAME (0) && OP_SAME (1));
 
 	case ARRAY_REF:
Comment 1 Richard Biener 2013-09-24 11:04:06 UTC
Author: rguenth
Date: Tue Sep 24 11:04:04 2013
New Revision: 202865

URL: http://gcc.gnu.org/viewcvs?rev=202865&root=gcc&view=rev
Log:
2013-09-24  Richard Biener  <rguenther@suse.de>

	PR middle-end/58513
	* tree.c (reference_alias_ptr_type): Move ...
	* alias.c (reference_alias_ptr_type): ... here and implement
	in terms of the new reference_alias_ptr_type_1.
	(ref_all_alias_ptr_type_p): New helper.
	(get_deref_alias_set_1): Drop flag_strict_aliasing here,
	use ref_all_alias_ptr_type_p.
	(get_deref_alias_set): Add flag_strict_aliasing check here.
	(reference_alias_ptr_type_1): New function, split out from ...
	(get_alias_set): ... here.
	(alias_ptr_types_compatible_p): New function.
	* alias.h (reference_alias_ptr_type): Declare.
	(alias_ptr_types_compatible_p): Likewise.
	* tree.h (reference_alias_ptr_type): Remove.
	* fold-const.c (operand_equal_p): Use alias_ptr_types_compatible_p
	to compare MEM_REF alias types.

	* g++.dg/vect/pr58513.cc: New testcase.

Added:
    trunk/gcc/testsuite/g++.dg/vect/pr58513.cc
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/alias.c
    trunk/gcc/alias.h
    trunk/gcc/fold-const.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree.c
    trunk/gcc/tree.h
Comment 2 Richard Biener 2013-09-24 11:04:28 UTC
Fixed.
Comment 3 Cong Hou 2013-09-26 01:36:52 UTC
Author: congh
Date: Thu Sep 26 01:36:49 2013
New Revision: 202932

URL: http://gcc.gnu.org/viewcvs?rev=202932&root=gcc&view=rev
Log:
2013-09-24  Cong Hou  <congh@google.com>

    Backport from mainline:
    2013-09-24  Richard Biener  <rguenther@suse.de>

    PR middle-end/58513
    * tree.c (reference_alias_ptr_type): Move ...
    * alias.c (reference_alias_ptr_type): ... here and implement
    in terms of the new reference_alias_ptr_type_1.
    (ref_all_alias_ptr_type_p): New helper.
    (get_deref_alias_set_1): Drop flag_strict_aliasing here,
    use ref_all_alias_ptr_type_p.
    (get_deref_alias_set): Add flag_strict_aliasing check here.
    (reference_alias_ptr_type_1): New function, split out from ...
    (get_alias_set): ... here.
    (alias_ptr_types_compatible_p): New function.
    * alias.h (reference_alias_ptr_type): Declare.
    (alias_ptr_types_compatible_p): Likewise.
    * tree.h (reference_alias_ptr_type): Remove.
    * fold-const.c (operand_equal_p): Use alias_ptr_types_compatible_p
    to compare MEM_REF alias types.

    2013-09-25  Richard Biener  <rguenther@suse.de>

    PR middle-end/58521
    * tree.c (iterative_hash_expr): Remove MEM_REF special handling.

2013-09-24  Cong Hou  <congh@google.com>

    Backport from mainline:
    2013-09-24  Richard Biener  <rguenther@suse.de>

    PR middle-end/58513
    * g++.dg/vect/pr58513.cc: New testcase.



Modified:
    branches/google/gcc-4_8/gcc/ChangeLog
    branches/google/gcc-4_8/gcc/alias.c
    branches/google/gcc-4_8/gcc/alias.h
    branches/google/gcc-4_8/gcc/fold-const.c
    branches/google/gcc-4_8/gcc/testsuite/ChangeLog
    branches/google/gcc-4_8/gcc/tree.c
    branches/google/gcc-4_8/gcc/tree.h