Skip to content

LLVM Memory Model needs more rigor to avoid undesired optimization results #34577

Open
@RalfJung

Description

@RalfJung
Bugzilla Link 35229
Version 5.0
OS Linux
Depends On #33896
Blocks #39717
CC @comex,@efriedma-quic,@hfinkel,@jrmuizel,@jplatte,@aqjune,@sunfishcode,@nunoplopes,@regehr,@rnk

Extended Description

Clang/LLVM currently miscompiles the following program:

// gvnbug.c
#include <stdio.h>
#include <stdint.h>

int foo();

void test(int* gp1, int* gp2)
{
  int g = 0;
  int a = 0, b = 0;
  int x = 7777, y = 6666; // also try swapping these
  int* p = &g;
  int* q = &g;
  int* r = &g;

  if (foo()) {
    a = 1;
    p = &y+1;
    q = &x;
  }

  *gp1 = (uintptr_t)p+1;
  if (q == p) {
    b = 1;
    *gp2 = (uintptr_t)q+1;
    r = q;
  }
  *r = 42;

  printf("a = %d, b = %d, x = %d\n", a, b, x);
}

int main() {
  int gp1 = 0;
  int gp2 = 0;

  test(&gp1, &gp2);

  return 0;
}

// aux.c
int foo() { return 1; }
$ clang-5.0 aux.c gvnbug.c -o gvnbug -O3 && ./gvnbug 
a = 1, b = 1, x = 7777

This result is not allowed. If a and b are both 1, the branch q == p must have been taken, so r was set to &x (via q), so x cannot be 7777.

I think this issue has already come up in #33896, but so far there was no example showing that the bug arises independent of the incorrect inttoptr-simplification.

What is happening here (if my analysis is correct) is that GVN sees the equality q == p and uses that to replace q by p in the then-branch. Next, LLVM notices that because p is derived from y, writing to r (which will either have value &g or p in the line where the assignment happens) cannot possibly affect x, and hence the initial value of x can be propagated into the printf. GVN is wrong to perform this kind of replacement; just because the bit representations of two pointers are equal, that doesn't mean that their provenance information is equal.

Test case by Gil Hur.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions