diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index 0b40d44c74437..37735a0442ce2 100644 --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -1611,37 +1611,33 @@ bool WidenIV::widenWithVariantUse(WidenIV::NarrowIVDefUse DU) { return false; ExtUsers.push_back(User); } - if (ExtUsers.empty()) { - DeadInsts.emplace_back(NarrowUse); - return true; - } - - // We'll prove some facts that should be true in the context of ext users. If - // there is no users, we are done now. If there are some, pick their common - // dominator as context. - const Instruction *CtxI = findCommonDominator(ExtUsers, *DT); - - 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 != ExtendKind::Zero) - return false; - const SCEV *LHS = SE->getSCEV(OBO->getOperand(0)); - const SCEV *RHS = SE->getSCEV(OBO->getOperand(1)); - // TODO: Support case for NarrowDef = NarrowUse->getOperand(1). - if (NarrowUse->getOperand(0) != NarrowDef) - return false; - if (!SE->isKnownNegative(RHS)) - return false; - bool ProvedSubNUW = SE->isKnownPredicateAt(ICmpInst::ICMP_UGE, LHS, - SE->getNegativeSCEV(RHS), CtxI); - 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 = ExtendKind::Sign; + if (!ExtUsers.empty()) { + // We'll prove some facts that should be true in the context of ext users. + // Pick their common dominator as context. + const Instruction *CtxI = findCommonDominator(ExtUsers, *DT); + + 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 != ExtendKind::Zero) + return false; + const SCEV *LHS = SE->getSCEV(OBO->getOperand(0)); + const SCEV *RHS = SE->getSCEV(OBO->getOperand(1)); + // TODO: Support case for NarrowDef = NarrowUse->getOperand(1). + if (NarrowUse->getOperand(0) != NarrowDef) + return false; + if (!SE->isKnownNegative(RHS)) + return false; + bool ProvedSubNUW = SE->isKnownPredicateAt(ICmpInst::ICMP_UGE, LHS, + SE->getNegativeSCEV(RHS), CtxI); + 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 = ExtendKind::Sign; + } } // Verifying that Defining operand is an AddRec diff --git a/llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll b/llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll index 620b0adaebfe5..7a3c829c3b0b6 100644 --- a/llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll +++ b/llvm/test/Transforms/IndVarSimplify/X86/pr57187.ll @@ -15,14 +15,15 @@ define void @test(i32 %start) { ; CHECK-NEXT: br label [[LOOP]] ; CHECK: loop: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP1]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 4294967295 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 -; CHECK-NEXT: [[INDVARS:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 ; CHECK-NEXT: [[LOOP_EXIT_COND:%.*]] = icmp slt i32 [[TMP0]], 11 ; CHECK-NEXT: br i1 [[LOOP_EXIT_COND]], label [[EXIT:%.*]], label [[STUCK_PREHEADER:%.*]] ; CHECK: stuck.preheader: ; CHECK-NEXT: br label [[STUCK:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[INDVARS]], [[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT_LCSSA_WIDE:%.*]] = phi i64 [ [[TMP2]], [[LOOP]] ] +; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[IV_NEXT_LCSSA_WIDE]] to i32 ; CHECK-NEXT: ret void ; CHECK: stuck: ; CHECK-NEXT: br i1 false, label [[BACKEDGE]], label [[STUCK]] diff --git a/llvm/test/Transforms/IndVarSimplify/widen-nonnegative-countdown.ll b/llvm/test/Transforms/IndVarSimplify/widen-nonnegative-countdown.ll index d473103f5824e..c9d84f1a5a63d 100644 --- a/llvm/test/Transforms/IndVarSimplify/widen-nonnegative-countdown.ll +++ b/llvm/test/Transforms/IndVarSimplify/widen-nonnegative-countdown.ll @@ -82,13 +82,12 @@ define void @zext_postinc(ptr %A, i32 %start) { ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[J_016_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[FOR_BODY]] ], [ [[START]], [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]] ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) -; CHECK-NEXT: [[INC_US]] = add nsw i32 [[J_016_US]], -1 -; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[INC_US]], 6 +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], 4294967295 +; CHECK-NEXT: [[CMP2_US_WIDE:%.*]] = icmp ugt i64 [[TMP1]], 6 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 -; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK-NEXT: br i1 [[CMP2_US_WIDE]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]] ; CHECK: exit.loopexit: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: @@ -365,16 +364,15 @@ define void @zext_postinc_offset_constant_one(ptr %A, i32 %start) { ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[J_016_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[FOR_BODY]] ], [ [[START]], [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32 ; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP1]], 1 ; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext i32 [[ADD_US]] to i64 ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[IDXPROM_US]] ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) -; CHECK-NEXT: [[INC_US]] = add nsw i32 [[J_016_US]], -1 -; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[INC_US]], 6 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[INDVARS_IV]], 4294967295 +; CHECK-NEXT: [[CMP2_US_WIDE:%.*]] = icmp ugt i64 [[TMP2]], 6 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 -; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK-NEXT: br i1 [[CMP2_US_WIDE]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]] ; CHECK: exit.loopexit: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: @@ -664,14 +662,13 @@ define void @zext_postinc_offset_constant_minus_one(ptr %A, i32 %start) { ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[J_016_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[FOR_BODY]] ], [ [[START]], [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1 ; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP1]] ; CHECK-NEXT: tail call void @use_ptr(ptr [[ARRAYIDX_US]]) -; CHECK-NEXT: [[INC_US]] = add nsw i32 [[J_016_US]], -1 -; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ugt i32 [[INC_US]], 6 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[INDVARS_IV]], 4294967295 +; CHECK-NEXT: [[CMP2_US_WIDE:%.*]] = icmp ugt i64 [[TMP2]], 6 ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 -; CHECK-NEXT: br i1 [[CMP2_US]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK-NEXT: br i1 [[CMP2_US_WIDE]], label [[FOR_BODY]], label [[EXIT_LOOPEXIT:%.*]] ; CHECK: exit.loopexit: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: diff --git a/llvm/test/Transforms/LoopFlatten/widen-iv3.ll b/llvm/test/Transforms/LoopFlatten/widen-iv3.ll index df8ee6ff07505..12c30c271f07d 100644 --- a/llvm/test/Transforms/LoopFlatten/widen-iv3.ll +++ b/llvm/test/Transforms/LoopFlatten/widen-iv3.ll @@ -34,11 +34,13 @@ define i16 @foo() { ; CHECK-NEXT: [[J_011:%.*]] = phi i16 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INC:%.*]], [[FOR_BODY4]] ] ; CHECK-NEXT: [[SUM_110:%.*]] = phi i16 [ [[SUM_012]], [[FOR_COND1_PREHEADER]] ], [ [[ADD5]], [[FOR_BODY4]] ] ; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i32 [[INDVAR]], [[TMP0]] +; CHECK-NEXT: [[TMP3:%.*]] = sext i16 [[J_011]] to i32 +; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i32 [[TMP3]], [[TMP0]] ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[J_011]], [[MUL]] -; CHECK-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16 -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [64 x i16], ptr @v, i16 0, i16 [[TMP3]] -; CHECK-NEXT: [[TMP4:%.*]] = load i16, ptr [[ARRAYIDX]], align 1 -; CHECK-NEXT: [[ADD5]] = add nsw i16 [[TMP4]], [[SUM_110]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP2]] to i16 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [64 x i16], ptr @v, i16 0, i16 [[TMP5]] +; CHECK-NEXT: [[TMP6:%.*]] = load i16, ptr [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[ADD5]] = add nsw i16 [[TMP6]], [[SUM_110]] ; CHECK-NEXT: [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1 ; CHECK-NEXT: [[INC]] = add nuw nsw i16 [[J_011]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INDVAR_NEXT]], 16