diff options
author | Michael Zolotukhin <mzolotukhin@apple.com> | 2014-05-24 08:09:57 +0000 |
---|---|---|
committer | Michael Zolotukhin <mzolotukhin@apple.com> | 2014-05-24 08:09:57 +0000 |
commit | d4c724625a7d044dcc4ffb44f3329df3f8738954 (patch) | |
tree | 98d1c7856abf1ba04fd3bce172e452077ee273bd /llvm/lib/Analysis/ScalarEvolution.cpp | |
parent | 188cafb03057fe6bfe5809b61782407d22995ca5 (diff) | |
download | bcm5719-llvm-d4c724625a7d044dcc4ffb44f3329df3f8738954.tar.gz bcm5719-llvm-d4c724625a7d044dcc4ffb44f3329df3f8738954.zip |
Implement sext(C1 + C2*X) --> sext(C1) + sext(C2*X) and
sext{C1,+,C2} --> sext(C1) + sext{0,+,C2} transformation in Scalar
Evolution.
That helps SLP-vectorizer to recognize consecutive loads/stores.
<rdar://problem/14860614>
llvm-svn: 209568
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 0c864d840f1..461fdac3c6c 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -1201,6 +1201,24 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, return getTruncateOrSignExtend(X, Ty); } + // sext(C1 + (C2 * x)) --> C1 + sext(C2 * x) if C1 < C2 + if (auto SA = dyn_cast<SCEVAddExpr>(Op)) { + if (SA->getNumOperands() == 2) { + auto SC1 = dyn_cast<SCEVConstant>(SA->getOperand(0)); + auto SMul = dyn_cast<SCEVMulExpr>(SA->getOperand(1)); + if (SMul && SC1) { + if (auto SC2 = dyn_cast<SCEVConstant>(SMul->getOperand(0))) { + APInt C1 = SC1->getValue()->getValue(); + APInt C2 = SC2->getValue()->getValue(); + APInt CDiff = C2 - C1; + if (C1.isStrictlyPositive() && C2.isStrictlyPositive() && + CDiff.isStrictlyPositive() && C2.isPowerOf2()) + return getAddExpr(getSignExtendExpr(SC1, Ty), + getSignExtendExpr(SMul, Ty)); + } + } + } + } // If the input value is a chrec scev, and we can prove that the value // did not overflow the old, smaller, value, we can sign extend all of the // operands (often constants). This allows analysis of something like @@ -1292,6 +1310,23 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, L, AR->getNoWrapFlags()); } } + // If Start and Step are constants, check if we can apply this + // transformation: + // sext{C1,+,C2} --> C1 + sext{0,+,C2} if C1 < C2 + auto SC1 = dyn_cast<SCEVConstant>(Start); + auto SC2 = dyn_cast<SCEVConstant>(Step); + if (SC1 && SC2) { + APInt C1 = SC1->getValue()->getValue(); + APInt C2 = SC2->getValue()->getValue(); + APInt CDiff = C2 - C1; + if (C1.isStrictlyPositive() && C2.isStrictlyPositive() && + CDiff.isStrictlyPositive() && C2.isPowerOf2()) { + Start = getSignExtendExpr(Start, Ty); + const SCEV *NewAR = getAddRecExpr(getConstant(AR->getType(), 0), Step, + L, AR->getNoWrapFlags()); + return getAddExpr(Start, getSignExtendExpr(NewAR, Ty)); + } + } } // The cast wasn't folded; create an explicit cast node. |