diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -688,11 +688,15 @@ unsigned DestNumSigBits = UseInst->getType()->getFPMantissaWidth(); if (IVRange.getActiveBits() <= DestNumSigBits) { for (User *U : UseInst->users()) { - // Match for fptosi of sitofp and with same type. - auto *CI = dyn_cast(U); + // Match for fptosi/fptoui of sitofp and with same type. + auto *CI = dyn_cast(U); if (!CI || IVOperand->getType() != CI->getType()) continue; + CastInst::CastOps Opcode = CI->getOpcode(); + if (Opcode != CastInst::FPToSI && Opcode != CastInst::FPToUI) + continue; + CI->replaceAllUsesWith(IVOperand); DeadInsts.push_back(CI); LLVM_DEBUG(dbgs() << "INDVARS: Replace IV user: " << *CI diff --git a/llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll b/llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll --- a/llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll +++ b/llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll @@ -3,7 +3,7 @@ @array = dso_local global [16777219 x i32] zeroinitializer, align 4 -define void @small_const_bound(i32 %index) { +define void @small_const_bound() { ; CHECK-LABEL: @small_const_bound( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] @@ -37,7 +37,7 @@ } ; Negative test: The transform is *not* valid because there are too many significant bits -define void @overflow_masked_const_bound(i32 %index) { +define void @overflow_masked_const_bound() { ; CHECK-LABEL: @overflow_masked_const_bound( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] @@ -73,7 +73,7 @@ } ; Negative test: Type mismatch between the integer IV and the fptosi result -define void @mismatch_type_const(i32 %index) { +define void @mismatch_type_const() { ; ; CHECK-LABEL: @mismatch_type_const( ; CHECK-NEXT: entry: @@ -110,3 +110,72 @@ cleanup: ; preds = %for.body ret void } + +define void @unsigned_const_bound() { +; CHECK-LABEL: @unsigned_const_bound( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[IV_INT]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] +; CHECK-NEXT: store i32 [[IV_INT]], i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC_INT]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] +; CHECK: cleanup: +; CHECK-NEXT: ret void +; +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] + %indvar.conv = sitofp i32 %iv.int to float + %conv = fptoui float %indvar.conv to i32 + %idxprom = zext i32 %conv to i64 + %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom + store i32 %conv, i32* %arrayidx, align 4 + %dec.int = add nsw i32 %iv.int, -1 + %cmp = icmp sgt i32 %dec.int, 0 + br i1 %cmp, label %for.body, label %cleanup + +cleanup: ; preds = %for.body + ret void +} + +; TODO: Range including negative value. +define void @unsigned_const_bound_with_negative () { +; CHECK-LABEL: @unsigned_const_bound_with_negative( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to float +; CHECK-NEXT: [[CONV:%.*]] = fptoui float [[INDVAR_CONV]] to i32 +; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[CONV]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM]] +; CHECK-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[DEC_INT]] = add nsw i32 [[IV_INT]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[DEC_INT]], -100 +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] +; CHECK: cleanup: +; CHECK-NEXT: ret void +; +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %iv.int = phi i32 [ 100, %entry ], [ %dec.int, %for.body ] + %indvar.conv = sitofp i32 %iv.int to float + %conv = fptoui float %indvar.conv to i32 + %idxprom = zext i32 %conv to i64 + %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom + store i32 %conv, i32* %arrayidx, align 4 + %dec.int = add nsw i32 %iv.int, -1 + %cmp = icmp sgt i32 %dec.int, -100 + br i1 %cmp, label %for.body, label %cleanup + +cleanup: ; preds = %for.body + ret void +}