diff options
author | gaynor-anthropic <gaynor@anthropic.com> | 2025-06-17 00:52:18 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-17 09:52:18 +0200 |
commit | 632151fbeea972f4aa3c14921eca1e45c07646f3 (patch) | |
tree | ad1d41a4263a8f55b468c243715b85ae9eb58066 /llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | |
parent | bb70023cbfecf7880e4cc89966947ef475e070e9 (diff) | |
download | llvm-632151fbeea972f4aa3c14921eca1e45c07646f3.zip llvm-632151fbeea972f4aa3c14921eca1e45c07646f3.tar.gz llvm-632151fbeea972f4aa3c14921eca1e45c07646f3.tar.bz2 |
InstCombine: improve optimizations for ceiling division with no overflow (#142869)
Fixes #142497.
Alive2: https://alive2.llvm.org/ce/z/CeaHaH
The contents of this pull request were substantially written using
claude-code. I've reviewed to the best of my ability (it's been years
since I did any compilers work).
---------
Co-authored-by: Yingwei Zheng <dtcxzyw@qq.com>
Co-authored-by: Nikita Popov <github@npopov.com>
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index c1ce364..0a3837f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1787,6 +1787,34 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) { if (Instruction *Ashr = foldAddToAshr(I)) return Ashr; + // Ceiling division by power-of-2: + // (X >> log2(N)) + zext(X & (N-1) != 0) --> (X + (N-1)) >> log2(N) + // This is valid when adding (N-1) to X doesn't overflow. + { + Value *X; + const APInt *ShiftAmt, *Mask; + CmpPredicate Pred; + + // Match: (X >> C) + zext((X & Mask) != 0) + // or: zext((X & Mask) != 0) + (X >> C) + if (match(&I, m_c_Add(m_OneUse(m_LShr(m_Value(X), m_APInt(ShiftAmt))), + m_ZExt(m_SpecificICmp( + ICmpInst::ICMP_NE, + m_And(m_Deferred(X), m_LowBitMask(Mask)), + m_ZeroInt())))) && + Mask->popcount() == *ShiftAmt) { + + // Check if X + Mask doesn't overflow + Constant *MaskC = ConstantInt::get(X->getType(), *Mask); + if (willNotOverflowUnsignedAdd(X, MaskC, I)) { + // (X + Mask) >> ShiftAmt + Value *Add = Builder.CreateNUWAdd(X, MaskC); + return BinaryOperator::CreateLShr( + Add, ConstantInt::get(X->getType(), *ShiftAmt)); + } + } + } + // (~X) + (~Y) --> -2 - (X + Y) { // To ensure we can save instructions we need to ensure that we consume both |