diff --git a/llvm/lib/IR/KnowledgeRetention.cpp b/llvm/lib/IR/KnowledgeRetention.cpp --- a/llvm/lib/IR/KnowledgeRetention.cpp +++ b/llvm/lib/IR/KnowledgeRetention.cpp @@ -20,6 +20,11 @@ cl::desc("enable preservation of all attrbitues. even those that are " "unlikely to be usefull")); +cl::opt EnableKnowledgeRetention( + "enable-knowledge-retention", cl::init(false), cl::Hidden, + cl::desc( + "enable preservation of attributes throughout code transformation")); + namespace { struct AssumedKnowledge { @@ -166,6 +171,8 @@ } // namespace CallInst *llvm::BuildAssumeFromInst(const Instruction *I, Module *M) { + if (!EnableKnowledgeRetention) + return nullptr; AssumeBuilderState Builder(M); Builder.addInstruction(I); return Builder.build(); diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -50,6 +50,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/KnowledgeRetention.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" @@ -1695,11 +1696,16 @@ VMap[&*I] = ActualArg; } + // TODO: Remove this when users have been updated to the assume bundles. // Add alignment assumptions if necessary. We do this before the inlined // instructions are actually cloned into the caller so that we can easily // check what will be known at the start of the inlined code. AddAlignmentAssumptions(CS, IFI); + /// Preserve all attributes on of the call and its parameters. + if (Instruction *Assume = BuildAssumeFromInst(CS.getInstruction())) + Assume->insertBefore(CS.getInstruction()); + // We want the inliner to prune the code as it copies. We would LOVE to // have no dead or constant instructions leftover after inlining occurs // (which can happen, e.g., because an argument was constant), but we'll be diff --git a/llvm/test/IR/assume-builder.ll b/llvm/test/IR/assume-builder.ll --- a/llvm/test/IR/assume-builder.ll +++ b/llvm/test/IR/assume-builder.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -passes='assume-builder,verify' -S %s | FileCheck %s --check-prefixes=BASIC -; RUN: opt -passes='assume-builder,verify' --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL +; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=BASIC +; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL declare void @func(i32*, i32*) declare void @func_cold(i32*) cold diff --git a/llvm/test/Transforms/Inline/arg-attr-propagation.ll b/llvm/test/Transforms/Inline/arg-attr-propagation.ll --- a/llvm/test/Transforms/Inline/arg-attr-propagation.ll +++ b/llvm/test/Transforms/Inline/arg-attr-propagation.ll @@ -1,11 +1,14 @@ -; RUN: opt -inline -S < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature +; RUN: opt -inline -S < %s | FileCheck --check-prefixes=CHECK,NO_ASSUME %s +; RUN: opt -inline -S --enable-knowledge-retention < %s | FileCheck %s --check-prefixes=CHECK,USE_ASSUME ; The callee guarantees that the pointer argument is nonnull and dereferenceable. ; That information should transfer to the caller. define i32 @callee(i32* dereferenceable(32) %t1) { -; CHECK-LABEL: @callee(i32* dereferenceable(32) %t1) -; CHECK-NEXT: [[T2:%.*]] = load i32, i32* %t1 +; CHECK-LABEL: define {{[^@]+}}@callee +; CHECK-SAME: (i32* dereferenceable(32) [[T1:%.*]]) +; CHECK-NEXT: [[T2:%.*]] = load i32, i32* [[T1]] ; CHECK-NEXT: ret i32 [[T2]] ; %t2 = load i32, i32* %t1 @@ -16,9 +19,16 @@ ; The caller argument could be known nonnull and dereferenceable(32). define i32 @caller1(i32* %t1) { -; CHECK-LABEL: @caller1(i32* %t1) -; CHECK-NEXT: [[T2_I:%.*]] = load i32, i32* %t1 -; CHECK-NEXT: ret i32 [[T2_I]] +; NO_ASSUME-LABEL: define {{[^@]+}}@caller1 +; NO_ASSUME-SAME: (i32* [[T1:%.*]]) +; NO_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]] +; NO_ASSUME-NEXT: ret i32 [[T2_I]] +; +; USE_ASSUME-LABEL: define {{[^@]+}}@caller1 +; USE_ASSUME-SAME: (i32* [[T1:%.*]]) +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[T1]], i64 32) ] +; USE_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]] +; USE_ASSUME-NEXT: ret i32 [[T2_I]] ; %t2 = tail call i32 @callee(i32* dereferenceable(32) %t1) ret i32 %t2 @@ -28,9 +38,16 @@ ; The dereferenceable amount could be increased. define i32 @caller2(i32* dereferenceable(31) %t1) { -; CHECK-LABEL: @caller2(i32* dereferenceable(31) %t1) -; CHECK-NEXT: [[T2_I:%.*]] = load i32, i32* %t1 -; CHECK-NEXT: ret i32 [[T2_I]] +; NO_ASSUME-LABEL: define {{[^@]+}}@caller2 +; NO_ASSUME-SAME: (i32* dereferenceable(31) [[T1:%.*]]) +; NO_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]] +; NO_ASSUME-NEXT: ret i32 [[T2_I]] +; +; USE_ASSUME-LABEL: define {{[^@]+}}@caller2 +; USE_ASSUME-SAME: (i32* dereferenceable(31) [[T1:%.*]]) +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[T1]], i64 32) ] +; USE_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]] +; USE_ASSUME-NEXT: ret i32 [[T2_I]] ; %t2 = tail call i32 @callee(i32* dereferenceable(32) %t1) ret i32 %t2 @@ -40,9 +57,16 @@ ; Make sure that we don't propagate a smaller dereferenceable amount. define i32 @caller3(i32* dereferenceable(33) %t1) { -; CHECK-LABEL: @caller3(i32* dereferenceable(33) %t1) -; CHECK-NEXT: [[T2_I:%.*]] = load i32, i32* %t1 -; CHECK-NEXT: ret i32 [[T2_I]] +; NO_ASSUME-LABEL: define {{[^@]+}}@caller3 +; NO_ASSUME-SAME: (i32* dereferenceable(33) [[T1:%.*]]) +; NO_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]] +; NO_ASSUME-NEXT: ret i32 [[T2_I]] +; +; USE_ASSUME-LABEL: define {{[^@]+}}@caller3 +; USE_ASSUME-SAME: (i32* dereferenceable(33) [[T1:%.*]]) +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[T1]], i64 32) ] +; USE_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]] +; USE_ASSUME-NEXT: ret i32 [[T2_I]] ; %t2 = tail call i32 @callee(i32* dereferenceable(32) %t1) ret i32 %t2 diff --git a/llvm/test/Transforms/Inline/noalias2.ll b/llvm/test/Transforms/Inline/noalias2.ll --- a/llvm/test/Transforms/Inline/noalias2.ll +++ b/llvm/test/Transforms/Inline/noalias2.ll @@ -1,8 +1,25 @@ -; RUN: opt -inline -enable-noalias-to-md-conversion -S < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature +; RUN: opt -inline -enable-noalias-to-md-conversion -S < %s | FileCheck %s --check-prefixes=CHECK,NO_ASSUME +; RUN: opt -inline -enable-noalias-to-md-conversion --enable-knowledge-retention -S < %s | FileCheck %s --check-prefixes=CHECK,USE_ASSUME + target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" define void @hello(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 { +; CHECK-LABEL: define {{[^@]+}}@hello +; CHECK-SAME: (float* noalias nocapture [[A:%.*]], float* noalias nocapture readonly [[C:%.*]]) #0 +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 +; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX]], align 4 +; CHECK-NEXT: ret void +; +; ASSUME-LABEL: @hello( +; ASSUME-NEXT: entry: +; ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C:%.*]], align 4 +; ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A:%.*]], i64 5 +; ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX]], align 4 +; ASSUME-NEXT: ret void entry: %0 = load float, float* %c, align 4 %arrayidx = getelementptr inbounds float, float* %a, i64 5 @@ -11,6 +28,29 @@ } define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 { +; NO_ASSUME-LABEL: define {{[^@]+}}@foo +; NO_ASSUME-SAME: (float* noalias nocapture [[A:%.*]], float* noalias nocapture readonly [[C:%.*]]) #0 +; NO_ASSUME-NEXT: entry: +; NO_ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4, !alias.scope !0, !noalias !3 +; NO_ASSUME-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 +; NO_ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I]], align 4, !alias.scope !3, !noalias !0 +; NO_ASSUME-NEXT: [[TMP1:%.*]] = load float, float* [[C]], align 4 +; NO_ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 7 +; NO_ASSUME-NEXT: store float [[TMP1]], float* [[ARRAYIDX]], align 4 +; NO_ASSUME-NEXT: ret void +; +; USE_ASSUME-LABEL: define {{[^@]+}}@foo +; USE_ASSUME-SAME: (float* noalias nocapture [[A:%.*]], float* noalias nocapture readonly [[C:%.*]]) #0 +; USE_ASSUME-NEXT: entry: +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "noalias"(float* [[A]]), "noalias"(float* [[C]]), "nocapture"(float* [[A]]), "nocapture"(float* [[C]]), "readonly"(float* [[C]]) ] +; USE_ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4, !alias.scope !0, !noalias !3 +; USE_ASSUME-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 +; USE_ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I]], align 4, !alias.scope !3, !noalias !0 +; USE_ASSUME-NEXT: [[TMP1:%.*]] = load float, float* [[C]], align 4 +; USE_ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 7 +; USE_ASSUME-NEXT: store float [[TMP1]], float* [[ARRAYIDX]], align 4 +; USE_ASSUME-NEXT: ret void +; entry: tail call void @hello(float* %a, float* %c) %0 = load float, float* %c, align 4 @@ -19,18 +59,17 @@ ret void } -; CHECK: define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 { -; CHECK: entry: -; CHECK: %0 = load float, float* %c, align 4, !alias.scope !0, !noalias !3 -; CHECK: %arrayidx.i = getelementptr inbounds float, float* %a, i64 5 -; CHECK: store float %0, float* %arrayidx.i, align 4, !alias.scope !3, !noalias !0 -; CHECK: %1 = load float, float* %c, align 4 -; CHECK: %arrayidx = getelementptr inbounds float, float* %a, i64 7 -; CHECK: store float %1, float* %arrayidx, align 4 -; CHECK: ret void -; CHECK: } - define void @hello2(float* noalias nocapture %a, float* noalias nocapture %b, float* nocapture readonly %c) #0 { +; CHECK-LABEL: define {{[^@]+}}@hello2 +; CHECK-SAME: (float* noalias nocapture [[A:%.*]], float* noalias nocapture [[B:%.*]], float* nocapture readonly [[C:%.*]]) #0 +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 6 +; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds float, float* [[B]], i64 8 +; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX1]], align 4 +; CHECK-NEXT: ret void +; entry: %0 = load float, float* %c, align 4 %arrayidx = getelementptr inbounds float, float* %a, i64 6 @@ -43,6 +82,47 @@ ; Check that when hello() is inlined into foo(), and then foo() is inlined into ; foo2(), the noalias scopes are properly concatenated. define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +; NO_ASSUME-LABEL: define {{[^@]+}}@foo2 +; NO_ASSUME-SAME: (float* nocapture [[A:%.*]], float* nocapture [[B:%.*]], float* nocapture readonly [[C:%.*]]) #0 +; NO_ASSUME-NEXT: entry: +; NO_ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4, !alias.scope !5, !noalias !10 +; NO_ASSUME-NEXT: [[ARRAYIDX_I_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 +; NO_ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I_I]], align 4, !alias.scope !10, !noalias !5 +; NO_ASSUME-NEXT: [[TMP1:%.*]] = load float, float* [[C]], align 4, !alias.scope !13, !noalias !14 +; NO_ASSUME-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 7 +; NO_ASSUME-NEXT: store float [[TMP1]], float* [[ARRAYIDX_I]], align 4, !alias.scope !14, !noalias !13 +; NO_ASSUME-NEXT: [[TMP2:%.*]] = load float, float* [[C]], align 4, !noalias !15 +; NO_ASSUME-NEXT: [[ARRAYIDX_I1:%.*]] = getelementptr inbounds float, float* [[A]], i64 6 +; NO_ASSUME-NEXT: store float [[TMP2]], float* [[ARRAYIDX_I1]], align 4, !alias.scope !19, !noalias !20 +; NO_ASSUME-NEXT: [[ARRAYIDX1_I:%.*]] = getelementptr inbounds float, float* [[B]], i64 8 +; NO_ASSUME-NEXT: store float [[TMP2]], float* [[ARRAYIDX1_I]], align 4, !alias.scope !20, !noalias !19 +; NO_ASSUME-NEXT: [[TMP3:%.*]] = load float, float* [[C]], align 4 +; NO_ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 7 +; NO_ASSUME-NEXT: store float [[TMP3]], float* [[ARRAYIDX]], align 4 +; NO_ASSUME-NEXT: ret void +; +; USE_ASSUME-LABEL: define {{[^@]+}}@foo2 +; USE_ASSUME-SAME: (float* nocapture [[A:%.*]], float* nocapture [[B:%.*]], float* nocapture readonly [[C:%.*]]) #0 +; USE_ASSUME-NEXT: entry: +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "noalias"(float* [[A]]), "noalias"(float* [[C]]), "nocapture"(float* [[A]]), "nocapture"(float* [[C]]), "readonly"(float* [[C]]) ] +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) #2 [ "noalias"(float* [[A]]), "noalias"(float* [[C]]), "nocapture"(float* [[A]]), "nocapture"(float* [[C]]), "readonly"(float* [[C]]) ], !noalias !5 +; USE_ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4, !alias.scope !9, !noalias !12 +; USE_ASSUME-NEXT: [[ARRAYIDX_I_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 +; USE_ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I_I]], align 4, !alias.scope !12, !noalias !9 +; USE_ASSUME-NEXT: [[TMP1:%.*]] = load float, float* [[C]], align 4, !alias.scope !14, !noalias !15 +; USE_ASSUME-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 7 +; USE_ASSUME-NEXT: store float [[TMP1]], float* [[ARRAYIDX_I]], align 4, !alias.scope !15, !noalias !14 +; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "noalias"(float* [[A]]), "noalias"(float* [[B]]), "nocapture"(float* [[A]]), "nocapture"(float* [[B]]), "nocapture"(float* [[C]]), "readonly"(float* [[C]]) ] +; USE_ASSUME-NEXT: [[TMP2:%.*]] = load float, float* [[C]], align 4, !noalias !16 +; USE_ASSUME-NEXT: [[ARRAYIDX_I1:%.*]] = getelementptr inbounds float, float* [[A]], i64 6 +; USE_ASSUME-NEXT: store float [[TMP2]], float* [[ARRAYIDX_I1]], align 4, !alias.scope !20, !noalias !21 +; USE_ASSUME-NEXT: [[ARRAYIDX1_I:%.*]] = getelementptr inbounds float, float* [[B]], i64 8 +; USE_ASSUME-NEXT: store float [[TMP2]], float* [[ARRAYIDX1_I]], align 4, !alias.scope !21, !noalias !20 +; USE_ASSUME-NEXT: [[TMP3:%.*]] = load float, float* [[C]], align 4 +; USE_ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 7 +; USE_ASSUME-NEXT: store float [[TMP3]], float* [[ARRAYIDX]], align 4 +; USE_ASSUME-NEXT: ret void +; entry: tail call void @foo(float* %a, float* %c) tail call void @hello2(float* %a, float* %b, float* %c) @@ -52,46 +132,27 @@ ret void } -; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { -; CHECK: entry: -; CHECK: %0 = load float, float* %c, align 4, !alias.scope !5, !noalias !10 -; CHECK: %arrayidx.i.i = getelementptr inbounds float, float* %a, i64 5 -; CHECK: store float %0, float* %arrayidx.i.i, align 4, !alias.scope !10, !noalias !5 -; CHECK: %1 = load float, float* %c, align 4, !alias.scope !13, !noalias !14 -; CHECK: %arrayidx.i = getelementptr inbounds float, float* %a, i64 7 -; CHECK: store float %1, float* %arrayidx.i, align 4, !alias.scope !14, !noalias !13 -; CHECK: %2 = load float, float* %c, align 4, !noalias !15 -; CHECK: %arrayidx.i1 = getelementptr inbounds float, float* %a, i64 6 -; CHECK: store float %2, float* %arrayidx.i1, align 4, !alias.scope !19, !noalias !20 -; CHECK: %arrayidx1.i = getelementptr inbounds float, float* %b, i64 8 -; CHECK: store float %2, float* %arrayidx1.i, align 4, !alias.scope !20, !noalias !19 -; CHECK: %3 = load float, float* %c, align 4 -; CHECK: %arrayidx = getelementptr inbounds float, float* %a, i64 7 -; CHECK: store float %3, float* %arrayidx, align 4 -; CHECK: ret void -; CHECK: } - -; CHECK: !0 = !{!1} -; CHECK: !1 = distinct !{!1, !2, !"hello: %c"} -; CHECK: !2 = distinct !{!2, !"hello"} -; CHECK: !3 = !{!4} -; CHECK: !4 = distinct !{!4, !2, !"hello: %a"} -; CHECK: !5 = !{!6, !8} -; CHECK: !6 = distinct !{!6, !7, !"hello: %c"} -; CHECK: !7 = distinct !{!7, !"hello"} -; CHECK: !8 = distinct !{!8, !9, !"foo: %c"} -; CHECK: !9 = distinct !{!9, !"foo"} -; CHECK: !10 = !{!11, !12} -; CHECK: !11 = distinct !{!11, !7, !"hello: %a"} -; CHECK: !12 = distinct !{!12, !9, !"foo: %a"} -; CHECK: !13 = !{!8} -; CHECK: !14 = !{!12} -; CHECK: !15 = !{!16, !18} -; CHECK: !16 = distinct !{!16, !17, !"hello2: %a"} -; CHECK: !17 = distinct !{!17, !"hello2"} -; CHECK: !18 = distinct !{!18, !17, !"hello2: %b"} -; CHECK: !19 = !{!16} -; CHECK: !20 = !{!18} +; NO_ASSUME: !0 = !{!1} +; NO_ASSUME: !1 = distinct !{!1, !2, !"hello: %c"} +; NO_ASSUME: !2 = distinct !{!2, !"hello"} +; NO_ASSUME: !3 = !{!4} +; NO_ASSUME: !4 = distinct !{!4, !2, !"hello: %a"} +; NO_ASSUME: !5 = !{!6, !8} +; NO_ASSUME: !6 = distinct !{!6, !7, !"hello: %c"} +; NO_ASSUME: !7 = distinct !{!7, !"hello"} +; NO_ASSUME: !8 = distinct !{!8, !9, !"foo: %c"} +; NO_ASSUME: !9 = distinct !{!9, !"foo"} +; NO_ASSUME: !10 = !{!11, !12} +; NO_ASSUME: !11 = distinct !{!11, !7, !"hello: %a"} +; NO_ASSUME: !12 = distinct !{!12, !9, !"foo: %a"} +; NO_ASSUME: !13 = !{!8} +; NO_ASSUME: !14 = !{!12} +; NO_ASSUME: !15 = !{!16, !18} +; NO_ASSUME: !16 = distinct !{!16, !17, !"hello2: %a"} +; NO_ASSUME: !17 = distinct !{!17, !"hello2"} +; NO_ASSUME: !18 = distinct !{!18, !17, !"hello2: %b"} +; NO_ASSUME: !19 = !{!16} +; NO_ASSUME: !20 = !{!18} attributes #0 = { nounwind uwtable } diff --git a/llvm/unittests/IR/KnowledgeRetentionTest.cpp b/llvm/unittests/IR/KnowledgeRetentionTest.cpp --- a/llvm/unittests/IR/KnowledgeRetentionTest.cpp +++ b/llvm/unittests/IR/KnowledgeRetentionTest.cpp @@ -20,6 +20,7 @@ using namespace llvm; extern cl::opt ShouldPreserveAllAttributes; +extern cl::opt EnableKnowledgeRetention; static void RunTest( StringRef Head, StringRef Tail, @@ -79,6 +80,7 @@ } TEST(AssumeQueryAPI, hasAttributeInAssume) { + EnableKnowledgeRetention.setValue(true); StringRef Head = "declare void @llvm.assume(i1)\n" "declare void @func(i32*, i32*)\n" @@ -263,7 +265,8 @@ } TEST(AssumeQueryAPI, fillMapFromAssume) { - StringRef Head = + EnableKnowledgeRetention.setValue(true); + StringRef Head = "declare void @llvm.assume(i1)\n" "declare void @func(i32*, i32*)\n" "declare void @func1(i32*, i32*, i32*, i32*)\n"