summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorDaniil Suchkov <suc-daniil@yandex.ru>2019-11-14 15:25:31 +0700
committerDaniil Suchkov <suc-daniil@yandex.ru>2019-11-14 17:04:32 +0700
commita2f6ae9abffcba260c22bb235879f0576bf3b783 (patch)
treeebece2b3649cab3594802418b9857d748f460346 /llvm/lib
parent2eb0862ed8a824f0d02c3df6ec4e05175cf8c3f1 (diff)
downloadbcm5719-llvm-a2f6ae9abffcba260c22bb235879f0576bf3b783.tar.gz
bcm5719-llvm-a2f6ae9abffcba260c22bb235879f0576bf3b783.zip
[InstCombine] Fold PHIs with equal incoming pointers
This is a resubmission of bbb29738b58aaf6f6518269abdcf8f64131665a9 that was reverted due to clang tests failures. It includes the fix and additional IR tests for the missed case. Summary: In case when all incoming values of a PHI are equal pointers, this transformation inserts a definition of such a pointer right after definition of the base pointer and replaces with this value both PHI and all it's incoming pointers. Primary goal of this transformation is canonicalization of this pattern in order to enable optimizations that can't handle PHIs. Non-inbounds pointers aren't currently supported. Reviewers: spatel, RKSimon, lebedev.ri, apilipenko Reviewed By: apilipenko Tags: #llvm Subscribers: hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D68128
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineInternal.h5
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp65
2 files changed, 70 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 524f9313d8c..52aeb787aaf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -895,6 +895,11 @@ private:
/// insert a new pointer typed PHI and replace the original one.
Instruction *FoldIntegerTypedPHI(PHINode &PN);
+ /// If all incoming values of a pointer typed PHI are pointers with the same
+ /// base and offset, replace the PHI and all incoming values with one
+ /// definition of such pointer.
+ Instruction *FoldPHIWithEqualPointers(PHINode &PN);
+
/// Helper function for FoldPHIArgXIntoPHI() to set debug location for the
/// folded operation.
void PHIArgMergedDebugLoc(Instruction *Inst, PHINode &PN);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
index e0376b7582f..d1035414560 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -1122,6 +1122,68 @@ Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
return replaceInstUsesWith(FirstPhi, Undef);
}
+Instruction *InstCombiner::FoldPHIWithEqualPointers(PHINode &PN) {
+ auto *PhiTy = dyn_cast<PointerType>(PN.getType());
+ if (!PhiTy)
+ return nullptr;
+
+ // Make sure all incoming pointers have the same base pointers and offsets.
+ // Also, make sure no addrspacecasts involved.
+ // Note: only inbounds GEPs are supported!
+ const DataLayout &DL = PN.getModule()->getDataLayout();
+ Value *FirstValue = PN.getIncomingValue(0);
+ int64_t Offset;
+ Value *Base = GetPointerBaseWithConstantOffset(
+ FirstValue, Offset, DL, /* AllowNonInbounds */ false);
+
+ auto *BaseTy = cast<PointerType>(Base->getType());
+ if (BaseTy->getAddressSpace() != PhiTy->getAddressSpace())
+ return nullptr;
+
+ for (Use &Incoming : PN.incoming_values()) {
+ if (!isa<Instruction>(Incoming))
+ return nullptr;
+ int64_t CurrentOffset;
+ Value *CurrentBase = GetPointerBaseWithConstantOffset(
+ Incoming, CurrentOffset, DL, /* AllowNonInbounds */ false);
+ if (CurrentBase != Base || CurrentOffset != Offset)
+ return nullptr;
+ }
+
+ Instruction *InsertPt = nullptr;
+ if (auto *BaseInst = dyn_cast<Instruction>(Base)) {
+ if (isa<PHINode>(BaseInst)) {
+ BasicBlock *InsertBB = BaseInst->getParent();
+ BasicBlock::iterator InsertPtIter = InsertBB->getFirstInsertionPt();
+ // Make sure the insertion point exists. At the moment the only reason why
+ // insertion point may not exist is EHPad being a terminator. This check
+ // is a bit more future-proof than just `if (!TI->isEHPad())`.
+ if (InsertPtIter != InsertBB->end())
+ InsertPt = &*InsertPtIter;
+ } else
+ InsertPt = BaseInst->getNextNode();
+ } else
+ InsertPt = &*PN.getFunction()->getEntryBlock().getFirstInsertionPt();
+
+ if (!InsertPt)
+ return nullptr;
+
+ Builder.SetInsertPoint(InsertPt);
+ Type *I8PtrTy = Builder.getInt8PtrTy(PhiTy->getAddressSpace());
+ Value *BaseI8Ptr = Builder.CreateBitCast(Base, I8PtrTy);
+ Value *GEP = Builder.CreateConstInBoundsGEP1_64(BaseI8Ptr, Offset);
+ Value *GEPTyped = Builder.CreateBitCast(GEP, PhiTy);
+
+ for (Use &Incoming : PN.incoming_values()) {
+ auto *IncomingInst = cast<Instruction>(Incoming);
+ // If we haven't already replaced this instruction.
+ if (IncomingInst != GEPTyped)
+ replaceInstUsesWith(*IncomingInst, GEPTyped);
+ }
+
+ return replaceInstUsesWith(PN, GEPTyped);
+}
+
// PHINode simplification
//
Instruction *InstCombiner::visitPHINode(PHINode &PN) {
@@ -1143,6 +1205,9 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) {
if (Instruction *Result = FoldPHIArgOpIntoPHI(PN))
return Result;
+ if (Instruction *Result = FoldPHIWithEqualPointers(PN))
+ return Result;
+
// If this is a trivial cycle in the PHI node graph, remove it. Basically, if
// this PHI only has a single use (a PHI), and if that PHI only has one use (a
// PHI)... break the cycle.
OpenPOWER on IntegriCloud