diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -440,6 +440,7 @@ Instruction *visitLoadInst(LoadInst &LI); Instruction *visitStoreInst(StoreInst &SI); Instruction *visitAtomicRMWInst(AtomicRMWInst &SI); + Instruction *visitUnconditionalBranchInst(BranchInst &BI); Instruction *visitBranchInst(BranchInst &BI); Instruction *visitFenceInst(FenceInst &FI); Instruction *visitSwitchInst(SwitchInst &SI); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -1425,34 +1425,6 @@ if (isa(Val)) return eraseInstFromFunction(SI); - auto IsNoopInstrForStoreMerging = [](BasicBlock::iterator BBI) { - return isa(BBI) || - (isa(BBI) && BBI->getType()->isPointerTy()); - }; - - // If this store is the second-to-last instruction in the basic block - // (excluding debug info and bitcasts of pointers) and if the block ends with - // an unconditional branch, try to move the store to the successor block. - BBI = SI.getIterator(); - do { - ++BBI; - } while (IsNoopInstrForStoreMerging(BBI)); - - if (BranchInst *BI = dyn_cast(BBI)) - if (BI->isUnconditional()) - if (mergeStoreIntoSuccessor(SI)) { - // Okay, we've managed to do that. Now, let's see if now-second-to-last - // instruction is also a store that we can also sink. - BasicBlock::iterator FirstInstr = BBI->getParent()->begin(); - do { - if (BBI != FirstInstr) - --BBI; - } while (BBI != FirstInstr && IsNoopInstrForStoreMerging(BBI)); - if (StoreInst *PrevStore = dyn_cast(BBI)) - Worklist.add(PrevStore); - return nullptr; - } - return nullptr; } @@ -1462,8 +1434,8 @@ /// *P = v1; if () { *P = v2; } /// into a phi node with a store in the successor. bool InstCombiner::mergeStoreIntoSuccessor(StoreInst &SI) { - assert(SI.isUnordered() && - "This code has not been audited for volatile or ordered store case."); + if (!SI.isUnordered()) + return false; // This code has not been audited for volatile/ordered case. // Check if the successor block has exactly 2 incoming edges. BasicBlock *StoreBB = SI.getParent(); diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2734,10 +2734,42 @@ return nullptr; } +Instruction *InstCombiner::visitUnconditionalBranchInst(BranchInst &BI) { + assert(BI.isUnconditional() && "Only for unconditional branches."); + + // If this store is the second-to-last instruction in the basic block + // (excluding debug info and bitcasts of pointers) and if the block ends with + // an unconditional branch, try to move the store to the successor block. + + auto GetLastSinkableStore = [](BasicBlock::iterator BBI) { + auto IsNoopInstrForStoreMerging = [](BasicBlock::iterator BBI) { + return isa(BBI) || + (isa(BBI) && BBI->getType()->isPointerTy()); + }; + + BasicBlock::iterator FirstInstr = BBI->getParent()->begin(); + do { + if (BBI != FirstInstr) + --BBI; + } while (BBI != FirstInstr && IsNoopInstrForStoreMerging(BBI)); + + return dyn_cast(BBI); + }; + + if (StoreInst *SI = GetLastSinkableStore(BasicBlock::iterator(BI))) + if (mergeStoreIntoSuccessor(*SI)) { + // Okay, we've managed to do that. Now, let's see if now-second-to-last + // instruction is also a store that we can also sink. + if (StoreInst *SI = GetLastSinkableStore(BasicBlock::iterator(BI))) + return &BI; // Let's revisit this `br` once more then. + } + + return nullptr; +} + Instruction *InstCombiner::visitBranchInst(BranchInst &BI) { - // Nothing to do about unconditional branches. if (BI.isUnconditional()) - return nullptr; + return visitUnconditionalBranchInst(BI); // Change br (not X), label True, label False to: br X, label False, True Value *X = nullptr;