#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
-#include "llvm/Analysis/MustExecute.h"
-#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
ArrayRef<Value *> Invariants,
bool Direction,
BasicBlock &UnswitchedSucc,
- BasicBlock &NormalSucc,
- bool InsertFreeze) {
+ BasicBlock &NormalSucc) {
IRBuilder<> IRB(&BB);
Value *Cond = Direction ? IRB.CreateOr(Invariants) :
IRB.CreateAnd(Invariants);
- if (InsertFreeze)
- Cond = IRB.CreateFreeze(Cond, Cond->getName() + ".fr");
IRB.CreateCondBr(Cond, Direction ? &UnswitchedSucc : &NormalSucc,
Direction ? &NormalSucc : &UnswitchedSucc);
}
Instruction::And &&
"Must have an `and` of `i1`s for the condition!");
buildPartialUnswitchConditionalBranch(*OldPH, Invariants, ExitDirection,
- *UnswitchedBB, *NewPH, false);
+ *UnswitchedBB, *NewPH);
}
// Update the dominator tree with the added edge.
SE->forgetTopmostLoop(&L);
}
- ICFLoopSafetyInfo SafetyInfo(&DT);
- SafetyInfo.computeLoopSafetyInfo(&L);
- bool InsertFreeze = !SafetyInfo.isGuaranteedToExecute(TI, &DT, &L);
-
// If the edge from this terminator to a successor dominates that successor,
// store a map from each block in its dominator subtree to it. This lets us
// tell when cloning for a particular successor if a block is dominated by
BasicBlock *ClonedPH = ClonedPHs.begin()->second;
BI->setSuccessor(ClonedSucc, ClonedPH);
BI->setSuccessor(1 - ClonedSucc, LoopPH);
- if (InsertFreeze) {
- auto Cond = BI->getCondition();
- if (!isGuaranteedNotToBeUndefOrPoison(Cond))
- BI->setCondition(new FreezeInst(Cond, Cond->getName() + ".fr", BI));
- }
-
DTUpdates.push_back({DominatorTree::Insert, SplitBB, ClonedPH});
} else {
assert(SI && "Must either be a branch or switch!");
else
Case.setSuccessor(ClonedPHs.find(Case.getCaseSuccessor())->second);
- if (InsertFreeze) {
- auto Cond = SI->getCondition();
- if (!isGuaranteedNotToBeUndefOrPoison(Cond))
- SI->setCondition(new FreezeInst(Cond, Cond->getName() + ".fr", SI));
- }
-
// We need to use the set to populate domtree updates as even when there
// are multiple cases pointing at the same successor we only want to
// remove and insert one edge in the domtree.
// When doing a partial unswitch, we have to do a bit more work to build up
// the branch in the split block.
buildPartialUnswitchConditionalBranch(*SplitBB, Invariants, Direction,
- *ClonedPH, *LoopPH, InsertFreeze);
+ *ClonedPH, *LoopPH);
DTUpdates.push_back({DominatorTree::Insert, SplitBB, ClonedPH});
if (MSSAU) {
; CHECK-NEXT: %[[A_INNER_PHI:.*]] = phi i32 [ %[[A]], %loop_begin ], [ %[[A2:.*]], %inner_inner_loop_exit ]
; CHECK-NEXT: %[[COND:.*]] = load i1, i1* %cond.ptr
; CHECK-NEXT: %[[B:.*]] = load i32, i32* %b.ptr
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %[[COND]]
-; CHECK-NEXT: br i1 %[[COND_FR]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
+; CHECK-NEXT: br i1 %[[COND]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
inner_inner_loop_begin:
%v1 = load i1, i1* %ptr
; CHECK-NEXT: %[[A_INNER_PHI:.*]] = phi i32 [ %[[A]], %loop_begin ], [ %[[A2:.*]], %inner_inner_loop_exit ]
; CHECK-NEXT: %[[COND:.*]] = load i1, i1* %cond.ptr
; CHECK-NEXT: %[[B:.*]] = load i32, i32* %b.ptr
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %[[COND]]
-; CHECK-NEXT: br i1 %[[COND_FR]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
+; CHECK-NEXT: br i1 %[[COND]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
inner_inner_loop_begin:
%v1 = load i1, i1* %ptr
; CHECK-NEXT: %[[A_INNER_PHI:.*]] = phi i32 [ %[[A]], %loop_begin ], [ %[[A2:.*]], %inner_inner_loop_exit ]
; CHECK-NEXT: %[[COND:.*]] = load i1, i1* %cond.ptr
; CHECK-NEXT: %[[B:.*]] = load i32, i32* %b.ptr
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %[[COND]]
-; CHECK-NEXT: br i1 %[[COND_FR]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
+; CHECK-NEXT: br i1 %[[COND]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
inner_inner_loop_begin:
%v1 = load i1, i1* %ptr
; CHECK-NEXT: %[[A_INNER_PHI:.*]] = phi i32 [ %[[A]], %loop_begin ], [ %[[A2:.*]], %inner_inner_loop_exit ]
; CHECK-NEXT: %[[COND:.*]] = load i1, i1* %cond.ptr
; CHECK-NEXT: %[[B:.*]] = load i32, i32* %b.ptr
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %[[COND]]
-; CHECK-NEXT: br i1 %[[COND_FR]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
+; CHECK-NEXT: br i1 %[[COND]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
inner_inner_loop_begin:
%v1 = load i1, i1* %ptr
entry:
br label %loop_begin
; CHECK-NEXT: entry:
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %cond
-; CHECK-NEXT: br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
+; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
loop_begin:
%a = load i32, i32* %a.ptr
entry:
br label %loop_begin
; CHECK-NEXT: entry:
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %cond
-; CHECK-NEXT: br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
+; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
loop_begin:
%a = load i32, i32* %a.ptr
br label %inner_loop_begin
; CHECK: inner_loop_ph:
; CHECK-NEXT: %[[COND:.*]] = load i1, i1* %cond.ptr
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %[[COND]]
-; CHECK-NEXT: br i1 %[[COND_FR]], label %inner_loop_ph.split.us, label %inner_loop_ph.split
+; CHECK-NEXT: br i1 %[[COND]], label %inner_loop_ph.split.us, label %inner_loop_ph.split
inner_loop_begin:
call void @sink1(i32 %b)
br label %inner_loop_begin
; CHECK: inner_loop_ph:
; CHECK-NEXT: %[[COND:.*]] = load i1, i1* %cond.ptr
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %[[COND]]
-; CHECK-NEXT: br i1 %[[COND_FR]], label %inner_loop_ph.split.us, label %inner_loop_ph.split
+; CHECK-NEXT: br i1 %[[COND]], label %inner_loop_ph.split.us, label %inner_loop_ph.split
inner_loop_begin:
call void @sink1(i32 %b)
br label %inner_inner_loop_begin
; CHECK: inner_inner_loop_ph:
; CHECK-NEXT: %[[COND:.*]] = load i1, i1* %cond.ptr
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %[[COND]]
-; CHECK-NEXT: br i1 %[[COND_FR]], label %inner_inner_loop_ph.split.us, label %inner_inner_loop_ph.split
+; CHECK-NEXT: br i1 %[[COND]], label %inner_inner_loop_ph.split.us, label %inner_inner_loop_ph.split
inner_inner_loop_begin:
call void @sink1(i32 %b)
br label %inner_inner_loop_begin
; CHECK: inner_inner_loop_ph:
; CHECK-NEXT: %[[COND:.*]] = load i1, i1* %cond.ptr
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %[[COND]]
-; CHECK-NEXT: br i1 %[[COND_FR]], label %inner_inner_loop_ph.split.us, label %inner_inner_loop_ph.split
+; CHECK-NEXT: br i1 %[[COND]], label %inner_inner_loop_ph.split.us, label %inner_inner_loop_ph.split
inner_inner_loop_begin:
call void @sink1(i32 %b)
entry:
br label %loop_begin
; CHECK-NEXT: entry:
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %cond
-; CHECK-NEXT: br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
+; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
loop_begin:
%a = load i32, i32* %a.ptr
entry:
br label %loop_begin
; CHECK-NEXT: entry:
-; CHECK-NEXT: %[[COND_FR:.*]] = freeze i1 %cond
-; CHECK-NEXT: br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
+; CHECK-NEXT: br i1 %cond, label %entry.split.us, label %entry.split
loop_begin:
%a = load i32, i32* %a.ptr
; paths to reach an inner loop after unswitching, and one of them is via the
; predecessors of the unswitched loop header. That can allow us to find the loop
; through multiple different paths.
-define void @test21(i1 %a0, i1 %b) {
+define void @test21(i1 %a, i1 %b) {
; CHECK-LABEL: @test21(
bb:
- %a = freeze i1 %a0
br label %bb3
; CHECK-NOT: br i1 %a
;
entry:
br label %outer.header
; CHECK: entry:
-; CHECK-NEXT: %[[ARG_FR:.*]] = freeze i1 %arg
-; CHECK-NEXT: br i1 %[[ARG_FR]],
+; CHECK-NEXT: br i1 %arg,
;
; Just verify that we unswitched the correct bits. We should call `@f` twice in
; one unswitch and `@f` and then `@g` in the other.
entry:
br label %header
; CHECK-NEXT: entry:
-; CHECK-NEXT: %arg.fr = freeze i32 %arg
-; CHECK-NEXT: switch i32 %arg.fr, label %[[ENTRY_SPLIT_C:.*]] [
+; CHECK-NEXT: switch i32 %arg, label %[[ENTRY_SPLIT_C:.*]] [
; CHECK-NEXT: i32 0, label %[[ENTRY_SPLIT_A:.*]]
; CHECK-NEXT: i32 1, label %[[ENTRY_SPLIT_A]]
; CHECK-NEXT: i32 2, label %[[ENTRY_SPLIT_B:.*]]
; a loop exit edge as those can in some cases be special. Among other things,
; this includes an LCSSA phi with multiple entries despite being a dedicated
; exit block.
-define i32 @test30(i32 %arg0) {
+define i32 @test30(i32 %arg) {
; CHECK-LABEL: define i32 @test30(
entry:
- %arg = freeze i32 %arg0
br label %header
; CHECK-NEXT: entry:
-; CHECK-NEXT: %arg = freeze i32 %arg0
; CHECK-NEXT: switch i32 %arg, label %[[ENTRY_SPLIT_EXIT:.*]] [
; CHECK-NEXT: i32 -1, label %[[ENTRY_SPLIT_EXIT]]
; CHECK-NEXT: i32 0, label %[[ENTRY_SPLIT_A:.*]]
br label %c.header
; CHECK: b.header:
; CHECK-NEXT: %v1 = call i1 @cond()
-; CHECK-NEXT: %[[V1_FR:.*]] = freeze i1 %v1
-; CHECK-NEXT: br i1 %[[V1_FR]], label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
+; CHECK-NEXT: br i1 %v1, label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
;
; CHECK: [[B_HEADER_SPLIT_US]]:
; CHECK-NEXT: br label %[[C_HEADER_US:.*]]
; CHECK: b.header:
; CHECK-NEXT: %x.b = load i32, i32* %ptr
; CHECK-NEXT: %v1 = call i1 @cond()
-; CHECK-NEXT: %[[V1_FR:.*]] = freeze i1 %v1
-; CHECK-NEXT: br i1 %[[V1_FR]], label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
+; CHECK-NEXT: br i1 %v1, label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
;
; CHECK: [[B_HEADER_SPLIT_US]]:
; CHECK-NEXT: br label %[[C_HEADER_US:.*]]
; CHECK: b.header:
; CHECK-NEXT: %x.b = load i32, i32* %ptr
; CHECK-NEXT: %v1 = call i1 @cond()
-; CHECK-NEXT: %[[V1_FR:.*]] = freeze i1 %v1
-; CHECK-NEXT: br i1 %[[V1_FR]], label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
+; CHECK-NEXT: br i1 %v1, label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
;
; CHECK: [[B_HEADER_SPLIT_US]]:
; CHECK-NEXT: br label %[[C_HEADER_US:.*]]
; CHECK: b.header:
; CHECK-NEXT: %x.b = load i32, i32* %ptr
; CHECK-NEXT: %v1 = call i1 @cond()
-; CHECK-NEXT: %[[V1_FR:.*]] = freeze i1 %v1
-; CHECK-NEXT: br i1 %[[V1_FR]], label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
+; CHECK-NEXT: br i1 %v1, label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
;
; CHECK: [[B_HEADER_SPLIT_US]]:
; CHECK-NEXT: br label %[[C_HEADER_US:.*]]
br label %d.header
; CHECK: c.header:
; CHECK-NEXT: %v1 = call i1 @cond()
-; CHECK-NEXT: %[[V1_FR:.*]] = freeze i1 %v1
-; CHECK-NEXT: br i1 %[[V1_FR]], label %[[C_HEADER_SPLIT_US:.*]], label %[[C_HEADER_SPLIT:.*]]
+; CHECK-NEXT: br i1 %v1, label %[[C_HEADER_SPLIT_US:.*]], label %[[C_HEADER_SPLIT:.*]]
;
; CHECK: [[C_HEADER_SPLIT_US]]:
; CHECK-NEXT: br label %[[D_HEADER_US:.*]]
; CHECK: c.header:
; CHECK-NEXT: %x.c = load i32, i32* %ptr
; CHECK-NEXT: %v1 = call i1 @cond()
-; CHECK-NEXT: %[[V1_FR:.*]] = freeze i1 %v1
-; CHECK-NEXT: br i1 %[[V1_FR]], label %[[C_HEADER_SPLIT_US:.*]], label %[[C_HEADER_SPLIT:.*]]
+; CHECK-NEXT: br i1 %v1, label %[[C_HEADER_SPLIT_US:.*]], label %[[C_HEADER_SPLIT:.*]]
;
; CHECK: [[C_HEADER_SPLIT_US]]:
; CHECK-NEXT: br label %[[D_HEADER_US:.*]]
; CHECK: b.header:
; CHECK-NEXT: %x.b = load i32, i32* %ptr
; CHECK-NEXT: %v1 = call i32 @cond.i32()
-; CHECK-NEXT: %[[V1_FR]] = freeze i32 %v1
-; CHECK-NEXT: switch i32 %[[V1_FR]], label %[[B_HEADER_SPLIT:.*]] [
+; CHECK-NEXT: switch i32 %v1, label %[[B_HEADER_SPLIT:.*]] [
; CHECK-NEXT: i32 1, label %[[B_HEADER_SPLIT_US:.*]]
; CHECK-NEXT: i32 2, label %[[B_HEADER_SPLIT_US]]
; CHECK-NEXT: i32 3, label %[[B_HEADER_SPLIT_US]]