tree-ssa-forwprop.c (associate_plusminus): Extend (T)(P + A) - (T)P -> (T)A transform...
authorEric Botcazou <ebotcazou@adacore.com>
Thu, 22 May 2014 14:32:56 +0000 (14:32 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Thu, 22 May 2014 14:32:56 +0000 (14:32 +0000)
* tree-ssa-forwprop.c (associate_plusminus): Extend (T)(P + A) - (T)P
-> (T)A transformation to integer types.

From-SVN: r210807

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/opt37.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt37.ads [new file with mode: 0644]
gcc/tree-ssa-forwprop.c

index d2dbcbd..307df9a 100644 (file)
@@ -1,3 +1,8 @@
+2014-05-22  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * tree-ssa-forwprop.c (associate_plusminus): Extend (T)(P + A) - (T)P
+       -> (T)A transformation to integer types.
+
 2014-05-22  Teresa Johnson  <tejohnson@google.com>
 
        * gcov-io.c (gcov_position): Use gcov_nonruntime_assert.
index 1b9c60a..4d81463 100644 (file)
@@ -1,3 +1,7 @@
+2014-05-22  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/opt37.ad[sb]: New test.
+
 2014-05-21  Jonathan Wakely  <jwakely@redhat.com>
 
        PR c/61271
diff --git a/gcc/testsuite/gnat.dg/opt37.adb b/gcc/testsuite/gnat.dg/opt37.adb
new file mode 100644 (file)
index 0000000..fe37f90
--- /dev/null
@@ -0,0 +1,42 @@
+-- { dg-compile }
+-- { dg-options "-O2 -gnato -fdump-tree-optimized" }
+
+package body Opt37 is
+
+   function To_Unchecked (Bits : T_Bit_Array) return Unsigned32 is
+      Value : Unsigned32 := 0;
+   begin
+      for I in Bits'Range loop
+         Value := Value * 2 + Unsigned32 (Bits(I));
+      end loop;
+      return Value;
+   end;
+
+   function To_Scalar (Bits : T_Bit_Array) return Positive is
+      Tmp   : Unsigned32;
+      Value : Positive;
+   begin
+      Tmp := To_Unchecked (Bits);
+      if Tmp in 0 .. Unsigned32 (Positive'last) then
+         Value := Positive (Tmp);
+      else
+         Value := -Positive (Unsigned32'last - Tmp);
+         if Value > Positive'first then
+            Value := Value - 1;
+         else
+            raise Program_Error;
+         end if;
+      end if;
+      return Value;
+   end;
+
+   function Func (Bit_Array : T_Bit_Array;
+                  Bit_Index : T_Bit_Index) return Positive is
+   begin
+      return To_Scalar (Bit_Array (Bit_Index .. Bit_Index + 1));
+   end;
+
+end Opt37;
+
+-- { dg-final { scan-tree-dump-not "alloca" "optimized" } }
+-- { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc/testsuite/gnat.dg/opt37.ads b/gcc/testsuite/gnat.dg/opt37.ads
new file mode 100644 (file)
index 0000000..7507679
--- /dev/null
@@ -0,0 +1,18 @@
+package Opt37 is\r
+\r
+   type T_Bit is range 0 .. 1;\r
+   for T_Bit'Size use 1;\r
+\r
+   type Positive is range 0 .. (2 ** 31) - 1;\r
+   type Unsigned32 is mod 2 ** 32;\r
+\r
+   subtype T_Bit_Count is Positive;\r
+   subtype T_Bit_Index is T_Bit_Count range 1 .. T_Bit_Count'Last;\r
+\r
+   type T_Bit_Array is array (T_Bit_Count range <>) of T_Bit;\r
+   pragma Pack (T_Bit_Array);\r
+\r
+   function Func (Bit_Array : in T_Bit_Array;\r
+                  Bit_Index : in T_Bit_Index) return Positive;\r
+\r
+end Opt37;\r
index 563abe0..e863567 100644 (file)
@@ -2642,49 +2642,47 @@ associate_plusminus (gimple_stmt_iterator *gsi)
                  gimple_set_modified (stmt, true);
                }
            }
-         else if (CONVERT_EXPR_CODE_P (def_code) && code == MINUS_EXPR
+         else if (code == MINUS_EXPR
+                  && CONVERT_EXPR_CODE_P (def_code)
+                  && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
                   && TREE_CODE (rhs2) == SSA_NAME)
            {
-             /* (T)(ptr + adj) - (T)ptr -> (T)adj.  */
+             /* (T)(P + A) - (T)P -> (T)A.  */
              gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs2);
-             if (TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
-                 && is_gimple_assign (def_stmt2)
+             if (is_gimple_assign (def_stmt2)
                  && can_propagate_from (def_stmt2)
                  && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
                  && TREE_CODE (gimple_assign_rhs1 (def_stmt2)) == SSA_NAME)
                {
-                 /* Now we have (T)A - (T)ptr.  */
-                 tree ptr = gimple_assign_rhs1 (def_stmt2);
+                 /* Now we have (T)X - (T)P.  */
+                 tree p = gimple_assign_rhs1 (def_stmt2);
                  def_stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt));
                  if (is_gimple_assign (def_stmt2)
-                     && gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
-                     && gimple_assign_rhs1 (def_stmt2) == ptr)
+                     && can_propagate_from (def_stmt2)
+                     && (gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR
+                         || gimple_assign_rhs_code (def_stmt2) == PLUS_EXPR)
+                     && gimple_assign_rhs1 (def_stmt2) == p)
                    {
-                     /* And finally (T)(ptr + X) - (T)ptr.  */
-                     tree adj = gimple_assign_rhs2 (def_stmt2);
-                     /* If the conversion of the pointer adjustment to the
-                        final type requires a sign- or zero-extension we
-                        have to punt - it is not defined which one is
-                        correct.  */
-                     if (TYPE_PRECISION (TREE_TYPE (rhs1))
-                         <= TYPE_PRECISION (TREE_TYPE (adj))
-                         || (TREE_CODE (adj) == INTEGER_CST
-                             && tree_int_cst_sign_bit (adj) == 0))
+                     /* And finally (T)(P + A) - (T)P.  */
+                     tree a = gimple_assign_rhs2 (def_stmt2);
+                     /* For pointer types, if the conversion of A to the final
+                        type requires a sign- or zero-extension, then we have
+                        to punt - it is not defined which one is correct.  */
+                     if (!POINTER_TYPE_P (TREE_TYPE (rhs1))
+                         || TYPE_PRECISION (TREE_TYPE (rhs1))
+                            <= TYPE_PRECISION (TREE_TYPE (a))
+                         || (TREE_CODE (a) == INTEGER_CST
+                             && tree_int_cst_sign_bit (a) == 0))
                        {
                          if (useless_type_conversion_p (TREE_TYPE (rhs1),
-                                                        TREE_TYPE (adj)))
-                           {
-                             code = TREE_CODE (adj);
-                             rhs1 = adj;
-                           }
+                                                        TREE_TYPE (a)))
+                           code = TREE_CODE (a);
                          else
-                           {
-                             code = NOP_EXPR;
-                             rhs1 = adj;
-                           }
+                           code = NOP_EXPR;
+                         rhs1 = a;
                          rhs2 = NULL_TREE;
                          gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
-                                                         NULL_TREE);
+                                                         rhs2);
                          gcc_assert (gsi_stmt (*gsi) == stmt);
                          gimple_set_modified (stmt, true);
                        }