summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis/ScalarEvolution.cpp
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
commitd4c724625a7d044dcc4ffb44f3329df3f8738954 (patch)
tree98d1c7856abf1ba04fd3bce172e452077ee273bd /llvm/lib/Analysis/ScalarEvolution.cpp
parent188cafb03057fe6bfe5809b61782407d22995ca5 (diff)
downloadbcm5719-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.cpp35
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.
OpenPOWER on IntegriCloud