[PATCH] D47854: [LangRef] Clarify semantics of load metadata.

Hal Finkel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 7 07:14:02 PDT 2018


hfinkel added a comment.

In https://reviews.llvm.org/D47854#1124963, @nlopes wrote:

> I just got a scary ah-ah moment..
>  Take this code:
>
>   int f(int &p, int n, int a) {
>       int r = 0;
>       for (int i = 0; i < n; ++i) {
>         if (a) {
>           r = r * p + 3;
>         } else {
>           ++a;
>         }
>       }
>       return r;
>   }
>
>
> This code doesn't load p if `f` is called with `a = false` and `n = 1` (i.e., only 1 iteration of the loop and goes to the else branch).
>
> clang -O1 (not -O2 to avoid hard-to-read-unrolling):
>
>   define i32 @f(i32* dereferenceable(4), i32, i32) {
>     %4 = icmp sgt i32 %1, 0
>     br i1 %4, label %5, label %7
>  
>   ; <label>:5:
>     %6 = load i32, i32* %0, align 4   ; <---
>     br label %9
>  
>   ; <label>:7:
>     %8 = phi i32 [ 0, %3 ], [ %17, %9 ]
>     ret i32 %8
>  
>   ; <label>:9:
>     %10 = phi i32 [ 0, %5 ], [ %18, %9 ]
>     %11 = phi i32 [ 0, %5 ], [ %17, %9 ]
>     %12 = phi i32 [ %2, %5 ], [ %16, %9 ]
>     %13 = icmp eq i32 %12, 0
>     %14 = mul nsw i32 %6, %11
>     %15 = add nsw i32 %14, 3
>     %16 = select i1 %13, i32 1, i32 %12
>     %17 = select i1 %13, i32 %11, i32 %15
>     %18 = add nuw nsw i32 %10, 1
>     %19 = icmp eq i32 %18, %1
>     br i1 %19, label %7, label %9
>   }
>
>
> https://godbolt.org/g/SQh8EJ
>
> The load was moved to the loop preheader, but it's executed irrespective of `a`.
>  Hence if p is not 4-byte aligned, then LLVM introduce undefined behavior. Being dereferenceable doesn't imply it's so with a 4-byte alignment load.
>
> This implies we need to remove the !align attribute (as well as all the other) when hoisting loads. Lowering 1-byte loads is not particularly efficient..
>  We can't really define load !align as returning poison or anything other than UB since some chips trap with unaligned memory accesses. So this is a real bug we need to fix for those folks using SPARC & friends.


Yes, although hopefully align(4) would have also been specified on the function argument. As the reference must have been bound to a valid object, from C++ semantics, we should know that it's properly aligned. Do we do that now?


Repository:
  rL LLVM

https://reviews.llvm.org/D47854





More information about the llvm-commits mailing list