InstCombine: Remove infinite loop caused by FoldOpIntoPhi

FoldOpIntoPhi could create an infinite loop if the PHI could potentially
reach a BB it was considering inserting instructions into.  The
instructions it would insert would eventually lead to other combines
firing which would, again, lead to FoldOpIntoPhi firing.

The solution is to handicap FoldOpIntoPhi so that it doesn't attempt to
insert instructions that the PHI might reach.

This fixes PR21377.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221187 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer
2014-11-03 21:55:12 +00:00
parent fcd4288009
commit c671375e8e
3 changed files with 28 additions and 18 deletions

View File

@@ -40,8 +40,10 @@
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
#include "llvm/Analysis/AssumptionTracker.h" #include "llvm/Analysis/AssumptionTracker.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/CFG.h" #include "llvm/IR/CFG.h"
@@ -794,13 +796,14 @@ Instruction *InstCombiner::FoldOpIntoPhi(Instruction &I) {
// If the incoming non-constant value is in I's block, we will remove one // If the incoming non-constant value is in I's block, we will remove one
// instruction, but insert another equivalent one, leading to infinite // instruction, but insert another equivalent one, leading to infinite
// instcombine. // instcombine.
if (NonConstBB == I.getParent()) if (isPotentiallyReachable(I.getParent(), NonConstBB, DT,
getAnalysisIfAvailable<LoopInfo>()))
return nullptr; return nullptr;
} }
// If there is exactly one non-constant value, we can insert a copy of the // If there is exactly one non-constant value, we can insert a copy of the
// operation in that block. However, if this is a critical edge, we would be // operation in that block. However, if this is a critical edge, we would be
// inserting the computation one some other paths (e.g. inside a loop). Only // inserting the computation on some other paths (e.g. inside a loop). Only
// do this if the pred block is unconditionally branching into the phi block. // do this if the pred block is unconditionally branching into the phi block.
if (NonConstBB != nullptr) { if (NonConstBB != nullptr) {
BranchInst *BI = dyn_cast<BranchInst>(NonConstBB->getTerminator()); BranchInst *BI = dyn_cast<BranchInst>(NonConstBB->getTerminator());

View File

@@ -17,23 +17,30 @@ end:
ret float %add5 ret float %add5
} }
; CHECK: fold_phi ; CHECK-LABEL: @pr21377(
define float @fold_phi(float %a) nounwind { define void @pr21377(i32, i32) {
entry: entry:
br label %for.body br label %while.cond.i
for.body: while.cond.i: ; preds = %while.end.i, %entry
; CHECK: phi float %g.0.i = phi i64 [ 0, %entry ], [ %phitmp5.i, %while.end.i ]
; CHECK-NEXT: br i1 undef br i1 undef, label %fn2.exit, label %while.body.i
%sum.057 = phi float [ 0.000000e+00, %entry ], [ %add5, %bb0 ]
%add5 = fadd float %sum.057, 1.0 ;; Should be moved to the latch!
br i1 undef, label %bb0, label %end
; CHECK: bb0: while.body.i: ; preds = %while.cond.i
bb0: %conv.i = zext i32 %0 to i64
; CHECK: fadd float %phitmp3.i = or i64 %g.0.i, %conv.i
br label %for.body br label %while.cond3.i
end: while.cond3.i: ; preds = %while.cond3.i, %while.body.i
ret float %add5 %g.1.i = phi i64 [ %phitmp3.i, %while.body.i ], [ 0, %while.cond3.i ]
br i1 undef, label %while.end.i, label %while.cond3.i
while.end.i: ; preds = %while.cond3.i
%conv.i.i = zext i32 %1 to i64
%or7.i = or i64 %g.1.i, %conv.i.i
%phitmp5.i = and i64 %or7.i, 4294967295
br label %while.cond.i
fn2.exit: ; preds = %while.cond.i
ret void
} }

View File

@@ -6,7 +6,6 @@ entry:
for.cond: for.cond:
%local = phi <1 x i32> [ <i32 0>, %entry ], [ %phi2, %cond.end47 ] %local = phi <1 x i32> [ <i32 0>, %entry ], [ %phi2, %cond.end47 ]
; CHECK: sub <1 x i32> <i32 92>, %local
%phi3 = sub <1 x i32> zeroinitializer, %local %phi3 = sub <1 x i32> zeroinitializer, %local
br label %cond.end br label %cond.end
@@ -19,6 +18,7 @@ cond.end:
cond.end47: cond.end47:
%sum = add <1 x i32> %cond, <i32 92> %sum = add <1 x i32> %cond, <i32 92>
; CHECK: sub <1 x i32> <i32 -92>, %cond
%phi2 = sub <1 x i32> zeroinitializer, %sum %phi2 = sub <1 x i32> zeroinitializer, %sum
br label %for.cond br label %for.cond
} }