Skip to content

Revert "[Transforms] LoopIdiomRecognize recognize strlen and wcslen (#108985)" #131405

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 14, 2025

Conversation

mustartt
Copy link
Member

This reverts commit bf6357f.

@mustartt
Copy link
Member Author

#108985

@llvmbot
Copy link
Member

llvmbot commented Mar 14, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Henry Jiang (mustartt)

Changes

This reverts commit bf6357f.


Patch is 56.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131405.diff

7 Files Affected:

  • (modified) llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h (-6)
  • (modified) llvm/include/llvm/Transforms/Utils/BuildLibCalls.h (-6)
  • (modified) llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp (+5-306)
  • (modified) llvm/lib/Transforms/Utils/BuildLibCalls.cpp (-9)
  • (removed) llvm/test/Transforms/LoopIdiom/strlen.ll (-614)
  • (removed) llvm/test/Transforms/LoopIdiom/wcslen16.ll (-126)
  • (removed) llvm/test/Transforms/LoopIdiom/wcslen32.ll (-134)
diff --git a/llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h b/llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
index 241a3fc109360..0c6406d861851 100644
--- a/llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
+++ b/llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
@@ -34,12 +34,6 @@ struct DisableLIRP {
 
   /// When true, Memcpy is disabled.
   static bool Memcpy;
-
-  /// When true, Strlen is disabled.
-  static bool Strlen;
-
-  /// When true, Wcslen is disabled.
-  static bool Wcslen;
 };
 
 /// Performs Loop Idiom Recognize Pass.
diff --git a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
index 50f695dbe6c07..a8fb38e726004 100644
--- a/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
@@ -93,12 +93,6 @@ namespace llvm {
   Value *emitStrLen(Value *Ptr, IRBuilderBase &B, const DataLayout &DL,
                     const TargetLibraryInfo *TLI);
 
-  /// Emit a call to the wcslen function to the builder, for the specified
-  /// pointer. Ptr is required to be some pointer type, and the return value has
-  /// 'size_t' type.
-  Value *emitWcsLen(Value *Ptr, IRBuilderBase &B, const DataLayout &DL,
-                    const TargetLibraryInfo *TLI);
-
   /// Emit a call to the strdup function to the builder, for the specified
   /// pointer. Ptr is required to be some pointer type, and the return value has
   /// 'i8*' type.
diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index 22d1165b37b83..2462ec33e0c20 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -20,7 +20,8 @@
 //
 // TODO List:
 //
-// Future loop memory idioms to recognize: memcmp, etc.
+// Future loop memory idioms to recognize:
+//   memcmp, strlen, etc.
 //
 // This could recognize common matrix multiplies and dot product idioms and
 // replace them with calls to BLAS (if linked in??).
@@ -32,7 +33,6 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
@@ -97,7 +97,6 @@ using namespace llvm;
 STATISTIC(NumMemSet, "Number of memset's formed from loop stores");
 STATISTIC(NumMemCpy, "Number of memcpy's formed from loop load+stores");
 STATISTIC(NumMemMove, "Number of memmove's formed from loop load+stores");
-STATISTIC(NumStrLen, "Number of strlen's and wcslen's formed from loop loads");
 STATISTIC(
     NumShiftUntilBitTest,
     "Number of uncountable loops recognized as 'shift until bitttest' idiom");
@@ -127,26 +126,6 @@ static cl::opt<bool, true>
                       cl::location(DisableLIRP::Memcpy), cl::init(false),
                       cl::ReallyHidden);
 
-bool DisableLIRP::Strlen;
-static cl::opt<bool, true>
-    DisableLIRPStrlen("disable-loop-idiom-strlen",
-                      cl::desc("Proceed with loop idiom recognize pass, but do "
-                               "not convert loop(s) to strlen."),
-                      cl::location(DisableLIRP::Strlen), cl::init(false),
-                      cl::ReallyHidden);
-
-/// Some target libraries have a significant call overhead for `wcslen`,
-/// which can degrade performance when the input string is not long enough
-/// to justify the cost. To avoid unnecessary performance penalties,
-/// we disable it by default.
-bool DisableLIRP::Wcslen;
-static cl::opt<bool, true>
-    EnableLIRPWcslen("enable-loop-idiom-wcslen",
-                     cl::desc("Proceed with loop idiom recognize pass, "
-                              "enable conversion of loop(s) to wcslen."),
-                     cl::location(DisableLIRP::Wcslen), cl::init(true),
-                     cl::ReallyHidden);
-
 static cl::opt<bool> UseLIRCodeSizeHeurs(
     "use-lir-code-size-heurs",
     cl::desc("Use loop idiom recognition code size heuristics when compiling "
@@ -267,7 +246,6 @@ class LoopIdiomRecognize {
 
   bool recognizeShiftUntilBitTest();
   bool recognizeShiftUntilZero();
-  bool recognizeAndInsertStrLen();
 
   /// @}
 };
@@ -1516,17 +1494,7 @@ bool LoopIdiomRecognize::runOnNoncountableLoop() {
 
   return recognizePopcount() || recognizeAndInsertFFS() ||
          recognizeShiftUntilBitTest() || recognizeShiftUntilZero() ||
-         recognizeShiftUntilLessThan() || recognizeAndInsertStrLen();
-}
-
-/// Check if a Value is either a nullptr or a constant int zero
-static bool isZeroConstant(const Value *Val) {
-  if (isa<ConstantPointerNull>(Val))
-    return true;
-  const ConstantInt *CmpZero = dyn_cast<ConstantInt>(Val);
-  if (!CmpZero || !CmpZero->isZero())
-    return false;
-  return true;
+         recognizeShiftUntilLessThan();
 }
 
 /// Check if the given conditional branch is based on the comparison between
@@ -1544,7 +1512,8 @@ static Value *matchCondition(BranchInst *BI, BasicBlock *LoopEntry,
   if (!Cond)
     return nullptr;
 
-  if (!isZeroConstant(Cond->getOperand(1)))
+  ConstantInt *CmpZero = dyn_cast<ConstantInt>(Cond->getOperand(1));
+  if (!CmpZero || !CmpZero->isZero())
     return nullptr;
 
   BasicBlock *TrueSucc = BI->getSuccessor(0);
@@ -1560,276 +1529,6 @@ static Value *matchCondition(BranchInst *BI, BasicBlock *LoopEntry,
   return nullptr;
 }
 
-namespace {
-
-class StrlenVerifier {
-public:
-  explicit StrlenVerifier(const Loop *CurLoop, ScalarEvolution *SE,
-                          const TargetLibraryInfo *TLI)
-      : CurLoop(CurLoop), SE(SE), TLI(TLI) {}
-
-  bool isValidStrlenIdiom() {
-    // Give up if the loop has multiple blocks, multiple backedges, or
-    // multiple exit blocks
-    if (CurLoop->getNumBackEdges() != 1 || CurLoop->getNumBlocks() != 1 ||
-        !CurLoop->getUniqueExitBlock())
-      return false;
-
-    // It should have a preheader and a branch instruction.
-    BasicBlock *Preheader = CurLoop->getLoopPreheader();
-    if (!Preheader)
-      return false;
-
-    BranchInst *EntryBI = dyn_cast<BranchInst>(Preheader->getTerminator());
-    if (!EntryBI)
-      return false;
-
-    // The loop exit must be conditioned on an icmp with 0 the null terminator.
-    // The icmp operand has to be a load on some SSA reg that increments
-    // by 1 in the loop.
-    BasicBlock *LoopBody = *CurLoop->block_begin();
-
-    // Skip if the body is too big as it most likely is not a strlen idiom.
-    if (!LoopBody || LoopBody->size() >= 15)
-      return false;
-
-    BranchInst *LoopTerm = dyn_cast<BranchInst>(LoopBody->getTerminator());
-    Value *LoopCond = matchCondition(LoopTerm, LoopBody);
-    if (!LoopCond)
-      return false;
-
-    LoadInst *LoopLoad = dyn_cast<LoadInst>(LoopCond);
-    if (!LoopLoad || LoopLoad->getPointerAddressSpace() != 0)
-      return false;
-
-    OperandType = LoopLoad->getType();
-    if (!OperandType || !OperandType->isIntegerTy())
-      return false;
-
-    // See if the pointer expression is an AddRec with constant step a of form
-    // ({n,+,a}) where a is the width of the char type.
-    Value *IncPtr = LoopLoad->getPointerOperand();
-    const SCEVAddRecExpr *LoadEv =
-        dyn_cast<SCEVAddRecExpr>(SE->getSCEV(IncPtr));
-    if (!LoadEv || LoadEv->getLoop() != CurLoop || !LoadEv->isAffine())
-      return false;
-    LoadBaseEv = LoadEv->getStart();
-
-    LLVM_DEBUG({
-      dbgs() << "pointer load scev: ";
-      LoadEv->print(outs());
-      dbgs() << "\n";
-    });
-
-    const SCEVConstant *Step =
-        dyn_cast<SCEVConstant>(LoadEv->getStepRecurrence(*SE));
-    if (!Step)
-      return false;
-
-    unsigned StepSize = 0;
-    StepSizeCI = dyn_cast<ConstantInt>(Step->getValue());
-    if (!StepSizeCI)
-      return false;
-    StepSize = StepSizeCI->getZExtValue();
-
-    // Verify that StepSize is consistent with platform char width.
-    OpWidth = OperandType->getIntegerBitWidth();
-    unsigned WcharSize = TLI->getWCharSize(*LoopLoad->getModule());
-    if (OpWidth != StepSize * 8)
-      return false;
-    if (OpWidth != 8 && OpWidth != 16 && OpWidth != 32)
-      return false;
-    if (OpWidth >= 16)
-      if (OpWidth != WcharSize * 8)
-        return false;
-
-    // Scan every instruction in the loop to ensure there are no side effects.
-    for (Instruction &I : *LoopBody)
-      if (I.mayHaveSideEffects())
-        return false;
-
-    BasicBlock *LoopExitBB = CurLoop->getExitBlock();
-    if (!LoopExitBB)
-      return false;
-
-    for (PHINode &PN : LoopExitBB->phis()) {
-      if (!SE->isSCEVable(PN.getType()))
-        return false;
-
-      const SCEV *Ev = SE->getSCEV(&PN);
-      if (!Ev)
-        return false;
-
-      LLVM_DEBUG({
-        dbgs() << "loop exit phi scev: ";
-        Ev->print(dbgs());
-        dbgs() << "\n";
-      });
-
-      // Since we verified that the loop trip count will be a valid strlen
-      // idiom, we can expand all lcssa phi with {n,+,1} as (n + strlen) and use
-      // SCEVExpander materialize the loop output.
-      const SCEVAddRecExpr *AddRecEv = dyn_cast<SCEVAddRecExpr>(Ev);
-      if (!AddRecEv || !AddRecEv->isAffine())
-        return false;
-
-      // We only want RecAddExpr with recurrence step that is constant. This
-      // is good enough for all the idioms we want to recognize. Later we expand
-      // and materialize the recurrence as {base,+,a} -> (base + a * strlen)
-      if (!dyn_cast<SCEVConstant>(AddRecEv->getStepRecurrence(*SE)))
-        return false;
-    }
-
-    return true;
-  }
-
-public:
-  const Loop *CurLoop;
-  ScalarEvolution *SE;
-  const TargetLibraryInfo *TLI;
-
-  unsigned OpWidth;
-  ConstantInt *StepSizeCI;
-  const SCEV *LoadBaseEv;
-  Type *OperandType;
-};
-
-} // namespace
-
-/// The Strlen Idiom we are trying to detect has the following structure
-///
-/// preheader:
-///   ...
-///   br label %body, ...
-///
-/// body:
-///   ... ; %0 is incremented by a gep
-///   %1 = load i8, ptr %0, align 1
-///   %2 = icmp eq i8 %1, 0
-///   br i1 %2, label %exit, label %body
-///
-/// exit:
-///   %lcssa = phi [%0, %body], ...
-///
-/// We expect the strlen idiom to have a load of a character type that
-/// is compared against '\0', and such load pointer operand must have scev
-/// expression of the form {%str,+,c} where c is a ConstantInt of the
-/// appropiate character width for the idiom, and %str is the base of the string
-/// And, that all lcssa phis have the form {...,+,n} where n is a constant,
-///
-/// When transforming the output of the strlen idiom, the lccsa phi are
-/// expanded using SCEVExpander as {base scev,+,a} -> (base scev + a * strlen)
-/// and all subsequent uses are replaced. For example,
-///
-/// \code{.c}
-///     const char* base = str;
-///     while (*str != '\0')
-///         ++str;
-///     size_t result = str - base;
-/// \endcode
-///
-/// will be transformed as follows: The idiom will be replaced by a strlen
-/// computation to compute the address of the null terminator of the string.
-///
-/// \code{.c}
-///     const char* base = str;
-///     const char* end = base + strlen(str);
-///     size_t result = end - base;
-/// \endcode
-///
-/// In the case we index by an induction variable, as long as the induction
-/// variable has a constant int increment, we can replace all such indvars
-/// with the closed form computation of strlen
-///
-/// \code{.c}
-///     size_t i = 0;
-///     while (str[i] != '\0')
-///         ++i;
-///     size_t result = i;
-/// \endcode
-///
-/// Will be replaced by
-///
-/// \code{.c}
-///     size_t i = 0 + strlen(str);
-///     size_t result = i;
-/// \endcode
-///
-bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
-  if (DisableLIRP::All)
-    return false;
-
-  StrlenVerifier Verifier(CurLoop, SE, TLI);
-
-  if (!Verifier.isValidStrlenIdiom())
-    return false;
-
-  BasicBlock *Preheader = CurLoop->getLoopPreheader();
-  BasicBlock *LoopExitBB = CurLoop->getExitBlock();
-
-  IRBuilder<> Builder(Preheader->getTerminator());
-  SCEVExpander Expander(*SE, Preheader->getModule()->getDataLayout(),
-                        "strlen_idiom");
-  Value *MaterialzedBase = Expander.expandCodeFor(
-      Verifier.LoadBaseEv, Verifier.LoadBaseEv->getType(),
-      Builder.GetInsertPoint());
-
-  Value *StrLenFunc = nullptr;
-  if (Verifier.OpWidth == 8) {
-    if (!isLibFuncEmittable(Preheader->getModule(), TLI, LibFunc_strlen))
-      return false;
-    StrLenFunc = emitStrLen(MaterialzedBase, Builder, *DL, TLI);
-  } else {
-    if (!isLibFuncEmittable(Preheader->getModule(), TLI, LibFunc_wcslen) &&
-        !DisableLIRP::Wcslen)
-      return false;
-    StrLenFunc = emitWcsLen(MaterialzedBase, Builder, *DL, TLI);
-  }
-  assert(StrLenFunc && "Failed to emit strlen function.");
-
-  const SCEV *StrlenEv = SE->getSCEV(StrLenFunc);
-  SmallVector<PHINode *, 4> Cleanup;
-  for (PHINode &PN : LoopExitBB->phis()) {
-    // We can now materialize the loop output as all phi have scev {base,+,a}.
-    // We expand the phi as:
-    //   %strlen = call i64 @strlen(%str)
-    //   %phi.new = base expression + step * %strlen
-    const SCEV *Ev = SE->getSCEV(&PN);
-    const SCEVAddRecExpr *AddRecEv = dyn_cast<SCEVAddRecExpr>(Ev);
-    const SCEVConstant *Step =
-        dyn_cast<SCEVConstant>(AddRecEv->getStepRecurrence(*SE));
-    const SCEV *Base = AddRecEv->getStart();
-
-    // It is safe to truncate to base since if base is narrower than size_t
-    // the equivalent user code will have to truncate anyways.
-    const SCEV *NewEv = SE->getAddExpr(
-        Base, SE->getMulExpr(Step, SE->getTruncateOrSignExtend(
-                                       StrlenEv, Base->getType())));
-
-    Value *MaterializedPHI = Expander.expandCodeFor(NewEv, NewEv->getType(),
-                                                    Builder.GetInsertPoint());
-    Expander.clear();
-    PN.replaceAllUsesWith(MaterializedPHI);
-    Cleanup.push_back(&PN);
-  }
-
-  // All LCSSA Loop Phi are dead, the left over dead loop body can be cleaned
-  // up by later passes
-  for (PHINode *PN : Cleanup)
-    RecursivelyDeleteDeadPHINode(PN);
-  SE->forgetLoop(CurLoop);
-
-  ++NumStrLen;
-  LLVM_DEBUG(dbgs() << "  Formed strlen idiom: " << *StrLenFunc << "\n");
-  ORE.emit([&]() {
-    return OptimizationRemark(DEBUG_TYPE, "recognizeAndInsertStrLen",
-                              CurLoop->getStartLoc(), Preheader)
-           << "Transformed " << StrLenFunc->getName() << " loop idiom";
-  });
-
-  return true;
-}
-
 /// Check if the given conditional branch is based on an unsigned less-than
 /// comparison between a variable and a constant, and if the comparison is false
 /// the control yields to the loop entry. If the branch matches the behaviour,
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 24eefc91117b4..2301be6977cef 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1582,15 +1582,6 @@ Value *llvm::emitStrLen(Value *Ptr, IRBuilderBase &B, const DataLayout &DL,
   return emitLibCall(LibFunc_strlen, SizeTTy, CharPtrTy, Ptr, B, TLI);
 }
 
-Value *llvm::emitWcsLen(Value *Ptr, IRBuilderBase &B, const DataLayout &DL,
-                        const TargetLibraryInfo *TLI) {
-  assert(Ptr && Ptr->getType()->isPointerTy() &&
-         "Argument to wcslen intrinsic must be a pointer.");
-  Type *PtrTy = B.getPtrTy();
-  Type *SizeTTy = getSizeTTy(B, TLI);
-  return emitLibCall(LibFunc_wcslen, SizeTTy, PtrTy, Ptr, B, TLI);
-}
-
 Value *llvm::emitStrDup(Value *Ptr, IRBuilderBase &B,
                         const TargetLibraryInfo *TLI) {
   Type *CharPtrTy = B.getPtrTy();
diff --git a/llvm/test/Transforms/LoopIdiom/strlen.ll b/llvm/test/Transforms/LoopIdiom/strlen.ll
deleted file mode 100644
index 137a17f541cd4..0000000000000
--- a/llvm/test/Transforms/LoopIdiom/strlen.ll
+++ /dev/null
@@ -1,614 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -passes='loop(loop-idiom),verify' < %s -S | FileCheck %s
-
-declare void @other()
-declare void @use(ptr)
-declare void @usei(i32)
-declare void @usel(i64)
-
-; size_t basic_strlen(const char* str) {
-;     while (*str != '\0') {
-;         ++str;
-;     }
-;     return str - base;
-; }
-define i64 @valid_basic_strlen(ptr %str) {
-; CHECK-LABEL: define i64 @valid_basic_strlen(
-; CHECK-SAME: ptr [[STR:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    [[STRLEN:%.*]] = call i64 @strlen(ptr [[STR]])
-; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[STR]], i64 [[STRLEN]]
-; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
-; CHECK:       [[WHILE_COND]]:
-; CHECK-NEXT:    [[STR_ADDR_0:%.*]] = phi ptr [ [[STR]], %[[ENTRY]] ], [ [[INCDEC_PTR:%.*]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[STR_ADDR_0]], align 1
-; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i8 [[TMP0]], 0
-; CHECK-NEXT:    [[INCDEC_PTR]] = getelementptr i8, ptr [[STR_ADDR_0]], i64 1
-; CHECK-NEXT:    br i1 [[CMP_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_COND]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[SCEVGEP]] to i64
-; CHECK-NEXT:    [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[STR]] to i64
-; CHECK-NEXT:    [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
-; CHECK-NEXT:    ret i64 [[SUB_PTR_SUB]]
-;
-entry:
-  br label %while.cond
-
-while.cond:
-  %str.addr.0 = phi ptr [ %str, %entry ], [ %incdec.ptr, %while.cond ]
-  %0 = load i8, ptr %str.addr.0, align 1
-  %cmp.not = icmp eq i8 %0, 0
-  %incdec.ptr = getelementptr i8, ptr %str.addr.0, i64 1
-  br i1 %cmp.not, label %while.end, label %while.cond
-
-while.end:
-  %sub.ptr.lhs.cast = ptrtoint ptr %str.addr.0 to i64
-  %sub.ptr.rhs.cast = ptrtoint ptr %str to i64
-  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
-  ret i64 %sub.ptr.sub
-}
-
-; int valid_basic_strlen_rotated(const char* str) {
-;     const char* base = str;
-;     if (!*str) return 0;
-;     do {
-;         ++str;
-;     } while (*str);
-;     return str - base;
-; }
-define i32 @valid_basic_strlen_rotated(ptr %str) {
-; CHECK-LABEL: define i32 @valid_basic_strlen_rotated(
-; CHECK-SAME: ptr [[STR:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[STR]], align 1
-; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i8 [[TMP0]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label %[[CLEANUP:.*]], label %[[DO_BODY_PREHEADER:.*]]
-; CHECK:       [[DO_BODY_PREHEADER]]:
-; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[STR]], i64 1
-; CHECK-NEXT:    [[STRLEN:%.*]] = call i64 @strlen(ptr [[SCEVGEP]])
-; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[STRLEN]], 1
-; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[STR]], i64 [[TMP1]]
-; CHECK-NEXT:    br label %[[DO_BODY:.*]]
-; CHECK:       [[DO_BODY]]:
-; CHECK-NEXT:    [[STR_ADDR_0:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], %[[DO_BODY]] ], [ [[STR]], %[[DO_BODY_PREHEADER]] ]
-; CHECK-NEXT:    [[INCDEC_PTR]] = getelementptr inbounds nuw i8, ptr [[STR_ADDR_0]], i64 1
-; CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[INCDEC_PTR]], align 1
-; CHECK-NEXT:    [[TOBOOL1_NOT:%.*]] = icmp eq i8 [[TMP2]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL1_NOT]], label %[[DO_END:.*]], label %[[DO_BODY]]
-; CHECK:       [[DO_END]]:
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[SCEVGEP1]] to i64
-; CHECK-NEXT:    [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[STR]] to i64
-; CHECK-NEXT:    [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
-; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[SUB_PTR_SUB]] to i32
-; CHECK-NEXT:    br label %[[CLEANUP]]
-; CHECK:       [[CLEANUP]]:
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CONV]], %[[DO_END]] ], [ 0, %[[ENTRY]] ]
-; CHECK-NEXT:    ret i32 [[RETVAL_0]]
-;
-entry:
-  %0 = load i8, ptr %str, align 1
-  %tobool.not = icmp eq i8 %0, 0
-  br i1 %tobool.not, label %cleanup, label %do.body
-
-do.body:
-  %str.addr.0 = phi ptr [ %incdec.ptr, %do.body ], [ %str, %entry ]
-  %incdec.ptr = getelementptr inbounds nuw i8, ptr %str.addr.0, i64 1
-  %1 = load i8, ptr %incdec.ptr, align 1
-  %tobool1.not = icmp eq i8 %1, 0
-  br i1 %tobool1.not, label %do.end, label %do.body
-
-do.end:
-  %sub.ptr.lhs.cast = ptrtoint ptr %incdec.ptr to i64
-  %sub.ptr.rhs.cast = ptrtoint p...
[truncated]

@mustartt mustartt merged commit 5b2a881 into llvm:main Mar 14, 2025
8 of 12 checks passed
@mustartt mustartt deleted the revert-strlen-idiom branch March 14, 2025 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants