diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -1250,15 +1250,18 @@ return; } + Value *OriginalVal = PBranch->OriginalOp; Value *CmpOp0 = Cmp->getOperand(0); Value *CmpOp1 = Cmp->getOperand(1); - if (CopyOf != CmpOp0 && CopyOf != CmpOp1) { + + // Bail out if neither of the operands matches the OriginalVal or CopyOf. + if (CmpOp0 != OriginalVal && CmpOp1 != OriginalVal) { mergeInValue(ValueState[I], I, getValueState(CopyOf)); return; } auto Pred = Cmp->getPredicate(); - if (CmpOp0 != CopyOf) { + if (CmpOp1 == OriginalVal) { std::swap(CmpOp0, CmpOp1); Pred = Cmp->getSwappedPredicate(); } @@ -1269,13 +1272,18 @@ return; } + // The code below relies on PredicateInfo only inserting copies for the + // true branch when the branch condition is an AND and only inserting + // copies for the false branch when the branch condition is an OR. This + // ensures we can intersect the range from the condition with the range of + // CopyOf. if (!PBranch->TrueEdge) Pred = CmpInst::getInversePredicate(Pred); ValueLatticeElement CondVal = getValueState(CmpOp1); ValueLatticeElement &IV = ValueState[I]; - ValueLatticeElement OriginalVal = getValueState(CopyOf); - if (CondVal.isConstantRange() || OriginalVal.isConstantRange()) { + ValueLatticeElement CopyOfVal = getValueState(CopyOf); + if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) { auto NewCR = ConstantRange::getFull(DL.getTypeSizeInBits(CopyOf->getType())); @@ -1286,11 +1294,11 @@ // Combine range info for the original value with the new range from the // condition. - auto OriginalCR = OriginalVal.isConstantRange() - ? OriginalVal.getConstantRange() - : ConstantRange::getFull( - DL.getTypeSizeInBits(CopyOf->getType())); - NewCR = NewCR.intersectWith(OriginalCR); + auto CopyOfCR = CopyOfVal.isConstantRange() + ? CopyOfVal.getConstantRange() + : ConstantRange::getFull( + DL.getTypeSizeInBits(CopyOf->getType())); + NewCR = NewCR.intersectWith(CopyOfCR); addAdditionalUser(CmpOp1, I); // TODO: Actually filp MayIncludeUndef for the created range to false, diff --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll --- a/llvm/test/Transforms/SCCP/conditions-ranges.ll +++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll @@ -814,14 +814,11 @@ ; CHECK-NEXT: [[BC:%.*]] = and i1 [[LT]], [[GT]] ; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: -; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 0 -; CHECK-NEXT: call void @use(i1 [[F_1]]) -; CHECK-NEXT: [[F_2:%.*]] = icmp eq i32 [[A]], 20 -; CHECK-NEXT: call void @use(i1 [[F_2]]) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) -; CHECK-NEXT: [[T_2:%.*]] = icmp ne i32 [[A]], 20 -; CHECK-NEXT: call void @use(i1 [[T_2]]) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21 @@ -899,10 +896,8 @@ ; CHECK: false: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) -; CHECK-NEXT: [[F_3:%.*]] = icmp ugt i32 [[A]], 100 -; CHECK-NEXT: call void @use(i1 [[F_3]]) -; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[A]], 100 -; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_1]]) @@ -1181,7 +1176,8 @@ ; CHECK-NEXT: [[BC:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[BC]], label [[BB139:%.*]], label [[BB122]] ; CHECK: bb139: -; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: [[TMP140:%.*]] = icmp eq i32 [[TMP136]], 0 +; CHECK-NEXT: call void @use(i1 [[TMP140]]) ; CHECK-NEXT: ret void ; bb11: ; preds = %bb1