diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -312,6 +312,12 @@ AAMDNodes AAInfo; OrigLoad->getAAMetadata(AAInfo); newLoad->setAAMetadata(AAInfo); + // And other metadata. + newLoad->copyMetadata( + *OrigLoad, + {LLVMContext::MD_nontemporal, LLVMContext::MD_nonnull, + LLVMContext::MD_dereferenceable, LLVMContext::MD_align, + LLVMContext::MD_noundef, LLVMContext::MD_range}); Args.push_back(newLoad); ArgAttrVec.push_back(AttributeSet()); diff --git a/llvm/test/Transforms/ArgumentPromotion/metadata.ll b/llvm/test/Transforms/ArgumentPromotion/metadata.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/ArgumentPromotion/metadata.ll @@ -0,0 +1,44 @@ +; RUN: opt < %s -argpromotion -S | FileCheck %s + +define i32 @should_copy_range({ i32, i32 }* %x) { +; CHECK-LABEL: define i32 @should_copy_range( +; CHECK: %x.idx = getelementptr { i32, i32 }, { i32, i32 }* %x, i64 0, i32 0 +; CHECK-NEXT: %x.idx.val = load i32, i32* %x.idx, align 4, !range !0 +; CHECK-NEXT: %1 = call i32 @f_load_range(i32 %x.idx.val) +; CHECK-NEXT: ret i32 %1 +; + %1 = call i32 @f_load_range({ i32, i32 }* %x) + ret i32 %1 +} + +define internal i32 @f_load_range({ i32, i32 }* %v) { +; CHECK-LABEL: define internal i32 @f_load_range( +; CHECK: ret i32 +; + %1 = getelementptr inbounds { i32, i32 }, { i32, i32 }* %v, i64 0, i32 0 + %2 = load i32, i32* %1, align 4, !range !0 + ret i32 %2 +} + +define i32* @should_copy_nonnull({ i32*, i32* }* %x) { +; CHECK-LABEL: define i32* @should_copy_nonnull( +; CHECK: %x.idx = getelementptr { i32*, i32* }, { i32*, i32* }* %x, i64 0, i32 0 +; CHECK-NEXT: %x.idx.val = load i32*, i32** %x.idx, align 4, !nonnull !1 +; CHECK-NEXT: %1 = call i32* @f_load_nonnull(i32* %x.idx.val) +; CHECK-NEXT: ret i32* %1 +; + %1 = call i32* @f_load_nonnull({ i32*, i32* }* %x) + ret i32* %1 +} + +define internal i32* @f_load_nonnull({ i32*, i32* }* %v) { +; CHECK-LABEL: define internal i32* @f_load_nonnull( +; CHECK: ret i32* +; + %1 = getelementptr inbounds { i32*, i32* }, { i32*, i32* }* %v, i64 0, i32 0 + %2 = load i32*, i32** %1, align 4, !nonnull !1 + ret i32* %2 +} + +!0 = !{i32 0, i32 4} +!1 = !{}