diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -16,9 +16,9 @@ }; auto getAnalysis = [&FAM](Function &F) -> AnalysisResultsForFn { DominatorTree &DT = FAM.getResult(F); - return { - std::make_unique(F, DT, FAM.getResult(F)), - &DT, FAM.getCachedResult(F)}; + return {std::make_unique( + F, DT, FAM.getResult(F), true), + &DT, FAM.getCachedResult(F)}; }; if (!runIPSCCP(M, DL, GetTLI, getAnalysis)) @@ -59,8 +59,8 @@ return { std::make_unique( F, DT, - this->getAnalysis().getAssumptionCache( - F)), + this->getAnalysis().getAssumptionCache(F), + true), nullptr, // We cannot preserve the DT or PDT with the legacy pass nullptr}; // manager, so set them to nullptr. }; 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 @@ -1241,28 +1241,30 @@ Value *CopyOf = CB.getOperand(0); auto *PI = getPredicateInfoFor(&CB); auto *PBranch = dyn_cast_or_null(PI); - ValueLatticeElement OriginalVal = getValueState(CopyOf); + ValueLatticeElement OriginalValState = getValueState(CopyOf); if (!PI || !PBranch) { - mergeInValue(ValueState[&CB], &CB, OriginalVal); + mergeInValue(ValueState[&CB], &CB, OriginalValState); return; } // Everything below relies on the condition being a comparison. auto *Cmp = dyn_cast(PBranch->Condition); if (!Cmp) { - mergeInValue(ValueState[&CB], &CB, OriginalVal); + mergeInValue(ValueState[&CB], &CB, OriginalValState); return; } + Value *OriginalVal = PBranch->OriginalOp; Value *CmpOp0 = Cmp->getOperand(0); Value *CmpOp1 = Cmp->getOperand(1); - if (CopyOf != CmpOp0 && CopyOf != CmpOp1) { - mergeInValue(ValueState[&CB], &CB, OriginalVal); + // Bail out if neither of the operands matches the OriginalVal or CopyOf. + if (CmpOp0 != OriginalVal && CmpOp1 != OriginalVal) { + mergeInValue(ValueState[&CB], &CB, getValueState(CopyOf)); return; } auto Pred = Cmp->getPredicate(); - if (CmpOp0 != CopyOf) { + if (CmpOp1 == OriginalVal) { std::swap(CmpOp0, CmpOp1); Pred = Cmp->getSwappedPredicate(); } @@ -1273,27 +1275,41 @@ 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[&CB]; - if (CondVal.isConstantRange() || OriginalVal.isConstantRange()) { - auto NewCR = + ValueLatticeElement CopyOfVal = getValueState(CopyOf); + if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) { + auto ImposedCR = ConstantRange::getFull(DL.getTypeSizeInBits(CopyOf->getType())); // Get the range imposed by the condition. if (CondVal.isConstantRange()) - NewCR = ConstantRange::makeAllowedICmpRegion( + ImposedCR = ConstantRange::makeAllowedICmpRegion( Pred, CondVal.getConstantRange()); // 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())); + auto NewCR = ImposedCR; + // If the existing information is != x, do not use the information from + // a chained predicate, as the != x information is more likely to be + // helpful in practice. + if (CopyOfCR.getLower() - 1 == CopyOfCR.getUpper() && + CopyOf != OriginalVal) + NewCR = CopyOfCR; + else + NewCR = NewCR.intersectWith(CopyOfCR); addAdditionalUser(CmpOp1, &CB); // TODO: Actually filp MayIncludeUndef for the created range to false, @@ -1317,7 +1333,7 @@ return; } - return (void)mergeInValue(IV, &CB, OriginalVal); + return (void)mergeInValue(IV, &CB, OriginalValState); } } 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]])