Skip to content

Commit e4590bc

Browse files
committed
replace LCSSA with null term ptr
1 parent 5335b7d commit e4590bc

File tree

1 file changed

+32
-93
lines changed

1 file changed

+32
-93
lines changed

llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp

Lines changed: 32 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "llvm/ADT/ArrayRef.h"
3434
#include "llvm/ADT/DenseMap.h"
3535
#include "llvm/ADT/MapVector.h"
36+
#include "llvm/ADT/STLExtras.h"
3637
#include "llvm/ADT/SetVector.h"
3738
#include "llvm/ADT/SmallPtrSet.h"
3839
#include "llvm/ADT/SmallVector.h"
@@ -1536,57 +1537,6 @@ static Value *matchCondition(BranchInst *BI, BasicBlock *LoopEntry,
15361537
return nullptr;
15371538
}
15381539

1539-
/// getCandidateResInstr - If there is strlen calculated, return the Result
1540-
/// instruction based on the \p OpWidth passed, else return nullptr
1541-
static Instruction *getCandidateResInstr(Instruction *EndAddress,
1542-
Value *StartAddress,
1543-
unsigned OpWidth) {
1544-
using namespace llvm::PatternMatch;
1545-
1546-
assert(StartAddress && "Valid start address required.");
1547-
1548-
// lambda expression to check that the instruction has a single user
1549-
auto GetSingleUser = [](Instruction *I) -> User * {
1550-
if (I->hasOneUse())
1551-
return *I->user_begin();
1552-
return nullptr;
1553-
};
1554-
1555-
// The pointer to the end address should only have one use which is a pointer
1556-
// to int instruction.
1557-
auto *TmpUser = GetSingleUser(EndAddress);
1558-
if (!TmpUser)
1559-
return nullptr;
1560-
1561-
if (PtrToIntInst *PToI = dyn_cast<PtrToIntInst>(TmpUser)) {
1562-
// The only user of the PtrToIntInst should be the sub instruction that
1563-
// calculates the difference b/w the two pointer operands.
1564-
TmpUser = GetSingleUser(PToI);
1565-
if (!TmpUser)
1566-
return nullptr;
1567-
Instruction *Inst = dyn_cast<Instruction>(TmpUser);
1568-
1569-
if (!Inst || Inst->getOpcode() != Instruction::Sub ||
1570-
Inst->getOperand(0) != PToI)
1571-
return nullptr;
1572-
Value *MatchAddr;
1573-
if (match(Inst->getOperand(1), m_PtrToInt(m_Value(MatchAddr)))) {
1574-
if (MatchAddr != StartAddress)
1575-
return nullptr;
1576-
1577-
// We found the candidate sub instruction
1578-
switch (OpWidth) {
1579-
case 8:
1580-
return Inst;
1581-
default:
1582-
return nullptr;
1583-
}
1584-
}
1585-
}
1586-
1587-
return nullptr;
1588-
}
1589-
15901540
/// Recognizes a strlen idiom by checking for loops that increment
15911541
/// a char pointer and then subtract with the base pointer.
15921542
///
@@ -1595,22 +1545,19 @@ static Instruction *getCandidateResInstr(Instruction *EndAddress,
15951545
///
15961546
/// The core idiom we are trying to detect is:
15971547
/// \code
1598-
/// if (str == NULL)
1599-
/// goto loop-exit // the precondition of the loop
16001548
/// start = str;
16011549
/// do {
16021550
/// str++;
1603-
/// } while(*str!='\0');
1604-
/// return (str - start);
1605-
/// loop-exit:
1551+
/// } while(*str != '\0');
16061552
/// \endcode
16071553
///
16081554
/// The transformed output is similar to below c-code:
16091555
/// \code
1610-
/// if (str == NULL)
1611-
/// goto loop-exit // the precondition of the loop
1612-
/// return strlen(str);
1556+
/// str = start + strlen(start)
1557+
/// len = str - start
16131558
/// \endcode
1559+
///
1560+
/// Later the pointer subtraction will be folded by InstCombine
16141561
bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
16151562
if (DisableLIRPStrlen)
16161563
return false;
@@ -1620,30 +1567,20 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
16201567
return false;
16211568

16221569
// It should have a preheader containing nothing but an unconditional branch.
1623-
auto *Pre = CurLoop->getLoopPreheader();
1624-
if (!Pre || &Pre->front() != Pre->getTerminator())
1570+
auto *Preheader = CurLoop->getLoopPreheader();
1571+
if (!Preheader || &Preheader->front() != Preheader->getTerminator())
16251572
return false;
16261573

1627-
auto *EntryBI = dyn_cast<BranchInst>(Pre->getTerminator());
1574+
auto *EntryBI = dyn_cast<BranchInst>(Preheader->getTerminator());
16281575
if (!EntryBI || EntryBI->isConditional())
16291576
return false;
16301577

1631-
// It should have a precondition block
1632-
auto *PreCondBB = Pre->getSinglePredecessor();
1633-
if (!PreCondBB)
1634-
return false;
1635-
1636-
// The precondition terminator instruction should skip the loop body based on
1637-
// an icmp with zero/null.
1638-
if (!matchCondition(dyn_cast<BranchInst>(PreCondBB->getTerminator()), Pre))
1639-
return false;
1640-
16411578
// The loop exit must be conditioned on an icmp with 0.
16421579
// The icmp operand has to be a load on some SSA reg that increments
16431580
// by 1 in the loop.
1644-
auto *LoopBody = *(CurLoop->block_begin());
1645-
auto *LoopTerm = dyn_cast<BranchInst>(LoopBody->getTerminator());
1646-
auto *LoopCond = matchCondition(LoopTerm, LoopBody);
1581+
BasicBlock *LoopBody = *CurLoop->block_begin();
1582+
BranchInst *LoopTerm = dyn_cast<BranchInst>(LoopBody->getTerminator());
1583+
Value *LoopCond = matchCondition(LoopTerm, LoopBody);
16471584

16481585
if (!LoopCond)
16491586
return false;
@@ -1660,6 +1597,7 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
16601597
// the loop, indicating strlen calculation.
16611598
auto *IncPtr = LoopLoad->getPointerOperand();
16621599
const SCEVAddRecExpr *LoadEv = dyn_cast<SCEVAddRecExpr>(SE->getSCEV(IncPtr));
1600+
16631601
if (!LoadEv || LoadEv->getLoop() != CurLoop || !LoadEv->isAffine())
16641602
return false;
16651603

@@ -1700,6 +1638,7 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
17001638
if (!LCSSAPhi || !SE->isSCEVable(LCSSAPhi->getType()))
17011639
return false;
17021640

1641+
// This matched the pointer version of the idiom
17031642
if (LCSSAPhi->getIncomingValueForBlock(LoopBody) !=
17041643
LoopLoad->getPointerOperand())
17051644
return false;
@@ -1712,35 +1651,34 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
17121651
return false;
17131652

17141653
// We can now expand the base of the str
1715-
IRBuilder<> Builder(Pre->getTerminator());
1654+
IRBuilder<> Builder(Preheader->getTerminator());
17161655

1717-
PHINode *LoopPhi = &*LoopBody->phis().begin();
1718-
if (!LoopPhi || ++LoopBody->phis().begin() != LoopBody->phis().end())
1656+
auto LoopPhiRange = LoopBody->phis();
1657+
if (!hasNItems(LoopPhiRange, 1))
17191658
return false;
1720-
Value *PreVal = LoopBody->phis().begin()->getIncomingValueForBlock(Pre);
1659+
auto *LoopPhi = &*LoopPhiRange.begin();
1660+
Value *PreVal = LoopPhi->getIncomingValueForBlock(Preheader);
17211661
if (!PreVal)
17221662
return false;
17231663

17241664
Value *Expanded = nullptr;
1665+
Type *ExpandedType = nullptr;
17251666
if (auto *GEP = dyn_cast<GetElementPtrInst>(LoopLoad->getPointerOperand())) {
17261667
if (GEP->getPointerOperand() != LoopPhi)
17271668
return false;
17281669
GetElementPtrInst *NewGEP =
17291670
GetElementPtrInst::Create(GEP->getSourceElementType(), PreVal,
17301671
SmallVector<Value *, 4>(GEP->indices()),
1731-
"newgep", Pre->getTerminator());
1672+
"newgep", Preheader->getTerminator());
17321673
Expanded = NewGEP;
1733-
} else if (LoopLoad->getPointerOperand() == LoopPhi)
1674+
ExpandedType = NewGEP->getSourceElementType();
1675+
} else if (LoopLoad->getPointerOperand() == LoopPhi) {
17341676
Expanded = PreVal;
1677+
ExpandedType = LoopLoad->getType();
1678+
}
17351679
if (!Expanded)
17361680
return false;
17371681

