> > > I might also point back to the idea I threw in somewhere, adding
> > > OEP_VALUE (or a better name) to the set of flags accepted by
> > > operand_equal_p.  You mentioned hashing IIRC but I don't see the patches
> > > touching hashing?
> > >
> >
> > Yes, That can indeed be done with this approach.  The hashing was that 
> > before I
> > was trying to prevent the "duplicate" IV expressions from being created in 
> > the
> > first place by modifying get_loop_invariant_expr.
> >
> > This function looks up if we have already seen a particular IV expression 
> > and if
> > we have it just returns that expression.  However after reading more of the 
> > code
> > I realized this wasn't the right approach, as without also dealing with the
> candidates
> > we'd end up creating IV expression that can't be handled by any candidate.
> >
> > IVops would just give up then.   Reading the code it seems that
> get_loop_invariant_expr
> > is just there to prevent blatant duplicates.  i.e. it treats `(signed) a` 
> > and `a` as the
> same.
> >
> > This is also why I think that everywhere else *has* to continue stripping 
> > the
> expression.
> >
> > On a note from Richard S that he thought IVopts already had some code to 
> > deal
> with
> > expressions that differ only in signs led me to take a different approach.
> >
> > The goal wasn't to remove the different sign/unsigned IV expressions, but
> instead get
> > Then to be servable by the same candidates. i.e. we want them in the same
> candidate
> > groups and then candidate optimization will just do its thing.
> >
> > That seemed a more natural fit to how it worked.
> 
> Yeah, I agree that sounds like the better strathegy.
> 
> > Do you want me to try the operand_equal_p approach? Though in this case the
> issue
> > is we not only need to know they're equal, but also need to know the scale
> factor.
> 
> For this case yes, but if you'd keep the code as-is, the equal with scale
> factor one case would be fixed.  Not a case with different scale factors
> though - but conversions "elsewhere" should be handled via the stripping.
> So it would work to simply adjust the operand_equal_p check here?
> 
> > get_computation_aff_1 scales the common type IV by the scale we determined,
> > so I think operand_equal_p would not be very useful here.  But it does look 
> > like
> > constant_multiple_of can just be implemented with
> aff_combination_constant_multiple_p.
> >
> > Should I try?
> 
> You've had the other places where you replace operand_equal_p with
> affine-compute and compare.  As said that has some associated cost
> as well as a limit on the number of elements after which it resorts
> back to operand_equal_p.  So for strict equality tests implementing
> a weaker operand_equal_p might be a better solution.
> 

The structural comparison is implemented as a new mode for operand_equal_p which
compares two expressions ignoring NOP converts (unless their bitsizes differ)
and ignoring constant values, but requiring both operands be a constant.

There is one downside compared to affine comparison, in that this approach does
not deal well with commutative operations. i.e. it does not see a + (b + c) as
equivalent to c + (b + a).

This means we lose out on some of the more complicated addressing modes, but
with so many operations the address will likely be split anyway and we'll deal
with it then.

Bootstrapped Regtested on aarch64-none-linux-gnu,
x86_64-pc-linux-gnu -m32, -m64 and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

        PR tree-optimization/114932
        * fold-const.cc (operand_compare::operand_equal_p): Use it.
        (operand_compare::verify_hash_value): Likewise.
        * tree-core.h (enum operand_equal_flag): Add OEP_STRUCTURAL_EQ.
        * tree-ssa-loop-ivopts.cc (record_group_use): Check for structural eq.

gcc/testsuite/ChangeLog:

        PR tree-optimization/114932
        * gfortran.dg/addressing-modes_2.f90: New test.

