[PATCH] D74935: [LangRef][AliasAnalysis] Clarify `noalias` affects only modified objects

Jeroen Dobbelaere via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 5 01:41:28 PST 2020


jeroen.dobbelaere added a comment.

Just to give an example:

  int foo(int* restrict *pA, int* restrict *pB) {
    int tmp=**pB;
    **pA=42;
    return tmp - **pB; // **pA and **pB can refer to the same objects
  }

This gives following llvm-ir code with the 'full noalias' clang version (after optimizations):

  ; Function Attrs: nofree nounwind uwtable
  define dso_local i32 @foo(i32** nocapture %pA, i32** nocapture readonly %pB) local_unnamed_addr #0 !noalias !2 {
  entry:
    %0 = load i32*, i32** %pB, noalias_sidechannel i32** undef, align 8, !tbaa !5, !noalias !2
    %1 = tail call i32* @llvm.side.noalias.p0i32.p0i8.p0p0i32.p0p0i32.i64(i32* %0, i8* null, i32** %pB, i32** undef, i64 0, metadata !2), !tbaa !5, !noalias !2
    %2 = load i32, i32* %0, noalias_sidechannel i32* %1, align 4, !tbaa !9, !noalias !2
    %3 = load i32*, i32** %pA, noalias_sidechannel i32** undef, align 8, !tbaa !5, !noalias !2
    %4 = tail call i32* @llvm.side.noalias.p0i32.p0i8.p0p0i32.p0p0i32.i64(i32* %3, i8* null, i32** %pA, i32** undef, i64 0, metadata !2), !tbaa !5, !noalias !2
    store i32 42, i32* %3, noalias_sidechannel i32* %4, align 4, !tbaa !9, !noalias !2
    %5 = load i32, i32* %0, noalias_sidechannel i32* %1, align 4, !tbaa !9, !noalias !2
    %sub = sub nsw i32 %2, %5
    ret i32 %sub
  }

When adding 'noalias' to the arguments (my understanding is that this  is what the attributer would deduce, as pA and pB are only read):

  ; Function Attrs: nofree nounwind uwtable
  define dso_local i32 @foo(i32** noalias nocapture %pA, i32** noalias nocapture readonly %pB) local_unnamed_addr #0 !noalias !2 {
  entry:
    %0 = load i32*, i32** %pB, noalias_sidechannel i32** undef, align 8, !tbaa !5, !noalias !2
    %1 = tail call i32* @llvm.side.noalias.p0i32.p0i8.p0p0i32.p0p0i32.i64(i32* %0, i8* null, i32** %pB, i32** undef, i64 0, metadata !2), !tbaa !5, !noalias !2
    %2 = load i32, i32* %0, noalias_sidechannel i32* %1, align 4, !tbaa !9, !noalias !2
    %3 = load i32*, i32** %pA, noalias_sidechannel i32** undef, align 8, !tbaa !5, !noalias !2
    %4 = tail call i32* @llvm.side.noalias.p0i32.p0i8.p0p0i32.p0p0i32.i64(i32* %3, i8* null, i32** %pA, i32** undef, i64 0, metadata !2), !tbaa !5, !noalias !2
    store i32 42, i32* %3, noalias_sidechannel i32* %4, align 4, !tbaa !9, !noalias !2
    %5 = load i32, i32* %0, noalias_sidechannel i32* %1, align 4, !tbaa !9, !noalias !2
    %sub = sub nsw i32 %2, %5
    ret i32 %sub
  }

and reoptimizing, we now get:

  ; Function Attrs: nofree nounwind uwtable
  define dso_local i32 @foo(i32** noalias nocapture %pA, i32** noalias nocapture readonly %pB) local_unnamed_addr #0 !noalias !2 {
  entry:
    %0 = load i32*, i32** %pA, noalias_sidechannel i32** undef, align 8, !tbaa !5, !noalias !2
    %1 = tail call i32* @llvm.side.noalias.p0i32.p0i8.p0p0i32.p0p0i32.i64(i32* %0, i8* null, i32** %pA, i32** undef, i64 0, metadata !2), !tbaa !5, !noalias !2
    store i32 42, i32* %0, noalias_sidechannel i32* %1, align 4, !tbaa !9, !noalias !2
    ret i32 0
  }

'%sub' is optimized away because the now the alias analyzer deduces that '%pA' and '%pB' cannot refer to the same objects. This implies (because of restrict) that '*%pA' and '*%pB' cannot refer to the same objects and because of that, the 'store i32' could not have interfered with the 'load i32'.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D74935/new/

https://reviews.llvm.org/D74935





More information about the cfe-commits mailing list