[llvm] [AggressiveInstCombine] Expand strchr/memchr with small constant strings (PR #98501)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 12 03:02:36 PDT 2024


================
@@ -1103,6 +1108,81 @@ void StrNCmpInliner::inlineCompare(Value *LHS, StringRef RHS, uint64_t N,
   }
 }
 
+/// Convert strchr/memchr with a small constant string into a switch
+static bool foldStrChr(CallInst *Call, LibFunc Func, DomTreeUpdater *DTU,
+                       const DataLayout &DL) {
+  assert((Func == LibFunc_strchr || Func == LibFunc_memchr) &&
+         "Unexpected LibFunc");
+  if (isa<Constant>(Call->getArgOperand(1)))
+    return false;
+
+  StringRef Str;
+  Value *Base = Call->getArgOperand(0);
+  if (!getConstantStringInfo(Base, Str, /*TrimAtNul=*/Func == LibFunc_strchr))
+    return false;
+
+  uint64_t N = Str.size();
+  if (Func == LibFunc_memchr) {
+    if (auto *ConstInt = dyn_cast<ConstantInt>(Call->getArgOperand(2)))
+      N = std::min(N, ConstInt->getZExtValue());
----------------
goldsteinn wrote:

I would say you should either go all in on "Reading past `Str.size()` is UB" or drop this.

All in being, if `Call->getArgOperand(2) > Str.size()` we *must* find a match so the result cannot be `NULL` (drop default case in the switch). Or (IMO the better choice for now) conservatively don't do this transform if `Call->getArgOperand(2) > Str.size()`.

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


More information about the llvm-commits mailing list