summaryrefslogtreecommitdiff
path: root/lib/Analysis
diff options
context:
space:
mode:
authorMichael Zolotukhin <mzolotukhin@apple.com>2014-05-24 08:09:57 +0000
committerMichael Zolotukhin <mzolotukhin@apple.com>2014-05-24 08:09:57 +0000
commit45788be6e2603ecfc149f43df1a6d5e04c5734d8 (patch)
treebd70a5049ceac2d3d050ae7d1fce340227808277 /lib/Analysis
parent6a04ef99f64c60e8368f23fa7717b74dc83cd6e1 (diff)
downloadllvm-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.cpp35
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.