Index: llvm/lib/Transforms/Utils/SimplifyIndVar.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -683,7 +683,7 @@ UseInst->getOpcode() != CastInst::UIToFP) return false; - Value *IVOperand = UseInst->getOperand(0); + Instruction *IVOperand = cast(UseInst->getOperand(0)); // Get the symbolic expression for this instruction. const SCEV *IV = SE->getSCEV(IVOperand); unsigned MaskBits; @@ -696,17 +696,32 @@ for (User *U : UseInst->users()) { // Match for fptosi/fptoui of sitofp and with same type. auto *CI = dyn_cast(U); - if (!CI || IVOperand->getType() != CI->getType()) + if (!CI) continue; CastInst::CastOps Opcode = CI->getOpcode(); if (Opcode != CastInst::FPToSI && Opcode != CastInst::FPToUI) continue; - CI->replaceAllUsesWith(IVOperand); + Value *Conv = nullptr; + if (IVOperand->getType() != CI->getType()) { + IRBuilder<> Builder(&*IVOperand->getParent()->getFirstInsertionPt()); + StringRef Name = IVOperand->getName(); + if (SE->getTypeSizeInBits(IVOperand->getType()) > + SE->getTypeSizeInBits(CI->getType())) { + Conv = Builder.CreateTrunc(IVOperand, CI->getType(), Name + ".trunc"); + } else if (Opcode == CastInst::FPToSI) { + Conv = Builder.CreateSExt(IVOperand, CI->getType(), Name + ".sext"); + } else { + Conv = Builder.CreateZExt(IVOperand, CI->getType(), Name + ".zext"); + } + } else + Conv = IVOperand; + + CI->replaceAllUsesWith(Conv); DeadInsts.push_back(CI); LLVM_DEBUG(dbgs() << "INDVARS: Replace IV user: " << *CI - << " with: " << *IVOperand << '\n'); + << " with: " << *Conv << '\n'); ++NumFoldedUser; Changed = true; Index: llvm/test/Transforms/IndVarSimplify/floating-point-iv.ll =================================================================== --- llvm/test/Transforms/IndVarSimplify/floating-point-iv.ll +++ llvm/test/Transforms/IndVarSimplify/floating-point-iv.ll @@ -377,17 +377,17 @@ ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[FLOAT_IV_INT:%.*]] = phi i32 [ 1000, [[ENTRY:%.*]] ], [ [[FLOAT_IV_NEXT_INT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[FLOAT_IV_INT_ZEXT:%.*]] = zext i32 [[FLOAT_IV_INT]] to i64 +; CHECK-NEXT: [[FLOAT_IV_INT_TRUNC2:%.*]] = trunc i32 [[FLOAT_IV_INT]] to i16 +; CHECK-NEXT: [[FLOAT_IV_INT_SEXT:%.*]] = sext i32 [[FLOAT_IV_INT]] to i64 +; CHECK-NEXT: [[FLOAT_IV_INT_TRUNC:%.*]] = trunc i32 [[FLOAT_IV_INT]] to i16 ; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[FLOAT_IV_INT]] to float ; CHECK-NEXT: call void @use.float(float [[INDVAR_CONV]]) ; CHECK-NEXT: call void @use.i32(i32 [[FLOAT_IV_INT]]) -; CHECK-NEXT: [[CONV_I16:%.*]] = fptosi float [[INDVAR_CONV]] to i16 -; CHECK-NEXT: [[CONV_I64:%.*]] = fptosi float [[INDVAR_CONV]] to i64 -; CHECK-NEXT: call void @use.i16(i16 [[CONV_I16]]) -; CHECK-NEXT: call void @use.i64(i64 [[CONV_I64]]) -; CHECK-NEXT: [[UCONV_I16:%.*]] = fptoui float [[INDVAR_CONV]] to i16 -; CHECK-NEXT: [[UCONV_I64:%.*]] = fptoui float [[INDVAR_CONV]] to i64 -; CHECK-NEXT: call void @use.i16(i16 [[UCONV_I16]]) -; CHECK-NEXT: call void @use.i64(i64 [[UCONV_I64]]) +; CHECK-NEXT: call void @use.i16(i16 [[FLOAT_IV_INT_TRUNC]]) +; CHECK-NEXT: call void @use.i64(i64 [[FLOAT_IV_INT_SEXT]]) +; CHECK-NEXT: call void @use.i16(i16 [[FLOAT_IV_INT_TRUNC2]]) +; CHECK-NEXT: call void @use.i64(i64 [[FLOAT_IV_INT_ZEXT]]) ; CHECK-NEXT: [[FLOAT_IV_NEXT_INT]] = add nsw i32 [[FLOAT_IV_INT]], -1 ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[FLOAT_IV_NEXT_INT]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] Index: llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll =================================================================== --- llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll +++ llvm/test/Transforms/IndVarSimplify/floating-point-small-iv.ll @@ -72,22 +72,19 @@ ret void } -; Negative test: Type mismatch between the integer IV and the fptosi result -define void @sitofp_fptosi_range_mismatch_type() { +; Type mismatch between the integer IV and the fptosi result +define void @sitofp_fptosi_range_trunc() { ; -; CHECK-LABEL: @sitofp_fptosi_range_mismatch_type( +; CHECK-LABEL: @sitofp_fptosi_range_trunc( ; 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:%.*]] = fptosi float [[INDVAR_CONV]] to i16 -; CHECK-NEXT: [[IDXPROM32:%.*]] = sext i16 [[CONV]] to i32 -; CHECK-NEXT: [[IDXPROM64:%.*]] = sext i16 [[CONV]] to i64 -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IDXPROM64]] -; CHECK-NEXT: store i32 [[IDXPROM32]], 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: [[IV_INT:%.*]] = phi i64 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[IV_INT_TRUNC:%.*]] = trunc i64 [[IV_INT]] to i32 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IV_INT]] +; CHECK-NEXT: store i32 [[IV_INT_TRUNC]], i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[DEC_INT]] = add nsw i64 [[IV_INT]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[DEC_INT]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP:%.*]] ; CHECK: cleanup: ; CHECK-NEXT: ret void @@ -96,15 +93,119 @@ 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 = fptosi float %indvar.conv to i16 - %idxprom32 = sext i16 %conv to i32 - %idxprom64 = sext i16 %conv to i64 + %iv.int = phi i64 [ 100, %entry ], [ %dec.int, %for.body ] + %indvar.conv = sitofp i64 %iv.int to float + %idxprom32 = fptosi float %indvar.conv to i32 + %idxprom64 = fptosi float %indvar.conv to i64 %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom64 store i32 %idxprom32, i32* %arrayidx, align 4 - %dec.int = add nsw i32 %iv.int, -1 - %cmp = icmp ugt i32 %dec.int, 0 + %dec.int = add nsw i64 %iv.int, -1 + %cmp = icmp ugt i64 %dec.int, 0 + br i1 %cmp, label %for.body, label %cleanup + +cleanup: ; preds = %for.body + ret void +} + +define void @sitofp_fptosi_range_sext() { +; +; CHECK-LABEL: @sitofp_fptosi_range_sext( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV_INT:%.*]] = phi i16 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[IV_INT_SEXT1:%.*]] = sext i16 [[IV_INT]] to i32 +; CHECK-NEXT: [[IV_INT_SEXT:%.*]] = sext i16 [[IV_INT]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IV_INT_SEXT]] +; CHECK-NEXT: store i32 [[IV_INT_SEXT1]], i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[DEC_INT]] = add nsw i16 [[IV_INT]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i16 [[DEC_INT]], -3 +; 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 i16 [ 100, %entry ], [ %dec.int, %for.body ] + %indvar.conv = sitofp i16 %iv.int to float + %idxprom32 = fptosi float %indvar.conv to i32 + %idxprom64 = fptosi float %indvar.conv to i64 + %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom64 + store i32 %idxprom32, i32* %arrayidx, align 4 + %dec.int = add nsw i16 %iv.int, -1 + %cmp = icmp sgt i16 %dec.int, -3 + br i1 %cmp, label %for.body, label %cleanup + +cleanup: ; preds = %for.body + ret void +} + +define void @sitofp_fptosi_range_zext() { +; +; CHECK-LABEL: @sitofp_fptosi_range_zext( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV_INT:%.*]] = phi i16 [ 100, [[ENTRY:%.*]] ], [ [[DEC_INT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[IV_INT_ZEXT1:%.*]] = zext i16 [[IV_INT]] to i32 +; CHECK-NEXT: [[IV_INT_ZEXT:%.*]] = zext i16 [[IV_INT]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IV_INT_ZEXT]] +; CHECK-NEXT: store i32 [[IV_INT_ZEXT1]], i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[DEC_INT]] = add nsw i16 [[IV_INT]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[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 i16 [ 100, %entry ], [ %dec.int, %for.body ] + %indvar.conv = sitofp i16 %iv.int to float + %idxprom32 = fptoui float %indvar.conv to i32 + %idxprom64 = fptoui float %indvar.conv to i64 + %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom64 + store i32 %idxprom32, i32* %arrayidx, align 4 + %dec.int = add nsw i16 %iv.int, -1 + %cmp = icmp ugt i16 %dec.int, 0 + br i1 %cmp, label %for.body, label %cleanup + +cleanup: ; preds = %for.body + ret void +} + +define void @sitofp_fptosi_range_zext_postinc() { +; +; CHECK-LABEL: @sitofp_fptosi_range_zext_postinc( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[IV_INT:%.*]] = phi i16 [ 100, [[ENTRY:%.*]] ], [ [[INC_INT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[IV_INT_ZEXT1:%.*]] = zext i16 [[IV_INT]] to i32 +; CHECK-NEXT: [[IV_INT_ZEXT:%.*]] = zext i16 [[IV_INT]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 [[IV_INT_ZEXT]] +; CHECK-NEXT: store i32 [[IV_INT_ZEXT1]], i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[INC_INT]] = add nuw nsw i16 [[IV_INT]], 2 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[INC_INT]], 200 +; 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 i16 [ 100, %entry ], [ %inc.int, %for.body ] + %indvar.conv = sitofp i16 %iv.int to float + %idxprom32 = fptoui float %indvar.conv to i32 + %idxprom64 = fptoui float %indvar.conv to i64 + %arrayidx = getelementptr inbounds [16777219 x i32], [16777219 x i32]* @array, i64 0, i64 %idxprom64 + store i32 %idxprom32, i32* %arrayidx, align 4 + %inc.int = add nsw i16 %iv.int, 2 + %cmp = icmp ult i16 %inc.int, 200 br i1 %cmp, label %for.body, label %cleanup cleanup: ; preds = %for.body