Index: lib/Transforms/Utils/FlattenCFG.cpp =================================================================== --- lib/Transforms/Utils/FlattenCFG.cpp +++ lib/Transforms/Utils/FlattenCFG.cpp @@ -199,8 +199,34 @@ if (Idx == -1) Idx = CIdx; - else if (CIdx != Idx) - return false; + else if (CIdx != Idx) { + bool EverChanged = false; + if (FirstCondBlock && LastCondBlock) { + // Do branch inversion. + BasicBlock *CurrBlock = LastCondBlock; + + for (; CurrBlock != FirstCondBlock; + CurrBlock = CurrBlock->getSinglePredecessor()) { + if (!CurrBlock) + break; + BranchInst *BI = dyn_cast(CurrBlock->getTerminator()); + CmpInst *CI = dyn_cast(BI->getCondition()); + if (!CI) + continue; + + CmpInst::Predicate Predicate = CI->getPredicate(); + // Canonicalize icmp_ne -> icmp_eq, fcmp_one -> fcmp_oeq + if ((Predicate == CmpInst::ICMP_NE) || + (Predicate == CmpInst::FCMP_ONE) || + (Predicate == CmpInst::FCMP_UNE)) { + CI->setPredicate(ICmpInst::getInversePredicate(Predicate)); + BI->swapSuccessors(); + EverChanged = true; + } + } + } + return EverChanged; + } // PS is the successor which is not BB. Check successors to identify // the last conditional branch. @@ -224,37 +250,6 @@ BasicBlock *PS1 = TBB->getSuccessor(0); BasicBlock *PS2 = TBB->getSuccessor(1); BranchInst *PBI1 = dyn_cast(PS1->getTerminator()); - BranchInst *PBI2 = dyn_cast(PS2->getTerminator()); - - // If PS1 does not jump into PS2, but PS2 jumps into PS1, - // attempt branch inversion. - if (!PBI1 || !PBI1->isUnconditional() || - (PS1->getTerminator()->getSuccessor(0) != PS2)) { - // Check whether PS2 jumps into PS1. - if (!PBI2 || !PBI2->isUnconditional() || - (PS2->getTerminator()->getSuccessor(0) != PS1)) - return false; - - // Do branch inversion. - BasicBlock *CurrBlock = LastCondBlock; - bool EverChanged = false; - for (;CurrBlock != FirstCondBlock; - CurrBlock = CurrBlock->getSinglePredecessor()) { - BranchInst *BI = dyn_cast(CurrBlock->getTerminator()); - CmpInst *CI = dyn_cast(BI->getCondition()); - if (!CI) - continue; - - CmpInst::Predicate Predicate = CI->getPredicate(); - // Canonicalize icmp_ne -> icmp_eq, fcmp_one -> fcmp_oeq - if ((Predicate == CmpInst::ICMP_NE) || (Predicate == CmpInst::FCMP_ONE)) { - CI->setPredicate(ICmpInst::getInversePredicate(Predicate)); - BI->swapSuccessors(); - EverChanged = true; - } - } - return EverChanged; - } // PS1 must have a conditional branch. if (!PBI1 || !PBI1->isUnconditional()) Index: test/Transforms/Util/flattencfg.ll =================================================================== --- test/Transforms/Util/flattencfg.ll +++ test/Transforms/Util/flattencfg.ll @@ -24,3 +24,71 @@ exit: ; preds = %entry, %b0, %b1 ret void } + +; CHECK: and +define void @test_fold_and(i32 %in_a) #0 { +entry: + %cmp0 = icmp eq i32 %in_a, -1 + br i1 %cmp0, label %b0, label %exit + +b0: ; preds = %entry + %cmp1 = icmp eq i32 %in_a, 0 + br i1 %cmp1, label %b1, label %exit + +b1: ; preds = %entry, %b0 + br label %exit + +exit: ; preds = %entry, %b0, %b1 + ret void +} + +; CHECK: and +define void @test_fold_and_reverse(i32 %in_a) #0 { +entry: + %cmp0 = icmp eq i32 %in_a, -1 + br i1 %cmp0, label %b0, label %exit + +b0: ; preds = %entry + %cmp1 = icmp ne i32 %in_a, 0 + br i1 %cmp1, label %exit, label %b1 + +b1: ; preds = %entry, %b0 + br label %exit + +exit: ; preds = %entry, %b0, %b1 + ret void +} + +; CHECK: or +define void @test_fold_or(i32 %in_a) #0 { +entry: + %cmp0 = icmp eq i32 %in_a, -1 + br i1 %cmp0, label %b1, label %b0 + +b0: ; preds = %entry + %cmp1 = icmp eq i32 %in_a, 0 + br i1 %cmp1, label %b1, label %exit + +b1: ; preds = %entry, %b0 + br label %exit + +exit: ; preds = %entry, %b0, %b1 + ret void +} + +; CHECK: or +define void @test_fold_or_reverse(i32 %in_a) #0 { +entry: + %cmp0 = icmp eq i32 %in_a, -1 + br i1 %cmp0, label %b1, label %b0 + +b0: ; preds = %entry + %cmp1 = icmp ne i32 %in_a, 0 + br i1 %cmp1, label %exit, label %b1 + +b1: ; preds = %entry, %b0 + br label %exit + +exit: ; preds = %entry, %b0, %b1 + ret void +}