<div dir="ltr">The problem is fixed in r187786.</div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/8/6 Timur Iskhodzhanov <span dir="ltr"><<a href="mailto:timurrrr@google.com" target="_blank">timurrrr@google.com</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">FYI this has broken the MSVS build<br>
<br>
100>------ Build started: Project: LLVMTransformUtils, Configuration:<br>
Debug Win32 ------<br>
...<br>
100> FlattenCFG.cpp<br>
100> llvm\lib\Transforms\Utils\FlattenCFG.cpp(301):<br>
error C2027: use of undefined type 'llvm::raw_ostream'<br>
<br>
2013/8/6 Tom Stellard <<a href="mailto:thomas.stellard@amd.com">thomas.stellard@amd.com</a>>:<br>
<div class="HOEnZb"><div class="h5">> Author: tstellar<br>
> Date: Mon Aug 5 21:43:45 2013<br>
> New Revision: 187764<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=187764&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=187764&view=rev</a><br>
> Log:<br>
> Factor FlattenCFG out from SimplifyCFG<br>
><br>
> Patch by: Mei Ye<br>
><br>
> Added:<br>
> llvm/trunk/lib/Transforms/Scalar/FlattenCFGPass.cpp<br>
> llvm/trunk/lib/Transforms/Utils/FlattenCFG.cpp<br>
> llvm/trunk/test/CodeGen/R600/parallelandifcollapse.ll<br>
> - copied, changed from r187754, llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll<br>
> llvm/trunk/test/CodeGen/R600/parallelorifcollapse.ll<br>
> - copied, changed from r187754, llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll<br>
> Modified:<br>
> llvm/trunk/include/llvm/InitializePasses.h<br>
> llvm/trunk/include/llvm/Transforms/Scalar.h<br>
> llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h<br>
> llvm/trunk/include/llvm/Transforms/Utils/Local.h<br>
> llvm/trunk/lib/Target/R600/AMDGPUTargetMachine.cpp<br>
> llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp<br>
> llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt<br>
> llvm/trunk/lib/Transforms/Scalar/Scalar.cpp<br>
> llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp<br>
> llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp<br>
> llvm/trunk/lib/Transforms/Utils/CMakeLists.txt<br>
> llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp<br>
> llvm/trunk/test/Transforms/SimplifyCFG/R600/lit.local.cfg<br>
> llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll<br>
> llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll<br>
> llvm/trunk/test/Transforms/SimplifyCFG/lit.local.cfg<br>
> llvm/trunk/tools/lto/LTOCodeGenerator.cpp<br>
><br>
> Modified: llvm/trunk/include/llvm/InitializePasses.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/InitializePasses.h (original)<br>
> +++ llvm/trunk/include/llvm/InitializePasses.h Mon Aug 5 21:43:45 2013<br>
> @@ -86,8 +86,8 @@ void initializeCallGraphViewerPass(PassR<br>
> void initializeCFGOnlyPrinterPass(PassRegistry&);<br>
> void initializeCFGOnlyViewerPass(PassRegistry&);<br>
> void initializeCFGPrinterPass(PassRegistry&);<br>
> -void initializeCFGOptimizePass(PassRegistry&);<br>
> -void initializeCFGCanonicalizePass(PassRegistry&);<br>
> +void initializeCFGSimplifyPassPass(PassRegistry&);<br>
> +void initializeFlattenCFGPassPass(PassRegistry&);<br>
> void initializeStructurizeCFGPass(PassRegistry&);<br>
> void initializeCFGViewerPass(PassRegistry&);<br>
> void initializeCalculateSpillWeightsPass(PassRegistry&);<br>
><br>
> Modified: llvm/trunk/include/llvm/Transforms/Scalar.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/Transforms/Scalar.h (original)<br>
> +++ llvm/trunk/include/llvm/Transforms/Scalar.h Mon Aug 5 21:43:45 2013<br>
> @@ -196,7 +196,14 @@ FunctionPass *createJumpThreadingPass();<br>
> // CFGSimplification - Merge basic blocks, eliminate unreachable blocks,<br>
> // simplify terminator instructions, etc...<br>
> //<br>
> -FunctionPass *createCFGSimplificationPass(bool IsTargetAware = false);<br>
> +FunctionPass *createCFGSimplificationPass();<br>
> +<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// FlattenCFG - flatten CFG, reduce number of conditional branches by using<br>
> +// parallel-and and parallel-or mode, etc...<br>
> +//<br>
> +FunctionPass *createFlattenCFGPass();<br>
><br>
> //===----------------------------------------------------------------------===//<br>
> //<br>
><br>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h (original)<br>
> +++ llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h Mon Aug 5 21:43:45 2013<br>
> @@ -205,6 +205,15 @@ ReturnInst *FoldReturnIntoUncondBranch(R<br>
> TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp,<br>
> bool Unreachable, MDNode *BranchWeights = 0);<br>
><br>
> +///<br>
> +/// GetIfCondition - Check whether BB is the merge point of a if-region.<br>
> +/// If so, return the boolean condition that determines which entry into<br>
> +/// BB will be taken. Also, return by references the block that will be<br>
> +/// entered from if the condition is true, and the block that will be<br>
> +/// entered if the condition is false.<br>
> +<br>
> +Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,<br>
> + BasicBlock *&IfFalse);<br>
> } // End llvm namespace<br>
><br>
> #endif<br>
><br>
> Modified: llvm/trunk/include/llvm/Transforms/Utils/Local.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/Transforms/Utils/Local.h (original)<br>
> +++ llvm/trunk/include/llvm/Transforms/Utils/Local.h Mon Aug 5 21:43:45 2013<br>
> @@ -137,7 +137,13 @@ bool EliminateDuplicatePHINodes(BasicBlo<br>
> /// the basic block that was pointed to.<br>
> ///<br>
> bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,<br>
> - const DataLayout *TD = 0, AliasAnalysis *AA = 0);<br>
> + const DataLayout *TD = 0);<br>
> +<br>
> +/// FlatternCFG - This function is used to flatten a CFG. For<br>
> +/// example, it uses parallel-and and parallel-or mode to collapse<br>
> +// if-conditions and merge if-regions with identical statements.<br>
> +///<br>
> +bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = 0);<br>
><br>
> /// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch,<br>
> /// and if a predecessor branches to us and one of our successors, fold the<br>
><br>
> Modified: llvm/trunk/lib/Target/R600/AMDGPUTargetMachine.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/R600/AMDGPUTargetMachine.cpp?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/R600/AMDGPUTargetMachine.cpp?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/R600/AMDGPUTargetMachine.cpp (original)<br>
> +++ llvm/trunk/lib/Target/R600/AMDGPUTargetMachine.cpp Mon Aug 5 21:43:45 2013<br>
> @@ -91,7 +91,6 @@ public:<br>
> AMDGPUTargetMachine &getAMDGPUTargetMachine() const {<br>
> return getTM<AMDGPUTargetMachine>();<br>
> }<br>
> -<br>
> virtual bool addPreISel();<br>
> virtual bool addInstSelector();<br>
> virtual bool addPreRegAlloc();<br>
> @@ -120,6 +119,7 @@ void AMDGPUTargetMachine::addAnalysisPas<br>
> bool<br>
> AMDGPUPassConfig::addPreISel() {<br>
> const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();<br>
> + addPass(createFlattenCFGPass());<br>
> if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {<br>
> addPass(createStructurizeCFGPass());<br>
> addPass(createSIAnnotateControlFlowPass());<br>
><br>
> Modified: llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Mon Aug 5 21:43:45 2013<br>
> @@ -235,7 +235,7 @@ void PassManagerBuilder::populateModuleP<br>
> }<br>
><br>
> MPM.add(createAggressiveDCEPass()); // Delete dead instructions<br>
> - MPM.add(createCFGSimplificationPass(true)); // Merge & remove BBs<br>
> + MPM.add(createCFGSimplificationPass()); // Merge & remove BBs<br>
> MPM.add(createInstructionCombiningPass()); // Clean up after everything.<br>
><br>
> // As an experimental mode, run any vectorization passes in a separate<br>
> @@ -371,7 +371,7 @@ void PassManagerBuilder::populateLTOPass<br>
> PM.add(createJumpThreadingPass());<br>
><br>
> // Delete basic blocks, which optimization passes may have killed.<br>
> - PM.add(createCFGSimplificationPass(true));<br>
> + PM.add(createCFGSimplificationPass());<br>
><br>
> // Now that we have optimized the program, discard unreachable functions.<br>
> PM.add(createGlobalDCEPass());<br>
><br>
> Modified: llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt (original)<br>
> +++ llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt Mon Aug 5 21:43:45 2013<br>
> @@ -28,6 +28,7 @@ add_llvm_library(LLVMScalarOpts<br>
> Scalar.cpp<br>
> ScalarReplAggregates.cpp<br>
> SimplifyCFGPass.cpp<br>
> + FlattenCFGPass.cpp<br>
> Sink.cpp<br>
> StructurizeCFG.cpp<br>
> TailRecursionElimination.cpp<br>
><br>
> Added: llvm/trunk/lib/Transforms/Scalar/FlattenCFGPass.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/FlattenCFGPass.cpp?rev=187764&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/FlattenCFGPass.cpp?rev=187764&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Scalar/FlattenCFGPass.cpp (added)<br>
> +++ llvm/trunk/lib/Transforms/Scalar/FlattenCFGPass.cpp Mon Aug 5 21:43:45 2013<br>
> @@ -0,0 +1,79 @@<br>
> +//===- FlattenCFGPass.cpp - CFG Flatten Pass ----------------------===//<br>
> +//<br>
> +// The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This file implements flattening of CFG.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#define DEBUG_TYPE "flattencfg"<br>
> +#include "llvm/Transforms/Scalar.h"<br>
> +#include "llvm/Analysis/AliasAnalysis.h"<br>
> +#include "llvm/Pass.h"<br>
> +#include "llvm/Support/CFG.h"<br>
> +#include "llvm/Transforms/Utils/Local.h"<br>
> +using namespace llvm;<br>
> +<br>
> +namespace {<br>
> +struct FlattenCFGPass : public FunctionPass {<br>
> + static char ID; // Pass identification, replacement for typeid<br>
> +public:<br>
> + FlattenCFGPass() : FunctionPass(ID) {<br>
> + initializeFlattenCFGPassPass(*PassRegistry::getPassRegistry());<br>
> + }<br>
> + bool runOnFunction(Function &F);<br>
> +<br>
> + void getAnalysisUsage(AnalysisUsage &AU) const {<br>
> + AU.addRequired<AliasAnalysis>();<br>
> + }<br>
> +<br>
> +private:<br>
> + AliasAnalysis *AA;<br>
> +};<br>
> +}<br>
> +<br>
> +char FlattenCFGPass::ID = 0;<br>
> +INITIALIZE_PASS_BEGIN(FlattenCFGPass, "flattencfg", "Flatten the CFG", false,<br>
> + false)<br>
> +INITIALIZE_AG_DEPENDENCY(AliasAnalysis)<br>
> +INITIALIZE_PASS_END(FlattenCFGPass, "flattencfg", "Flatten the CFG", false,<br>
> + false)<br>
> +<br>
> +// Public interface to the FlattenCFG pass<br>
> +FunctionPass *llvm::createFlattenCFGPass() { return new FlattenCFGPass(); }<br>
> +<br>
> +/// iterativelyFlattenCFG - Call FlattenCFG on all the blocks in the function,<br>
> +/// iterating until no more changes are made.<br>
> +static bool iterativelyFlattenCFG(Function &F, AliasAnalysis *AA) {<br>
> + bool Changed = false;<br>
> + bool LocalChange = true;<br>
> + while (LocalChange) {<br>
> + LocalChange = false;<br>
> +<br>
> + // Loop over all of the basic blocks and remove them if they are unneeded...<br>
> + //<br>
> + for (Function::iterator BBIt = F.begin(); BBIt != F.end();) {<br>
> + if (FlattenCFG(BBIt++, AA)) {<br>
> + LocalChange = true;<br>
> + }<br>
> + }<br>
> + Changed |= LocalChange;<br>
> + }<br>
> + return Changed;<br>
> +}<br>
> +<br>
> +bool FlattenCFGPass::runOnFunction(Function &F) {<br>
> + AA = &getAnalysis<AliasAnalysis>();<br>
> + bool EverChanged = false;<br>
> + // iterativelyFlattenCFG can make some blocks dead.<br>
> + while (iterativelyFlattenCFG(F, AA)) {<br>
> + removeUnreachableBlocks(F);<br>
> + EverChanged = true;<br>
> + }<br>
> + return EverChanged;<br>
> +}<br>
><br>
> Modified: llvm/trunk/lib/Transforms/Scalar/Scalar.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalar.cpp?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalar.cpp?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Scalar/Scalar.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/Scalar/Scalar.cpp Mon Aug 5 21:43:45 2013<br>
> @@ -57,8 +57,7 @@ void llvm::initializeScalarOpts(PassRegi<br>
> initializeSROAPass(Registry);<br>
> initializeSROA_DTPass(Registry);<br>
> initializeSROA_SSAUpPass(Registry);<br>
> - initializeCFGCanonicalizePass(Registry);<br>
> - initializeCFGOptimizePass(Registry);<br>
> + initializeCFGSimplifyPassPass(Registry);<br>
> initializeStructurizeCFGPass(Registry);<br>
> initializeSinkingPass(Registry);<br>
> initializeTailCallElimPass(Registry);<br>
><br>
> Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp Mon Aug 5 21:43:45 2013<br>
> @@ -27,7 +27,6 @@<br>
> #include "llvm/ADT/SmallVector.h"<br>
> #include "llvm/ADT/Statistic.h"<br>
> #include "llvm/Analysis/TargetTransformInfo.h"<br>
> -#include "llvm/Analysis/AliasAnalysis.h"<br>
> #include "llvm/IR/Attributes.h"<br>
> #include "llvm/IR/Constants.h"<br>
> #include "llvm/IR/DataLayout.h"<br>
> @@ -43,61 +42,28 @@ STATISTIC(NumSimpl, "Number of blocks si<br>
><br>
> namespace {<br>
> struct CFGSimplifyPass : public FunctionPass {<br>
> - CFGSimplifyPass(char &ID, bool isTargetAware)<br>
> - : FunctionPass(ID), IsTargetAware(isTargetAware) {}<br>
> - virtual bool runOnFunction(Function &F);<br>
> -<br>
> - virtual void getAnalysisUsage(AnalysisUsage &AU) const {<br>
> - AU.addRequired<TargetTransformInfo>();<br>
> - }<br>
> -private:<br>
> - AliasAnalysis *AA;<br>
> - bool IsTargetAware; // Should the pass be target-aware?<br>
> -};<br>
> -<br>
> -// CFGSimplifyPass that does optimizations.<br>
> -struct CFGOptimize : public CFGSimplifyPass {<br>
> static char ID; // Pass identification, replacement for typeid<br>
> -public:<br>
> - CFGOptimize() : CFGSimplifyPass(ID, true) {<br>
> - initializeCFGOptimizePass(*PassRegistry::getPassRegistry());<br>
> + CFGSimplifyPass() : FunctionPass(ID) {<br>
> + initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry());<br>
> }<br>
> + virtual bool runOnFunction(Function &F);<br>
> +<br>
> virtual void getAnalysisUsage(AnalysisUsage &AU) const {<br>
> AU.addRequired<TargetTransformInfo>();<br>
> - AU.addRequired<AliasAnalysis>();<br>
> - }<br>
> -};<br>
> -<br>
> -// CFGSimplifyPass that does canonicalizations.<br>
> -struct CFGCanonicalize : public CFGSimplifyPass {<br>
> - static char ID; // Pass identification, replacement for typeid<br>
> -public:<br>
> - CFGCanonicalize() : CFGSimplifyPass(ID, false) {<br>
> - initializeCFGCanonicalizePass(*PassRegistry::getPassRegistry());<br>
> }<br>
> };<br>
> }<br>
><br>
> -char CFGCanonicalize::ID = 0;<br>
> -char CFGOptimize::ID = 0;<br>
> -INITIALIZE_PASS_BEGIN(CFGCanonicalize, "simplifycfg", "Simplify the CFG", false,<br>
> - false)<br>
> -INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)<br>
> -INITIALIZE_PASS_END(CFGCanonicalize, "simplifycfg", "Simplify the CFG", false,<br>
> - false)<br>
> -INITIALIZE_PASS_BEGIN(CFGOptimize, "optimizecfg", "optimize the CFG", false,<br>
> +char CFGSimplifyPass::ID = 0;<br>
> +INITIALIZE_PASS_BEGIN(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false,<br>
> false)<br>
> INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)<br>
> -INITIALIZE_AG_DEPENDENCY(AliasAnalysis)<br>
> -INITIALIZE_PASS_END(CFGOptimize, "optimizecfg", "Optimize the CFG", false,<br>
> +INITIALIZE_PASS_END(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false,<br>
> false)<br>
><br>
> // Public interface to the CFGSimplification pass<br>
> -FunctionPass *llvm::createCFGSimplificationPass(bool IsTargetAware) {<br>
> - if (IsTargetAware)<br>
> - return new CFGOptimize();<br>
> - else<br>
> - return new CFGCanonicalize();<br>
> +FunctionPass *llvm::createCFGSimplificationPass() {<br>
> + return new CFGSimplifyPass();<br>
> }<br>
><br>
> /// changeToUnreachable - Insert an unreachable instruction before the specified<br>
> @@ -334,7 +300,7 @@ static bool mergeEmptyReturnBlocks(Funct<br>
> /// iterativelySimplifyCFG - Call SimplifyCFG on all the blocks in the function,<br>
> /// iterating until no more changes are made.<br>
> static bool iterativelySimplifyCFG(Function &F, const TargetTransformInfo &TTI,<br>
> - const DataLayout *TD, AliasAnalysis *AA) {<br>
> + const DataLayout *TD) {<br>
> bool Changed = false;<br>
> bool LocalChange = true;<br>
> while (LocalChange) {<br>
> @@ -343,7 +309,7 @@ static bool iterativelySimplifyCFG(Funct<br>
> // Loop over all of the basic blocks and remove them if they are unneeded...<br>
> //<br>
> for (Function::iterator BBIt = F.begin(); BBIt != F.end(); ) {<br>
> - if (SimplifyCFG(BBIt++, TTI, TD, AA)) {<br>
> + if (SimplifyCFG(BBIt++, TTI, TD)) {<br>
> LocalChange = true;<br>
> ++NumSimpl;<br>
> }<br>
> @@ -357,15 +323,11 @@ static bool iterativelySimplifyCFG(Funct<br>
> // simplify the CFG.<br>
> //<br>
> bool CFGSimplifyPass::runOnFunction(Function &F) {<br>
> - if (IsTargetAware)<br>
> - AA = &getAnalysis<AliasAnalysis>();<br>
> - else<br>
> - AA = NULL;<br>
> const TargetTransformInfo &TTI = getAnalysis<TargetTransformInfo>();<br>
> const DataLayout *TD = getAnalysisIfAvailable<DataLayout>();<br>
> bool EverChanged = removeUnreachableBlocksFromFn(F);<br>
> EverChanged |= mergeEmptyReturnBlocks(F);<br>
> - EverChanged |= iterativelySimplifyCFG(F, TTI, TD, AA);<br>
> + EverChanged |= iterativelySimplifyCFG(F, TTI, TD);<br>
><br>
> // If neither pass changed anything, we're done.<br>
> if (!EverChanged) return false;<br>
> @@ -379,7 +341,7 @@ bool CFGSimplifyPass::runOnFunction(Func<br>
> return true;<br>
><br>
> do {<br>
> - EverChanged = iterativelySimplifyCFG(F, TTI, TD, AA);<br>
> + EverChanged = iterativelySimplifyCFG(F, TTI, TD);<br>
> EverChanged |= removeUnreachableBlocksFromFn(F);<br>
> } while (EverChanged);<br>
><br>
><br>
> Modified: llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp Mon Aug 5 21:43:45 2013<br>
> @@ -665,3 +665,104 @@ TerminatorInst *llvm::SplitBlockAndInser<br>
> ReplaceInstWithInst(HeadOldTerm, HeadNewTerm);<br>
> return CheckTerm;<br>
> }<br>
> +<br>
> +/// GetIfCondition - Given a basic block (BB) with two predecessors,<br>
> +/// check to see if the merge at this block is due<br>
> +/// to an "if condition". If so, return the boolean condition that determines<br>
> +/// which entry into BB will be taken. Also, return by references the block<br>
> +/// that will be entered from if the condition is true, and the block that will<br>
> +/// be entered if the condition is false.<br>
> +///<br>
> +/// This does no checking to see if the true/false blocks have large or unsavory<br>
> +/// instructions in them.<br>
> +Value *llvm::GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,<br>
> + BasicBlock *&IfFalse) {<br>
> + PHINode *SomePHI = dyn_cast<PHINode>(BB->begin());<br>
> + BasicBlock *Pred1 = NULL;<br>
> + BasicBlock *Pred2 = NULL;<br>
> +<br>
> + if (SomePHI) {<br>
> + if (SomePHI->getNumIncomingValues() != 2)<br>
> + return NULL;<br>
> + Pred1 = SomePHI->getIncomingBlock(0);<br>
> + Pred2 = SomePHI->getIncomingBlock(1);<br>
> + } else {<br>
> + pred_iterator PI = pred_begin(BB), PE = pred_end(BB);<br>
> + if (PI == PE) // No predecessor<br>
> + return NULL;<br>
> + Pred1 = *PI++;<br>
> + if (PI == PE) // Only one predecessor<br>
> + return NULL;<br>
> + Pred2 = *PI++;<br>
> + if (PI != PE) // More than two predecessors<br>
> + return NULL;<br>
> + }<br>
> +<br>
> + // We can only handle branches. Other control flow will be lowered to<br>
> + // branches if possible anyway.<br>
> + BranchInst *Pred1Br = dyn_cast<BranchInst>(Pred1->getTerminator());<br>
> + BranchInst *Pred2Br = dyn_cast<BranchInst>(Pred2->getTerminator());<br>
> + if (Pred1Br == 0 || Pred2Br == 0)<br>
> + return 0;<br>
> +<br>
> + // Eliminate code duplication by ensuring that Pred1Br is conditional if<br>
> + // either are.<br>
> + if (Pred2Br->isConditional()) {<br>
> + // If both branches are conditional, we don't have an "if statement". In<br>
> + // reality, we could transform this case, but since the condition will be<br>
> + // required anyway, we stand no chance of eliminating it, so the xform is<br>
> + // probably not profitable.<br>
> + if (Pred1Br->isConditional())<br>
> + return 0;<br>
> +<br>
> + std::swap(Pred1, Pred2);<br>
> + std::swap(Pred1Br, Pred2Br);<br>
> + }<br>
> +<br>
> + if (Pred1Br->isConditional()) {<br>
> + // The only thing we have to watch out for here is to make sure that Pred2<br>
> + // doesn't have incoming edges from other blocks. If it does, the condition<br>
> + // doesn't dominate BB.<br>
> + if (Pred2->getSinglePredecessor() == 0)<br>
> + return 0;<br>
> +<br>
> + // If we found a conditional branch predecessor, make sure that it branches<br>
> + // to BB and Pred2Br. If it doesn't, this isn't an "if statement".<br>
> + if (Pred1Br->getSuccessor(0) == BB &&<br>
> + Pred1Br->getSuccessor(1) == Pred2) {<br>
> + IfTrue = Pred1;<br>
> + IfFalse = Pred2;<br>
> + } else if (Pred1Br->getSuccessor(0) == Pred2 &&<br>
> + Pred1Br->getSuccessor(1) == BB) {<br>
> + IfTrue = Pred2;<br>
> + IfFalse = Pred1;<br>
> + } else {<br>
> + // We know that one arm of the conditional goes to BB, so the other must<br>
> + // go somewhere unrelated, and this must not be an "if statement".<br>
> + return 0;<br>
> + }<br>
> +<br>
> + return Pred1Br->getCondition();<br>
> + }<br>
> +<br>
> + // Ok, if we got here, both predecessors end with an unconditional branch to<br>
> + // BB. Don't panic! If both blocks only have a single (identical)<br>
> + // predecessor, and THAT is a conditional branch, then we're all ok!<br>
> + BasicBlock *CommonPred = Pred1->getSinglePredecessor();<br>
> + if (CommonPred == 0 || CommonPred != Pred2->getSinglePredecessor())<br>
> + return 0;<br>
> +<br>
> + // Otherwise, if this is a conditional branch, then we can use it!<br>
> + BranchInst *BI = dyn_cast<BranchInst>(CommonPred->getTerminator());<br>
> + if (BI == 0) return 0;<br>
> +<br>
> + assert(BI->isConditional() && "Two successors but not conditional?");<br>
> + if (BI->getSuccessor(0) == Pred1) {<br>
> + IfTrue = Pred1;<br>
> + IfFalse = Pred2;<br>
> + } else {<br>
> + IfTrue = Pred2;<br>
> + IfFalse = Pred1;<br>
> + }<br>
> + return BI->getCondition();<br>
> +}<br>
><br>
> Modified: llvm/trunk/lib/Transforms/Utils/CMakeLists.txt<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Utils/CMakeLists.txt (original)<br>
> +++ llvm/trunk/lib/Transforms/Utils/CMakeLists.txt Mon Aug 5 21:43:45 2013<br>
> @@ -25,6 +25,7 @@ add_llvm_library(LLVMTransformUtils<br>
> PromoteMemoryToRegister.cpp<br>
> SSAUpdater.cpp<br>
> SimplifyCFG.cpp<br>
> + FlattenCFG.cpp<br>
> SimplifyIndVar.cpp<br>
> SimplifyInstructions.cpp<br>
> SimplifyLibCalls.cpp<br>
><br>
> Added: llvm/trunk/lib/Transforms/Utils/FlattenCFG.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/FlattenCFG.cpp?rev=187764&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/FlattenCFG.cpp?rev=187764&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Utils/FlattenCFG.cpp (added)<br>
> +++ llvm/trunk/lib/Transforms/Utils/FlattenCFG.cpp Mon Aug 5 21:43:45 2013<br>
> @@ -0,0 +1,487 @@<br>
> +//===- FlatternCFG.cpp - Code to perform CFG flattening ---------------===//<br>
> +//<br>
> +// The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// Reduce conditional branches in CFG.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#define DEBUG_TYPE "flattencfg"<br>
> +#include "llvm/Transforms/Utils/Local.h"<br>
> +#include "llvm/ADT/SmallPtrSet.h"<br>
> +#include "llvm/Analysis/AliasAnalysis.h"<br>
> +#include "llvm/Analysis/ValueTracking.h"<br>
> +#include "llvm/IR/IRBuilder.h"<br>
> +#include "llvm/Support/Debug.h"<br>
> +#include "llvm/Transforms/Utils/BasicBlockUtils.h"<br>
> +using namespace llvm;<br>
> +<br>
> +namespace {<br>
> +class FlattenCFGOpt {<br>
> + AliasAnalysis *AA;<br>
> + /// \brief Use parallel-and or parallel-or to generate conditions for<br>
> + /// conditional branches.<br>
> + bool FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder, Pass *P = 0);<br>
> + /// \brief If \param BB is the merge block of an if-region, attempt to merge<br>
> + /// the if-region with an adjacent if-region upstream if two if-regions<br>
> + /// contain identical instructions.<br>
> + bool MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder, Pass *P = 0);<br>
> + /// \brief Compare a pair of blocks: \p Block1 and \p Block2, which<br>
> + /// are from two if-regions whose entry blocks are \p Head1 and \p<br>
> + /// Head2. \returns true if \p Block1 and \p Block2 contain identical<br>
> + /// instructions, and have no memory reference alias with \p Head2.<br>
> + /// This is used as a legality check for merging if-regions.<br>
> + bool CompareIfRegionBlock(BasicBlock *Head1, BasicBlock *Head2,<br>
> + BasicBlock *Block1, BasicBlock *Block2);<br>
> +<br>
> +public:<br>
> + FlattenCFGOpt(AliasAnalysis *AA) : AA(AA) {}<br>
> + bool run(BasicBlock *BB);<br>
> +};<br>
> +}<br>
> +<br>
> +/// If \param [in] BB has more than one predecessor that is a conditional<br>
> +/// branch, attempt to use parallel and/or for the branch condition. \returns<br>
> +/// true on success.<br>
> +///<br>
> +/// Before:<br>
> +/// ......<br>
> +/// %cmp10 = fcmp une float %tmp1, %tmp2<br>
> +/// br i1 %cmp1, label %if.then, label %lor.rhs<br>
> +///<br>
> +/// lor.rhs:<br>
> +/// ......<br>
> +/// %cmp11 = fcmp une float %tmp3, %tmp4<br>
> +/// br i1 %cmp11, label %if.then, label %ifend<br>
> +///<br>
> +/// if.end: // the merge block<br>
> +/// ......<br>
> +///<br>
> +/// if.then: // has two predecessors, both of them contains conditional branch.<br>
> +/// ......<br>
> +/// br label %if.end;<br>
> +///<br>
> +/// After:<br>
> +/// ......<br>
> +/// %cmp10 = fcmp une float %tmp1, %tmp2<br>
> +/// ......<br>
> +/// %cmp11 = fcmp une float %tmp3, %tmp4<br>
> +/// %cmp12 = or i1 %cmp10, %cmp11 // parallel-or mode.<br>
> +/// br i1 %cmp12, label %if.then, label %ifend<br>
> +///<br>
> +/// if.end:<br>
> +/// ......<br>
> +///<br>
> +/// if.then:<br>
> +/// ......<br>
> +/// br label %if.end;<br>
> +///<br>
> +/// Current implementation handles two cases.<br>
> +/// Case 1: \param BB is on the else-path.<br>
> +///<br>
> +/// BB1<br>
> +/// / |<br>
> +/// BB2 |<br>
> +/// / \ |<br>
> +/// BB3 \ | where, BB1, BB2 contain conditional branches.<br>
> +/// \ | / BB3 contains unconditional branch.<br>
> +/// \ | / BB4 corresponds to \param BB which is also the merge.<br>
> +/// BB => BB4<br>
> +///<br>
> +///<br>
> +/// Corresponding source code:<br>
> +///<br>
> +/// if (a == b && c == d)<br>
> +/// statement; // BB3<br>
> +///<br>
> +/// Case 2: \param BB BB is on the then-path.<br>
> +///<br>
> +/// BB1<br>
> +/// / |<br>
> +/// | BB2<br>
> +/// \ / | where BB1, BB2 contain conditional branches.<br>
> +/// BB => BB3 | BB3 contains unconditiona branch and corresponds<br>
> +/// \ / to \param BB. BB4 is the merge.<br>
> +/// BB4<br>
> +///<br>
> +/// Corresponding source code:<br>
> +///<br>
> +/// if (a == b || c == d)<br>
> +/// statement; // BB3<br>
> +///<br>
> +/// In both cases, \param BB is the common successor of conditional branches.<br>
> +/// In Case 1, \param BB (BB4) has an unconditional branch (BB3) as<br>
> +/// its predecessor. In Case 2, \param BB (BB3) only has conditional branches<br>
> +/// as its predecessors.<br>
> +///<br>
> +bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder,<br>
> + Pass *P) {<br>
> + PHINode *PHI = dyn_cast<PHINode>(BB->begin());<br>
> + if (PHI)<br>
> + return false; // For simplicity, avoid cases containing PHI nodes.<br>
> +<br>
> + BasicBlock *LastCondBlock = NULL;<br>
> + BasicBlock *FirstCondBlock = NULL;<br>
> + BasicBlock *UnCondBlock = NULL;<br>
> + int Idx = -1;<br>
> +<br>
> + // Check predecessors of \param BB.<br>
> + SmallPtrSet<BasicBlock *, 16> Preds(pred_begin(BB), pred_end(BB));<br>
> + for (SmallPtrSetIterator<BasicBlock *> PI = Preds.begin(), PE = Preds.end();<br>
> + PI != PE; ++PI) {<br>
> + BasicBlock *Pred = *PI;<br>
> + BranchInst *PBI = dyn_cast<BranchInst>(Pred->getTerminator());<br>
> +<br>
> + // All predecessors should terminate with a branch.<br>
> + if (!PBI)<br>
> + return false;<br>
> +<br>
> + BasicBlock *PP = Pred->getSinglePredecessor();<br>
> +<br>
> + if (PBI->isUnconditional()) {<br>
> + // Case 1: Pred (BB3) is an unconditional block, it should<br>
> + // have a single predecessor (BB2) that is also a predecessor<br>
> + // of \param BB (BB4) and should not have address-taken.<br>
> + // There should exist only one such unconditional<br>
> + // branch among the predecessors.<br>
> + if (UnCondBlock || !PP || (Preds.count(PP) == 0) ||<br>
> + Pred->hasAddressTaken())<br>
> + return false;<br>
> +<br>
> + UnCondBlock = Pred;<br>
> + continue;<br>
> + }<br>
> +<br>
> + // Only conditional branches are allowed beyond this point.<br>
> + assert(PBI->isConditional());<br>
> +<br>
> + // Condition's unique use should be the branch instruction.<br>
> + Value *PC = PBI->getCondition();<br>
> + if (!PC || !PC->hasOneUse())<br>
> + return false;<br>
> +<br>
> + if (PP && Preds.count(PP)) {<br>
> + // These are internal condition blocks to be merged from, e.g.,<br>
> + // BB2 in both cases.<br>
> + // Should not be address-taken.<br>
> + if (Pred->hasAddressTaken())<br>
> + return false;<br>
> +<br>
> + // Instructions in the internal condition blocks should be safe<br>
> + // to hoist up.<br>
> + for (BasicBlock::iterator BI = Pred->begin(), BE = PBI; BI != BE;) {<br>
> + Instruction *CI = BI++;<br>
> + if (isa<PHINode>(CI) || !isSafeToSpeculativelyExecute(CI))<br>
> + return false;<br>
> + }<br>
> + } else {<br>
> + // This is the condition block to be merged into, e.g. BB1 in<br>
> + // both cases.<br>
> + if (FirstCondBlock)<br>
> + return false;<br>
> + FirstCondBlock = Pred;<br>
> + }<br>
> +<br>
> + // Find whether BB is uniformly on the true (or false) path<br>
> + // for all of its predecessors.<br>
> + BasicBlock *PS1 = PBI->getSuccessor(0);<br>
> + BasicBlock *PS2 = PBI->getSuccessor(1);<br>
> + BasicBlock *PS = (PS1 == BB) ? PS2 : PS1;<br>
> + int CIdx = (PS1 == BB) ? 0 : 1;<br>
> +<br>
> + if (Idx == -1)<br>
> + Idx = CIdx;<br>
> + else if (CIdx != Idx)<br>
> + return false;<br>
> +<br>
> + // PS is the successor which is not BB. Check successors to identify<br>
> + // the last conditional branch.<br>
> + if (Preds.count(PS) == 0) {<br>
> + // Case 2.<br>
> + LastCondBlock = Pred;<br>
> + } else {<br>
> + // Case 1<br>
> + BranchInst *BPS = dyn_cast<BranchInst>(PS->getTerminator());<br>
> + if (BPS && BPS->isUnconditional()) {<br>
> + // Case 1: PS(BB3) should be an unconditional branch.<br>
> + LastCondBlock = Pred;<br>
> + }<br>
> + }<br>
> + }<br>
> +<br>
> + if (!FirstCondBlock || !LastCondBlock || (FirstCondBlock == LastCondBlock))<br>
> + return false;<br>
> +<br>
> + TerminatorInst *TBB = LastCondBlock->getTerminator();<br>
> + BasicBlock *PS1 = TBB->getSuccessor(0);<br>
> + BasicBlock *PS2 = TBB->getSuccessor(1);<br>
> + BranchInst *PBI1 = dyn_cast<BranchInst>(PS1->getTerminator());<br>
> + BranchInst *PBI2 = dyn_cast<BranchInst>(PS2->getTerminator());<br>
> +<br>
> + // If PS1 does not jump into PS2, but PS2 jumps into PS1,<br>
> + // attempt branch inversion.<br>
> + if (!PBI1 || !PBI1->isUnconditional() ||<br>
> + (PS1->getTerminator()->getSuccessor(0) != PS2)) {<br>
> + // Check whether PS2 jumps into PS1.<br>
> + if (!PBI2 || !PBI2->isUnconditional() ||<br>
> + (PS2->getTerminator()->getSuccessor(0) != PS1))<br>
> + return false;<br>
> +<br>
> + // Do branch inversion.<br>
> + BasicBlock *CurrBlock = LastCondBlock;<br>
> + bool EverChanged = false;<br>
> + while (1) {<br>
> + BranchInst *BI = dyn_cast<BranchInst>(CurrBlock->getTerminator());<br>
> + CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition());<br>
> + CmpInst::Predicate Predicate = CI->getPredicate();<br>
> + // Cannonicalize icmp_ne -> icmp_eq, fcmp_one -> fcmp_oeq<br>
> + if ((Predicate == CmpInst::ICMP_NE) || (Predicate == CmpInst::FCMP_ONE)) {<br>
> + CI->setPredicate(ICmpInst::getInversePredicate(Predicate));<br>
> + BI->swapSuccessors();<br>
> + EverChanged = true;<br>
> + }<br>
> + if (CurrBlock == FirstCondBlock)<br>
> + break;<br>
> + CurrBlock = CurrBlock->getSinglePredecessor();<br>
> + }<br>
> + return EverChanged;<br>
> + }<br>
> +<br>
> + // PS1 must have a conditional branch.<br>
> + if (!PBI1 || !PBI1->isUnconditional())<br>
> + return false;<br>
> +<br>
> + // PS2 should not contain PHI node.<br>
> + PHI = dyn_cast<PHINode>(PS2->begin());<br>
> + if (PHI)<br>
> + return false;<br>
> +<br>
> + // Do the transformation.<br>
> + BasicBlock *CB;<br>
> + BranchInst *PBI = dyn_cast<BranchInst>(FirstCondBlock->getTerminator());<br>
> + bool Iteration = true;<br>
> + BasicBlock *SaveInsertBB = Builder.GetInsertBlock();<br>
> + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint();<br>
> + Value *PC = PBI->getCondition();<br>
> +<br>
> + do {<br>
> + CB = PBI->getSuccessor(1 - Idx);<br>
> + // Delete the conditional branch.<br>
> + FirstCondBlock->getInstList().pop_back();<br>
> + FirstCondBlock->getInstList()<br>
> + .splice(FirstCondBlock->end(), CB->getInstList());<br>
> + PBI = cast<BranchInst>(FirstCondBlock->getTerminator());<br>
> + Value *CC = PBI->getCondition();<br>
> + // Merge conditions.<br>
> + Builder.SetInsertPoint(PBI);<br>
> + Value *NC;<br>
> + if (Idx == 0)<br>
> + // Case 2, use parallel or.<br>
> + NC = Builder.CreateOr(PC, CC);<br>
> + else<br>
> + // Case 1, use parallel and.<br>
> + NC = Builder.CreateAnd(PC, CC);<br>
> +<br>
> + PBI->replaceUsesOfWith(CC, NC);<br>
> + PC = NC;<br>
> + if (CB == LastCondBlock)<br>
> + Iteration = false;<br>
> + // Remove internal conditional branches.<br>
> + CB->dropAllReferences();<br>
> + // make CB unreachable and let downstream to delete the block.<br>
> + new UnreachableInst(CB->getContext(), CB);<br>
> + } while (Iteration);<br>
> +<br>
> + Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt);<br>
> + DEBUG(dbgs() << "Use parallel and/or in:\n" << *FirstCondBlock);<br>
> + return true;<br>
> +}<br>
> +<br>
> +/// Compare blocks from two if-regions, where \param Head1 is the entry of the<br>
> +/// 1st if-region. \param Head2 is the entry of the 2nd if-region. \param<br>
> +/// Block1 is a block in the 1st if-region to compare. \param Block2 is a block<br>
> +// in the 2nd if-region to compare. \returns true if \param Block1 and \param<br>
> +/// Block2 have identical instructions and do not have memory reference alias<br>
> +/// with \param Head2.<br>
> +///<br>
> +bool FlattenCFGOpt::CompareIfRegionBlock(BasicBlock *Head1, BasicBlock *Head2,<br>
> + BasicBlock *Block1,<br>
> + BasicBlock *Block2) {<br>
> + TerminatorInst *PTI2 = Head2->getTerminator();<br>
> + Instruction *PBI2 = Head2->begin();<br>
> +<br>
> + bool eq1 = (Block1 == Head1);<br>
> + bool eq2 = (Block2 == Head2);<br>
> + if (eq1 || eq2) {<br>
> + // An empty then-path or else-path.<br>
> + return (eq1 == eq2);<br>
> + }<br>
> +<br>
> + // Check whether instructions in Block1 and Block2 are identical<br>
> + // and do not alias with instructions in Head2.<br>
> + BasicBlock::iterator iter1 = Block1->begin();<br>
> + BasicBlock::iterator end1 = Block1->getTerminator();<br>
> + BasicBlock::iterator iter2 = Block2->begin();<br>
> + BasicBlock::iterator end2 = Block2->getTerminator();<br>
> +<br>
> + while (1) {<br>
> + if (iter1 == end1) {<br>
> + if (iter2 != end2)<br>
> + return false;<br>
> + break;<br>
> + }<br>
> +<br>
> + if (!iter1->isIdenticalTo(iter2))<br>
> + return false;<br>
> +<br>
> + // Illegal to remove instructions with side effects except<br>
> + // non-volatile stores.<br>
> + if (iter1->mayHaveSideEffects()) {<br>
> + Instruction *CurI = &*iter1;<br>
> + StoreInst *SI = dyn_cast<StoreInst>(CurI);<br>
> + if (!SI || SI->isVolatile())<br>
> + return false;<br>
> + }<br>
> +<br>
> + // For simplicity and speed, data dependency check can be<br>
> + // avoided if read from memory doesn't exist.<br>
> + if (iter1->mayReadFromMemory())<br>
> + return false;<br>
> +<br>
> + if (iter1->mayWriteToMemory()) {<br>
> + for (BasicBlock::iterator BI = PBI2, BE = PTI2; BI != BE; ++BI) {<br>
> + if (BI->mayReadFromMemory() || BI->mayWriteToMemory()) {<br>
> + // Check alias with Head2.<br>
> + if (!AA || AA->alias(iter1, BI))<br>
> + return false;<br>
> + }<br>
> + }<br>
> + }<br>
> + ++iter1;<br>
> + ++iter2;<br>
> + }<br>
> +<br>
> + return true;<br>
> +}<br>
> +<br>
> +/// Check whether \param BB is the merge block of a if-region. If yes, check<br>
> +/// whether there exists an adjacent if-region upstream, the two if-regions<br>
> +/// contain identical instuctions and can be legally merged. \returns true if<br>
> +/// the two if-regions are merged.<br>
> +///<br>
> +/// From:<br>
> +/// if (a)<br>
> +/// statement;<br>
> +/// if (b)<br>
> +/// statement;<br>
> +///<br>
> +/// To:<br>
> +/// if (a || b)<br>
> +/// statement;<br>
> +///<br>
> +bool FlattenCFGOpt::MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder,<br>
> + Pass *P) {<br>
> + BasicBlock *IfTrue2, *IfFalse2;<br>
> + Value *IfCond2 = GetIfCondition(BB, IfTrue2, IfFalse2);<br>
> + Instruction *CInst2 = dyn_cast_or_null<Instruction>(IfCond2);<br>
> + if (!CInst2)<br>
> + return false;<br>
> +<br>
> + BasicBlock *SecondEntryBlock = CInst2->getParent();<br>
> + if (SecondEntryBlock->hasAddressTaken())<br>
> + return false;<br>
> +<br>
> + BasicBlock *IfTrue1, *IfFalse1;<br>
> + Value *IfCond1 = GetIfCondition(SecondEntryBlock, IfTrue1, IfFalse1);<br>
> + Instruction *CInst1 = dyn_cast_or_null<Instruction>(IfCond1);<br>
> + if (!CInst1)<br>
> + return false;<br>
> +<br>
> + BasicBlock *FirstEntryBlock = CInst1->getParent();<br>
> +<br>
> + // Either then-path or else-path should be empty.<br>
> + if ((IfTrue1 != FirstEntryBlock) && (IfFalse1 != FirstEntryBlock))<br>
> + return false;<br>
> + if ((IfTrue2 != SecondEntryBlock) && (IfFalse2 != SecondEntryBlock))<br>
> + return false;<br>
> +<br>
> + TerminatorInst *PTI2 = SecondEntryBlock->getTerminator();<br>
> + Instruction *PBI2 = SecondEntryBlock->begin();<br>
> +<br>
> + if (!CompareIfRegionBlock(FirstEntryBlock, SecondEntryBlock, IfTrue1,<br>
> + IfTrue2))<br>
> + return false;<br>
> +<br>
> + if (!CompareIfRegionBlock(FirstEntryBlock, SecondEntryBlock, IfFalse1,<br>
> + IfFalse2))<br>
> + return false;<br>
> +<br>
> + // Check whether \param SecondEntryBlock has side-effect and is safe to<br>
> + // speculate.<br>
> + for (BasicBlock::iterator BI = PBI2, BE = PTI2; BI != BE; ++BI) {<br>
> + Instruction *CI = BI;<br>
> + if (isa<PHINode>(CI) || CI->mayHaveSideEffects() ||<br>
> + !isSafeToSpeculativelyExecute(CI))<br>
> + return false;<br>
> + }<br>
> +<br>
> + // Merge \param SecondEntryBlock into \param FirstEntryBlock.<br>
> + FirstEntryBlock->getInstList().pop_back();<br>
> + FirstEntryBlock->getInstList()<br>
> + .splice(FirstEntryBlock->end(), SecondEntryBlock->getInstList());<br>
> + BranchInst *PBI = dyn_cast<BranchInst>(FirstEntryBlock->getTerminator());<br>
> + Value *CC = PBI->getCondition();<br>
> + BasicBlock *SaveInsertBB = Builder.GetInsertBlock();<br>
> + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint();<br>
> + Builder.SetInsertPoint(PBI);<br>
> + Value *NC = Builder.CreateOr(CInst1, CC);<br>
> + PBI->replaceUsesOfWith(CC, NC);<br>
> + Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt);<br>
> +<br>
> + // Remove IfTrue1<br>
> + if (IfTrue1 != FirstEntryBlock) {<br>
> + IfTrue1->dropAllReferences();<br>
> + IfTrue1->eraseFromParent();<br>
> + }<br>
> +<br>
> + // Remove IfFalse1<br>
> + if (IfFalse1 != FirstEntryBlock) {<br>
> + IfFalse1->dropAllReferences();<br>
> + IfFalse1->eraseFromParent();<br>
> + }<br>
> +<br>
> + // Remove \param SecondEntryBlock<br>
> + SecondEntryBlock->dropAllReferences();<br>
> + SecondEntryBlock->eraseFromParent();<br>
> + DEBUG(dbgs() << "If conditions merged into:\n" << *FirstEntryBlock);<br>
> + return true;<br>
> +}<br>
> +<br>
> +bool FlattenCFGOpt::run(BasicBlock *BB) {<br>
> + bool Changed = false;<br>
> + assert(BB && BB->getParent() && "Block not embedded in function!");<br>
> + assert(BB->getTerminator() && "Degenerate basic block encountered!");<br>
> +<br>
> + IRBuilder<> Builder(BB);<br>
> +<br>
> + if (FlattenParallelAndOr(BB, Builder))<br>
> + return true;<br>
> +<br>
> + if (MergeIfRegion(BB, Builder))<br>
> + return true;<br>
> +<br>
> + return Changed;<br>
> +}<br>
> +<br>
> +/// FlattenCFG - This function is used to flatten a CFG. For<br>
> +/// example, it uses parallel-and and parallel-or mode to collapse<br>
> +// if-conditions and merge if-regions with identical statements.<br>
> +///<br>
> +bool llvm::FlattenCFG(BasicBlock *BB, AliasAnalysis *AA) {<br>
> + return FlattenCFGOpt(AA).run(BB);<br>
> +}<br>
><br>
> Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Mon Aug 5 21:43:45 2013<br>
> @@ -19,7 +19,6 @@<br>
> #include "llvm/ADT/SmallPtrSet.h"<br>
> #include "llvm/ADT/SmallVector.h"<br>
> #include "llvm/ADT/Statistic.h"<br>
> -#include "llvm/Analysis/AliasAnalysis.h"<br>
> #include "llvm/Analysis/InstructionSimplify.h"<br>
> #include "llvm/Analysis/TargetTransformInfo.h"<br>
> #include "llvm/Analysis/ValueTracking.h"<br>
> @@ -66,10 +65,6 @@ static cl::opt<bool><br>
> HoistCondStores("simplifycfg-hoist-cond-stores", cl::Hidden, cl::init(true),<br>
> cl::desc("Hoist conditional stores if an unconditional store preceeds"));<br>
><br>
> -static cl::opt<bool><br>
> -ParallelAndOr("simplifycfg-parallel-and-or", cl::Hidden, cl::init(true),<br>
> - cl::desc("Use parallel-and-or mode for branch conditions"));<br>
> -<br>
> STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps");<br>
> STATISTIC(NumLookupTables, "Number of switch instructions turned into lookup tables");<br>
> STATISTIC(NumSinkCommons, "Number of common instructions sunk down to the end block");<br>
> @@ -95,8 +90,6 @@ namespace {<br>
> class SimplifyCFGOpt {<br>
> const TargetTransformInfo &TTI;<br>
> const DataLayout *const TD;<br>
> - AliasAnalysis *AA;<br>
> -<br>
> Value *isValueEqualityComparison(TerminatorInst *TI);<br>
> BasicBlock *GetValueEqualityComparisonCases(TerminatorInst *TI,<br>
> std::vector<ValueEqualityComparisonCase> &Cases);<br>
> @@ -113,25 +106,10 @@ class SimplifyCFGOpt {<br>
> bool SimplifyIndirectBr(IndirectBrInst *IBI);<br>
> bool SimplifyUncondBranch(BranchInst *BI, IRBuilder <> &Builder);<br>
> bool SimplifyCondBranch(BranchInst *BI, IRBuilder <>&Builder);<br>
> - /// \brief Use parallel-and or parallel-or to generate conditions for<br>
> - /// conditional branches.<br>
> - bool SimplifyParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder, Pass *P = 0);<br>
> - /// \brief If \param BB is the merge block of an if-region, attempt to merge<br>
> - /// the if-region with an adjacent if-region upstream if two if-regions<br>
> - /// contain identical instructions.<br>
> - bool MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder, Pass *P = 0);<br>
> - /// \brief Compare a pair of blocks: \p Block1 and \p Block2, which<br>
> - /// are from two if-regions whose entry blocks are \p Head1 and \p<br>
> - /// Head2. \returns true if \p Block1 and \p Block2 contain identical<br>
> - /// instructions, and have no memory reference alias with \p Head2.<br>
> - /// This is used as a legality check for merging if-regions.<br>
> - bool CompareIfRegionBlock(BasicBlock *Head1, BasicBlock *Head2,<br>
> - BasicBlock *Block1, BasicBlock *Block2);<br>
><br>
> public:<br>
> - SimplifyCFGOpt(const TargetTransformInfo &TTI, const DataLayout *TD,<br>
> - AliasAnalysis *AA)<br>
> - : TTI(TTI), TD(TD), AA(AA) {}<br>
> + SimplifyCFGOpt(const TargetTransformInfo &TTI, const DataLayout *TD)<br>
> + : TTI(TTI), TD(TD) {}<br>
> bool run(BasicBlock *BB);<br>
> };<br>
> }<br>
> @@ -217,108 +195,6 @@ static void AddPredecessorToBlock(BasicB<br>
> PN->addIncoming(PN->getIncomingValueForBlock(ExistPred), NewPred);<br>
> }<br>
><br>
> -<br>
> -/// GetIfCondition - Given a basic block (BB) with two predecessors,<br>
> -/// check to see if the merge at this block is due<br>
> -/// to an "if condition". If so, return the boolean condition that determines<br>
> -/// which entry into BB will be taken. Also, return by references the block<br>
> -/// that will be entered from if the condition is true, and the block that will<br>
> -/// be entered if the condition is false.<br>
> -///<br>
> -/// This does no checking to see if the true/false blocks have large or unsavory<br>
> -/// instructions in them.<br>
> -static Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,<br>
> - BasicBlock *&IfFalse) {<br>
> - PHINode *SomePHI = dyn_cast<PHINode>(BB->begin());<br>
> - BasicBlock *Pred1 = NULL;<br>
> - BasicBlock *Pred2 = NULL;<br>
> -<br>
> - if (SomePHI) {<br>
> - if (SomePHI->getNumIncomingValues() != 2)<br>
> - return NULL;<br>
> - Pred1 = SomePHI->getIncomingBlock(0);<br>
> - Pred2 = SomePHI->getIncomingBlock(1);<br>
> - } else {<br>
> - pred_iterator PI = pred_begin(BB), PE = pred_end(BB);<br>
> - if (PI == PE) // No predecessor<br>
> - return NULL;<br>
> - Pred1 = *PI++;<br>
> - if (PI == PE) // Only one predecessor<br>
> - return NULL;<br>
> - Pred2 = *PI++;<br>
> - if (PI != PE) // More than two predecessors<br>
> - return NULL;<br>
> - }<br>
> -<br>
> - // We can only handle branches. Other control flow will be lowered to<br>
> - // branches if possible anyway.<br>
> - BranchInst *Pred1Br = dyn_cast<BranchInst>(Pred1->getTerminator());<br>
> - BranchInst *Pred2Br = dyn_cast<BranchInst>(Pred2->getTerminator());<br>
> - if (Pred1Br == 0 || Pred2Br == 0)<br>
> - return 0;<br>
> -<br>
> - // Eliminate code duplication by ensuring that Pred1Br is conditional if<br>
> - // either are.<br>
> - if (Pred2Br->isConditional()) {<br>
> - // If both branches are conditional, we don't have an "if statement". In<br>
> - // reality, we could transform this case, but since the condition will be<br>
> - // required anyway, we stand no chance of eliminating it, so the xform is<br>
> - // probably not profitable.<br>
> - if (Pred1Br->isConditional())<br>
> - return 0;<br>
> -<br>
> - std::swap(Pred1, Pred2);<br>
> - std::swap(Pred1Br, Pred2Br);<br>
> - }<br>
> -<br>
> - if (Pred1Br->isConditional()) {<br>
> - // The only thing we have to watch out for here is to make sure that Pred2<br>
> - // doesn't have incoming edges from other blocks. If it does, the condition<br>
> - // doesn't dominate BB.<br>
> - if (Pred2->getSinglePredecessor() == 0)<br>
> - return 0;<br>
> -<br>
> - // If we found a conditional branch predecessor, make sure that it branches<br>
> - // to BB and Pred2Br. If it doesn't, this isn't an "if statement".<br>
> - if (Pred1Br->getSuccessor(0) == BB &&<br>
> - Pred1Br->getSuccessor(1) == Pred2) {<br>
> - IfTrue = Pred1;<br>
> - IfFalse = Pred2;<br>
> - } else if (Pred1Br->getSuccessor(0) == Pred2 &&<br>
> - Pred1Br->getSuccessor(1) == BB) {<br>
> - IfTrue = Pred2;<br>
> - IfFalse = Pred1;<br>
> - } else {<br>
> - // We know that one arm of the conditional goes to BB, so the other must<br>
> - // go somewhere unrelated, and this must not be an "if statement".<br>
> - return 0;<br>
> - }<br>
> -<br>
> - return Pred1Br->getCondition();<br>
> - }<br>
> -<br>
> - // Ok, if we got here, both predecessors end with an unconditional branch to<br>
> - // BB. Don't panic! If both blocks only have a single (identical)<br>
> - // predecessor, and THAT is a conditional branch, then we're all ok!<br>
> - BasicBlock *CommonPred = Pred1->getSinglePredecessor();<br>
> - if (CommonPred == 0 || CommonPred != Pred2->getSinglePredecessor())<br>
> - return 0;<br>
> -<br>
> - // Otherwise, if this is a conditional branch, then we can use it!<br>
> - BranchInst *BI = dyn_cast<BranchInst>(CommonPred->getTerminator());<br>
> - if (BI == 0) return 0;<br>
> -<br>
> - assert(BI->isConditional() && "Two successors but not conditional?");<br>
> - if (BI->getSuccessor(0) == Pred1) {<br>
> - IfTrue = Pred1;<br>
> - IfFalse = Pred2;<br>
> - } else {<br>
> - IfTrue = Pred2;<br>
> - IfFalse = Pred1;<br>
> - }<br>
> - return BI->getCondition();<br>
> -}<br>
> -<br>
> /// ComputeSpeculationCost - Compute an abstract "cost" of speculating the<br>
> /// given instruction, which is assumed to be safe to speculate. 1 means<br>
> /// cheap, 2 means less cheap, and UINT_MAX means prohibitively expensive.<br>
> @@ -4102,386 +3978,6 @@ bool SimplifyCFGOpt::SimplifyCondBranch(<br>
> return false;<br>
> }<br>
><br>
> -/// If \param [in] BB has more than one predecessor that is a conditional<br>
> -/// branch, attempt to use parallel and/or for the branch condition. \returns<br>
> -/// true on success.<br>
> -///<br>
> -/// Before:<br>
> -/// ......<br>
> -/// %cmp10 = fcmp une float %tmp1, %tmp2<br>
> -/// br i1 %cmp1, label %if.then, label %lor.rhs<br>
> -///<br>
> -/// lor.rhs:<br>
> -/// ......<br>
> -/// %cmp11 = fcmp une float %tmp3, %tmp4<br>
> -/// br i1 %cmp11, label %if.then, label %ifend<br>
> -///<br>
> -/// if.end: // the merge block<br>
> -/// ......<br>
> -///<br>
> -/// if.then: // has two predecessors, both of them contains conditional branch.<br>
> -/// ......<br>
> -/// br label %if.end;<br>
> -///<br>
> -/// After:<br>
> -/// ......<br>
> -/// %cmp10 = fcmp une float %tmp1, %tmp2<br>
> -/// ......<br>
> -/// %cmp11 = fcmp une float %tmp3, %tmp4<br>
> -/// %cmp12 = or i1 %cmp10, %cmp11 // parallel-or mode.<br>
> -/// br i1 %cmp12, label %if.then, label %ifend<br>
> -///<br>
> -/// if.end:<br>
> -/// ......<br>
> -///<br>
> -/// if.then:<br>
> -/// ......<br>
> -/// br label %if.end;<br>
> -///<br>
> -/// Current implementation handles two cases.<br>
> -/// Case 1: \param BB is on the else-path.<br>
> -///<br>
> -/// BB1<br>
> -/// / |<br>
> -/// BB2 |<br>
> -/// / \ |<br>
> -/// BB3 \ | where, BB1, BB2 contain conditional branches.<br>
> -/// \ | / BB3 contains unconditional branch.<br>
> -/// \ | / BB4 corresponds to \param BB which is also the merge.<br>
> -/// BB => BB4<br>
> -///<br>
> -///<br>
> -/// Corresponding source code:<br>
> -///<br>
> -/// if (a == b && c == d)<br>
> -/// statement; // BB3<br>
> -///<br>
> -/// Case 2: \param BB BB is on the then-path.<br>
> -///<br>
> -/// BB1<br>
> -/// / |<br>
> -/// | BB2<br>
> -/// \ / | where BB1, BB2 contain conditional branches.<br>
> -/// BB => BB3 | BB3 contains unconditiona branch and corresponds<br>
> -/// \ / to \param BB. BB4 is the merge.<br>
> -/// BB4<br>
> -///<br>
> -/// Corresponding source code:<br>
> -///<br>
> -/// if (a == b || c == d)<br>
> -/// statement; // BB3<br>
> -///<br>
> -/// In both cases, \param BB is the common successor of conditional branches.<br>
> -/// In Case 1, \param BB (BB4) has an unconditional branch (BB3) as<br>
> -/// its predecessor. In Case 2, \param BB (BB3) only has conditional branches<br>
> -/// as its predecessors.<br>
> -///<br>
> -bool SimplifyCFGOpt::SimplifyParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder,<br>
> - Pass *P) {<br>
> - PHINode *PHI = dyn_cast<PHINode>(BB->begin());<br>
> - if (PHI)<br>
> - return false; // For simplicity, avoid cases containing PHI nodes.<br>
> -<br>
> - BasicBlock *LastCondBlock = NULL;<br>
> - BasicBlock *FirstCondBlock = NULL;<br>
> - BasicBlock *UnCondBlock = NULL;<br>
> - int Idx = -1;<br>
> -<br>
> - // Check predecessors of \param BB.<br>
> - SmallPtrSet<BasicBlock*, 16> Preds(pred_begin(BB), pred_end(BB));<br>
> - for (SmallPtrSetIterator<BasicBlock*> PI = Preds.begin(), PE = Preds.end();<br>
> - PI != PE; ++PI) {<br>
> - BasicBlock *Pred = *PI;<br>
> - BranchInst *PBI = dyn_cast<BranchInst>(Pred->getTerminator());<br>
> -<br>
> - // All predecessors should terminate with a branch.<br>
> - if (!PBI)<br>
> - return false;<br>
> -<br>
> - BasicBlock *PP = Pred->getSinglePredecessor();<br>
> -<br>
> - if (PBI->isUnconditional()) {<br>
> - // Case 1: Pred (BB3) is an unconditional block, it should<br>
> - // have a single predecessor (BB2) that is also a predecessor<br>
> - // of \param BB (BB4) and should not have address-taken.<br>
> - // There should exist only one such unconditional<br>
> - // branch among the predecessors.<br>
> - if (UnCondBlock || !PP || (Preds.count(PP) == 0) ||<br>
> - Pred->hasAddressTaken())<br>
> - return false;<br>
> -<br>
> - UnCondBlock = Pred;<br>
> - continue;<br>
> - }<br>
> -<br>
> - // Only conditional branches are allowed beyond this point.<br>
> - assert(PBI->isConditional());<br>
> -<br>
> - // Condition's unique use should be the branch instruction.<br>
> - Value *PC = PBI->getCondition();<br>
> - if (!PC || !PC->hasOneUse())<br>
> - return false;<br>
> -<br>
> - if (PP && Preds.count(PP)) {<br>
> - // These are internal condition blocks to be merged from, e.g.,<br>
> - // BB2 in both cases.<br>
> - // Should not be address-taken.<br>
> - if (Pred->hasAddressTaken())<br>
> - return false;<br>
> -<br>
> - // Instructions in the internal condition blocks should be safe<br>
> - // to hoist up.<br>
> - for (BasicBlock::iterator BI = Pred->begin(), BE = PBI; BI != BE;) {<br>
> - Instruction *CI = BI++;<br>
> - if (isa<PHINode>(CI) ||<br>
> - !isSafeToSpeculativelyExecute(CI))<br>
> - return false;<br>
> - }<br>
> - } else {<br>
> - // This is the condition block to be merged into, e.g. BB1 in<br>
> - // both cases.<br>
> - if (FirstCondBlock)<br>
> - return false;<br>
> - FirstCondBlock = Pred;<br>
> - }<br>
> -<br>
> - // Find whether BB is uniformly on the true (or false) path<br>
> - // for all of its predecessors.<br>
> - BasicBlock *PS1 = PBI->getSuccessor(0);<br>
> - BasicBlock *PS2 = PBI->getSuccessor(1);<br>
> - BasicBlock *PS = (PS1 == BB) ? PS2 : PS1;<br>
> - int CIdx = (PS1 == BB) ? 0 : 1;<br>
> -<br>
> - if (Idx == -1)<br>
> - Idx = CIdx;<br>
> - else if (CIdx != Idx)<br>
> - return false;<br>
> -<br>
> - // PS is the successor which is not BB. Check successors to identify<br>
> - // the last conditional branch.<br>
> - if (Preds.count(PS) == 0) {<br>
> - // Case 2.<br>
> - // BB must have an unique successor.<br>
> - TerminatorInst *TBB = BB->getTerminator();<br>
> - if (TBB->getNumSuccessors() != 1)<br>
> - return false;<br>
> -<br>
> - BasicBlock *SBB = TBB->getSuccessor(0);<br>
> - PHI = dyn_cast<PHINode>(SBB->begin());<br>
> - if (PHI)<br>
> - return false;<br>
> -<br>
> - // PS (BB4) should be BB's successor.<br>
> - if (SBB != PS)<br>
> - return false;<br>
> - LastCondBlock = Pred;<br>
> - } else {<br>
> - BranchInst *BPS = dyn_cast<BranchInst>(PS->getTerminator());<br>
> - if (BPS && BPS->isUnconditional()) {<br>
> - // Case 1: PS(BB3) should be an unconditional branch.<br>
> - LastCondBlock = Pred;<br>
> - }<br>
> - }<br>
> - }<br>
> -<br>
> - if (!FirstCondBlock || !LastCondBlock || (FirstCondBlock == LastCondBlock))<br>
> - return false;<br>
> -<br>
> - // Do the transformation.<br>
> - BasicBlock *CB;<br>
> - bool Iteration = true;<br>
> - BasicBlock *SaveInsertBB = Builder.GetInsertBlock();<br>
> - BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint();<br>
> - BranchInst *PBI = dyn_cast<BranchInst>(FirstCondBlock->getTerminator());<br>
> - Value *PC = PBI->getCondition();<br>
> - do {<br>
> - CB = PBI->getSuccessor(1 - Idx);<br>
> - // Delete the conditional branch.<br>
> - FirstCondBlock->getInstList().pop_back();<br>
> - FirstCondBlock->getInstList().splice(FirstCondBlock->end(), CB->getInstList());<br>
> - PBI = cast<BranchInst>(FirstCondBlock->getTerminator());<br>
> - Value *CC = PBI->getCondition();<br>
> - // Merge conditions.<br>
> - Builder.SetInsertPoint(PBI);<br>
> - Value *NC;<br>
> - if (Idx == 0)<br>
> - // Case 2, use parallel or.<br>
> - NC = Builder.CreateOr(PC, CC);<br>
> - else<br>
> - // Case 1, use parallel and.<br>
> - NC = Builder.CreateAnd(PC, CC);<br>
> -<br>
> - PBI->replaceUsesOfWith(CC, NC);<br>
> - PC = NC;<br>
> - if (CB == LastCondBlock)<br>
> - Iteration = false;<br>
> - // Remove internal conditional branches.<br>
> - CB->dropAllReferences();<br>
> - // make CB unreachable and let downstream to delete the block.<br>
> - new UnreachableInst(CB->getContext(), CB);<br>
> - } while (Iteration);<br>
> - if (SaveInsertBB)<br>
> - Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt);<br>
> - DEBUG(dbgs() << "Use parallel and/or in:\n" << *FirstCondBlock);<br>
> - return true;<br>
> -}<br>
> -<br>
> -/// Compare blocks from two if-regions, where \param Head1 is the entry of the<br>
> -/// 1st if-region. \param Head2 is the entry of the 2nd if-region. \param<br>
> -/// Block1 is a block in the 1st if-region to compare. \param Block2 is a block<br>
> -// in the 2nd if-region to compare. \returns true if \param Block1 and \param<br>
> -/// Block2 have identical instructions and do not have memory reference alias<br>
> -/// with \param Head2.<br>
> -///<br>
> -bool SimplifyCFGOpt::CompareIfRegionBlock(BasicBlock *Head1, BasicBlock *Head2,<br>
> - BasicBlock *Block1, BasicBlock *Block2) {<br>
> - TerminatorInst *PTI2 = Head2->getTerminator();<br>
> - Instruction *PBI2 = Head2->begin();<br>
> -<br>
> - bool eq1 = (Block1 == Head1);<br>
> - bool eq2 = (Block2 == Head2);<br>
> - if (eq1 || eq2) {<br>
> - // An empty then-path or else-path.<br>
> - return (eq1 == eq2);<br>
> - }<br>
> -<br>
> - // Check whether instructions in Block1 and Block2 are identical<br>
> - // and do not alias with instructions in Head2.<br>
> - BasicBlock::iterator iter1 = Block1->begin();<br>
> - BasicBlock::iterator end1 = Block1->getTerminator();<br>
> - BasicBlock::iterator iter2 = Block2->begin();<br>
> - BasicBlock::iterator end2 = Block2->getTerminator();<br>
> -<br>
> - while (1) {<br>
> - if (iter1 == end1) {<br>
> - if (iter2 != end2)<br>
> - return false;<br>
> - break;<br>
> - }<br>
> -<br>
> - if (!iter1->isIdenticalTo(iter2))<br>
> - return false;<br>
> -<br>
> - // Illegal to remove instructions with side effects except<br>
> - // non-volatile stores.<br>
> - if (iter1->mayHaveSideEffects()) {<br>
> - Instruction *CurI = &*iter1;<br>
> - StoreInst *SI = dyn_cast<StoreInst>(CurI);<br>
> - if (!SI || SI->isVolatile())<br>
> - return false;<br>
> - }<br>
> -<br>
> - // For simplicity and speed, data dependency check can be<br>
> - // avoided if read from memory doesn't exist.<br>
> - if (iter1->mayReadFromMemory())<br>
> - return false;<br>
> -<br>
> - if (iter1->mayWriteToMemory()) {<br>
> - for (BasicBlock::iterator BI = PBI2, BE = PTI2; BI != BE; ++BI) {<br>
> - if (BI->mayReadFromMemory() || BI->mayWriteToMemory()) {<br>
> - // Check alias with Head2.<br>
> - if (!AA || AA->alias(iter1, BI))<br>
> - return false;<br>
> - }<br>
> - }<br>
> - }<br>
> - ++iter1;<br>
> - ++iter2;<br>
> - }<br>
> -<br>
> - return true;<br>
> -}<br>
> -<br>
> -/// Check whether \param BB is the merge block of a if-region. If yes, check<br>
> -/// whether there exists an adjacent if-region upstream, the two if-regions<br>
> -/// contain identical instuctions and can be legally merged. \returns true if<br>
> -/// the two if-regions are merged.<br>
> -///<br>
> -/// From:<br>
> -/// if (a)<br>
> -/// statement;<br>
> -/// if (b)<br>
> -/// statement;<br>
> -///<br>
> -/// To:<br>
> -/// if (a || b)<br>
> -/// statement;<br>
> -///<br>
> -bool SimplifyCFGOpt::MergeIfRegion(BasicBlock *BB, IRBuilder<> &Builder,<br>
> - Pass *P) {<br>
> - BasicBlock *IfTrue2, *IfFalse2;<br>
> - Value *IfCond2 = GetIfCondition(BB, IfTrue2, IfFalse2);<br>
> - Instruction *CInst2 = dyn_cast_or_null<Instruction>(IfCond2);<br>
> - if (!CInst2)<br>
> - return false;<br>
> -<br>
> - BasicBlock *SecondEntryBlock = CInst2->getParent();<br>
> - if (SecondEntryBlock->hasAddressTaken())<br>
> - return false;<br>
> -<br>
> - BasicBlock *IfTrue1, *IfFalse1;<br>
> - Value *IfCond1 = GetIfCondition(SecondEntryBlock, IfTrue1, IfFalse1);<br>
> - Instruction *CInst1 = dyn_cast_or_null<Instruction>(IfCond1);<br>
> - if (!CInst1)<br>
> - return false;<br>
> -<br>
> - BasicBlock *FirstEntryBlock = CInst1->getParent();<br>
> -<br>
> - // Either then-path or else-path should be empty.<br>
> - if ((IfTrue1 != FirstEntryBlock) && (IfFalse1 != FirstEntryBlock))<br>
> - return false;<br>
> - if ((IfTrue2 != SecondEntryBlock) && (IfFalse2 != SecondEntryBlock))<br>
> - return false;<br>
> -<br>
> - TerminatorInst *PTI2 = SecondEntryBlock->getTerminator();<br>
> - Instruction *PBI2 = SecondEntryBlock->begin();<br>
> -<br>
> - if (!CompareIfRegionBlock(FirstEntryBlock, SecondEntryBlock, IfTrue1, IfTrue2))<br>
> - return false;<br>
> -<br>
> - if (!CompareIfRegionBlock(FirstEntryBlock, SecondEntryBlock, IfFalse1, IfFalse2))<br>
> - return false;<br>
> -<br>
> - // Check whether \param SecondEntryBlock has side-effect and is safe to speculate.<br>
> - for (BasicBlock::iterator BI = PBI2, BE = PTI2; BI != BE; ++BI) {<br>
> - Instruction *CI = BI;<br>
> - if (isa<PHINode>(CI) || CI->mayHaveSideEffects() ||<br>
> - !isSafeToSpeculativelyExecute(CI))<br>
> - return false;<br>
> - }<br>
> -<br>
> - // Merge \param SecondEntryBlock into \param FirstEntryBlock.<br>
> - FirstEntryBlock->getInstList().pop_back();<br>
> - FirstEntryBlock->getInstList().splice(FirstEntryBlock->end(), SecondEntryBlock->getInstList());<br>
> - BranchInst *PBI = dyn_cast<BranchInst>(FirstEntryBlock->getTerminator());<br>
> - Value *CC = PBI->getCondition();<br>
> - BasicBlock *SaveInsertBB = Builder.GetInsertBlock();<br>
> - BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint();<br>
> - Builder.SetInsertPoint(PBI);<br>
> - Value *NC = Builder.CreateOr(CInst1, CC);<br>
> - PBI->replaceUsesOfWith(CC, NC);<br>
> - if (SaveInsertBB)<br>
> - Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt);<br>
> -<br>
> - // Remove IfTrue1<br>
> - if (IfTrue1 != FirstEntryBlock) {<br>
> - IfTrue1->dropAllReferences();<br>
> - IfTrue1->eraseFromParent();<br>
> - }<br>
> -<br>
> - // Remove IfFalse1<br>
> - if (IfFalse1 != FirstEntryBlock) {<br>
> - IfFalse1->dropAllReferences();<br>
> - IfFalse1->eraseFromParent();<br>
> - }<br>
> -<br>
> - // Remove \param SecondEntryBlock<br>
> - SecondEntryBlock->dropAllReferences();<br>
> - SecondEntryBlock->eraseFromParent();<br>
> - DEBUG(dbgs() << "If conditions merged into:\n" << *FirstEntryBlock);<br>
> - return true;<br>
> -}<br>
> -<br>
> /// Check if passing a value to an instruction will cause undefined behavior.<br>
> static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I) {<br>
> Constant *C = dyn_cast<Constant>(V);<br>
> @@ -4584,11 +4080,6 @@ bool SimplifyCFGOpt::run(BasicBlock *BB)<br>
> return true;<br>
><br>
> IRBuilder<> Builder(BB);<br>
> - // Whether to optimize conditional branches.<br>
> - bool OptCB = (ParallelAndOr && AA && TTI.hasBranchDivergence());<br>
> -<br>
> - if (OptCB && SimplifyParallelAndOr(BB, Builder))<br>
> - return true;<br>
><br>
> // If there is a trivial two-entry PHI node in this basic block, and we can<br>
> // eliminate it, do so now.<br>
> @@ -4617,9 +4108,6 @@ bool SimplifyCFGOpt::run(BasicBlock *BB)<br>
> if (SimplifyIndirectBr(IBI)) return true;<br>
> }<br>
><br>
> - if (OptCB && MergeIfRegion(BB, Builder))<br>
> - return true;<br>
> -<br>
> return Changed;<br>
> }<br>
><br>
> @@ -4629,6 +4117,6 @@ bool SimplifyCFGOpt::run(BasicBlock *BB)<br>
> /// of the CFG. It returns true if a modification was made.<br>
> ///<br>
> bool llvm::SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,<br>
> - const DataLayout *TD, AliasAnalysis *AA) {<br>
> - return SimplifyCFGOpt(TTI, TD, AA).run(BB);<br>
> + const DataLayout *TD) {<br>
> + return SimplifyCFGOpt(TTI, TD).run(BB);<br>
> }<br>
><br>
> Copied: llvm/trunk/test/CodeGen/R600/parallelandifcollapse.ll (from r187754, llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll)<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/R600/parallelandifcollapse.ll?p2=llvm/trunk/test/CodeGen/R600/parallelandifcollapse.ll&p1=llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll&r1=187754&r2=187764&rev=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/R600/parallelandifcollapse.ll?p2=llvm/trunk/test/CodeGen/R600/parallelandifcollapse.ll&p1=llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll&r1=187754&r2=187764&rev=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/R600/parallelandifcollapse.ll Mon Aug 5 21:43:45 2013<br>
> @@ -1,14 +1,12 @@<br>
> ; Function Attrs: nounwind<br>
> -; RUN: opt < %s -mtriple=r600-unknown-linux-gnu -optimizecfg -basicaa -S | FileCheck %s<br>
> +; RUN: llc < %s -march=r600 -mcpu=redwood | FileCheck %s<br>
> ;<br>
> -; CFG optimization should use parallel-or mode to generate branch conditions and<br>
> -; then merge if-regions with the same bodies, which should result in 2 branches.<br>
> -; To see the assembly output without this transformation, remove -basicaa option.<br>
> +; CFG flattening should use parallel-and mode to generate branch conditions and<br>
> +; then merge if-regions with the same bodies.<br>
> ;<br>
> -; CHECK: or i1<br>
> -; CHECK-NEXT: br<br>
> -; CHECK: br<br>
> -; CHECK: ret<br>
> +; CHECK: AND_INT<br>
> +; CHECK-NEXT: AND_INT<br>
> +; CHECK-NEXT: OR_INT<br>
> define void @_Z9chk1D_512v() #0 {<br>
> entry:<br>
> %a0 = alloca i32, align 4<br>
><br>
> Copied: llvm/trunk/test/CodeGen/R600/parallelorifcollapse.ll (from r187754, llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll)<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/R600/parallelorifcollapse.ll?p2=llvm/trunk/test/CodeGen/R600/parallelorifcollapse.ll&p1=llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll&r1=187754&r2=187764&rev=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/R600/parallelorifcollapse.ll?p2=llvm/trunk/test/CodeGen/R600/parallelorifcollapse.ll&p1=llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll&r1=187754&r2=187764&rev=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/R600/parallelorifcollapse.ll Mon Aug 5 21:43:45 2013<br>
> @@ -1,14 +1,12 @@<br>
> ; Function Attrs: nounwind<br>
> -; RUN: opt < %s -mtriple=r600-unknown-linux-gnu -optimizecfg -basicaa -S | FileCheck %s<br>
> +; RUN: llc < %s -march=r600 -mcpu=redwood | FileCheck %s<br>
> ;<br>
> -; CFG optimization should use parallel-and mode to generate branch conditions and<br>
> -; then merge if-regions with the same bodies, which should result in 2 branches.<br>
> -; To see the assembly output without this transformation, remove -basicaa option.<br>
> -;<br>
> -; CHECK: or i1<br>
> -; CHECK-NEXT: br<br>
> -; CHECK: br<br>
> -; CHECK: ret<br>
> +; CFG flattening should use parallel-or to generate branch conditions and<br>
> +; then merge if-regions with the same bodies.<br>
> +;<br>
> +; CHECK: OR_INT<br>
> +; CHECK-NEXT: OR_INT<br>
> +; CHECK-NEXT: OR_INT<br>
> define void @_Z9chk1D_512v() #0 {<br>
> entry:<br>
> %a0 = alloca i32, align 4<br>
><br>
> Modified: llvm/trunk/test/Transforms/SimplifyCFG/R600/lit.local.cfg<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/R600/lit.local.cfg?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/R600/lit.local.cfg?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/SimplifyCFG/R600/lit.local.cfg (original)<br>
> +++ llvm/trunk/test/Transforms/SimplifyCFG/R600/lit.local.cfg Mon Aug 5 21:43:45 2013<br>
> @@ -1,6 +0,0 @@<br>
> -config.suffixes = ['.ll', '.c', '.cpp']<br>
> -<br>
> -targets = set(config.root.targets_to_build.split())<br>
> -if not 'R600' in targets:<br>
> - config.unsupported = True<br>
> -<br>
><br>
> Modified: llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll (original)<br>
> +++ llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelandifcollapse.ll Mon Aug 5 21:43:45 2013<br>
> @@ -1,63 +0,0 @@<br>
> -; Function Attrs: nounwind<br>
> -; RUN: opt < %s -mtriple=r600-unknown-linux-gnu -optimizecfg -basicaa -S | FileCheck %s<br>
> -;<br>
> -; CFG optimization should use parallel-and mode to generate branch conditions and<br>
> -; then merge if-regions with the same bodies, which should result in 2 branches.<br>
> -; To see the assembly output without this transformation, remove -basicaa option.<br>
> -;<br>
> -; CHECK: or i1<br>
> -; CHECK-NEXT: br<br>
> -; CHECK: br<br>
> -; CHECK: ret<br>
> -define void @_Z9chk1D_512v() #0 {<br>
> -entry:<br>
> - %a0 = alloca i32, align 4<br>
> - %b0 = alloca i32, align 4<br>
> - %c0 = alloca i32, align 4<br>
> - %d0 = alloca i32, align 4<br>
> - %a1 = alloca i32, align 4<br>
> - %b1 = alloca i32, align 4<br>
> - %c1 = alloca i32, align 4<br>
> - %d1 = alloca i32, align 4<br>
> - %data = alloca i32, align 4<br>
> - %0 = load i32* %a0, align 4<br>
> - %1 = load i32* %b0, align 4<br>
> - %cmp = icmp ne i32 %0, %1<br>
> - br i1 %cmp, label %land.lhs.true, label %if.else<br>
> -<br>
> -land.lhs.true: ; preds = %entry<br>
> - %2 = load i32* %c0, align 4<br>
> - %3 = load i32* %d0, align 4<br>
> - %cmp1 = icmp ne i32 %2, %3<br>
> - br i1 %cmp1, label %if.then, label %if.else<br>
> -<br>
> -if.then: ; preds = %land.lhs.true<br>
> - br label %if.end<br>
> -<br>
> -if.else: ; preds = %land.lhs.true, %entry<br>
> - store i32 1, i32* %data, align 4<br>
> - br label %if.end<br>
> -<br>
> -if.end: ; preds = %if.else, %if.then<br>
> - %4 = load i32* %a1, align 4<br>
> - %5 = load i32* %b1, align 4<br>
> - %cmp2 = icmp ne i32 %4, %5<br>
> - br i1 %cmp2, label %land.lhs.true3, label %if.else6<br>
> -<br>
> -land.lhs.true3: ; preds = %if.end<br>
> - %6 = load i32* %c1, align 4<br>
> - %7 = load i32* %d1, align 4<br>
> - %cmp4 = icmp ne i32 %6, %7<br>
> - br i1 %cmp4, label %if.then5, label %if.else6<br>
> -<br>
> -if.then5: ; preds = %land.lhs.true3<br>
> - br label %if.end7<br>
> -<br>
> -if.else6: ; preds = %land.lhs.true3, %if.end<br>
> - store i32 1, i32* %data, align 4<br>
> - br label %if.end7<br>
> -<br>
> -if.end7: ; preds = %if.else6, %if.then5<br>
> - ret void<br>
> -}<br>
> -<br>
><br>
> Modified: llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll (original)<br>
> +++ llvm/trunk/test/Transforms/SimplifyCFG/R600/parallelorifcollapse.ll Mon Aug 5 21:43:45 2013<br>
> @@ -1,56 +0,0 @@<br>
> -; Function Attrs: nounwind<br>
> -; RUN: opt < %s -mtriple=r600-unknown-linux-gnu -optimizecfg -basicaa -S | FileCheck %s<br>
> -;<br>
> -; CFG optimization should use parallel-or mode to generate branch conditions and<br>
> -; then merge if-regions with the same bodies, which should result in 2 branches.<br>
> -; To see the assembly output without this transformation, remove -basicaa option.<br>
> -;<br>
> -; CHECK: or i1<br>
> -; CHECK-NEXT: br<br>
> -; CHECK: br<br>
> -; CHECK: ret<br>
> -define void @_Z9chk1D_512v() #0 {<br>
> -entry:<br>
> - %a0 = alloca i32, align 4<br>
> - %b0 = alloca i32, align 4<br>
> - %c0 = alloca i32, align 4<br>
> - %d0 = alloca i32, align 4<br>
> - %a1 = alloca i32, align 4<br>
> - %b1 = alloca i32, align 4<br>
> - %c1 = alloca i32, align 4<br>
> - %d1 = alloca i32, align 4<br>
> - %data = alloca i32, align 4<br>
> - %0 = load i32* %a0, align 4<br>
> - %1 = load i32* %b0, align 4<br>
> - %cmp = icmp ne i32 %0, %1<br>
> - br i1 %cmp, label %land.lhs.true, label %if.end<br>
> -<br>
> -land.lhs.true: ; preds = %entry<br>
> - %2 = load i32* %c0, align 4<br>
> - %3 = load i32* %d0, align 4<br>
> - %cmp1 = icmp ne i32 %2, %3<br>
> - br i1 %cmp1, label %if.then, label %if.end<br>
> -<br>
> -if.then: ; preds = %land.lhs.true<br>
> - store i32 1, i32* %data, align 4<br>
> - br label %if.end<br>
> -<br>
> -if.end: ; preds = %if.then, %land.lhs.true, %entry<br>
> - %4 = load i32* %a1, align 4<br>
> - %5 = load i32* %b1, align 4<br>
> - %cmp2 = icmp ne i32 %4, %5<br>
> - br i1 %cmp2, label %land.lhs.true3, label %if.end6<br>
> -<br>
> -land.lhs.true3: ; preds = %if.end<br>
> - %6 = load i32* %c1, align 4<br>
> - %7 = load i32* %d1, align 4<br>
> - %cmp4 = icmp ne i32 %6, %7<br>
> - br i1 %cmp4, label %if.then5, label %if.end6<br>
> -<br>
> -if.then5: ; preds = %land.lhs.true3<br>
> - store i32 1, i32* %data, align 4<br>
> - br label %if.end6<br>
> -<br>
> -if.end6: ; preds = %if.then5, %land.lhs.true3, %if.end<br>
> - ret void<br>
> -}<br>
><br>
> Modified: llvm/trunk/test/Transforms/SimplifyCFG/lit.local.cfg<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/lit.local.cfg?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/lit.local.cfg?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/SimplifyCFG/lit.local.cfg (original)<br>
> +++ llvm/trunk/test/Transforms/SimplifyCFG/lit.local.cfg Mon Aug 5 21:43:45 2013<br>
> @@ -1 +0,0 @@<br>
> -config.suffixes = ['.ll', '.c', '.cpp']<br>
><br>
> Modified: llvm/trunk/tools/lto/LTOCodeGenerator.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto/LTOCodeGenerator.cpp?rev=187764&r1=187763&r2=187764&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto/LTOCodeGenerator.cpp?rev=187764&r1=187763&r2=187764&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/tools/lto/LTOCodeGenerator.cpp (original)<br>
> +++ llvm/trunk/tools/lto/LTOCodeGenerator.cpp Mon Aug 5 21:43:45 2013<br>
> @@ -118,7 +118,7 @@ void LTOCodeGenerator::initializeLTOPass<br>
> initializeGVNPass(R);<br>
> initializeMemCpyOptPass(R);<br>
> initializeDCEPass(R);<br>
> - initializeCFGCanonicalizePass(R);<br>
> + initializeCFGSimplifyPassPass(R);<br>
> }<br>
><br>
> bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) {<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br>Thanks,<br>--Serge<br>
</div>