On Wed, Jan 03, 2018 at 01:49:11PM +0100, Richard Biener wrote:
> On January 3, 2018 1:21:40 PM GMT+01:00, Nathan Sidwell <[email protected]>
> wrote:
> >On 01/02/2018 04:12 PM, Jakub Jelinek wrote:
> >> Hi!
> >>
> >> This patch improves code generated for:
> >> struct A { int a; };
> >> struct B { int b; };
> >> struct C : A, B { int c; };
> >> C *bar (B *b) { return &static_cast<C &>(*b); }
> >> Unlike return static_cast<C *>(b); where b can be validly NULL, the
> >> reference shouldn't bind to NULL, but we still emit
> >> b ? b - 4 : 0. The following patch omits the non-NULL check except
> >when
> >> -fsanitize=null (or undefined) and when sanitizing makes sure such
> >bugs are
> >> diagnosed.
> >
> >It's sad the optimizers don't know REFERENCE_TYPE (x) means x != NULL.
> >(or perhaps that's just a C++ semantic of REFERENCE_TYPE?).
>
> Given we treat reference and pointer types as interchangeable we indeed don't
> know that.
Yeah, within functions that is quickly lost, sometimes even during folding as
in this case.
In some cases the optimizers can infer that, e.g. nonnull_arg_p has:
/* Values passed by reference are always non-NULL. */
if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
&& flag_delete_null_pointer_checks)
return true;
because we don't change randomly types of function arguments...
Though, the above snippet reminds me I should probably also replace:
+ expr = build_base_path (MINUS_EXPR, expr, base,
+ /*nonnull=*/!sanitize_null_p, complain);
with:
+ expr = build_base_path (MINUS_EXPR, expr, base,
+ /*nonnull=*/(!sanitize_null_p
+ && flag_delete_null_pointer_checks),
+ complain);
Instead of checking for generated asm without sanitization, I think it will
be easier/more portable to verify no conditionals in *.optimized dump.
Let me repost the updated patch.
Jakub