-- inline copy of --

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 
710d697c0217c784b34f9f9f7b00b1945369076a..3d43020541c082c094164724da9d17fbb5793237
 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -3191,6 +3191,9 @@ operand_compare::operand_equal_p (const_tree arg0, 
const_tree arg1,
      precision differences.  */
   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
     {
+      if (flags & OEP_STRUCTURAL_EQ)
+       return true;
+
       /* Address of INTEGER_CST is not defined; check that we did not forget
         to drop the OEP_ADDRESS_OF flags.  */
       gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
@@ -3204,7 +3207,8 @@ operand_compare::operand_equal_p (const_tree arg0, 
const_tree arg1,
         because they may change the signedness of the arguments.  As pointers
         strictly don't have a signedness, require either two pointers or
         two non-pointers as well.  */
-      if (TYPE_UNSIGNED (TREE_TYPE (arg0)) != TYPE_UNSIGNED (TREE_TYPE (arg1))
+      if ((TYPE_UNSIGNED (TREE_TYPE (arg0)) != TYPE_UNSIGNED (TREE_TYPE (arg1))
+          && !(flags & OEP_STRUCTURAL_EQ))
          || POINTER_TYPE_P (TREE_TYPE (arg0))
                             != POINTER_TYPE_P (TREE_TYPE (arg1)))
        return false;
@@ -4204,7 +4208,7 @@ operand_compare::verify_hash_value (const_tree arg0, 
const_tree arg1,
     {
       if (operand_equal_p (arg0, arg1, flags | OEP_NO_HASH_CHECK))
        {
-         if (arg0 != arg1 && !(flags & OEP_DECL_NAME))
+         if (arg0 != arg1 && !(flags & (OEP_DECL_NAME | OEP_STRUCTURAL_EQ)))
            {
              inchash::hash hstate0 (0), hstate1 (0);
              hash_operand (arg0, hstate0, flags | OEP_HASH_CHECK);
diff --git a/gcc/testsuite/gfortran.dg/addressing-modes_2.f90 
b/gcc/testsuite/gfortran.dg/addressing-modes_2.f90
new file mode 100644
index 
0000000000000000000000000000000000000000..8eee4be3dc4d69fecfacd4c2e24a4973c8539fae
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/addressing-modes_2.f90
@@ -0,0 +1,20 @@
+! { dg-do compile { target aarch64-*-* } }
+! { dg-additional-options "-w -Ofast -fdump-tree-ivopts-all" }
+
+module a
+integer, parameter :: b=3, c=b
+contains
+subroutine d(block)
+integer f, col   , block(:, :, :), e
+do f = 1, c
+   do col = 1, c
+             block(:f,                          :, e()) = do
+     end do
+  end do
+  end
+  end
+
+! { dg-final { scan-tree-dump-not {Selected IV set for loop .+ niters, 3 IVs:} 
ivopts } }
+! { dg-final { scan-tree-dump-times {Selected IV set for loop .+ niters, 2 
IVs:} 1 ivopts } }
+! { dg-final { scan-tree-dump-times {Selected IV set for loop .+ niters, 1 
IVs:} 1 ivopts } }
+
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 
27c569c77022227643151fa4a909a95f3d45bf55..fe398d99bcaa9e8fcec45e5e07d133bc393aa4a7
 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -962,7 +962,9 @@ enum operand_equal_flag {
   /* In conjunction with OEP_LEXICOGRAPHIC considers names of declarations
      of the same kind.  Used to compare VLA bounds involving parameters
      across redeclarations of the same function.  */
-  OEP_DECL_NAME = 512
+  OEP_DECL_NAME = 512,
+  /* Check for structural equivalence and ignore NOP_CONVERT casts.  */
+  OEP_STRUCTURAL_EQ = 1024
 };
 
 /* Enum and arrays used for tree allocation stats.
diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc
index 
c3218a3e8eedbb8d0a7f14c01eeb069cb6024c29..b05e4ac1e63b5c110707a8a3ed5e614b7ccc702f
 100644
--- a/gcc/tree-ssa-loop-ivopts.cc
+++ b/gcc/tree-ssa-loop-ivopts.cc
@@ -1623,8 +1623,8 @@ record_group_use (struct ivopts_data *data, tree *use_p,
 
          /* Check if it has the same stripped base and step.  */
          if (operand_equal_p (iv->base_object, use->iv->base_object, 0)
-             && operand_equal_p (iv->step, use->iv->step, 0)
-             && operand_equal_p (addr_base, use->addr_base, 0))
+             && operand_equal_p (iv->step, use->iv->step, OEP_STRUCTURAL_EQ)
+             && operand_equal_p (addr_base, use->addr_base, OEP_STRUCTURAL_EQ))
            break;
        }
       if (i == data->vgroups.length ())

Attachment: rb18566.patch
Description: rb18566.patch

Reply via email to