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 | 45788be6e2603ecfc149f43df1a6d5e04c5734d8 (patch) | |
tree | bd70a5049ceac2d3d050ae7d1fce340227808277 /lib/Analysis | |
parent | 6a04ef99f64c60e8368f23fa7717b74dc83cd6e1 (diff) | |
download | llvm-45788be6e2603ecfc149f43df1a6d5e04c5734d8.tar.gz llvm-45788be6e2603ecfc149f43df1a6d5e04c5734d8.tar.bz2 llvm-45788be6e2603ecfc149f43df1a6d5e04c5734d8.tar.xz |
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>
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209568 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/ScalarEvolution.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 0c864d840f..461fdac3c6 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/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. |