aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
diff options
context:
space:
mode:
authorMax Kazantsev <mkazantsev@azul.com>2020-11-12 10:49:01 +0700
committerMax Kazantsev <mkazantsev@azul.com>2020-11-12 10:51:29 +0700
commit2e01ceafaa1ceef2428182128c3654bab56a0a4f (patch)
treeda5a0becd3039066cba0bcf2be85e49674d2a4a8 /llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
parent813781a923007a6070521ebfcb939796b0a47df8 (diff)
downloadllvm-2e01ceafaa1ceef2428182128c3654bab56a0a4f.zip
llvm-2e01ceafaa1ceef2428182128c3654bab56a0a4f.tar.gz
llvm-2e01ceafaa1ceef2428182128c3654bab56a0a4f.tar.bz2
[IndVars] Recognize 'sub nuw' expressed as 'add' for widening
InstCombine canonicalizes 'sub nuw' instructions to 'add' without the `nuw` flag. The typical case where we see it is decrementing induction variables. For them, IndVars fails to prove that it's legal to widen them, and inserts unprofitable `zext`'s. This patch adds recognition of such pattern using SCEV. Differential Revision: https://reviews.llvm.org/D89550 Reviewed By: fhahn, skatkov
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyIndVar.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyIndVar.cpp26
1 files changed, 22 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 079ec7f..c7c0815 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -1539,8 +1539,26 @@ bool WidenIV::widenWithVariantUse(WidenIV::NarrowIVDefUse DU) {
ExtendKind ExtKind = getExtendKind(NarrowDef);
bool CanSignExtend = ExtKind == SignExtended && OBO->hasNoSignedWrap();
bool CanZeroExtend = ExtKind == ZeroExtended && OBO->hasNoUnsignedWrap();
- if (!CanSignExtend && !CanZeroExtend)
- return false;
+ auto AnotherOpExtKind = ExtKind;
+ if (!CanSignExtend && !CanZeroExtend) {
+ // Because InstCombine turns 'sub nuw' to 'add' losing the no-wrap flag, we
+ // will most likely not see it. Let's try to prove it.
+ if (OpCode != Instruction::Add)
+ return false;
+ if (ExtKind != ZeroExtended)
+ return false;
+ const SCEV *LHS = SE->getSCEV(OBO->getOperand(0));
+ const SCEV *RHS = SE->getSCEV(OBO->getOperand(1));
+ if (!SE->isKnownNegative(RHS))
+ return false;
+ bool ProvedSubNUW = SE->isKnownPredicateAt(
+ ICmpInst::ICMP_UGE, LHS, SE->getNegativeSCEV(RHS), NarrowUse);
+ if (!ProvedSubNUW)
+ return false;
+ // In fact, our 'add' is 'sub nuw'. We will need to widen the 2nd operand as
+ // neg(zext(neg(op))), which is basically sext(op).
+ AnotherOpExtKind = SignExtended;
+ }
// Verifying that Defining operand is an AddRec
const SCEV *Op1 = SE->getSCEV(WideDef);
@@ -1564,11 +1582,11 @@ bool WidenIV::widenWithVariantUse(WidenIV::NarrowIVDefUse DU) {
Value *LHS = (NarrowUse->getOperand(0) == NarrowDef)
? WideDef
: createExtendInst(NarrowUse->getOperand(0), WideType,
- ExtKind, NarrowUse);
+ AnotherOpExtKind, NarrowUse);
Value *RHS = (NarrowUse->getOperand(1) == NarrowDef)
? WideDef
: createExtendInst(NarrowUse->getOperand(1), WideType,
- ExtKind, NarrowUse);
+ AnotherOpExtKind, NarrowUse);
auto *NarrowBO = cast<BinaryOperator>(NarrowUse);
auto *WideBO = BinaryOperator::Create(NarrowBO->getOpcode(), LHS, RHS,