diff --git a/clang/test/CodeGenCXX/auto-var-init.cpp b/clang/test/CodeGenCXX/auto-var-init.cpp index d50967c40216c..761458da90841 100644 --- a/clang/test/CodeGenCXX/auto-var-init.cpp +++ b/clang/test/CodeGenCXX/auto-var-init.cpp @@ -597,9 +597,7 @@ TEST_UNINIT(empty, empty); // PATTERN-O1: store i8 [[I8]], {{.*}} align 1, !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_empty_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i8 0, {{.*}} align 1 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i8 0, {{.*}} align 1, !annotation [[AUTO_INIT]] TEST_BRACES(empty, empty); // CHECK-LABEL: @test_empty_braces() @@ -618,9 +616,7 @@ TEST_UNINIT(small, small); // PATTERN-O1: store i8 [[I8]], {{.*}} align 1, !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_small_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i8 0, {{.*}} align 1 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i8 0, {{.*}} align 1, !annotation [[AUTO_INIT]] TEST_BRACES(small, small); // CHECK-LABEL: @test_small_braces() @@ -671,10 +667,8 @@ TEST_UNINIT(smallpartinit, smallpartinit); // PATTERN-O1: store i8 42, {{.*}} align 1 // ZERO-LABEL: @test_smallpartinit_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1-LEGACY: store i16 0, i16* %uninit, align 2 -// ZERO-O1-NEWPM: store i16 0, i16* %uninit, align 2 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1-LEGACY: store i16 0, i16* %uninit, align 2, !annotation [[AUTO_INIT]] +// ZERO-O1-NEWPM: store i16 0, i16* %uninit, align 2, !annotation [[AUTO_INIT]] TEST_BRACES(smallpartinit, smallpartinit); // CHECK-LABEL: @test_smallpartinit_braces() @@ -726,14 +720,10 @@ TEST_UNINIT(padded, padded); // CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) // PATTERN-LABEL: @test_padded_uninit() // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_padded_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] -// PATTERN-O1: store i64 [[I64]], i64* %uninit, align 8 -// FIXME: !annotation dropped by optimizations -// PATTERN-O1-NOT: !annotation +// PATTERN-O1: store i64 [[I64]], i64* %uninit, align 8, !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_padded_uninit() -// ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}) -// ZERO-O1: store i64 0, i64* %uninit, align 8 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] +// ZERO-O1: store i64 0, i64* %uninit, align 8, !annotation [[AUTO_INIT]] TEST_BRACES(padded, padded); // CHECK-LABEL: @test_padded_braces() @@ -758,15 +748,16 @@ TEST_UNINIT(paddednullinit, paddednullinit); // CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) // PATTERN-LABEL: @test_paddednullinit_uninit() // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_paddednullinit_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] -// PATTERN-O1-LEGACY: store i64 [[I64]], i64* %uninit, align 8 -// PATTERN-O1-NEWPM: store i64 [[I64]], i64* %uninit, align 8 -// FIXME: !annotation dropped by optimizations -// PATTERN-O1-NOT: !annotation +// PATTERN-O1-LEGACY: store i64 [[I64]], i64* %uninit, align 8, !annotation [[AUTO_INIT]] +// PATTERN-O1-NEWPM: store i64 [[I64]], i64* %uninit, align 8, !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_paddednullinit_uninit() -// ZERO-O0: call void @llvm.memset{{.*}}, i8 0, -// ZERO-O1: store i64 0, i64* %uninit, align 8 +// ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.*}}, !annotation [[AUTO_INIT]] +// ZERO-O1-LEGACY: store i64 0, i64* %uninit, align 8, !annotation [[AUTO_INIT]] +// ZERO-O1-NEWPM: store i64 0, i64* %uninit, align 8 // FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1-NEWPM-NOT: !annotation +// ZERO: ret + TEST_BRACES(paddednullinit, paddednullinit); // CHECK-LABEL: @test_paddednullinit_braces() @@ -922,9 +913,7 @@ TEST_UNINIT(bitfield, bitfield); // PATTERN-O1-NOT: !annotation // ZERO-LABEL: @test_bitfield_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i32 0, i32* %uninit, align 4 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i32 0, i32* %uninit, align 4, !annotation [[AUTO_INIT]] TEST_BRACES(bitfield, bitfield); // CHECK-LABEL: @test_bitfield_braces() @@ -953,9 +942,7 @@ TEST_UNINIT(bitfieldaligned, bitfieldaligned); // PATTERN-O1-NOT: !annotation // ZERO-LABEL: @test_bitfieldaligned_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i64 0, i64* %uninit, align 8 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i64 0, i64* %uninit, align 8, !annotation [[AUTO_INIT]] TEST_BRACES(bitfieldaligned, bitfieldaligned); // CHECK-LABEL: @test_bitfieldaligned_braces() @@ -1007,9 +994,7 @@ TEST_UNINIT(arraytail, arraytail); // PATTERN-O1: store i32 [[I32]], {{.*}} align 4, !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_arraytail_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i32 0, {{.*}} align 4 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i32 0, {{.*}} align 4, !annotation [[AUTO_INIT]] TEST_BRACES(arraytail, arraytail); // CHECK-LABEL: @test_arraytail_braces() @@ -1053,9 +1038,7 @@ TEST_UNINIT(int1, int[1]); // PATTERN-O1: store i32 [[I32]], {{.*}} align 4, !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_int1_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i32 0, {{.*}} align 4 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i32 0, {{.*}} align 4, !annotation [[AUTO_INIT]] TEST_BRACES(int1, int[1]); // CHECK-LABEL: @test_int1_braces() @@ -1109,9 +1092,7 @@ TEST_UNINIT(bool4, bool[4]); // PATTERN-O1-NOT: !annotation // ZERO-LABEL: @test_bool4_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i32 0, i32* %uninit, align 4 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i32 0, i32* %uninit, align 4, !annotation [[AUTO_INIT]] TEST_BRACES(bool4, bool[4]); // CHECK-LABEL: @test_bool4_braces() @@ -1244,7 +1225,7 @@ TEST_UNINIT(atomicnotlockfree, _Atomic(notlockfree)); // PATTERN-LABEL: @test_atomicnotlockfree_uninit() // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_atomicnotlockfree_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // PATTERN-O1: bitcast -// PATTERN-O1: call void @llvm.memset{{.*}}({{.*}}, i8 [[I8]], i64 32 +// PATTERN-O1: call void @llvm.memset{{.*}}({{.*}}, i8 [[I8]], i64 32{{.*}} // FIXME: !annotation dropped by optimizations // PATTERN-O1-NOT: !annotation // ZERO-LABEL: @test_atomicnotlockfree_uninit() @@ -1256,14 +1237,10 @@ TEST_UNINIT(atomicpadded, _Atomic(padded)); // CHECK-NEXT: call void @{{.*}}used{{.*}}%uninit) // PATTERN-LABEL: @test_atomicpadded_uninit() // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_atomicpadded_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] -// PATTERN-O1: store i64 [[IPTR]], i64* %uninit, align 8 -// FIXME: !annotation dropped by optimizations -// PATTERN-O1-NOT: !annotation +// PATTERN-O1: store i64 [[IPTR]], i64* %uninit, align 8, !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_atomicpadded_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i64 0, i64* %uninit, align 8 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i64 0, i64* %uninit, align 8, !annotation [[AUTO_INIT]] TEST_UNINIT(atomictailpad, _Atomic(tailpad)); // CHECK-LABEL: @test_atomictailpad_uninit() @@ -1273,9 +1250,7 @@ TEST_UNINIT(atomictailpad, _Atomic(tailpad)); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_atomictailpad_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_atomictailpad_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i32 0, i32* %uninit, align 4 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i32 0, i32* %uninit, align 4, !annotation [[AUTO_INIT]] TEST_UNINIT(complexfloat, _Complex float); // CHECK-LABEL: @test_complexfloat_uninit() @@ -1291,9 +1266,7 @@ TEST_UNINIT(complexfloat, _Complex float); // ZERO-LABEL: @test_complexfloat_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i64 0, i64* %uninit, align 8 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i64 0, i64* %uninit, align 8, !annotation [[AUTO_INIT]] TEST_BRACES(complexfloat, _Complex float); // CHECK-LABEL: @test_complexfloat_braces() @@ -1372,9 +1345,7 @@ TEST_UNINIT(semivolatile, semivolatile); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_semivolatile_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_semivolatile_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i64 0, i64* %uninit, align 8 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i64 0, i64* %uninit, align 8, !annotation [[AUTO_INIT]] TEST_BRACES(semivolatile, semivolatile); // CHECK-LABEL: @test_semivolatile_braces() @@ -1433,8 +1404,7 @@ TEST_UNINIT(base, base); // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] // ZERO-O1-LEGACY: store i64 0, {{.*}} align 8 // ZERO-O1-NEWPM: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV4base, i64 0, inrange i32 0, i64 2) to i32 (...)**), {{.*}}, align 8 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1-NOT-NEWPM: !annotation TEST_BRACES(base, base); // CHECK-LABEL: @test_base_braces() @@ -1454,10 +1424,8 @@ TEST_UNINIT(derived, derived); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_derived_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_derived_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1-LEGACY: store i64 0, {{.*}} align 8 +// ZERO-O1: store i64 0, {{.*}} align 8, !annotation [[AUTO_INIT]] // ZERO-O1-NEWPM: store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV7derived, i64 0, inrange i32 0, i64 2) to i32 (...)**), {{.*}} align 8 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation TEST_BRACES(derived, derived); // CHECK-LABEL: @test_derived_braces() @@ -1497,9 +1465,7 @@ TEST_UNINIT(matching, matching); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_matching_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_matching_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i32 0, {{.*}} align 4 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i32 0, {{.*}} align 4, !annotation [[AUTO_INIT]] TEST_BRACES(matching, matching); // CHECK-LABEL: @test_matching_braces() @@ -1529,9 +1495,7 @@ TEST_UNINIT(matchingreverse, matchingreverse); // PATTERN-O1: store float 0xFFFFFFFFE0000000, {{.+}}, !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_matchingreverse_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i32 0, {{.*}} align 4 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i32 0, {{.*}} align 4, !annotation [[AUTO_INIT]] TEST_BRACES(matchingreverse, matchingreverse); // CHECK-LABEL: @test_matchingreverse_braces() @@ -1559,9 +1523,7 @@ TEST_UNINIT(unmatched, unmatched); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_unmatched_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_unmatched_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i32 0, {{.*}} align 4 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i32 0, {{.*}} align 4, !annotation [[AUTO_INIT]] TEST_BRACES(unmatched, unmatched); // CHECK-LABEL: @test_unmatched_braces() @@ -1589,9 +1551,7 @@ TEST_UNINIT(unmatchedreverse, unmatchedreverse); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_unmatchedreverse_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_unmatchedreverse_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i32 0, {{.*}} align 4 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i32 0, {{.*}} align 4, !annotation [[AUTO_INIT]] TEST_BRACES(unmatchedreverse, unmatchedreverse); // CHECK-LABEL: @test_unmatchedreverse_braces() @@ -1619,9 +1579,7 @@ TEST_UNINIT(unmatchedfp, unmatchedfp); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_unmatchedfp_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_unmatchedfp_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store i64 0, {{.*}} align 8 -// FIXME: !annotation dropped by optimizations -// ZERO-O1-NOT: !annotation +// ZERO-O1: store i64 0, {{.*}} align 8, !annotation [[AUTO_INIT]] TEST_BRACES(unmatchedfp, unmatchedfp); // CHECK-LABEL: @test_unmatchedfp_braces() diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index b90480ebc59ef..0e2a1ce93aebc 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -17,6 +17,7 @@ #include "llvm-c/Types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/BasicBlock.h" @@ -24,6 +25,7 @@ #include "llvm/IR/ConstantFolder.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" @@ -91,7 +93,28 @@ class IRBuilderCallbackInserter : public IRBuilderDefaultInserter { /// Common base class shared among various IRBuilders. class IRBuilderBase { - DebugLoc CurDbgLocation; + /// Pairs of (metadata kind, MDNode *) that should be added to all newly + /// created instructions, like !dbg metadata. + SmallVector, 2> MetadataToCopy; + + /// Add or update the an entry (Kind, MD) to MetadataToCopy, if \p MD is not + /// null. If \p MD is null, remove the entry with \p Kind. + void AddOrRemoveMetadataToCopy(unsigned Kind, MDNode *MD) { + if (!MD) { + erase_if(MetadataToCopy, [Kind](const std::pair &KV) { + return KV.first == Kind; + }); + return; + } + + for (auto &KV : MetadataToCopy) + if (KV.first == Kind) { + KV.second = MD; + return; + } + + MetadataToCopy.emplace_back(Kind, MD); + } protected: BasicBlock *BB; @@ -125,7 +148,7 @@ class IRBuilderBase { template InstTy *Insert(InstTy *I, const Twine &Name = "") const { Inserter.InsertHelper(I, Name, BB, InsertPt); - SetInstDebugLocation(I); + AddMetadataToInst(I); return I; } @@ -182,16 +205,42 @@ class IRBuilderBase { } /// Set location information used by debugging information. - void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); } + void SetCurrentDebugLocation(DebugLoc L) { + AddOrRemoveMetadataToCopy(LLVMContext::MD_dbg, L.getAsMDNode()); + } + + /// Collect metadata with IDs \p MetadataKinds from \p Src which should be + /// added to all created instructions. Entries present in MedataDataToCopy but + /// not on \p Src will be dropped from MetadataToCopy. + void CollectMetadataToCopy(Instruction *Src, + ArrayRef MetadataKinds) { + for (unsigned K : MetadataKinds) + AddOrRemoveMetadataToCopy(K, Src->getMetadata(K)); + } /// Get location information used by debugging information. - const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } + DebugLoc getCurrentDebugLocation() const { + for (auto &KV : MetadataToCopy) + if (KV.first == LLVMContext::MD_dbg) + return {cast(KV.second)}; + + return {}; + } /// If this builder has a current debug location, set it on the /// specified instruction. void SetInstDebugLocation(Instruction *I) const { - if (CurDbgLocation) - I->setDebugLoc(CurDbgLocation); + for (const auto &KV : MetadataToCopy) + if (KV.first == LLVMContext::MD_dbg) { + I->setDebugLoc(DebugLoc(KV.second)); + return; + } + } + + /// Add all entries in MetadataToCopy to \p I. + void AddMetadataToInst(Instruction *I) const { + for (auto &KV : MetadataToCopy) + I->setMetadata(KV.first, KV.second); } /// Get the return type of the current function that we're emitting diff --git a/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h b/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h index 0c88f9f79e766..790bc2c56c8b1 100644 --- a/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h +++ b/llvm/include/llvm/Transforms/Utils/ScalarEvolutionExpander.h @@ -305,7 +305,7 @@ namespace llvm { } /// Get location information used by debugging information. - const DebugLoc &getCurrentDebugLocation() const { + DebugLoc getCurrentDebugLocation() const { return Builder.getCurrentDebugLocation(); } diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index 952564870eb10..04f2099b3dd45 100644 --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -547,6 +547,8 @@ void PassManagerBuilder::populateModulePassManager( // new unnamed globals. MPM.add(createNameAnonGlobalPass()); } + + MPM.add(createAnnotationRemarksLegacyPass()); return; } diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index e444af31de057..4b1f7f970f4dd 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3550,7 +3550,8 @@ bool InstCombiner::run() { // Now that we have an instruction, try combining it to simplify it. Builder.SetInsertPoint(I); - Builder.SetCurrentDebugLocation(I->getDebugLoc()); + Builder.CollectMetadataToCopy( + I, {LLVMContext::MD_dbg, LLVMContext::MD_annotation}); #ifndef NDEBUG std::string OrigI; @@ -3565,8 +3566,8 @@ bool InstCombiner::run() { LLVM_DEBUG(dbgs() << "IC: Old = " << *I << '\n' << " New = " << *Result << '\n'); - if (I->getDebugLoc()) - Result->setDebugLoc(I->getDebugLoc()); + Result->copyMetadata(*I, + {LLVMContext::MD_dbg, LLVMContext::MD_annotation}); // Everything uses the new instruction now. I->replaceAllUsesWith(Result); diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index b450d71c996cb..8a653c9a0d47a 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2761,11 +2761,15 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI, MemorySSAUpdater *MSSAU, Changed = true; IRBuilder<> Builder(PBI); + // The builder is used to create instructions to eliminate the branch in BB. + // If BB's terminator has !annotation metadata, add it to the new + // instructions. + Builder.CollectMetadataToCopy(BB->getTerminator(), + {LLVMContext::MD_annotation}); // If we need to invert the condition in the pred block to match, do so now. if (InvertPredCond) { Value *NewCond = PBI->getCondition(); - if (NewCond->hasOneUse() && isa(NewCond)) { CmpInst *CI = cast(NewCond); CI->setPredicate(CI->getInversePredicate()); @@ -2803,8 +2807,9 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI, MemorySSAUpdater *MSSAU, // its potential value. The previous information might have been valid // only given the branch precondition. // For an analogous reason, we must also drop all the metadata whose - // semantics we don't understand. - NewBonusInst->dropUnknownNonDebugMetadata(); + // semantics we don't understand. We *can* preserve !annotation, because + // it is tied to the instruction itself, not the value or position. + NewBonusInst->dropUnknownNonDebugMetadata(LLVMContext::MD_annotation); PredBlock->getInstList().insert(PBI->getIterator(), NewBonusInst); NewBonusInst->takeName(&*BonusInst); diff --git a/llvm/test/Other/opt-O0-pipeline.ll b/llvm/test/Other/opt-O0-pipeline.ll index 4dcb15358f093..ef165cfc194ea 100644 --- a/llvm/test/Other/opt-O0-pipeline.ll +++ b/llvm/test/Other/opt-O0-pipeline.ll @@ -22,6 +22,7 @@ ; CHECK-NEXT: Inliner for always_inline functions ; A No-Op Barrier Pass ; CHECK: FunctionPass Manager +; CHECK-NEXT: Annotation Remarks ; CHECK-NEXT: Module Verifier ; CHECK-NEXT: Bitcode Writer diff --git a/llvm/test/Transforms/InstCombine/annotations.ll b/llvm/test/Transforms/InstCombine/annotations.ll new file mode 100644 index 0000000000000..c260828d2df24 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/annotations.ll @@ -0,0 +1,153 @@ +; RUN: opt < %s -instcombine -S | FileCheck --match-full-lines %s + +; Test cases to make sure !annotation metadata is preserved, if possible. +; Currently we fail to preserve !annotation metadata in many cases. + +; Make sure !annotation metadata is added to new instructions, if the source +; instruction has !annotation metadata. +define i1 @fold_to_new_instruction(i8* %a, i8* %b) { +; CHECK-LABEL: define {{.+}} @fold_to_new_instruction({{.+}} +; CHECK-NEXT: [[C:%.*]] = icmp uge i8* [[A:%.*]], [[B:%[a-z]*]], !annotation [[ANN:![0-9]+]] +; CHECK-NEXT: ret i1 [[C]] +; + %a.c = bitcast i8* %a to i32*, !annotation !0 + %b.c = bitcast i8* %b to i32*, !annotation !0 + %c = icmp uge i32* %a.c, %b.c, !annotation !0 + ret i1 %c +} + +; Make sure !annotation is not added to new instructions if the source +; instruction does not have it (even if some folded operands do have +; !annotation). +define i1 @fold_to_new_instruction2(i8* %a, i8* %b) { +; CHECK-LABEL: define {{.+}} @fold_to_new_instruction2({{.+}} +; CHECK-NEXT: [[C:%.*]] = icmp uge i8* [[A:%.*]], [[B:%[a-z]+]] +; CHECK-NEXT: ret i1 [[C]] +; + %a.c = bitcast i8* %a to i32*, !annotation !0 + %b.c = bitcast i8* %b to i32*, !annotation !0 + %c = icmp uge i32* %a.c, %b.c + ret i1 %c +} + +; Make sure !annotation metadata is *not* added if we replace an instruction +; with !annotation with an existing one without. +define i32 @do_not_add_annotation_to_existing_instr(i32 %a, i32 %b) { +; CHECK-LABEL: define {{.+}} @do_not_add_annotation_to_existing_instr({{.+}} +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A:%.*]], [[B:%[a-z]+]] +; CHECK-NEXT: ret i32 [[ADD]] +; + %add = add i32 %a, %b + %res = add i32 0, %add, !annotation !0 + ret i32 %res +} + +; memcpy can be expanded inline with load/store. Verify that we keep the +; !annotation metadata. + +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind + +define void @copy_1_byte(i8* %d, i8* %s) { +; CHECK-LABEL: define {{.+}} @copy_1_byte({{.+}} +; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: ret void +; + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 1, i1 false), !annotation !0 + ret void +} + +declare i8* @memcpy(i8* noalias returned, i8* noalias nocapture readonly, i64) nofree nounwind + +define void @libcallcopy_1_byte(i8* %d, i8* %s) { +; CHECK-LABEL: define {{.+}} @libcallcopy_1_byte({{.+}} +; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: ret void +; + call i8* @memcpy(i8* %d, i8* %s, i64 1), !annotation !0 + ret void +} + +declare i8* @__memcpy_chk(i8*, i8*, i64, i64) nofree nounwind + +define void @libcallcopy_1_byte_chk(i8* %d, i8* %s) { +; CHECK-LABEL: define {{.+}} @libcallcopy_1_byte_chk({{.+}} +; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: ret void +; + call i8* @__memcpy_chk(i8* %d, i8* %s, i64 1, i64 1), !annotation !0 + ret void +} + +declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) nounwind + +define void @move_1_byte(i8* %d, i8* %s) { +; CHECK-LABEL: define {{.+}} @move_1_byte({{.+}} +; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: ret void +; + call void @llvm.memmove.p0i8.p0i8.i32(i8* %d, i8* %s, i32 1, i1 false), !annotation !0 + ret void +} + +declare i8* @memmove(i8* returned, i8* nocapture readonly, i64) nofree nounwind + +define void @libcallmove_1_byte(i8* %d, i8* %s) { +; CHECK-LABEL: define {{.+}} @libcallmove_1_byte({{.+}} +; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: ret void +; + call i8* @memmove(i8* %d, i8* %s, i64 1), !annotation !0 + ret void +} + +declare i8* @__memmove_chk(i8*, i8*, i64, i64) nofree nounwind + +define void @libcallmove_1_byte_chk(i8* %d, i8* %s) { +; CHECK-LABEL: define {{.+}} @libcallmove_1_byte_chk({{.+}} +; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: ret void +; + call i8* @__memmove_chk(i8* %d, i8* %s, i64 1, i64 1), !annotation !0 + ret void +} + +declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1) argmemonly nounwind + +define void @set_1_byte(i8* %d) { +; CHECK-LABEL: define {{.+}} @set_1_byte({{.+}} +; CHECK-NEXT: store i8 1, i8* [[D:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: ret void +; + call void @llvm.memset.p0i8.i32(i8* %d, i8 1, i32 1, i1 false), !annotation !0 + ret void +} + +declare i8* @memset(i8*, i32, i64) nofree + +define void @libcall_set_1_byte(i8* %d) { +; CHECK-LABEL: define {{.+}} @libcall_set_1_byte({{.+}} +; CHECK-NEXT: store i8 1, i8* [[D:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: ret void +; + call i8* @memset(i8* %d, i32 1, i64 1), !annotation !0 + ret void +} + +declare i8* @__memset_chk(i8*, i32, i64, i64) nofree + +define void @libcall_set_1_byte_chk(i8* %d) { +; CHECK-LABEL: define {{.+}} @libcall_set_1_byte_chk({{.+}} +; CHECK-NEXT: store i8 1, i8* [[D:%.*]], align 1, !annotation [[ANN]] +; CHECK-NEXT: ret void +; + call i8* @__memset_chk(i8* %d, i32 1, i64 1, i64 1), !annotation !0 + ret void +} + +!0 = !{ !"auto-init" } diff --git a/llvm/test/Transforms/SimplifyCFG/annotations.ll b/llvm/test/Transforms/SimplifyCFG/annotations.ll new file mode 100644 index 0000000000000..e6bc73d16992f --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/annotations.ll @@ -0,0 +1,145 @@ +; RUN: opt -simplifycfg -S %s | FileCheck --match-full-lines %s + +; The branch in %cont has !annotation metadata. Make sure generated AND +; has !annotation metadata. +define i32 @test_preserve_and(i8* %a, i8* %b, i8* %c, i8* %d) { +; CHECK-LABEL: define {{.*}} @test_preserve_and({{.*}} +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8* [[A:%.*]], [[B:%.*]], !annotation !0 +; CHECK-NEXT: [[C_2:%.*]] = icmp uge i8* [[C:%.*]], [[D:%.*]], !annotation !0 +; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C_1]], [[C_2]], !annotation !0 +; CHECK-NEXT: br i1 [[OR_COND]], label [[CONT1:%.*]], label [[TRAP:%.*]], !annotation !0 +; CHECK: trap: ; preds = %entry +; CHECK-NEXT: call void @fn1() +; CHECK-NEXT: unreachable +; CHECK: cont1: ; preds = %entry +; CHECK-NEXT: call void @fn2() +; CHECK-NEXT: ret i32 0 +; +entry: + %c.1 = icmp ult i8* %a, %b, !annotation !0 + br i1 %c.1, label %cont, label %trap, !annotation !0 + +cont: ; preds = %entry + %c.2 = icmp uge i8* %c, %d, !annotation !0 + br i1 %c.2, label %cont1, label %trap, !annotation !0 + +trap: ; preds = %cont, %entry + call void @fn1() + unreachable + +cont1: ; preds = %cont + call void @fn2() + ret i32 0 +} + +; The branch in %cont has !annotation metadata. Make sure generated OR +; has !annotation metadata. +define i32 @test_preserve_or(i8* %a, i8* %b, i8* %c, i8* %d) { +; CHECK-LABEL: define {{.*}} @test_preserve_or({{.*}} +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8* [[A:%.*]], [[B:%.*]], !annotation !0 +; CHECK-NEXT: [[C_2:%.*]] = icmp uge i8* [[C:%.*]], [[D:%.*]], !annotation !0 +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[C_1]], [[C_2]], !annotation !0 +; CHECK-NEXT: br i1 [[OR_COND]], label [[TRAP:%.*]], label [[CONT1:%.*]], !annotation !0 +; CHECK: trap: ; preds = %entry +; CHECK-NEXT: call void @fn1() +; CHECK-NEXT: unreachable +; CHECK: cont1: ; preds = %entry +; CHECK-NEXT: call void @fn2() +; CHECK-NEXT: ret i32 0 +; +entry: + %c.1 = icmp ult i8* %a, %b, !annotation !0 + br i1 %c.1, label %cont, label %trap, !annotation !0 + +cont: ; preds = %entry + %c.2 = icmp uge i8* %c, %d, !annotation !0 + br i1 %c.2, label %trap, label %cont1, !annotation !0 + +trap: ; preds = %cont, %entry + call void @fn1() + unreachable + +cont1: ; preds = %cont + call void @fn2() + ret i32 0 +} + +; The branch in %cont has !annotation metadata. Make sure generated negation +; and OR have !annotation metadata. +define i32 @test_preserve_or_not(i8* %a, i8* %b, i8* %c, i8* %d) { +; CHECK-LABEL: define {{.*}} @test_preserve_or_not({{.*}} +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8* [[A:%.*]], [[B:%.*]], !annotation !0 +; CHECK-NEXT: [[C_2:%.*]] = xor i1 [[C_1]], true +; CHECK-NEXT: [[C_2_NOT:%.*]] = xor i1 [[C_2]], true, !annotation !0 +; CHECK-NEXT: [[C_3:%.*]] = icmp uge i8* [[C:%.*]], [[D:%.*]], !annotation !0 +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[C_2_NOT]], [[C_3]], !annotation !0 +; CHECK-NEXT: br i1 [[OR_COND]], label [[TRAP:%.*]], label [[CONT1:%.*]], !annotation !0 +; CHECK: trap: ; preds = %entry +; CHECK-NEXT: call void @fn1() +; CHECK-NEXT: unreachable +; CHECK: cont1: ; preds = %entry +; CHECK-NEXT: call void @fn2() +; CHECK-NEXT: ret i32 0 +; +entry: + %c.1 = icmp ult i8* %a, %b, !annotation !0 + %c.2 = xor i1 %c.1, true + br i1 %c.2, label %cont, label %trap, !annotation !0 + +cont: ; preds = %entry + %c.3 = icmp uge i8* %c, %d, !annotation !0 + br i1 %c.3, label %trap, label %cont1, !annotation !0 + +trap: ; preds = %cont, %entry + call void @fn1() + unreachable + +cont1: ; preds = %cont + call void @fn2() + ret i32 0 +} + + +; The branch in %cont has no !annotation metadata. Make sure generated negation +; and OR do not have !annotation metadata. +define i32 @test_or_not_no_annotation(i8* %a, i8* %b, i8* %c, i8* %d) { +; CHECK-LABEL: define {{.*}} @test_or_not_no_annotation({{.*}} +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8* [[A:%.*]], [[B:%.*]], !annotation !0 +; CHECK-NEXT: [[C_2:%.*]] = xor i1 [[C_1]], true +; CHECK-NEXT: [[C_2_NOT:%.*]] = xor i1 [[C_2]], true +; CHECK-NEXT: [[C_3:%.*]] = icmp uge i8* [[C:%.*]], [[D:%.*]], !annotation !0 +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[C_2_NOT]], [[C_3]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[TRAP:%.*]], label [[CONT1:%.*]], !annotation !0 +; CHECK: trap: ; preds = %entry +; CHECK-NEXT: call void @fn1() +; CHECK-NEXT: unreachable +; CHECK: cont1: ; preds = %entry +; CHECK-NEXT: call void @fn2() +; CHECK-NEXT: ret i32 0 +; +entry: + %c.1 = icmp ult i8* %a, %b, !annotation !0 + %c.2 = xor i1 %c.1, true + br i1 %c.2, label %cont, label %trap, !annotation !0 + +cont: ; preds = %entry + %c.3 = icmp uge i8* %c, %d, !annotation !0 + br i1 %c.3, label %trap, label %cont1 + +trap: ; preds = %cont, %entry + call void @fn1() + unreachable + +cont1: ; preds = %cont + call void @fn2() + ret i32 0 +} + +declare void @fn1() +declare void @fn2() + +!0 = !{!"foo"}