diff options
author | Richard Biener <rguenther@suse.de> | 2016-07-19 10:19:46 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2016-07-19 10:19:46 +0000 |
commit | cef5388d95009657bd34179e4086da5074c67dcd (patch) | |
tree | 05880e90b539eab18ab3f9cd3a92b9fd7c120e74 /gcc/tree-ssa-sccvn.c | |
parent | 9a4cb9733db86b7be143a2b8ab7d03406e025a5d (diff) | |
download | gcc-cef5388d95009657bd34179e4086da5074c67dcd.zip gcc-cef5388d95009657bd34179e4086da5074c67dcd.tar.gz gcc-cef5388d95009657bd34179e4086da5074c67dcd.tar.bz2 |
re PR tree-optimization/71901 (ice in find_or_generate_expression)
2016-07-19 Richard Biener <rguenther@suse.de>
PR tree-optimization/71901
* tree-ssa-sccvn.h (struct vn_reference_op_struct): Add
align member, group stuff with the bitfield.
(vn_ref_op_align_unit): New inline.
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): For ARRAY_REFs
record element alignment and operand 3 unchanged.
(ao_ref_init_from_vn_reference): Adjust.
(valueize_refs_1): Likewise.
* tree-ssa-pre.c (create_component_ref_by_pieces_1): Likewise.
* gcc.dg/torture/pr71901.c: New testcase.
From-SVN: r238468
Diffstat (limited to 'gcc/tree-ssa-sccvn.c')
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index b1f10d5..e685342 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -805,24 +805,30 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result) break; case ARRAY_RANGE_REF: case ARRAY_REF: - /* Record index as operand. */ - temp.op0 = TREE_OPERAND (ref, 1); - /* Always record lower bounds and element size. */ - temp.op1 = array_ref_low_bound (ref); - temp.op2 = array_ref_element_size (ref); - /* array_ref_element_size forces the result to sizetype - even if that is the same as bitsizetype. */ - STRIP_USELESS_TYPE_CONVERSION (temp.op2); - if (TREE_CODE (temp.op0) == INTEGER_CST - && TREE_CODE (temp.op1) == INTEGER_CST - && TREE_CODE (temp.op2) == INTEGER_CST) - { - offset_int off = ((wi::to_offset (temp.op0) - - wi::to_offset (temp.op1)) - * wi::to_offset (temp.op2)); - if (wi::fits_shwi_p (off)) - temp.off = off.to_shwi(); - } + { + tree eltype = TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref, 0))); + /* Record index as operand. */ + temp.op0 = TREE_OPERAND (ref, 1); + /* Always record lower bounds and element size. */ + temp.op1 = array_ref_low_bound (ref); + /* But record element size in units of the type alignment. */ + temp.op2 = TREE_OPERAND (ref, 3); + temp.align = eltype->type_common.align; + if (! temp.op2) + temp.op2 = size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (eltype), + size_int (TYPE_ALIGN_UNIT (eltype))); + if (TREE_CODE (temp.op0) == INTEGER_CST + && TREE_CODE (temp.op1) == INTEGER_CST + && TREE_CODE (temp.op2) == INTEGER_CST) + { + offset_int off = ((wi::to_offset (temp.op0) + - wi::to_offset (temp.op1)) + * wi::to_offset (temp.op2) + * vn_ref_op_align_unit (&temp)); + if (wi::fits_shwi_p (off)) + temp.off = off.to_shwi(); + } + } break; case VAR_DECL: if (DECL_HARD_REGISTER (ref)) @@ -1021,7 +1027,7 @@ ao_ref_init_from_vn_reference (ao_ref *ref, offset_int woffset = wi::sext (wi::to_offset (op->op0) - wi::to_offset (op->op1), TYPE_PRECISION (TREE_TYPE (op->op0))); - woffset *= wi::to_offset (op->op2); + woffset *= wi::to_offset (op->op2) * vn_ref_op_align_unit (op); woffset <<= LOG2_BITS_PER_UNIT; offset += woffset; } @@ -1471,7 +1477,8 @@ valueize_refs_1 (vec<vn_reference_op_s> orig, bool *valueized_anything) { offset_int off = ((wi::to_offset (vro->op0) - wi::to_offset (vro->op1)) - * wi::to_offset (vro->op2)); + * wi::to_offset (vro->op2) + * vn_ref_op_align_unit (vro)); if (wi::fits_shwi_p (off)) vro->off = off.to_shwi (); } |