===================================================================
@@ -213,6 +213,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "params.h"
#include "tree-affine.h"
+#include "builtins.h"
/* The maximum number of iterations between the considered memory
references. */
@@ -1364,11 +1365,16 @@ replace_ref_with (gimple *stmt, tree new_tree, boo
/* Returns a memory reference to DR in the ITER-th iteration of
the loop it was analyzed in. Append init stmts to STMTS. */
-static tree
+static tree
ref_at_iteration (data_reference_p dr, int iter, gimple_seq *stmts)
{
tree off = DR_OFFSET (dr);
tree coff = DR_INIT (dr);
+ tree ref = DR_REF (dr);
+ enum tree_code ref_code = ERROR_MARK;
+ tree ref_type = NULL_TREE;
+ tree ref_op1 = NULL_TREE;
+ tree ref_op2 = NULL_TREE;
if (iter == 0)
;
else if (TREE_CODE (DR_STEP (dr)) == INTEGER_CST)
@@ -1377,27 +1383,48 @@ ref_at_iteration (data_reference_p dr, int iter, g
else
off = size_binop (PLUS_EXPR, off,
size_binop (MULT_EXPR, DR_STEP (dr), ssize_int (iter)));
- tree addr = fold_build_pointer_plus (DR_BASE_ADDRESS (dr), off);
- addr = force_gimple_operand_1 (unshare_expr (addr), stmts,
- is_gimple_mem_ref_addr, NULL_TREE);
- tree alias_ptr = fold_convert (reference_alias_ptr_type (DR_REF (dr)), coff);
/* While data-ref analysis punts on bit offsets it still handles
bitfield accesses at byte boundaries. Cope with that. Note that
- we cannot simply re-apply the outer COMPONENT_REF because the
- byte-granular portion of it is already applied via DR_INIT and
- DR_OFFSET, so simply build a BIT_FIELD_REF knowing that the bits
+ if the bitfield object also starts at a byte-boundary we can simply
+ replicate the COMPONENT_REF, but we have to subtract the component's
+ byte-offset from the MEM_REF address first.
+ Otherwise we simply build a BIT_FIELD_REF knowing that the bits
start at offset zero. */
- if (TREE_CODE (DR_REF (dr)) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (DR_REF (dr), 1)))
+ if (TREE_CODE (ref) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
{
- tree field = TREE_OPERAND (DR_REF (dr), 1);
- return build3 (BIT_FIELD_REF, TREE_TYPE (DR_REF (dr)),
- build2 (MEM_REF, DECL_BIT_FIELD_TYPE (field),
- addr, alias_ptr),
- DECL_SIZE (field), bitsize_zero_node);
+ unsigned HOST_WIDE_INT boff;
+ tree field = TREE_OPERAND (ref, 1);
+ ref_type = TREE_TYPE (ref);
+ boff = tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field));
+ /* This can occur in Ada. See the comment in get_bit_range. */
+ if (boff % BITS_PER_UNIT != 0)
+ {
+ ref_code = BIT_FIELD_REF;
+ ref_op1 = DECL_SIZE (field);
+ ref_op2 = bitsize_zero_node;
+ }
+ else
+ {
+ boff >>= LOG2_BITS_PER_UNIT;
+ boff += tree_to_uhwi (component_ref_field_offset (ref));
+ coff = size_binop (MINUS_EXPR, coff, ssize_int (boff));
+ ref_code = COMPONENT_REF;
+ ref_op1 = field;
+ ref_op2 = TREE_OPERAND (ref, 2);
+ ref = TREE_OPERAND (ref, 0);
+ }
}
- else
- return fold_build2 (MEM_REF, TREE_TYPE (DR_REF (dr)), addr, alias_ptr);
+ tree addr = fold_build_pointer_plus (DR_BASE_ADDRESS (dr), off);
+ addr = force_gimple_operand_1 (unshare_expr (addr), stmts,
+ is_gimple_mem_ref_addr, NULL_TREE);
+ tree alias_ptr = fold_convert (reference_alias_ptr_type (ref), coff);
+ tree type = build_aligned_type (TREE_TYPE (ref),
+ get_object_alignment (ref));
+ ref = build2 (MEM_REF, type, addr, alias_ptr);
+ if (ref_type)
+ ref = build3 (ref_code, ref_type, ref, ref_op1, ref_op2);
+ return ref;
}
/* Get the initialization expression for the INDEX-th temporary variable
===================================================================
@@ -0,0 +1,43 @@
+struct lock_chain {
+ unsigned int irq_context: 2,
+ depth: 6,
+ base: 24;
+};
+
+__attribute__((noinline, noclone))
+struct lock_chain * foo (struct lock_chain *chain)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ {
+ chain[i+1].base = chain[i].base;
+ }
+ return chain;
+}
+
+struct lock_chain1 {
+ char x;
+ unsigned short base;
+} __attribute__((packed));
+
+__attribute__((noinline, noclone))
+struct lock_chain1 * bar (struct lock_chain1 *chain)
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ {
+ chain[i+1].base = chain[i].base;
+ }
+ return chain;
+}
+
+struct lock_chain test [101];
+struct lock_chain1 test1 [101];
+
+int
+main ()
+{
+ foo (test);
+ bar (test1);
+ return 0;
+}
===================================================================
@@ -0,0 +1,14 @@
+-- { dg-do run }
+-- { dg-options "-O3" }
+-- PR tree-optimization/71083
+with Loop_Optimization23_Pkg;
+use Loop_Optimization23_Pkg;
+procedure Loop_Optimization23 is
+ Test : ArrayOfStructB;
+begin
+ Test (0).b.b := 9999;
+ Foo (Test);
+ if Test (100).b.b /= 9999 then
+ raise Program_Error;
+ end if;
+end;
===================================================================
@@ -0,0 +1,11 @@
+-- { dg-do compile }
+-- { dg-options "-O3" }
+-- PR tree-optimization/71083
+package body Loop_Optimization23_Pkg is
+ procedure Foo (X : in out ArrayOfStructB) is
+ begin
+ for K in 0..99 loop
+ X (K+1).b.b := X (K).b.b;
+ end loop;
+ end Foo;
+end Loop_Optimization23_Pkg;
===================================================================
@@ -0,0 +1,17 @@
+-- PR tree-optimization/71083
+package Loop_Optimization23_Pkg is
+ type Nibble is mod 2**4;
+ type Int24 is mod 2**24;
+ type StructA is record
+ a : Nibble;
+ b : Int24;
+ end record;
+ pragma Pack(StructA);
+ type StructB is record
+ a : Nibble;
+ b : StructA;
+ end record;
+ pragma Pack(StructB);
+ type ArrayOfStructB is array(0..100) of StructB;
+ procedure Foo (X : in out ArrayOfStructB);
+end Loop_Optimization23_Pkg;