Hi,
playing with testcases for path isolation and const function, I noticed
that we do not seem to even try to isolate out of range array accesses:
int a[3]={0,1,2};
test(int i)
{
       if (i > 3)
         return test2(a[i]);
       return a[i];
}

Here call to test2 is dead, since a[i] will access memory past of the
array.  We produce a warning:

t.c:5:24: warning: array subscript 4 is above array bounds of ‘int[3]’ 
[-Warray-bounds=]

but we still keep the call:

test:
.LFB0:
        .cfi_startproc
        movslq  %edi, %rax
        movl    a(,%rax,4), %eax
        cmpl    $3, %edi
        jg      .L4
        ret
        .p2align 4,,10
        .p2align 3
.L4:
        movl    %eax, %edi
        xorl    %eax, %eax
        jmp     test2

We eventually move the load before conditional, but at path isolation
time it is still quite obvious the conditional being true invokes
undefined behaviour

int test (int i)
{
  int _1;
  int _2;
  int _6;
  int _8;
  
  <bb 2> [local count: 1073741824]:
  if (i_4(D) > 3)
    goto <bb 3>; [20.24%]
  else
    goto <bb 4>; [79.76%]

  <bb 3> [local count: 217325344]:
  _1 = a[i_4(D)];
  _8 = test2 (_1);
  goto <bb 5>; [100.00%]

  <bb 4> [local count: 856416481]:
  _6 = a[i_4(D)];
  
  <bb 5> [local count: 1073741824]:
  # _2 = PHI <_8(3), _6(4)>
  return _2;
} 

Curiously adjusting the testcase:

const int a[3]={0,1,2};
test(int i)
{
        if (i == 3)
                return test2(a[i]);
        return a[i];
}
no longer has undefined behaviour visible at isolate-paths
int test (int i)
{
  int _1;
  int _5;
  int _7;

  <bb 2> [local count: 1073741824]:
  if (i_3(D) == 3)
    goto <bb 3>; [11.56%]
  else
    goto <bb 4>; [88.44%]

  <bb 3> [local count: 124124552]:
  _7 = test2 (0);
  goto <bb 5>; [100.00%]

  <bb 4> [local count: 949617273]:
  _5 = a[i_3(D)];

  <bb 5> [local count: 1073741824]:
  # _1 = PHI <_7(3), _5(4)>
  return _1;
}
since we fold the load to 0.  It would perhaps help optimizers to keep info on 
undefined behaviour happening there.

Honza

Reply via email to