Index: lib/CodeGen/IfConversion.cpp =================================================================== --- lib/CodeGen/IfConversion.cpp +++ lib/CodeGen/IfConversion.cpp @@ -248,8 +248,7 @@ bool IfConvertDiamondCommon(BBInfo &BBI, BBInfo &TrueBBI, BBInfo &FalseBBI, unsigned NumDups1, unsigned NumDups2, bool TClobbersPred, bool FClobbersPred, - bool RemoveTrueBranch, bool RemoveFalseBranch, - bool MergeAddEdges); + bool RemoveBranch, bool MergeAddEdges); bool IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, unsigned NumDups1, unsigned NumDups2, bool TClobbers, bool FClobbers); @@ -1678,19 +1677,16 @@ /// and FalseBBI /// \p NumDups2 - number of shared instructions at the end of \p TrueBBI /// and \p FalseBBI -/// \p RemoveTrueBranch - Remove the branch of the true block before predicating -/// Only false for unanalyzable fallthrough cases. -/// \p RemoveFalseBranch - Remove the branch of the false block before -/// predicating Only false for unanalyzable fallthrough -/// cases. +/// \p RemoveBranch - Remove the common branch of the two blocks before +/// predicating. Only false for unanalyzable fallthrough +/// cases. The caller will replace the branch if necessary. /// \p MergeAddEdges - Add successor edges when merging blocks. Only false for /// unanalyzable fallthrough bool IfConverter::IfConvertDiamondCommon( BBInfo &BBI, BBInfo &TrueBBI, BBInfo &FalseBBI, unsigned NumDups1, unsigned NumDups2, bool TClobbersPred, bool FClobbersPred, - bool RemoveTrueBranch, bool RemoveFalseBranch, - bool MergeAddEdges) { + bool RemoveBranch, bool MergeAddEdges) { if (TrueBBI.IsDone || FalseBBI.IsDone || TrueBBI.BB->pred_size() > 1 || FalseBBI.BB->pred_size() > 1) { @@ -1727,7 +1723,6 @@ if (DoSwap) { std::swap(BBI1, BBI2); std::swap(Cond1, Cond2); - std::swap(RemoveTrueBranch, RemoveFalseBranch); } // Remove the conditional branch from entry to the blocks. @@ -1780,8 +1775,7 @@ BBI.BB->splice(BBI.BB->end(), &MBB1, MBB1.begin(), DI1); MBB2.erase(MBB2.begin(), DI2); - if (RemoveTrueBranch) - BBI1->NonPredSize -= TII->RemoveBranch(*BBI1->BB); + BBI1->NonPredSize -= TII->RemoveBranch(*BBI1->BB); // Remove duplicated instructions. DI1 = MBB1.end(); for (unsigned i = 0; i != NumDups2; ) { @@ -1799,11 +1793,18 @@ // must be removed. RemoveKills(MBB1.begin(), MBB1.end(), DontKill, *TRI); - // Remove 'false' block branch, and find the last instruction to predicate. - // Save the debug location. - if (RemoveFalseBranch) - BBI2->NonPredSize -= TII->RemoveBranch(*BBI2->BB); DI2 = BBI2->BB->end(); + // The branches have been checked to match. Skip over the branch in the false + // block so that we don't try to predicate it. + if (RemoveBranch) + BBI2->NonPredSize -= TII->RemoveBranch(*BBI2->BB); + else { + do { + assert(DI2 != MBB2.begin()); + DI2--; + } while (DI2->isDebugValue() || DI2->isBranch()); + DI2++; + } while (NumDups2 != 0) { // NumDups2 only counted non-dbg_value instructions, so this won't // run off the head of the list. @@ -1901,8 +1902,7 @@ BBI, TrueBBI, FalseBBI, NumDups1, NumDups2, TClobbersPred, FClobbersPred, - /* RemoveTrueBranch */ true, /* RemoveFalseBranch */ true, - /* MergeAddEdges */ true)) + /* RemoveBranch */ true, /* MergeAddEdges */ true)) return false; // Add back the branch. @@ -1939,8 +1939,7 @@ BBI, TrueBBI, FalseBBI, NumDups1, NumDups2, TrueBBI.ClobbersPred, FalseBBI.ClobbersPred, - /* RemoveTrueBranch */ TrueBBI.IsBrAnalyzable, - /* RemoveFalseBranch */ FalseBBI.IsBrAnalyzable, + /* RemoveBranch */ TrueBBI.IsBrAnalyzable, /* MergeAddEdges */ TailBB == nullptr)) return false; Index: test/CodeGen/Hexagon/ifcvt-diamond-bug-2016-08-26.ll =================================================================== --- /dev/null +++ test/CodeGen/Hexagon/ifcvt-diamond-bug-2016-08-26.ll @@ -0,0 +1,37 @@ +; RUN: llc -march=hexagon -o - %s | FileCheck %s +target triple = "hexagon" + +%struct.0 = type { i16, i16 } + +@t = external local_unnamed_addr global %struct.0, align 2 + +define void @foo(i32 %p) local_unnamed_addr #0 { +entry: + %conv90 = trunc i32 %p to i16 + %call105 = call signext i16 @bar(i16 signext 16384, i16 signext undef) #0 + %call175 = call signext i16 @bar(i16 signext %conv90, i16 signext 4) #0 + %call197 = call signext i16 @bar(i16 signext %conv90, i16 signext 4) #0 + %cmp199 = icmp eq i16 %call197, 0 + br i1 %cmp199, label %if.then200, label %if.else201 + +; CHECK-DAG: [[R4:r[0-9]+]] = #4 +; CHECK: p0 = cmp.eq(r0, #0) +; CHECK: if (!p0.new) [[R3:r[0-9]+]] = #3 +; CHECK-DAG: if (!p0) memh(##t) = [[R3]] +; CHECK-DAG: if (p0) memh(##t) = [[R4]] +if.then200: ; preds = %entry + store i16 4, i16* getelementptr inbounds (%struct.0, %struct.0* @t, i32 0, i32 0), align 2 + store i16 0, i16* getelementptr inbounds (%struct.0, %struct.0* @t, i32 0, i32 1), align 2 + br label %if.end202 + +if.else201: ; preds = %entry + store i16 3, i16* getelementptr inbounds (%struct.0, %struct.0* @t, i32 0, i32 0), align 2 + br label %if.end202 + +if.end202: ; preds = %if.else201, %if.then200 + ret void +} + +declare signext i16 @bar(i16 signext, i16 signext) local_unnamed_addr #0 + +attributes #0 = { optsize "target-cpu"="hexagonv55" }