From 21f8ac235ec3c1312f835c988a7c2b456a702806 Mon Sep 17 00:00:00 2001 From: Xin Tong Date: Mon, 1 May 2017 15:34:17 +0000 Subject: [PATCH] [JumpThread] Do RAUW in case Cond folds to a constant in the CFG Summary: [JumpThread] Do RAUW in case Cond folds to a constant in the CFG Reviewers: sanjoy Reviewed By: sanjoy Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D32407 llvm-svn: 301804 --- llvm/lib/Transforms/Scalar/JumpThreading.cpp | 32 +++++++++--- .../Transforms/JumpThreading/fold-not-thread.ll | 57 ++++++++++++++++++++++ 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp index 340b0d0..d9717628 100644 --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -1250,6 +1250,8 @@ bool JumpThreadingPass::ProcessThreadableEdges(Value *Cond, BasicBlock *BB, BasicBlock *OnlyDest = nullptr; BasicBlock *MultipleDestSentinel = (BasicBlock*)(intptr_t)~0ULL; + Constant *OnlyVal = nullptr; + Constant *MultipleVal = (Constant *)(intptr_t)~0ULL; for (const auto &PredValue : PredValues) { BasicBlock *Pred = PredValue.second; @@ -1277,10 +1279,17 @@ bool JumpThreadingPass::ProcessThreadableEdges(Value *Cond, BasicBlock *BB, } // If we have exactly one destination, remember it for efficiency below. - if (PredToDestList.empty()) + if (PredToDestList.empty()) { OnlyDest = DestBB; - else if (OnlyDest != DestBB) - OnlyDest = MultipleDestSentinel; + OnlyVal = Val; + } else { + if (OnlyDest != DestBB) + OnlyDest = MultipleDestSentinel; + // It possible we have same destination, but different value, e.g. default + // case in switchinst. + if (Val != OnlyVal) + OnlyVal = MultipleVal; + } PredToDestList.push_back(std::make_pair(Pred, DestBB)); } @@ -1310,11 +1319,18 @@ bool JumpThreadingPass::ProcessThreadableEdges(Value *Cond, BasicBlock *BB, // If the condition is now dead due to the removal of the old terminator, // erase it. - auto *CondInst = dyn_cast(Cond); - if (CondInst && CondInst->use_empty()) - CondInst->eraseFromParent(); - // FIXME: in case this instruction is defined in the current BB and it - // resolves to a single value from all predecessors, we can do RAUW. + if (auto *CondInst = dyn_cast(Cond)) { + if (CondInst->use_empty() && !CondInst->mayHaveSideEffects()) + CondInst->eraseFromParent(); + else if (OnlyVal && OnlyVal != MultipleVal && + CondInst->getParent() == BB) { + // If we just learned Cond is the same value for all uses of the + // condition, replace it with a constant value + CondInst->replaceAllUsesWith(OnlyVal); + if (!CondInst->mayHaveSideEffects()) + CondInst->eraseFromParent(); + } + } return true; } } diff --git a/llvm/test/Transforms/JumpThreading/fold-not-thread.ll b/llvm/test/Transforms/JumpThreading/fold-not-thread.ll index 75deca6..3bd7106 100644 --- a/llvm/test/Transforms/JumpThreading/fold-not-thread.ll +++ b/llvm/test/Transforms/JumpThreading/fold-not-thread.ll @@ -133,3 +133,60 @@ L3: ret void } +; Make sure we can do the RAUW for %add... +; +; CHECK-LABEL: @rauw_if_possible( +; CHECK: call void @f4(i32 96) +define void @rauw_if_possible(i32 %value) nounwind { +entry: + %cmp = icmp eq i32 %value, 32 + br i1 %cmp, label %L0, label %L3 +L0: + call i32 @f2() + call i32 @f2() + %add = add i32 %value, 64 + switch i32 %add, label %L3 [ + i32 32, label %L1 + i32 96, label %L2 + ] + +L1: + call void @f3() + ret void +L2: + call void @f4(i32 %add) + ret void +L3: + call void @f3() + ret void +} + +; Make sure we can NOT do the RAUW for %add... +; +; CHECK-LABEL: @rauw_if_possible2( +; CHECK: call void @f4(i32 %add) +define void @rauw_if_possible2(i32 %value) nounwind { +entry: + %cmp = icmp eq i32 %value, 32 + %add = add i32 %value, 64 + br i1 %cmp, label %L0, label %L2 +L0: + call i32 @f2() + call i32 @f2() + switch i32 %add, label %L3 [ + i32 32, label %L1 + i32 96, label %L2 + ] + +L1: + call void @f3() + ret void +L2: + call void @f4(i32 %add) + ret void +L3: + call void @f3() + ret void +} + + -- 2.7.4