Index: lib/Transforms/Scalar/SROA.cpp =================================================================== --- lib/Transforms/Scalar/SROA.cpp +++ lib/Transforms/Scalar/SROA.cpp @@ -2402,9 +2402,15 @@ if (LI.isVolatile()) NewLI->setAtomic(LI.getOrdering(), LI.getSynchScope()); - // Try to preserve nonnull metadata - if (TargetTy->isPointerTy()) - NewLI->copyMetadata(LI, LLVMContext::MD_nonnull); + // Any !nonnull metadata on the old load is also valid on the new load, + // so we can add it to the new load. This is valid even if there is a + // `zext` (which does not make much sense, but can occur if someone + // is treating pointers as integers) - if the loaded value is a 0, + // the extended value will also be `null`. + if (MDNode *N = LI.getMetadata(LLVMContext::MD_nonnull)) { + copyNonnullMetadata(LI, N, *NewLI); + } + V = NewLI; // If this is an integer load past the end of the slice (which means the @@ -3587,7 +3593,7 @@ PartPtrTy, BasePtr->getName() + "."), getAdjustedAlignment(LI, PartOffset, DL), /*IsVolatile*/ false, LI->getName()); - PLoad->copyMetadata(*LI, LLVMContext::MD_mem_parallel_loop_access); + PLoad->copyMetadata(*LI, LLVMContext::MD_mem_parallel_loop_access); // Append this load onto the list of split loads so we can find it later // to rewrite the stores. Index: test/Transforms/SROA/pr32902.ll =================================================================== --- /dev/null +++ test/Transforms/SROA/pr32902.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -sroa -S | FileCheck %s +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux" + + + +%foo = type { %bar* } +%bar = type { [4 x i8] } + +declare void @foo(i64* noalias nocapture) + +; Make sure we properly handle the !nonnull attribute when we +; convert a pointer load to an integer load. +; CHECK-LABEL: @_ZN4core3fmt9Formatter12pad_integral17h1dcf0f409406b6e5E() +; CHECK-NEXT: start: +; CHECK-NEXT: %0 = inttoptr i64 0 to %bar* +; CHECK-NEXT: ret %bar* %0 +define %bar* @_ZN4core3fmt9Formatter12pad_integral17h1dcf0f409406b6e5E() { +start: + %arg4.i = alloca %foo, align 8 + + %0 = bitcast %foo* %arg4.i to i64* + store i64 0, i64* %0, align 8 + + %1 = getelementptr inbounds %foo, %foo* %arg4.i, i64 0, i32 0 + %2 = load %bar*, %bar** %1, align 8, !nonnull !0 + ret %bar* %2 +} + +!0 = !{}