From 9019a6092df23d44d1f9bf5917bf454073a7a9d1 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 14 Nov 2014 21:21:15 +0000 Subject: [PATCH] InstCombine: Fix infinite loop caused by visitFPTrunc We would attempt to replace a fptrunc of an frem with an identical fptrunc. This would cause the new fptrunc to be added to the worklist. Of course, this results in an infinite loop because we will keep visiting the newly created fptruncs. This fixes PR21576. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222040 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/InstCombine/InstCombineCasts.cpp | 15 +++++++++------ test/Transforms/InstCombine/fpcast.ll | 10 ++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index b41cdc65202..a0570f7ebd4 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1269,14 +1269,17 @@ Instruction *InstCombiner::visitFPTrunc(FPTruncInst &CI) { // type of OpI doesn't enter into things at all. We simply evaluate // in whichever source type is larger, then convert to the // destination type. + Value *NewLHS = LHSOrig, *NewRHS = RHSOrig; if (LHSWidth < SrcWidth) - LHSOrig = Builder->CreateFPExt(LHSOrig, RHSOrig->getType()); + NewLHS = Builder->CreateFPExt(NewLHS, RHSOrig->getType()); else if (RHSWidth <= SrcWidth) - RHSOrig = Builder->CreateFPExt(RHSOrig, LHSOrig->getType()); - Value *ExactResult = Builder->CreateFRem(LHSOrig, RHSOrig); - if (Instruction *RI = dyn_cast(ExactResult)) - RI->copyFastMathFlags(OpI); - return CastInst::CreateFPCast(ExactResult, CI.getType()); + NewRHS = Builder->CreateFPExt(NewRHS, LHSOrig->getType()); + if (NewLHS != LHSOrig || NewRHS != RHSOrig) { + Value *ExactResult = Builder->CreateFRem(NewLHS, NewRHS); + if (Instruction *RI = dyn_cast(ExactResult)) + RI->copyFastMathFlags(OpI); + return CastInst::CreateFPCast(ExactResult, CI.getType()); + } } // (fptrunc (fneg x)) -> (fneg (fptrunc x)) diff --git a/test/Transforms/InstCombine/fpcast.ll b/test/Transforms/InstCombine/fpcast.ll index 9be66fd42c6..c4c8578198b 100644 --- a/test/Transforms/InstCombine/fpcast.ll +++ b/test/Transforms/InstCombine/fpcast.ll @@ -53,3 +53,13 @@ define half @test5(float %a, float %b, float %c) { } declare float @llvm.fabs.f32(float) nounwind readonly + +define <1 x float> @test6(<1 x double> %V) { + %frem = frem <1 x double> %V, %V + %trunc = fptrunc <1 x double> %frem to <1 x float> + ret <1 x float> %trunc +; CHECK-LABEL: @test6 +; CHECK-NEXT: %[[frem:.*]] = frem <1 x double> %V, %V +; CHECK-NEXT: %[[trunc:.*]] = fptrunc <1 x double> %[[frem]] to <1 x float> +; CHECK-NEXT: ret <1 x float> %trunc +} -- 2.34.1