summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis
diff options
context:
space:
mode:
authorAmara Emerson <amara.emerson@arm.com>2017-08-04 20:19:46 +0000
committerAmara Emerson <amara.emerson@arm.com>2017-08-04 20:19:46 +0000
commit56dca4e3cae307cb7154c83f43282cad54be88a8 (patch)
treed192d4e67866c03627b7eedf82b0691a8875cad1 /llvm/lib/Analysis
parentfcf8e5e34572c16848378232f1b414a4686a4916 (diff)
downloadbcm5719-llvm-56dca4e3cae307cb7154c83f43282cad54be88a8.tar.gz
bcm5719-llvm-56dca4e3cae307cb7154c83f43282cad54be88a8.zip
[SCEV] Preserve NSW information for sext(subtract).
Pushes the sext onto the operands of a Sub if NSW is present. Also adds support for propagating the nowrap flags of the llvm.ssub.with.overflow intrinsic during analysis. Differential Revision: https://reviews.llvm.org/D35256 llvm-svn: 310117
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp32
1 files changed, 29 insertions, 3 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index d3baf532045..0d1c6d16f41 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -4168,10 +4168,21 @@ static Optional<BinaryOp> MatchBinaryOp(Value *V, DominatorTree &DT) {
}
case Intrinsic::ssub_with_overflow:
- case Intrinsic::usub_with_overflow:
- return BinaryOp(Instruction::Sub, CI->getArgOperand(0),
- CI->getArgOperand(1));
+ case Intrinsic::usub_with_overflow: {
+ if (!isOverflowIntrinsicNoWrap(cast<IntrinsicInst>(CI), DT))
+ return BinaryOp(Instruction::Sub, CI->getArgOperand(0),
+ CI->getArgOperand(1));
+ // The same reasoning as sadd/uadd above.
+ if (F->getIntrinsicID() == Intrinsic::ssub_with_overflow)
+ return BinaryOp(Instruction::Sub, CI->getArgOperand(0),
+ CI->getArgOperand(1), /* IsNSW = */ true,
+ /* IsNUW = */ false);
+ else
+ return BinaryOp(Instruction::Sub, CI->getArgOperand(0),
+ CI->getArgOperand(1), /* IsNSW = */ false,
+ /* IsNUW = */ true);
+ }
case Intrinsic::smul_with_overflow:
case Intrinsic::umul_with_overflow:
return BinaryOp(Instruction::Mul, CI->getArgOperand(0),
@@ -5952,6 +5963,21 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
return getZeroExtendExpr(getSCEV(U->getOperand(0)), U->getType());
case Instruction::SExt:
+ if (auto BO = MatchBinaryOp(U->getOperand(0), DT)) {
+ // The NSW flag of a subtract does not always survive the conversion to
+ // A + (-1)*B. By pushing sign extension onto its operands we are much
+ // more likely to preserve NSW and allow later AddRec optimisations.
+ //
+ // NOTE: This is effectively duplicating this logic from getSignExtend:
+ // sext((A + B + ...)<nsw>) --> (sext(A) + sext(B) + ...)<nsw>
+ // but by that point the NSW information has potentially been lost.
+ if (BO->Opcode == Instruction::Sub && BO->IsNSW) {
+ Type *Ty = U->getType();
+ auto *V1 = getSignExtendExpr(getSCEV(BO->LHS), Ty);
+ auto *V2 = getSignExtendExpr(getSCEV(BO->RHS), Ty);
+ return getMinusSCEV(V1, V2, SCEV::FlagNSW);
+ }
+ }
return getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType());
case Instruction::BitCast:
OpenPOWER on IntegriCloud