. */ if (TREE_CODE (addr) != ADDR_EXPR || DECL_P (TREE_OPERAND (addr, 0))) return fold_build2 (MEM_REF, type, addr, build_int_cst_wide (ptype, TREE_INT_CST_LOW (off), TREE_INT_CST_HIGH (off))); } /* *(foo *)fooarrptr => (*fooarrptr)[0] */ if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype)))) { tree type_domain; tree min_val = size_zero_node; tree osub = sub; sub = gimple_fold_indirect_ref (sub); if (! sub) sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), osub); type_domain = TYPE_DOMAIN (TREE_TYPE (sub)); if (type_domain && TYPE_MIN_VALUE (type_domain)) min_val = TYPE_MIN_VALUE (type_domain); if (TREE_CODE (min_val) == INTEGER_CST) return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE); } return NULL_TREE; } /* Return true if CODE is an operation that when operating on signed integer types involves undefined behavior on overflow and the operation can be expressed with unsigned arithmetic. */ bool arith_code_with_undefined_signed_overflow (tree_code code) { switch (code) { case PLUS_EXPR: case MINUS_EXPR: case MULT_EXPR: case NEGATE_EXPR: case POINTER_PLUS_EXPR: return true; default: return false; } } /* Rewrite STMT, an assignment with a signed integer or pointer arithmetic operation that can be transformed to unsigned arithmetic by converting its operand, carrying out the operation in the corresponding unsigned type and converting the result back to the original type. Returns a sequence of statements that replace STMT and also contain a modified form of STMT itself. */ gimple_seq rewrite_to_defined_overflow (gimple stmt) { if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "rewriting stmt with undefined signed " "overflow "); print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } tree lhs = gimple_assign_lhs (stmt); tree type = unsigned_type_for (TREE_TYPE (lhs)); gimple_seq stmts = NULL; for (unsigned i = 1; i < gimple_num_ops (stmt); ++i) { gimple_seq stmts2 = NULL; gimple_set_op (stmt, i, force_gimple_operand (fold_convert (type, gimple_op (stmt, i)), &stmts2, true, NULL_TREE)); gimple_seq_add_seq (&stmts, stmts2); } gimple_assign_set_lhs (stmt, make_ssa_name (type, stmt)); if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) gimple_assign_set_rhs_code (stmt, PLUS_EXPR); gimple_seq_add_stmt (&stmts, stmt); gimple cvt = gimple_build_assign_with_ops (NOP_EXPR, lhs, gimple_assign_lhs (stmt), NULL_TREE); gimple_seq_add_stmt (&stmts, cvt); return stmts; }