From 68623a0e9fbebfb2aa2edab710d021b26f3f1edf Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Mon, 25 Jul 2016 02:21:25 +0000 Subject: [PATCH] [GVNHoist] Merge metadata on hoisted instructions less conservatively We can combine metadata from multiple instructions intelligently for certain metadata nodes. llvm-svn: 276602 --- llvm/lib/Transforms/Scalar/GVNHoist.cpp | 24 +++++++++++++++++------- llvm/test/Transforms/GVN/hoist-md.ll | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/GVNHoist.cpp b/llvm/lib/Transforms/Scalar/GVNHoist.cpp index 0b5e94f..194405d 100644 --- a/llvm/lib/Transforms/Scalar/GVNHoist.cpp +++ b/llvm/lib/Transforms/Scalar/GVNHoist.cpp @@ -23,6 +23,7 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/MemorySSA.h" using namespace llvm; @@ -172,6 +173,15 @@ typedef DenseMap BBSideEffectsSet; typedef SmallVector SmallVecInsn; typedef SmallVectorImpl SmallVecImplInsn; +static void combineKnownMetadata(Instruction *ReplInst, Instruction *I) { + static const unsigned KnownIDs[] = { + LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope, + LLVMContext::MD_noalias, LLVMContext::MD_range, + LLVMContext::MD_fpmath, LLVMContext::MD_invariant_load, + LLVMContext::MD_invariant_group}; + combineMetadata(ReplInst, I, KnownIDs); +} + // This pass hoists common computations across branches sharing common // dominator. The primary goal is to reduce the code size, and in some // cases reduce critical path (by exposing more ILP). @@ -604,15 +614,15 @@ public: ClonedGep->insertBefore(HoistPt->getTerminator()); // Conservatively discard any optimization hints, they may differ on the // other paths. - ClonedGep->dropUnknownNonDebugMetadata(); - for (const Instruction *OtherInst : InstructionsToHoist) { - const GetElementPtrInst *OtherGep; + for (Instruction *OtherInst : InstructionsToHoist) { + GetElementPtrInst *OtherGep; if (auto *OtherLd = dyn_cast(OtherInst)) OtherGep = cast(OtherLd->getPointerOperand()); else OtherGep = cast( cast(OtherInst)->getPointerOperand()); ClonedGep->intersectOptionalDataWith(OtherGep); + combineKnownMetadata(ClonedGep, OtherGep); } Repl->replaceUsesOfWith(Gep, ClonedGep); @@ -622,11 +632,11 @@ public: ClonedVal->insertBefore(HoistPt->getTerminator()); // Conservatively discard any optimization hints, they may differ on the // other paths. - ClonedVal->dropUnknownNonDebugMetadata(); - for (const Instruction *OtherInst : InstructionsToHoist) { - const auto *OtherVal = + for (Instruction *OtherInst : InstructionsToHoist) { + auto *OtherVal = cast(cast(OtherInst)->getValueOperand()); ClonedVal->intersectOptionalDataWith(OtherVal); + combineKnownMetadata(ClonedVal, OtherVal); } Repl->replaceUsesOfWith(Val, ClonedVal); } @@ -668,7 +678,6 @@ public: Repl->moveBefore(HoistPt->getTerminator()); // TBAA may differ on one of the other paths, we need to get rid of // anything which might conflict. - Repl->dropUnknownNonDebugMetadata(); } if (isa(Repl)) @@ -702,6 +711,7 @@ public: ++NumCallsRemoved; } Repl->intersectOptionalDataWith(I); + combineKnownMetadata(Repl, I); I->replaceAllUsesWith(Repl); I->eraseFromParent(); } diff --git a/llvm/test/Transforms/GVN/hoist-md.ll b/llvm/test/Transforms/GVN/hoist-md.ll index 8661542..902bbb7 100644 --- a/llvm/test/Transforms/GVN/hoist-md.ll +++ b/llvm/test/Transforms/GVN/hoist-md.ll @@ -71,3 +71,28 @@ if.end: ; preds = %if.else, %if.then !4 = !{!"Simple C++ TBAA"} !5 = !{!6, !6, i64 0} !6 = !{!"_ZTS1e", !3, i64 0} + +define i32 @test4(i1 %b, i32* %y) { +entry: + br i1 %b, label %if.then, label %if.end + +if.then: ; preds = %entry + %0 = load i32, i32* %y, align 4, !range !7 + br label %return + +if.end: ; preds = %entry + %1 = load i32, i32* %y, align 4, !range !8 + br label %return + +return: ; preds = %if.end, %if.then + %retval.0 = phi i32 [ %0, %if.then ], [ %1, %if.end ] + ret i32 %retval.0 +} +; CHECK-LABEL: define i32 @test4( +; CHECK: %[[load:.*]] = load i32, i32* %y, align 4, !range ![[range_md:.*]] +; CHECK: %[[phi:.*]] = phi i32 [ %[[load]], %{{.*}} ], [ %[[load]], %{{.*}} ] +; CHECK: ret i32 %[[phi]] + +!7 = !{i32 0, i32 2} +!8 = !{i32 3, i32 4} +; CHECK: ![[range_md]] = !{i32 0, i32 2, i32 3, i32 4} -- 2.7.4