gimple *new_stmt = gsi_stmt (i);
if (gimple_has_mem_ops (new_stmt))
gimple_set_vuse (new_stmt, reaching_vuse);
+ gcc_checking_assert (! (gimple_assign_load_p (point)
+ && gimple_assign_load_p (new_stmt))
+ || (tree_could_trap_p (gimple_assign_rhs1 (point))
+ == tree_could_trap_p (gimple_assign_rhs1
+ (new_stmt))));
}
gimple_stmt_iterator gsi = gsi_for_stmt (point);
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-O" } */
+
+/* PR tree-optimization/118514 */
+
+/* Check that we don't pull optimized references that could trap out of
+ loops. */
+
+int a, c = 1;
+unsigned char b[1], d;
+int main() {
+ while (a || !c) {
+ signed char e = b[1000000000];
+ d = e < 0 || b[1000000000] > 1;
+ if (d)
+ __builtin_abort ();
+ }
+ return 0;
+}
return true;
}
+/* Return true iff EXPR, a BIT_FIELD_REF, accesses a bit range that is known to
+ be in bounds for the referred operand type. */
+
+static bool
+bit_field_ref_in_bounds_p (tree expr)
+{
+ tree size_tree;
+ poly_uint64 size_max, min, wid, max;
+
+ size_tree = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ if (!size_tree || !poly_int_tree_p (size_tree, &size_max))
+ return false;
+
+ min = bit_field_offset (expr);
+ wid = bit_field_size (expr);
+ max = min + wid;
+ if (maybe_lt (max, min)
+ || maybe_lt (size_max, max))
+ return false;
+
+ return true;
+}
+
/* Return true if EXPR can trap, as in dereferencing an invalid pointer
location or floating point arithmetic. C.f. the rtl version, may_trap_p.
This routine expects only GIMPLE lhs or rhs input. */
restart:
switch (code)
{
+ case BIT_FIELD_REF:
+ if (DECL_P (TREE_OPERAND (expr, 0)) && !bit_field_ref_in_bounds_p (expr))
+ return true;
+ /* Fall through. */
+
case COMPONENT_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
- case BIT_FIELD_REF:
case VIEW_CONVERT_EXPR:
case WITH_SIZE_EXPR:
expr = TREE_OPERAND (expr, 0);