https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67651

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |ASSIGNED
   Last reconfirmed|                            |2015-09-21
           Assignee|unassigned at gcc dot gnu.org      |rguenth at gcc dot 
gnu.org
     Ever confirmed|0                           |1

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
We optimize this since GCC 3.4 and -fno-delete-null-pointer-checks already
doesn't have any effect on that.  GCC 3.3 wasn't able to optimize this with
any setting of this flag.

@item -fdelete-null-pointer-checks
@opindex fdelete-null-pointer-checks
Assume that programs cannot safely dereference null pointers, and that
no code or data element resides at address zero.
This option enables simple constant
folding optimizations at all optimization levels.  In addition, other
optimization passes in GCC use this flag to control global dataflow
analyses that eliminate useless checks for null pointers; these assume
that a memory access to address zero always results in a trap, so
that if a pointer is checked after it has already been dereferenced,
it cannot be null.

Note however that in some environments this assumption is not true.
Use @option{-fno-delete-null-pointer-checks} to disable this optimization
for programs that depend on that behavior.

This option is enabled by default on most targets.  On Nios II ELF, it
defaults to off.  On AVR and CR16, this option is completely disabled.


so confirmed.  Note that GIMPLE optimizers are fine and we end up expanding
from

main ()
{
  int _1;

  <bb 2>:
  if (&_vector_table == 0B)
    goto <bb 4>;
  else
    goto <bb 3>;

  <bb 3>:

  <bb 4>:
  # _1 = PHI <1(2), 2(3)>
  return _1;

But RTL generation already fucks this up:

;; Generating RTL for gimple basic block 2

;; if (&_vector_table == 0B)

(nil)

...

;;
;; Full RTL generated for this function:
;;
(note 1 0 5 NOTE_INSN_DELETED)
;; basic block 2, loop depth 0, count 0, freq 10000, maybe hot
;;  prev block 0, next block 1, flags: (NEW, REACHABLE, RTL, MODIFIED)
;;  pred:       ENTRY [100.0%]  (FALLTHRU)
(note 5 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 2 5 4 2 NOTE_INSN_FUNCTION_BEG)
(insn 4 2 10 2 (set (reg:SI 87 [ D.1844 ])
        (const_int 2 [0x2])) t.c:10 -1
     (nil))
(insn 10 4 14 2 (set (reg:SI 88 [ <retval> ])
        (reg:SI 87 [ D.1844 ])) -1
     (nil))
(insn 14 10 15 2 (set (reg/i:SI 0 ax)
        (reg:SI 88 [ <retval> ])) t.c:12 -1
     (nil))
(insn 15 14 0 2 (use (reg/i:SI 0 ax)) t.c:12 -1
     (nil))
;;  succ:       EXIT [100.0%]  (FALLTHRU)


Because of

simplify_const_relational_operation (code=EQ, mode=DImode, op0=0x7ffff6a06168, 
    op1=0x7ffff68d3480)
    at /space/rguenther/src/svn/trunk/gcc/simplify-rtx.c:4840
5088          /* Some addresses are known to be nonzero.  We don't know
5089             their sign, but equality comparisons are known.  */
5090          if (nonzero_address_p (trueop0))
5091            {
5092              if (code == EQ || code == LEU)
5093                return const0_rtx;

on (symbol_ref:DI ("_vector_table") [flags 0x40] <var_decl 0x7ffff68d8c60
_vector_table>)

/* Return true if X is an address that is known to not be zero.  */

bool
nonzero_address_p (const_rtx x)
{
  const enum rtx_code code = GET_CODE (x);

  switch (code)
    {
    case SYMBOL_REF:
      return !SYMBOL_REF_WEAK (x);

which misses a check on flag_delete_null_pointer_checks.  Fixing that fixes the
bug.

Reply via email to