[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