From ce562622118c40d5a24a07960c15cd4912db0cbf Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 18 Nov 2010 17:05:13 +0000 Subject: [PATCH] Add support for PHI-translating sext, zext, and trunc instructions, enabling more PRE. PR8586. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119704 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/PHITransAddr.cpp | 44 ++++++++++++++++------------ test/Transforms/GVN/phi-translate.ll | 31 ++++++++++++++++++++ 2 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 test/Transforms/GVN/phi-translate.ll diff --git a/lib/Analysis/PHITransAddr.cpp b/lib/Analysis/PHITransAddr.cpp index a9ccab1f469..178d29e257d 100644 --- a/lib/Analysis/PHITransAddr.cpp +++ b/lib/Analysis/PHITransAddr.cpp @@ -20,9 +20,12 @@ using namespace llvm; static bool CanPHITrans(Instruction *Inst) { if (isa(Inst) || - isa(Inst) || isa(Inst)) return true; + + if (isa(Inst) && + Inst->isSafeToSpeculativelyExecute()) + return true; if (Inst->getOpcode() == Instruction::Add && isa(Inst->getOperand(1))) @@ -177,26 +180,29 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, // or because we just incorporated it into the expression). See if its // operands need to be phi translated, and if so, reconstruct it. - if (BitCastInst *BC = dyn_cast(Inst)) { - Value *PHIIn = PHITranslateSubExpr(BC->getOperand(0), CurBB, PredBB, DT); + if (CastInst *Cast = dyn_cast(Inst)) { + if (!Cast->isSafeToSpeculativelyExecute()) return 0; + Value *PHIIn = PHITranslateSubExpr(Cast->getOperand(0), CurBB, PredBB, DT); if (PHIIn == 0) return 0; - if (PHIIn == BC->getOperand(0)) - return BC; + if (PHIIn == Cast->getOperand(0)) + return Cast; // Find an available version of this cast. // Constants are trivial to find. if (Constant *C = dyn_cast(PHIIn)) - return AddAsInput(ConstantExpr::getBitCast(C, BC->getType())); + return AddAsInput(ConstantExpr::getCast(Cast->getOpcode(), + C, Cast->getType())); - // Otherwise we have to see if a bitcasted version of the incoming pointer + // Otherwise we have to see if a casted version of the incoming pointer // is available. If so, we can use it, otherwise we have to fail. for (Value::use_iterator UI = PHIIn->use_begin(), E = PHIIn->use_end(); UI != E; ++UI) { - if (BitCastInst *BCI = dyn_cast(*UI)) - if (BCI->getType() == BC->getType() && - (!DT || DT->dominates(BCI->getParent(), PredBB))) - return BCI; + if (CastInst *CastI = dyn_cast(*UI)) + if (CastI->getOpcode() == Cast->getOpcode() && + CastI->getType() == Cast->getType() && + (!DT || DT->dominates(CastI->getParent(), PredBB))) + return CastI; } return 0; } @@ -368,16 +374,18 @@ InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB, // instruction. Instruction *Inst = cast(InVal); - // Handle bitcast of PHI translatable value. - if (BitCastInst *BC = dyn_cast(Inst)) { - Value *OpVal = InsertPHITranslatedSubExpr(BC->getOperand(0), + // Handle cast of PHI translatable value. + if (CastInst *Cast = dyn_cast(Inst)) { + if (!Cast->isSafeToSpeculativelyExecute()) return 0; + Value *OpVal = InsertPHITranslatedSubExpr(Cast->getOperand(0), CurBB, PredBB, DT, NewInsts); if (OpVal == 0) return 0; - // Otherwise insert a bitcast at the end of PredBB. - BitCastInst *New = new BitCastInst(OpVal, InVal->getType(), - InVal->getName()+".phi.trans.insert", - PredBB->getTerminator()); + // Otherwise insert a cast at the end of PredBB. + CastInst *New = CastInst::Create(Cast->getOpcode(), + OpVal, InVal->getType(), + InVal->getName()+".phi.trans.insert", + PredBB->getTerminator()); NewInsts.push_back(New); return New; } diff --git a/test/Transforms/GVN/phi-translate.ll b/test/Transforms/GVN/phi-translate.ll new file mode 100644 index 00000000000..f10537e0c93 --- /dev/null +++ b/test/Transforms/GVN/phi-translate.ll @@ -0,0 +1,31 @@ +; RUN: opt -basicaa -gvn -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64" + +; CHECK: @foo +; CHECK: entry.end_crit_edge: +; CHECK: %n.pre = load i32* %q.phi.trans.insert +; CHECK: then: +; CHECK: store i32 %z +; CHECK: end: +; CHECK: %n = phi i32 [ %n.pre, %entry.end_crit_edge ], [ %z, %then ] +; CHECK: ret i32 %n + +@G = external global [100 x i32] +define i32 @foo(i32 %x, i32 %z) { +entry: + %tobool = icmp eq i32 %x, 0 + br i1 %tobool, label %end, label %then + +then: + %i = sext i32 %x to i64 + %p = getelementptr [100 x i32]* @G, i64 0, i64 %i + store i32 %z, i32* %p + br label %end + +end: + %j = sext i32 %x to i64 + %q = getelementptr [100 x i32]* @G, i64 0, i64 %j + %n = load i32* %q + ret i32 %n +}