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 @@ -1237,15 +1237,23 @@ 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. + // TODO: In some cases PredicateBranch::OriginalOp does not match any + // operand of the condition, due to the operands of the condition being + // renamed. This should be fixed in PredicateInfo, as currently we miss + // out on some cases we could optimize. + if (CmpOp0 != OriginalVal && CmpOp0 != CopyOf && CmpOp1 != OriginalVal && + CmpOp1 != CopyOf) { mergeInValue(ValueState[I], I, getValueState(CopyOf)); return; } auto Pred = Cmp->getPredicate(); - if (CmpOp0 != CopyOf) { + if (CmpOp1 == OriginalVal || CmpOp1 == CopyOf) { std::swap(CmpOp0, CmpOp1); Pred = Cmp->getSwappedPredicate(); } @@ -1256,13 +1264,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())); @@ -1273,11 +1286,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]])