diff --git a/lib/Analysis/LazyValueInfo.cpp b/lib/Analysis/LazyValueInfo.cpp index 0d1d34e0cb4..cdeaaa36ada 100644 --- a/lib/Analysis/LazyValueInfo.cpp +++ b/lib/Analysis/LazyValueInfo.cpp @@ -389,6 +389,8 @@ namespace { Value *Val, BasicBlock *BB); bool solveBlockValuePHINode(LVILatticeVal &BBLV, PHINode *PN, BasicBlock *BB); + bool solveBlockValueSelect(LVILatticeVal &BBLV, + SelectInst *S, BasicBlock *BB); bool solveBlockValueConstantRange(LVILatticeVal &BBLV, Instruction *BBI, BasicBlock *BB); void mergeAssumeBlockValueConstantRange(Value *Val, LVILatticeVal &BBLV, @@ -587,6 +589,13 @@ bool LazyValueInfoCache::solveBlockValue(Value *Val, BasicBlock *BB) { return true; } + if (auto *SI = dyn_cast(BBI)) { + if (!solveBlockValueSelect(Res, SI, BB)) + return false; + insertResult(Val, BB, Res); + return true; + } + // If this value is a nonnull pointer, record it's range and bailout. PointerType *PT = dyn_cast(BBI->getType()); if (PT && isKnownNonNull(BBI)) { @@ -809,6 +818,46 @@ void LazyValueInfoCache::mergeAssumeBlockValueConstantRange(Value *Val, } } +bool LazyValueInfoCache::solveBlockValueSelect(LVILatticeVal &BBLV, + SelectInst *SI, BasicBlock *BB) { + + // Recurse on our inputs if needed + if (!hasBlockValue(SI->getTrueValue(), BB)) { + if (pushBlockValue(std::make_pair(BB, SI->getTrueValue()))) + return false; + BBLV.markOverdefined(); + return true; + } + LVILatticeVal TrueVal = getBlockValue(SI->getTrueValue(), BB); + // If we hit overdefined, don't ask more queries. We want to avoid poisoning + // extra slots in the table if we can. + if (TrueVal.isOverdefined()) { + BBLV.markOverdefined(); + return true; + } + + if (!hasBlockValue(SI->getFalseValue(), BB)) { + if (pushBlockValue(std::make_pair(BB, SI->getFalseValue()))) + return false; + BBLV.markOverdefined(); + return true; + } + LVILatticeVal FalseVal = getBlockValue(SI->getFalseValue(), BB); + // If we hit overdefined, don't ask more queries. We want to avoid poisoning + // extra slots in the table if we can. + if (FalseVal.isOverdefined()) { + BBLV.markOverdefined(); + return true; + } + + LVILatticeVal Result; // Start Undefined. + Result.mergeIn(TrueVal, DL); + Result.mergeIn(FalseVal, DL); + assert(!Result.isOverdefined() && "Should have exited previously"); + BBLV = Result; + return true; +} + bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV, Instruction *BBI, BasicBlock *BB) { diff --git a/test/Transforms/CorrelatedValuePropagation/select.ll b/test/Transforms/CorrelatedValuePropagation/select.ll index be44bdcd921..bad8e6b74f5 100644 --- a/test/Transforms/CorrelatedValuePropagation/select.ll +++ b/test/Transforms/CorrelatedValuePropagation/select.ll @@ -73,3 +73,72 @@ if.end: ret i32 %sel ; CHECK: ret i32 1 } + +define i1 @test1(i32* %p, i1 %unknown) { +; CHECK-LABEL: @test1 + %pval = load i32, i32* %p + %cmp1 = icmp slt i32 %pval, 255 + br i1 %cmp1, label %next, label %exit + +next: + %min = select i1 %unknown, i32 %pval, i32 5 + ;; TODO: This pointless branch shouldn't be neccessary + br label %next2 +next2: +; CHECK-LABEL: next2: +; CHECK: ret i1 false + %res = icmp eq i32 %min, 255 + ret i1 %res + +exit: +; CHECK-LABEL: exit: +; CHECK: ret i1 true + ret i1 true +} + +; Check that we take a conservative meet +define i1 @test2(i32* %p, i32 %qval, i1 %unknown) { +; CHECK-LABEL: test2 + %pval = load i32, i32* %p + %cmp1 = icmp slt i32 %pval, 255 + br i1 %cmp1, label %next, label %exit + +next: + %min = select i1 %unknown, i32 %pval, i32 %qval + ;; TODO: This pointless branch shouldn't be neccessary + br label %next2 +next2: +; CHECK-LABEL: next2 +; CHECK: ret i1 %res + %res = icmp eq i32 %min, 255 + ret i1 %res + +exit: +; CHECK-LABEL: exit: +; CHECK: ret i1 true + ret i1 true +} + +; Same as @test2, but for the opposite select input +define i1 @test3(i32* %p, i32 %qval, i1 %unknown) { +; CHECK-LABEL: test3 + %pval = load i32, i32* %p + %cmp1 = icmp slt i32 %pval, 255 + br i1 %cmp1, label %next, label %exit + +next: + %min = select i1 %unknown, i32 %qval, i32 %pval + ;; TODO: This pointless branch shouldn't be neccessary + br label %next2 +next2: +; CHECK-LABEL: next2 +; CHECK: ret i1 %res + %res = icmp eq i32 %min, 255 + ret i1 %res + +exit: +; CHECK-LABEL: exit: +; CHECK: ret i1 true + ret i1 true +} +