Index: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp +++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp @@ -1250,6 +1250,8 @@ 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 @@ } // 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 @@ // 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; } } Index: llvm/trunk/test/Transforms/JumpThreading/fold-not-thread.ll =================================================================== --- llvm/trunk/test/Transforms/JumpThreading/fold-not-thread.ll +++ llvm/trunk/test/Transforms/JumpThreading/fold-not-thread.ll @@ -133,3 +133,60 @@ 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 +} + +