[llvm] [InstCombine] Fold icmp(constants[x]) when the range of x is given (PR #67093)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 2 06:38:48 PST 2024


================
@@ -285,40 +277,47 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
 
   // Now that we've scanned the entire array, emit our new comparison(s).  We
   // order the state machines in complexity of the generated code.
-  Value *Idx = GEP->getOperand(2);
-
-  // If the index is larger than the pointer offset size of the target, truncate
-  // the index down like the GEP would do implicitly.  We don't have to do this
-  // for an inbounds GEP because the index can't be out of range.
-  if (!GEP->isInBounds()) {
-    Type *PtrIdxTy = DL.getIndexType(GEP->getType());
-    unsigned OffsetSize = PtrIdxTy->getIntegerBitWidth();
-    if (Idx->getType()->getPrimitiveSizeInBits().getFixedValue() > OffsetSize)
-      Idx = Builder.CreateTrunc(Idx, PtrIdxTy);
-  }
 
-  // If inbounds keyword is not present, Idx * ElementSize can overflow.
-  // Let's assume that ElementSize is 2 and the wanted value is at offset 0.
+  // If inbounds keyword is not present, Idx * LongestStep can overflow.
+  // Let's assume that LongestStep is 2 and the wanted value is at offset 0.
   // Then, there are two possible values for Idx to match offset 0:
   // 0x00..00, 0x80..00.
   // Emitting 'icmp eq Idx, 0' isn't correct in this case because the
   // comparison is false if Idx was 0x80..00.
   // We need to erase the highest countTrailingZeros(ElementSize) bits of Idx.
-  unsigned ElementSize =
-      DL.getTypeAllocSize(Init->getType()->getArrayElementType());
   auto MaskIdx = [&](Value *Idx) {
-    if (!GEP->isInBounds() && llvm::countr_zero(ElementSize) != 0) {
+    if (!GEP->isInBounds() && OffsetStep.countr_zero() != 0) {
       Value *Mask = ConstantInt::get(Idx->getType(), -1);
-      Mask = Builder.CreateLShr(Mask, llvm::countr_zero(ElementSize));
+      Mask = Builder.CreateLShr(Mask, OffsetStep.countr_zero());
       Idx = Builder.CreateAnd(Idx, Mask);
     }
     return Idx;
   };
 
+  // Build the index expression lazily.
+  auto LazyGetIndex = [&](Value *CurIdx) -> Value * {
+    if (CurIdx)
+      return CurIdx;
+
+    // Initial bias for index. For example, when we fold cmp(GV[x + 3], C) into
+    // idx < 3, we actually get x + 3 < 3
+    Value *Bias = ConstantInt::get(
+        PtrIdxTy, (ConstantOffset - BeginOffset).sdiv(OffsetStep));
+    uint64_t IdxBitWidth = PtrIdxTy->getScalarSizeInBits();
+
+    auto [Var, Coefficient] = VariableOffsets.front();
+    uint64_t VarBitWidth = Var->getType()->getScalarSizeInBits();
+    assert("GEP indices do not get canonicalized to the index type" &&
+           VarBitWidth == IdxBitWidth);
----------------
nikic wrote:

You should check this condition at the start of the transform and bail out. While it is canonicalized, there's no guarantee that the GEP is canonicalized at this point yet.

https://github.com/llvm/llvm-project/pull/67093


More information about the llvm-commits mailing list