diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index ae3644183a735b..de2556f3cec19c 100644 --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -1201,6 +1201,15 @@ Value *WidenIV::createExtendInst(Value *NarrowOper, Type *WideType, L = L->getParentLoop()) Builder.SetInsertPoint(L->getLoopPreheader()->getTerminator()); + // If we know the operand is never negative, prefer zext nneg. + // For constant expressions, fall back to plain sext or zext. + if (SE->isKnownNonNegative(SE->getSCEV(NarrowOper))) { + auto *Res = Builder.CreateZExt(NarrowOper, WideType); + if (auto *I = dyn_cast(Res)) + I->setNonNeg(true); + return Res; + } + return IsSigned ? Builder.CreateSExt(NarrowOper, WideType) : Builder.CreateZExt(NarrowOper, WideType); } @@ -1686,6 +1695,16 @@ bool WidenIV::widenWithVariantUse(WidenIV::NarrowIVDefUse DU) { auto ExtendedOp = [&](Value * V)->Value * { if (V == NarrowUse) return WideBO; + + // If we know the operand is never negative, prefer zext nneg. + // For constant expressions, fall back to plain sext or zext. + if (SE->isKnownNonNegative(SE->getSCEV(V))) { + auto *Res = Builder.CreateZExt(V, WideBO->getType()); + if (auto *I = dyn_cast(Res)) + I->setNonNeg(true); + return Res; + } + if (ExtKind == ExtendKind::Zero) return Builder.CreateZExt(V, WideBO->getType()); else diff --git a/llvm/test/Analysis/ScalarEvolution/guards.ll b/llvm/test/Analysis/ScalarEvolution/guards.ll index ea17c5840067af..137630cd25e687 100644 --- a/llvm/test/Analysis/ScalarEvolution/guards.ll +++ b/llvm/test/Analysis/ScalarEvolution/guards.ll @@ -57,7 +57,7 @@ define void @test_2(i32 %n, ptr %len_buf) { ; CHECK-SAME: (i32 [[N:%.*]], ptr [[LEN_BUF:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_BUF]], align 4, !range [[RNG1:![0-9]+]] -; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[LEN]] to i64 +; CHECK-NEXT: [[TMP0:%.*]] = zext nneg i32 [[LEN]] to i64 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[N]] to i64 ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: diff --git a/llvm/test/Transforms/IndVarSimplify/X86/pr59615.ll b/llvm/test/Transforms/IndVarSimplify/X86/pr59615.ll index 17b7b9d40b07a5..4fe7f7fd01a066 100644 --- a/llvm/test/Transforms/IndVarSimplify/X86/pr59615.ll +++ b/llvm/test/Transforms/IndVarSimplify/X86/pr59615.ll @@ -17,7 +17,7 @@ define void @test() { ; CHECK-NEXT: ret void ; CHECK: bb8: ; CHECK-NEXT: [[VAR9:%.*]] = load atomic i32, ptr addrspace(1) poison unordered, align 8, !range [[RNG0]], !invariant.load !1, !noundef !1 -; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[VAR9]] to i64 +; CHECK-NEXT: [[TMP0:%.*]] = zext nneg i32 [[VAR9]] to i64 ; CHECK-NEXT: [[VAR10:%.*]] = icmp ult i64 [[INDVARS_IV]], [[TMP0]] ; CHECK-NEXT: br i1 [[VAR10]], label [[BB12]], label [[BB11:%.*]] ; CHECK: bb11: diff --git a/llvm/test/Transforms/IndVarSimplify/post-inc-range.ll b/llvm/test/Transforms/IndVarSimplify/post-inc-range.ll index 5c22ba1044b60a..1df0d62168af24 100644 --- a/llvm/test/Transforms/IndVarSimplify/post-inc-range.ll +++ b/llvm/test/Transforms/IndVarSimplify/post-inc-range.ll @@ -120,7 +120,7 @@ define void @test_range_metadata(ptr %array_length_ptr, ptr %base, ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ] ; CHECK-NEXT: [[ARRAY_LENGTH:%.*]] = load i32, ptr [[ARRAY_LENGTH_PTR:%.*]], align 4, !range [[RNG0:![0-9]+]] -; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[ARRAY_LENGTH]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = zext nneg i32 [[ARRAY_LENGTH]] to i64 ; CHECK-NEXT: [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], [[TMP2]] ; CHECK-NEXT: br i1 [[WITHIN_LIMITS]], label [[CONTINUE:%.*]], label [[FOR_END:%.*]] ; CHECK: continue: diff --git a/llvm/test/Transforms/LoopFlatten/widen-iv2.ll b/llvm/test/Transforms/LoopFlatten/widen-iv2.ll index 946b98420249e2..f4c8b90d4bc27b 100644 --- a/llvm/test/Transforms/LoopFlatten/widen-iv2.ll +++ b/llvm/test/Transforms/LoopFlatten/widen-iv2.ll @@ -39,7 +39,7 @@ define dso_local i32 @fn1() local_unnamed_addr #0 { ; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[FOR_BODY3_US]] ], [ 0, [[FOR_COND1_PREHEADER_US]] ] ; CHECK-NEXT: [[J_014_US:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[FOR_BODY3_US]] ] ; CHECK-NEXT: [[TMP7:%.*]] = add nsw i64 [[INDVAR]], [[TMP5]] -; CHECK-NEXT: [[TMP8:%.*]] = sext i32 [[J_014_US]] to i64 +; CHECK-NEXT: [[TMP8:%.*]] = zext nneg i32 [[J_014_US]] to i64 ; CHECK-NEXT: [[TMP9:%.*]] = add nsw i64 [[TMP8]], [[TMP5]] ; CHECK-NEXT: [[ADD_US:%.*]] = add nsw i32 [[J_014_US]], [[MUL_US]] ; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[ADD_US]] to i64 diff --git a/llvm/test/Transforms/LoopFlatten/widen-iv3.ll b/llvm/test/Transforms/LoopFlatten/widen-iv3.ll index df8ee6ff075057..b3a9ac823fd2df 100644 --- a/llvm/test/Transforms/LoopFlatten/widen-iv3.ll +++ b/llvm/test/Transforms/LoopFlatten/widen-iv3.ll @@ -18,7 +18,7 @@ define i16 @foo() { ; CHECK-NEXT: [[SUM_012:%.*]] = phi i16 [ 0, [[ENTRY]] ], [ [[ADD5_LCSSA:%.*]], [[FOR_COND_CLEANUP3]] ] ; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i32 [[INDVAR2]], 16 ; CHECK-NEXT: [[MUL:%.*]] = mul nsw i16 [[I_013]], 16 -; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[MUL]] to i32 +; CHECK-NEXT: [[TMP1:%.*]] = zext nneg i16 [[MUL]] to i32 ; CHECK-NEXT: br label [[FOR_BODY4:%.*]] ; CHECK: for.cond.cleanup: ; CHECK-NEXT: [[ADD5_LCSSA_LCSSA:%.*]] = phi i16 [ [[ADD5_LCSSA]], [[FOR_COND_CLEANUP3]] ]