1738-
// Check that the LoopExitBB is calculating the string length and identify
1739-
// the instruction that has the string length calculation
1740-
Instruction *ResInst = getCandidateResInstr(LCSSAPhi, PreVal, OpWidth);
1741-
if (!ResInst)
1742-
return false;
1743-
17441682
// Ensure that the GEP has the correct index if the pointer was modified.
17451683
// This can happen when the pointer in the user code, outside the loop,
17461684
// walks past a certain pre-checked index of the string.
@@ -1786,11 +1724,12 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
17861724

17871725
assert(StrLenFunc && "Failed to emit strlen function.");
17881726

1789-
// Replace the subtraction instruction by the result of strlen
1790-
ResInst->replaceAllUsesWith(StrLenFunc);
1791-
1792-
// Remove the loop-exit branch and delete dead instructions
1793-
RecursivelyDeleteTriviallyDeadInstructions(ResInst, TLI);
1727+
// Replace LCSSA Phi use with new pointer to the null terminator
1728+
SmallVector<Value *, 4> NewBaseIndex{StrLenFunc};
1729+
GetElementPtrInst *NewEndPtr = GetElementPtrInst::Create(
1730+
ExpandedType, Expanded, NewBaseIndex, "end", Preheader->getTerminator());
1731+
LCSSAPhi->replaceAllUsesWith(NewEndPtr);
1732+
RecursivelyDeleteDeadPHINode(LCSSAPhi);
17941733

17951734
ConstantInt *NewLoopCond = LoopTerm->getSuccessor(0) == LoopBody
17961735
? Builder.getFalse()
@@ -1805,7 +1744,7 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
18051744

18061745
ORE.emit([&]() {
18071746
return OptimizationRemark(DEBUG_TYPE, "recognizeAndInsertStrLen",
1808-
CurLoop->getStartLoc(), Pre)
1747+
CurLoop->getStartLoc(), Preheader)
18091748
<< "Transformed pointer difference into a call to strlen() function";
18101749
});
18111750

0 commit comments

Comments
 (0)