Index: lib/Transforms/Scalar/LoopUnswitch.cpp =================================================================== --- lib/Transforms/Scalar/LoopUnswitch.cpp +++ lib/Transforms/Scalar/LoopUnswitch.cpp @@ -593,13 +593,47 @@ continue; if (BranchInst *BI = dyn_cast(TI)) { + // Some branches may be rendered unreachable because of previous + // unswitching. + // Unswitch only those branches that are reachable. + auto *Node = DT->getNode(*I)->getIDom(); + BasicBlock *DomBB = Node->getBlock(); + bool isUnreachable = false; + while (currentLoop->contains(DomBB)) { + BranchInst *BInst = dyn_cast(DomBB->getTerminator()); + + Node = DT->getNode(DomBB)->getIDom(); + DomBB = Node->getBlock(); + + if (!BInst || !BInst->isConditional()) + continue; + + Value *Cond = BInst->getCondition(); + if (!isa(Cond)) + continue; + + BasicBlock *UnreachableSucc = + Cond == ConstantInt::getTrue(Cond->getContext()) + ? BInst->getSuccessor(1) + : BInst->getSuccessor(0); + + BasicBlockEdge UnreachableEdge(BInst->getParent(), UnreachableSucc); + if (DT->dominates(UnreachableEdge, *I)) { + isUnreachable = true; + break; + } + } + + if (isUnreachable) + continue; + // If this isn't branching on an invariant condition, we can't unswitch // it. if (BI->isConditional()) { // See if this, or some part of it, is loop invariant. If so, we can // unswitch on it if we desire. - Value *LoopCond = FindLIVLoopCondition(BI->getCondition(), - currentLoop, Changed); + Value *LoopCond = + FindLIVLoopCondition(BI->getCondition(), currentLoop, Changed); if (LoopCond && UnswitchIfProfitable(LoopCond, ConstantInt::getTrue(Context), TI)) { ++NumBranches; Index: test/Transforms/LoopUnswitch/elseif-non-exponential-behavior.ll =================================================================== --- /dev/null +++ test/Transforms/LoopUnswitch/elseif-non-exponential-behavior.ll @@ -0,0 +1,68 @@ +; REQUIRES: asserts +; RUN: opt < %s -O3 -loop-unswitch -stats -disable-output 2>&1 | grep "2 loop-unswitch - Number of branches unswitched" | count 1 + +; Function Attrs: nounwind uwtable +define i32 @b(i32 %x, i32 %y) #0 { +entry: + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + %pdt = alloca i32, align 4 + %i = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + store i32 1, i32* %pdt, align 4 + store i32 0, i32* %i, align 4 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %0 = load i32, i32* %i, align 4 + %cmp = icmp slt i32 %0, 100 + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %1 = load i32, i32* %x.addr, align 4 + %tobool = icmp ne i32 %1, 0 + br i1 %tobool, label %if.then, label %if.else + +if.then: ; preds = %for.body + %2 = load i32, i32* %pdt, align 4 + %mul = mul nsw i32 %2, 2 + store i32 %mul, i32* %pdt, align 4 + br label %if.end6 + +if.else: ; preds = %for.body + %3 = load i32, i32* %y.addr, align 4 + %tobool1 = icmp ne i32 %3, 0 + br i1 %tobool1, label %if.then2, label %if.else4 + +if.then2: ; preds = %if.else + %4 = load i32, i32* %pdt, align 4 + %mul3 = mul nsw i32 %4, 3 + store i32 %mul3, i32* %pdt, align 4 + br label %if.end + +if.else4: ; preds = %if.else + %5 = load i32, i32* %pdt, align 4 + %mul5 = mul nsw i32 %5, 4 + store i32 %mul5, i32* %pdt, align 4 + br label %if.end + +if.end: ; preds = %if.else4, %if.then2 + br label %if.end6 + +if.end6: ; preds = %if.end, %if.then + br label %for.inc + +for.inc: ; preds = %if.end6 + %6 = load i32, i32* %i, align 4 + %inc = add nsw i32 %6, 1 + store i32 %inc, i32* %i, align 4 + br label %for.cond + +for.end: ; preds = %for.cond + %7 = load i32, i32* %pdt, align 4 + ret i32 %7 +} + + +