From a0b59f6bd23afaeba923b94f46838cffd5218a12 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Fri, 27 Aug 2010 23:31:36 +0000 Subject: [PATCH] Add a prototype of a new peephole optimizing pass that uses LazyValue info to simplify PHIs and select's. This pass addresses the missed optimizations from PR2581 and PR4420. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@112325 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/LinkAllPasses.h | 1 + include/llvm/Transforms/Scalar.h | 6 ++ lib/Transforms/Scalar/ValuePropagation.cpp | 113 +++++++++++++++++++++ test/Transforms/ValuePropagation/dg.exp | 3 + test/Transforms/ValuePropagation/phi.ll | 17 ++++ test/Transforms/ValuePropagation/select.ll | 25 +++++ 6 files changed, 165 insertions(+) create mode 100644 lib/Transforms/Scalar/ValuePropagation.cpp create mode 100644 test/Transforms/ValuePropagation/dg.exp create mode 100644 test/Transforms/ValuePropagation/phi.ll create mode 100644 test/Transforms/ValuePropagation/select.ll diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 805db4ebf95..78428f92415 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -149,6 +149,7 @@ namespace { (void) llvm::createLintPass(); (void) llvm::createSinkingPass(); (void) llvm::createLowerAtomicPass(); + (void) llvm::createValuePropagationPass(); (void)new llvm::IntervalPartition(); (void)new llvm::FindUsedTypes(); diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 2278717d377..12f2a9812f1 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -343,6 +343,12 @@ FunctionPass *createSinkingPass(); // Pass *createLowerAtomicPass(); +//===----------------------------------------------------------------------===// +// +// ValuePropagation - Propagate CFG-derived value information +// +Pass *createValuePropagationPass(); + } // End llvm namespace #endif diff --git a/lib/Transforms/Scalar/ValuePropagation.cpp b/lib/Transforms/Scalar/ValuePropagation.cpp new file mode 100644 index 00000000000..c1384bb1d9b --- /dev/null +++ b/lib/Transforms/Scalar/ValuePropagation.cpp @@ -0,0 +1,113 @@ +//===- ValuePropagation.cpp - Propagate information derived control flow --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Value Propagation pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "value-propagation" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/LazyValueInfo.h" +#include "llvm/Transforms/Utils/Local.h" +using namespace llvm; + +namespace { + class ValuePropagation : public FunctionPass { + LazyValueInfo *LVI; + + bool processSelect(SelectInst *SI); + bool processPHI(PHINode *P); + + public: + static char ID; + ValuePropagation(): FunctionPass(ID) { } + + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + } + }; +} + +char ValuePropagation::ID = 0; +INITIALIZE_PASS(ValuePropagation, "value-propagation", + "Value Propagation", false, false); + +// Public interface to the Value Propagation pass +Pass *llvm::createValuePropagationPass() { + return new ValuePropagation(); +} + +bool ValuePropagation::processSelect(SelectInst *S) { + Constant *C = LVI->getConstant(S->getOperand(0), S->getParent()); + if (!C) return false; + + ConstantInt *CI = dyn_cast(C); + if (!CI) return false; + + if (CI->isZero()) { + S->replaceAllUsesWith(S->getOperand(2)); + S->eraseFromParent(); + } else if (CI->isOne()) { + S->replaceAllUsesWith(S->getOperand(1)); + S->eraseFromParent(); + } else { + assert(0 && "Select on constant is neither 0 nor 1?"); + } + + return true; +} + +bool ValuePropagation::processPHI(PHINode *P) { + bool changed = false; + + BasicBlock *BB = P->getParent(); + for (unsigned i = 0; i < P->getNumIncomingValues(); ++i) { + Constant *C = LVI->getConstantOnEdge(P->getIncomingValue(i), + P->getIncomingBlock(i), + BB); + if (!C || C == P->getIncomingValue(i)) continue; + + P->setIncomingValue(i, C); + changed = true; + } + + if (Value *ConstVal = P->hasConstantValue()) { + P->replaceAllUsesWith(ConstVal); + P->eraseFromParent(); + changed = true; + } + + return changed; +} + +bool ValuePropagation::runOnFunction(Function &F) { + LVI = &getAnalysis(); + + bool changed = false; + + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) { + Instruction *II = BI++; + if (SelectInst *SI = dyn_cast(II)) + changed |= processSelect(SI); + else if (PHINode *P = dyn_cast(II)) + changed |= processPHI(P); + } + + if (changed) + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) + SimplifyInstructionsInBlock(FI); + + return changed; +} \ No newline at end of file diff --git a/test/Transforms/ValuePropagation/dg.exp b/test/Transforms/ValuePropagation/dg.exp new file mode 100644 index 00000000000..de42dad163f --- /dev/null +++ b/test/Transforms/ValuePropagation/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.ll]] diff --git a/test/Transforms/ValuePropagation/phi.ll b/test/Transforms/ValuePropagation/phi.ll new file mode 100644 index 00000000000..f150876525c --- /dev/null +++ b/test/Transforms/ValuePropagation/phi.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -value-propagation -S | FileCheck %s +; PR2581 + +; CHECK: @run +define i32 @run(i1 %C) nounwind { + br i1 %C, label %exit, label %body + +body: ; preds = %0 +; CHECK-NOT: select + %A = select i1 %C, i32 10, i32 11 ; [#uses=1] +; CHECK: ret i32 11 + ret i32 %A + +exit: ; preds = %0 +; CHECK: ret i32 10 + ret i32 10 +} \ No newline at end of file diff --git a/test/Transforms/ValuePropagation/select.ll b/test/Transforms/ValuePropagation/select.ll new file mode 100644 index 00000000000..02acc8fc76d --- /dev/null +++ b/test/Transforms/ValuePropagation/select.ll @@ -0,0 +1,25 @@ +; RUN: opt < %s -value-propagation -S | FileCheck %s +; PR4420 + +declare i1 @ext() +; CHECK: @foo +define i1 @foo() { +entry: + %cond = tail call i1 @ext() ; [#uses=2] + br i1 %cond, label %bb1, label %bb2 + +bb1: ; preds = %entry + %cond2 = tail call i1 @ext() ; [#uses=1] + br i1 %cond2, label %bb3, label %bb2 + +bb2: ; preds = %bb1, %entry +; CHECK-NOT: phi i1 + %cond_merge = phi i1 [ %cond, %entry ], [ false, %bb1 ] ; [#uses=1] +; CHECK: ret i1 false + ret i1 %cond_merge + +bb3: ; preds = %bb1 + %res = tail call i1 @ext() ; [#uses=1] +; CHECK: ret i1 %res + ret i1 %res +} \ No newline at end of file