[llvm] [InstCombine] fold `gepi i8 %ptr, (srem x, y)` to `gepi i8 %ptr, (urem x, y)` if `y` is positive power-of-2 (PR #180148)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 6 02:39:38 PST 2026
================
@@ -3347,6 +3348,40 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
}
}
+ // srem -> (and/urem) for inbounds+nuw byte GEP ---
+ if (GEPEltType->isIntegerTy(8) && Indices.size() == 1 && GEP.isInBounds() &&
+ GEP.getNoWrapFlags().hasNoUnsignedWrap()) {
+
+ using namespace llvm::PatternMatch;
+
+ Value *X = nullptr;
+ Value *Y = nullptr;
+
+ // Match: idx = srem X, Y -- where Y is a power-of-two constant.
+ if (match(Indices[0], m_SRem(m_Value(X), m_Value(Y)))) {
+ if (isKnownToBeAPowerOfTwo(Y, false, &GEP)) {
+ // If GEP is inbounds+nuw, the offset cannot be negative
+ // -> srem by power-of-two can be treated as urem,
+ // and urem by power-of-two folds to 'and' later.
+ Instruction *OldIdxI = dyn_cast<Instruction>(Indices[0]);
+ Builder.SetInsertPoint(&GEP);
+ Value *NewIdx = Builder.CreateURem(X, Y, OldIdxI->getName());
+
+ auto *NewGEP = GetElementPtrInst::Create(
+ GEPEltType, PtrOp, {NewIdx}, GEP.getName(), GEP.getIterator());
+ NewGEP->setIsInBounds(GEP.isInBounds());
----------------
nikic wrote:
This is part of setNoWrapFlags already. But you can also pass it to the ctor.
https://github.com/llvm/llvm-project/pull/180148
More information about the llvm-commits
mailing list