[llvm] 2e01cea - [IndVars] Recognize 'sub nuw' expressed as 'add' for widening
Max Kazantsev via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 11 20:49:30 PST 2020
Author: Max Kazantsev
Date: 2020-11-12T10:51:29+07:00
New Revision: 2e01ceafaa1ceef2428182128c3654bab56a0a4f
URL: https://github.com/llvm/llvm-project/commit/2e01ceafaa1ceef2428182128c3654bab56a0a4f
DIFF: https://github.com/llvm/llvm-project/commit/2e01ceafaa1ceef2428182128c3654bab56a0a4f.diff
LOG: [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
Added:
Modified:
llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
llvm/test/Transforms/IndVarSimplify/widen-loop-comp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 079ec7f0acd9..c7c081522f72 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,
diff --git a/llvm/test/Transforms/IndVarSimplify/widen-loop-comp.ll b/llvm/test/Transforms/IndVarSimplify/widen-loop-comp.ll
index 07d31c49f6e9..48195a299fc8 100644
--- a/llvm/test/Transforms/IndVarSimplify/widen-loop-comp.ll
+++ b/llvm/test/Transforms/IndVarSimplify/widen-loop-comp.ll
@@ -657,13 +657,10 @@ define i32 @test13(i32 %start, i32* %p, i32* %q) {
; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0
; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]]
; CHECK: backedge:
-; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32
-; CHECK-NEXT: [[FOO:%.*]] = add i32 [[TMP1]], -1
-; CHECK-NEXT: [[INDEX:%.*]] = zext i32 [[FOO]] to i64
-; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[INDEX]]
+; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[TMP1]]
; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4
-; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, i32* [[Q:%.*]], i64 [[INDEX]]
-; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q]], align 4
+; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q:%.*]], align 4
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]]
More information about the llvm-commits
mailing list