From da224875b681a06eb160a1dd58eccb953792f41e Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 15 Dec 2020 14:44:38 +0000 Subject: [PATCH 1/7] [AnnotationRemarks] Also generate annotation remarks when using -O0. The AnnotationRemarks pass is already run at the end of the module pipeline. This patch also adds it before bailing out for -O0, so remarks are also generated with -O0. --- llvm/lib/Transforms/IPO/PassManagerBuilder.cpp | 2 ++ llvm/test/Other/opt-O0-pipeline.ll | 1 + 2 files changed, 3 insertions(+) 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/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 From 7c843b011f62b82bae2ef157989b7f21f8b6d00d Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 16 Dec 2020 11:30:01 +0000 Subject: [PATCH 2/7] [InstCombine] Precommit tests for !annotation metadata handling. --- .../Transforms/InstCombine/annotations.ll | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/annotations.ll diff --git a/llvm/test/Transforms/InstCombine/annotations.ll b/llvm/test/Transforms/InstCombine/annotations.ll new file mode 100644 index 0000000000000..1530b867bfb68 --- /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]*]] +; 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 +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 +; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 +; 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 +; 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 +; CHECK-NEXT: ret void +; + call i8* @__memset_chk(i8* %d, i32 1, i64 1, i64 1), !annotation !0 + ret void +} + +!0 = !{ !"auto-init" } From d96295ea5025fee901aea27f9b39bfc33d895b48 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 16 Dec 2020 16:51:14 +0000 Subject: [PATCH 3/7] [SimplifyCFG] Precommit test for preserving !annotation. --- .../Transforms/SimplifyCFG/annotations.ll | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 llvm/test/Transforms/SimplifyCFG/annotations.ll diff --git a/llvm/test/Transforms/SimplifyCFG/annotations.ll b/llvm/test/Transforms/SimplifyCFG/annotations.ll new file mode 100644 index 0000000000000..5e39107e1c89a --- /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:%.*]] +; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C_1]], [[C_2]] +; 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:%.*]] +; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[C_1]], [[C_2]] +; 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 +; CHECK-NEXT: [[C_3:%.*]] = icmp uge i8* [[C:%.*]], [[D:%.*]] +; 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, !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:%.*]] +; 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"} From 1e15425862941a327ab341b3ffb47fe1cffc7f54 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Thu, 17 Dec 2020 08:47:46 +0000 Subject: [PATCH 4/7] [InstCombine] Preserve !annotation for newly created instructions. When replacing an instruction with !annotation with a newly created replacement, add the !annotation metadata to the replacement. This mostly covers cases where the new instructions are created using the ::Create helpers. Instructions created by IRBuilder will be handled by D91444. Reviewed By: thegameg Differential Revision: https://reviews.llvm.org/D93399 --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 4 ++-- llvm/test/Transforms/InstCombine/annotations.ll | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index e444af31de057..b7c17f4230542 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3565,8 +3565,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/test/Transforms/InstCombine/annotations.ll b/llvm/test/Transforms/InstCombine/annotations.ll index 1530b867bfb68..3b0989402823e 100644 --- a/llvm/test/Transforms/InstCombine/annotations.ll +++ b/llvm/test/Transforms/InstCombine/annotations.ll @@ -7,7 +7,7 @@ ; 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]*]] +; 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 From 54eb1a24afcdb8e91a35288ee08c0c723125c7b6 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Thu, 17 Dec 2020 12:59:02 +0000 Subject: [PATCH 5/7] [IRBuilder] Generalize debug loc handling for arbitrary metadata. This patch extends IRBuilder to allow adding/preserving arbitrary metadata on created instructions. Instead of using references to specific metadata nodes (like DebugLoc), IRbuilder now keeps a vector of (metadata kind, MDNode *) pairs, which are added to each created instruction. The patch itself is a NFC and only moves the existing debug location handling over to the new system. In a follow-up patch it will be used to preserve !annotation metadata besides !dbg. The current approach requires iterating over MetadataToCopy to avoid adding duplicates, but given that the number of metadata kinds to copy/preserve is going to be very small initially (0, 1 (for !dbg) or 2 (!dbg and !annotation)) that should not matter. Reviewed By: lebedev.ri Differential Revision: https://reviews.llvm.org/D93400 --- llvm/include/llvm/IR/IRBuilder.h | 61 +++++++++++++++++-- .../Utils/ScalarEvolutionExpander.h | 2 +- .../InstCombine/InstructionCombining.cpp | 2 +- 3 files changed, 57 insertions(+), 8 deletions(-) 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/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index b7c17f4230542..1618b88a9c421 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3550,7 +3550,7 @@ 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}); #ifndef NDEBUG std::string OrigI; From 56e56e9e981a27a3099f9e57b17eb76ce8c9f3af Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Thu, 17 Dec 2020 13:42:29 +0000 Subject: [PATCH 6/7] [SimplifyCFG] Preserve !annotation in FoldBranchToCommonDest. When folding a branch to a common destination, preserve !annotation on the created instruction, if the terminator of the BB that is going to be removed has !annotation. This should ensure that !annotation is attached to the instructions that 'replace' the original terminator. Reviewed By: jdoerfert, lebedev.ri Differential Revision: https://reviews.llvm.org/D93410 --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 11 ++++++++--- llvm/test/Transforms/SimplifyCFG/annotations.ll | 16 ++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) 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/Transforms/SimplifyCFG/annotations.ll b/llvm/test/Transforms/SimplifyCFG/annotations.ll index 5e39107e1c89a..e6bc73d16992f 100644 --- a/llvm/test/Transforms/SimplifyCFG/annotations.ll +++ b/llvm/test/Transforms/SimplifyCFG/annotations.ll @@ -6,8 +6,8 @@ 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:%.*]] -; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C_1]], [[C_2]] +; 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() @@ -39,8 +39,8 @@ 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:%.*]] -; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[C_1]], [[C_2]] +; 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() @@ -73,9 +73,9 @@ define i32 @test_preserve_or_not(i8* %a, i8* %b, i8* %c, i8* %d) { ; 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:%.*]] -; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[C_2_NOT]], [[C_3]] +; 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() @@ -111,7 +111,7 @@ define i32 @test_or_not_no_annotation(i8* %a, i8* %b, i8* %c, i8* %d) { ; 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:%.*]] +; 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 From 0557af29dc3ef7deb85f93cf0ad285e74b4f2928 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Thu, 17 Dec 2020 14:42:12 +0000 Subject: [PATCH 7/7] [InstCombine] Preserve !annotation on newly created instructions. If the source instruction has !annotation metadata, all instructions created during combining should also have it. Tell the builder to add it. The !annotation system was discussed on llvm-dev as part of 'RFC: Combining Annotation Metadata and Remarks' (http://lists.llvm.org/pipermail/llvm-dev/2020-November/146393.html) This patch is based on an earlier patch by Francis Visoiu Mistrih. Reviewed By: thegameg, lebedev.ri Differential Revision: https://reviews.llvm.org/D91444 --- clang/test/CodeGenCXX/auto-var-init.cpp | 108 ++++++------------ .../InstCombine/InstructionCombining.cpp | 3 +- .../Transforms/InstCombine/annotations.ll | 30 ++--- 3 files changed, 50 insertions(+), 91 deletions(-) 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/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 1618b88a9c421..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.CollectMetadataToCopy(I, {LLVMContext::MD_dbg}); + Builder.CollectMetadataToCopy( + I, {LLVMContext::MD_dbg, LLVMContext::MD_annotation}); #ifndef NDEBUG std::string OrigI; diff --git a/llvm/test/Transforms/InstCombine/annotations.ll b/llvm/test/Transforms/InstCombine/annotations.ll index 3b0989402823e..c260828d2df24 100644 --- a/llvm/test/Transforms/InstCombine/annotations.ll +++ b/llvm/test/Transforms/InstCombine/annotations.ll @@ -49,8 +49,8 @@ declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) n define void @copy_1_byte(i8* %d, i8* %s) { ; CHECK-LABEL: define {{.+}} @copy_1_byte({{.+}} -; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1 -; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 @@ -61,8 +61,8 @@ declare i8* @memcpy(i8* noalias returned, i8* noalias nocapture readonly, i64) n define void @libcallcopy_1_byte(i8* %d, i8* %s) { ; CHECK-LABEL: define {{.+}} @libcallcopy_1_byte({{.+}} -; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1 -; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 @@ -73,8 +73,8 @@ 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 -; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 @@ -85,8 +85,8 @@ declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, define void @move_1_byte(i8* %d, i8* %s) { ; CHECK-LABEL: define {{.+}} @move_1_byte({{.+}} -; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[S:%.*]], align 1 -; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 @@ -97,8 +97,8 @@ 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 -; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 @@ -109,8 +109,8 @@ 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 -; CHECK-NEXT: store i8 [[TMP1]], i8* [[D:%.*]], align 1 +; 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 @@ -121,7 +121,7 @@ declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1) argmemo define void @set_1_byte(i8* %d) { ; CHECK-LABEL: define {{.+}} @set_1_byte({{.+}} -; CHECK-NEXT: store i8 1, i8* [[D:%.*]], align 1 +; 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 @@ -132,7 +132,7 @@ 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 +; 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 @@ -143,7 +143,7 @@ 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 +; 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