diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -252,17 +252,35 @@ // value can never be that constant. In that case replace the incoming // value with the other value of the select. This often allows us to // remove the select later. + + // The "false" case if (!V) { Constant *C = dyn_cast(SI->getFalseValue()); - if (!C) continue; + if (C) { + if (LVI->getPredicateOnEdge(ICmpInst::ICMP_EQ, SI, C, + P->getIncomingBlock(i), BB, + P) != LazyValueInfo::False) + continue; + V = SI->getTrueValue(); + } + } - if (LVI->getPredicateOnEdge(ICmpInst::ICMP_EQ, SI, C, - P->getIncomingBlock(i), BB, P) != - LazyValueInfo::False) - continue; - V = SI->getTrueValue(); + // The "true" case, + // similar to the select "false" case, but try the select "true" value + if (!V) { + Constant *C = dyn_cast(SI->getTrueValue()); + if (C) { + if (LVI->getPredicateOnEdge(ICmpInst::ICMP_EQ, SI, C, + P->getIncomingBlock(i), BB, + P) != LazyValueInfo::False) + continue; + V = SI->getFalseValue(); + } } + if (!V) + continue; + LLVM_DEBUG(dbgs() << "CVP: Threading PHI over " << *SI << '\n'); } diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/select_cond.ll b/llvm/test/Transforms/CorrelatedValuePropagation/select_cond.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/CorrelatedValuePropagation/select_cond.ll @@ -0,0 +1,65 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s + +declare i32* @f(i32*) + +; "false" case for CorrelatedValuePropagation +define void @loop1(i32* %x, i32* %y) { +; CHECK-LABEL: @loop1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[F:%.*]], [[LOOP]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[F]] = tail call i32* @f(i32* [[PHI]]) +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32* [[F]], [[Y:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32* [[F]], i32* null +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32* [[SEL]], null +; CHECK-NEXT: br i1 [[CMP2]], label [[RETURN:%.*]], label [[LOOP]] +; CHECK: return: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %phi = phi i32* [ %sel, %loop ], [ %x, %entry ] + %f = tail call i32* @f(i32* %phi) + %cmp1 = icmp ne i32* %f, %y + %sel = select i1 %cmp1, i32* %f, i32* null + %cmp2 = icmp eq i32* %sel, null + br i1 %cmp2, label %return, label %loop + +return: + ret void +} + + +; "true" case for CorrelatedValuePropagation +define void @loop2(i32* %x, i32* %y) { +; CHECK-LABEL: @loop2( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[F:%.*]], [[LOOP]] ], [ [[X:%.*]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[F]] = tail call i32* @f(i32* [[PHI]]) +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32* [[F]], [[Y:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i32* null, i32* [[F]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32* [[SEL]], null +; CHECK-NEXT: br i1 [[CMP2]], label [[RETURN:%.*]], label [[LOOP]] +; CHECK: return: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %phi = phi i32* [ %sel, %loop ], [ %x, %entry ] + %f = tail call i32* @f(i32* %phi) + %cmp1 = icmp eq i32* %f, %y + %sel = select i1 %cmp1, i32* null, i32* %f + %cmp2 = icmp eq i32* %sel, null + br i1 %cmp2, label %return, label %loop + +return: + ret void +}