Value *V = LVI->getConstantOnEdge(Incoming, P->getIncomingBlock(i), BB, P);
- // Look if the incoming value is a select with a constant but LVI tells us
- // that the incoming 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.
+ // Look if the incoming value is a select with a scalar condition for which
+ // LVI can tells us the value. In that case replace the incoming value with
+ // the appropriate value of the select. This often allows us to remove the
+ // select later.
if (!V) {
SelectInst *SI = dyn_cast<SelectInst>(Incoming);
if (!SI) continue;
- Constant *C = dyn_cast<Constant>(SI->getFalseValue());
- if (!C) continue;
+ Value *Condition = SI->getCondition();
+ if (!Condition->getType()->isVectorTy()) {
+ if (Constant *C = LVI->getConstantOnEdge(Condition, P->getIncomingBlock(i), BB, P)) {
+ if (C == ConstantInt::getTrue(Condition->getType())) {
+ V = SI->getTrueValue();
+ } else {
+ V = SI->getFalseValue();
+ }
+ // Once LVI learns to handle vector types, we could also add support
+ // for vector type constants that are not all zeroes or all ones.
+ }
+ }
- if (LVI->getPredicateOnEdge(ICmpInst::ICMP_EQ, SI, C,
- P->getIncomingBlock(i), BB, P) !=
- LazyValueInfo::False)
- continue;
+ // Look if the select has a constant but LVI tells us that the incoming
+ // 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.
+ if (!V) {
+ Constant *C = dyn_cast<Constant>(SI->getFalseValue());
+ if (!C) continue;
+
+ if (LVI->getPredicateOnEdge(ICmpInst::ICMP_EQ, SI, C,
+ P->getIncomingBlock(i), BB, P) !=
+ LazyValueInfo::False)
+ continue;
+ V = SI->getTrueValue();
+ }
DEBUG(dbgs() << "CVP: Threading PHI over " << *SI << '\n');
- V = SI->getTrueValue();
}
P->setIncomingValue(i, V);
--- /dev/null
+; RUN: opt < %s -correlated-propagation -S | FileCheck %s
+
+; CHECK-LABEL: @simple(
+define i8 @simple(i1) {
+entry:
+ %s = select i1 %0, i8 0, i8 1
+ br i1 %0, label %then, label %else
+
+then:
+; CHECK: ret i8 0
+ %a = phi i8 [ %s, %entry ]
+ ret i8 %a
+
+else:
+; CHECK: ret i8 1
+ %b = phi i8 [ %s, %entry ]
+ ret i8 %b
+}
+
+; CHECK-LABEL: @loop(
+define void @loop(i32) {
+entry:
+ br label %loop
+
+loop:
+ %idx = phi i32 [ %0, %entry ], [ %sel, %loop ]
+; CHECK: %idx = phi i32 [ %0, %entry ], [ %2, %loop ]
+ %1 = icmp eq i32 %idx, 0
+ %2 = add i32 %idx, -1
+ %sel = select i1 %1, i32 0, i32 %2
+ br i1 %1, label %out, label %loop
+
+out:
+ ret void
+}
+
+; CHECK-LABEL: @not_correlated(
+define i8 @not_correlated(i1, i1) {
+entry:
+ %s = select i1 %0, i8 0, i8 1
+ br i1 %1, label %then, label %else
+
+then:
+; CHECK: ret i8 %s
+ %a = phi i8 [ %s, %entry ]
+ ret i8 %a
+
+else:
+; CHECK: ret i8 %s
+ %b = phi i8 [ %s, %entry ]
+ ret i8 %b
+}
+