diff options
| author | Mingming Liu <mingmingl@google.com> | 2025-09-10 15:25:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 15:25:31 -0700 |
| commit | 1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch) | |
| tree | 57f4b1f313c8cf74eed8819870f39c36ea263c68 /llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | |
| parent | 898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff) | |
| parent | b8cefcb601ddaa18482555c4ff363c01a270c2fe (diff) | |
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index eb4332fbc095..9467463d39c0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1993,6 +1993,63 @@ Value *InstCombinerImpl::foldSelectWithConstOpToBinOp(ICmpInst *Cmp, return BinOp; } +/// Folds: +/// %a_sub = call @llvm.usub.sat(x, IntConst1) +/// %b_sub = call @llvm.usub.sat(y, IntConst2) +/// %or = or %a_sub, %b_sub +/// %cmp = icmp eq %or, 0 +/// %sel = select %cmp, 0, MostSignificantBit +/// into: +/// %a_sub' = usub.sat(x, IntConst1 - MostSignificantBit) +/// %b_sub' = usub.sat(y, IntConst2 - MostSignificantBit) +/// %or = or %a_sub', %b_sub' +/// %and = and %or, MostSignificantBit +/// Likewise, for vector arguments as well. +static Instruction *foldICmpUSubSatWithAndForMostSignificantBitCmp( + SelectInst &SI, ICmpInst *ICI, InstCombiner::BuilderTy &Builder) { + if (!SI.hasOneUse() || !ICI->hasOneUse()) + return nullptr; + CmpPredicate Pred; + Value *A, *B; + const APInt *Constant1, *Constant2; + if (!match(SI.getCondition(), + m_ICmp(Pred, + m_OneUse(m_Or(m_OneUse(m_Intrinsic<Intrinsic::usub_sat>( + m_Value(A), m_APInt(Constant1))), + m_OneUse(m_Intrinsic<Intrinsic::usub_sat>( + m_Value(B), m_APInt(Constant2))))), + m_Zero()))) + return nullptr; + + Value *TrueVal = SI.getTrueValue(); + Value *FalseVal = SI.getFalseValue(); + if (!(Pred == ICmpInst::ICMP_EQ && + (match(TrueVal, m_Zero()) && match(FalseVal, m_SignMask()))) || + (Pred == ICmpInst::ICMP_NE && + (match(TrueVal, m_SignMask()) && match(FalseVal, m_Zero())))) + return nullptr; + + auto *Ty = A->getType(); + unsigned BW = Constant1->getBitWidth(); + APInt MostSignificantBit = APInt::getSignMask(BW); + + // Anything over MSB is negative + if (Constant1->isNonNegative() || Constant2->isNonNegative()) + return nullptr; + + APInt AdjAP1 = *Constant1 - MostSignificantBit + 1; + APInt AdjAP2 = *Constant2 - MostSignificantBit + 1; + + auto *Adj1 = ConstantInt::get(Ty, AdjAP1); + auto *Adj2 = ConstantInt::get(Ty, AdjAP2); + + Value *NewA = Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, A, Adj1); + Value *NewB = Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, B, Adj2); + Value *Or = Builder.CreateOr(NewA, NewB); + Constant *MSBConst = ConstantInt::get(Ty, MostSignificantBit); + return BinaryOperator::CreateAnd(Or, MSBConst); +} + /// Visit a SelectInst that has an ICmpInst as its first operand. Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI) { @@ -2009,6 +2066,9 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI, if (Instruction *NewSel = tryToReuseConstantFromSelectInComparison(SI, *ICI, *this)) return NewSel; + if (Instruction *Folded = + foldICmpUSubSatWithAndForMostSignificantBitCmp(SI, ICI, Builder)) + return Folded; // NOTE: if we wanted to, this is where to detect integer MIN/MAX bool Changed = false; @@ -2315,7 +2375,7 @@ Instruction *InstCombinerImpl::foldSelectExtConst(SelectInst &Sel) { // If the constant is the same after truncation to the smaller type and // extension to the original type, we can narrow the select. Type *SelType = Sel.getType(); - Constant *TruncC = getLosslessTrunc(C, SmallType, ExtOpcode); + Constant *TruncC = getLosslessInvCast(C, SmallType, ExtOpcode, DL); if (TruncC && ExtInst->hasOneUse()) { Value *TruncCVal = cast<Value>(TruncC); if (ExtInst == Sel.getFalseValue()) |
