Skip to content

Interaction between C's restrict pointer and pointer casted from integer is ambiguous in LLVM's LangRef #39193

Open
@aqjune

Description

@aqjune
Bugzilla Link 39846
Version trunk
OS Linux
Depends On #33896
Blocks #39717
Attachments The example code
CC @hfinkel,@dobbelaj-snps,@aqjune,@LebedevRI,@zhengyang92,@nikic,@nunoplopes,@RalfJung,@regehr,@sanjoy

Extended Description

Consider this example:

#include <stdint.h>

int foo(int *restrict x, int *restrict y) {
  *y = 23;
  uintptr_t xi = (uintptr_t)x;
  uintptr_t yi = (uintptr_t)y;
  if (xi != yi) { // xi == yi, so this is never taken
    yi = xi;
  }
  *(int*)yi = 42; // changes *y or UB?
  return *y;
}

int bar() {
  int x;
  return foo(&x, &x); // returns 23
}

After -O3, foo(&x, &x) is optimized into ret i32 23 ( https://godbolt.org/z/ty73Xk ).

Here are several ways to explain this result:

(1) foo(&x, &x) is not allowed in LLVM IR - but I believe this makes the semantics more undefined than C (because C allows multiple restrict pointers to point have the same address if they are only read, but never written)

(2) *(int*)yi = 42 is not allowed - but LLVM IR LangRef's pointer aliasing rules ( https://llvm.org/docs/LangRef.html#pointer-aliasing-rules ) say that (int *)yi is based on y, so I think this behavior is well-defined. Perhaps we should update the definition of based-on relation, if we follow this option.

(3) Restrict pointer cannot be casted into integer - if we choose this option, LangRef should be updated to deal with this.

If we're to choose (2) and (3), we should update LLVM LangRef.

If this is considered to be miscompilation, I think this is related to #33896 .

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzillacllvmUmbrella label for LLVM issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions