[llvm] 5b2a881 - Revert "[Transforms] LoopIdiomRecognize recognize strlen and wcslen (#108985)" (#131405)

via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 14 16:11:29 PDT 2025


Author: Henry Jiang
Date: 2025-03-14T19:11:26-04:00
New Revision: 5b2a8819fbe0966b740cc0d9c73591b6d2c9d20f

URL: https://github.com/llvm/llvm-project/commit/5b2a8819fbe0966b740cc0d9c73591b6d2c9d20f
DIFF: https://github.com/llvm/llvm-project/commit/5b2a8819fbe0966b740cc0d9c73591b6d2c9d20f.diff

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

This reverts commit bf6357f0f51eccc48b92a130afb51c0280d56180.

Added: 
    

Modified: 
    llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
    llvm/include/llvm/Transforms/Utils/BuildLibCalls.h
    llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
    llvm/lib/Transforms/Utils/BuildLibCalls.cpp

Removed: 
    llvm/test/Transforms/LoopIdiom/strlen.ll
    llvm/test/Transforms/LoopIdiom/wcslen16.ll
    llvm/test/Transforms/LoopIdiom/wcslen32.ll


################################################################################
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 ptr %str to i64
-  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
-  %conv = trunc i64 %sub.ptr.sub to i32
-  br label %cleanup
-
-cleanup:
-  %retval.0 = phi i32 [ %conv, %do.end ], [ 0, %entry ]
-  ret i32 %retval.0
-}
-
-; int valid_strlen_with_aux_indvar(const char* str) {
-;   int count = 0;
-;   int count_offset = -10;
-;   int count_multiple = 0;
-;
-;   while (*str) {
-;     ++str;
-;     ++count;
-;     ++count_offset;
-;     count_multiple += 2;
-;     ++foo;
-;   }
-;
-;   usei(count);
-;   usei(count_offset);
-;   usei(count_multiple);
-;   use(str);
-;   use(foo);
-; }
-define dso_local void @valid_strlen_with_aux_indvar(ptr noundef %str, ptr noundef %foo) local_unnamed_addr {
-; CHECK-LABEL: define dso_local void @valid_strlen_with_aux_indvar(
-; CHECK-SAME: ptr noundef [[STR:%.*]], ptr noundef [[FOO:%.*]]) local_unnamed_addr {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[STR]], align 1
-; CHECK-NEXT:    [[TOBOOL_NOT9:%.*]] = icmp eq i8 [[TMP0]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT9]], label %[[WHILE_END:.*]], label %[[WHILE_BODY_PREHEADER:.*]]
-; CHECK:       [[WHILE_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:    [[TMP2:%.*]] = trunc i64 [[STRLEN]] to i32
-; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], 1
-; CHECK-NEXT:    [[TMP4:%.*]] = trunc i64 [[STRLEN]] to i32
-; CHECK-NEXT:    [[TMP5:%.*]] = add i32 [[TMP4]], -9
-; CHECK-NEXT:    [[TMP6:%.*]] = trunc i64 [[STRLEN]] to i32
-; CHECK-NEXT:    [[TMP7:%.*]] = shl i32 [[TMP6]], 1
-; CHECK-NEXT:    [[TMP8:%.*]] = add i32 [[TMP7]], 2
-; CHECK-NEXT:    [[TMP9:%.*]] = add i64 [[STRLEN]], 1
-; CHECK-NEXT:    [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[FOO]], i64 [[TMP9]]
-; CHECK-NEXT:    br label %[[WHILE_BODY:.*]]
-; CHECK:       [[WHILE_BODY]]:
-; CHECK-NEXT:    [[COUNT_MULTIPLE_014:%.*]] = phi i32 [ [[ADD:%.*]], %[[WHILE_BODY]] ], [ 0, %[[WHILE_BODY_PREHEADER]] ]
-; CHECK-NEXT:    [[COUNT_OFFSET_013:%.*]] = phi i32 [ [[INC1:%.*]], %[[WHILE_BODY]] ], [ -10, %[[WHILE_BODY_PREHEADER]] ]
-; CHECK-NEXT:    [[COUNT_012:%.*]] = phi i32 [ [[INC:%.*]], %[[WHILE_BODY]] ], [ 0, %[[WHILE_BODY_PREHEADER]] ]
-; CHECK-NEXT:    [[FOO_ADDR_011:%.*]] = phi ptr [ [[INCDEC_PTR2:%.*]], %[[WHILE_BODY]] ], [ [[FOO]], %[[WHILE_BODY_PREHEADER]] ]
-; CHECK-NEXT:    [[STR_ADDR_010:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], %[[WHILE_BODY]] ], [ [[STR]], %[[WHILE_BODY_PREHEADER]] ]
-; CHECK-NEXT:    [[INCDEC_PTR]] = getelementptr inbounds nuw i8, ptr [[STR_ADDR_010]], i64 1
-; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[COUNT_012]], 1
-; CHECK-NEXT:    [[INC1]] = add nsw i32 [[COUNT_OFFSET_013]], 1
-; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[COUNT_MULTIPLE_014]], 2
-; CHECK-NEXT:    [[INCDEC_PTR2]] = getelementptr inbounds nuw i8, ptr [[FOO_ADDR_011]], i64 1
-; CHECK-NEXT:    [[TMP10:%.*]] = load i8, ptr [[INCDEC_PTR]], align 1
-; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i8 [[TMP10]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label %[[WHILE_END_LOOPEXIT:.*]], label %[[WHILE_BODY]]
-; CHECK:       [[WHILE_END_LOOPEXIT]]:
-; CHECK-NEXT:    br label %[[WHILE_END]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    [[STR_ADDR_0_LCSSA:%.*]] = phi ptr [ [[STR]], %[[ENTRY]] ], [ [[SCEVGEP1]], %[[WHILE_END_LOOPEXIT]] ]
-; CHECK-NEXT:    [[FOO_ADDR_0_LCSSA:%.*]] = phi ptr [ [[FOO]], %[[ENTRY]] ], [ [[SCEVGEP2]], %[[WHILE_END_LOOPEXIT]] ]
-; CHECK-NEXT:    [[COUNT_0_LCSSA:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[TMP3]], %[[WHILE_END_LOOPEXIT]] ]
-; CHECK-NEXT:    [[COUNT_OFFSET_0_LCSSA:%.*]] = phi i32 [ -10, %[[ENTRY]] ], [ [[TMP5]], %[[WHILE_END_LOOPEXIT]] ]
-; CHECK-NEXT:    [[COUNT_MULTIPLE_0_LCSSA:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[TMP8]], %[[WHILE_END_LOOPEXIT]] ]
-; CHECK-NEXT:    tail call void @usei(i32 noundef [[COUNT_0_LCSSA]])
-; CHECK-NEXT:    tail call void @usei(i32 noundef [[COUNT_OFFSET_0_LCSSA]])
-; CHECK-NEXT:    tail call void @usei(i32 noundef [[COUNT_MULTIPLE_0_LCSSA]])
-; CHECK-NEXT:    tail call void @use(ptr noundef nonnull [[STR_ADDR_0_LCSSA]])
-; CHECK-NEXT:    tail call void @use(ptr noundef [[FOO_ADDR_0_LCSSA]])
-; CHECK-NEXT:    ret void
-;
-entry:
-  %0 = load i8, ptr %str, align 1
-  %tobool.not9 = icmp eq i8 %0, 0
-  br i1 %tobool.not9, label %while.end, label %while.body
-
-while.body:
-  %count_multiple.014 = phi i32 [ %add, %while.body ], [ 0, %entry ]
-  %count_offset.013 = phi i32 [ %inc1, %while.body ], [ -10, %entry ]
-  %count.012 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
-  %foo.addr.011 = phi ptr [ %incdec.ptr2, %while.body ], [ %foo, %entry ]
-  %str.addr.010 = phi ptr [ %incdec.ptr, %while.body ], [ %str, %entry ]
-  %incdec.ptr = getelementptr inbounds nuw i8, ptr %str.addr.010, i64 1
-  %inc = add nuw nsw i32 %count.012, 1
-  %inc1 = add nsw i32 %count_offset.013, 1
-  %add = add nuw nsw i32 %count_multiple.014, 2
-  %incdec.ptr2 = getelementptr inbounds nuw i8, ptr %foo.addr.011, i64 1
-  %1 = load i8, ptr %incdec.ptr, align 1
-  %tobool.not = icmp eq i8 %1, 0
-  br i1 %tobool.not, label %while.end, label %while.body
-
-while.end:
-  %str.addr.0.lcssa = phi ptr [ %str, %entry ], [ %incdec.ptr, %while.body ]
-  %foo.addr.0.lcssa = phi ptr [ %foo, %entry ], [ %incdec.ptr2, %while.body ]
-  %count.0.lcssa = phi i32 [ 0, %entry ], [ %inc, %while.body ]
-  %count_offset.0.lcssa = phi i32 [ -10, %entry ], [ %inc1, %while.body ]
-  %count_multiple.0.lcssa = phi i32 [ 0, %entry ], [ %add, %while.body ]
-  tail call void @usei(i32 noundef %count.0.lcssa) #3
-  tail call void @usei(i32 noundef %count_offset.0.lcssa) #3
-  tail call void @usei(i32 noundef %count_multiple.0.lcssa) #3
-  tail call void @use(ptr noundef nonnull %str.addr.0.lcssa) #3
-  tail call void @use(ptr noundef %foo.addr.0.lcssa) #3
-  ret void
-}
-
-; int valid_strlen_index(const char* str) {
-;     int i = 0;
-;     while (str[i]) {
-;         ++i;
-;     }
-;     return i;
-; }
-define i32 @valid_strlen_index(ptr %str) {
-; CHECK-LABEL: define i32 @valid_strlen_index(
-; CHECK-SAME: ptr [[STR:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    [[STRLEN:%.*]] = call i64 @strlen(ptr [[STR]])
-; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
-; CHECK:       [[WHILE_COND]]:
-; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[WHILE_COND]] ], [ 0, %[[ENTRY]] ]
-; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[STR]], i64 [[INDVARS_IV]]
-; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
-; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i8 [[TMP0]], 0
-; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_COND]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    [[TMP1:%.*]] = trunc nuw nsw i64 [[STRLEN]] to i32
-; CHECK-NEXT:    ret i32 [[TMP1]]
-;
-entry:
-  br label %while.cond
-
-while.cond:
-  %indvars.iv = phi i64 [ %indvars.iv.next, %while.cond ], [ 0, %entry ]
-  %arrayidx = getelementptr inbounds i8, ptr %str, i64 %indvars.iv
-  %0 = load i8, ptr %arrayidx, align 1
-  %tobool.not = icmp eq i8 %0, 0
-  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
-  br i1 %tobool.not, label %while.end, label %while.cond
-
-while.end:
-  %1 = trunc nuw nsw i64 %indvars.iv to i32
-  ret i32 %1
-}
-
-; void valid_strlen_offset(const my_char* str) {
-;     if (*(str++) == '\0') return;
-;     if (*(str++) == '\0') return;
-;     if (*(str++) == '\0') return;
-;     while (*str) {
-;         ++str;
-;     }
-;     use(str);
-; }
-define dso_local void @valid_strlen_offset(ptr noundef %str) local_unnamed_addr {
-; CHECK-LABEL: define dso_local void @valid_strlen_offset(
-; CHECK-SAME: ptr noundef [[STR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[STR]], align 1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[TMP0]], 0
-; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[IF_END:.*]]
-; CHECK:       [[IF_END]]:
-; CHECK-NEXT:    [[INCDEC_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[STR]], i64 1
-; CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[INCDEC_PTR]], align 1
-; CHECK-NEXT:    [[CMP4:%.*]] = icmp eq i8 [[TMP1]], 0
-; CHECK-NEXT:    br i1 [[CMP4]], label %[[RETURN]], label %[[IF_END7:.*]]
-; CHECK:       [[IF_END7]]:
-; CHECK-NEXT:    [[INCDEC_PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[STR]], i64 2
-; CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[INCDEC_PTR2]], align 1
-; CHECK-NEXT:    [[CMP10:%.*]] = icmp eq i8 [[TMP2]], 0
-; CHECK-NEXT:    br i1 [[CMP10]], label %[[RETURN]], label %[[WHILE_COND_PREHEADER:.*]]
-; CHECK:       [[WHILE_COND_PREHEADER]]:
-; CHECK-NEXT:    [[INCDEC_PTR8:%.*]] = getelementptr i8, ptr [[STR]], i64 3
-; CHECK-NEXT:    [[STRLEN:%.*]] = call i64 @strlen(ptr [[INCDEC_PTR8]])
-; CHECK-NEXT:    [[TMP3:%.*]] = add i64 [[STRLEN]], 3
-; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[STR]], i64 [[TMP3]]
-; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
-; CHECK:       [[WHILE_COND]]:
-; CHECK-NEXT:    [[STR_ADDR_0:%.*]] = phi ptr [ [[INCDEC_PTR14:%.*]], %[[WHILE_COND]] ], [ [[INCDEC_PTR8]], %[[WHILE_COND_PREHEADER]] ]
-; CHECK-NEXT:    [[TMP4:%.*]] = load i8, ptr [[STR_ADDR_0]], align 1
-; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i8 [[TMP4]], 0
-; CHECK-NEXT:    [[INCDEC_PTR14]] = getelementptr inbounds nuw i8, ptr [[STR_ADDR_0]], i64 1
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_COND]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    tail call void @use(ptr noundef nonnull [[SCEVGEP]])
-; CHECK-NEXT:    br label %[[RETURN]]
-; CHECK:       [[RETURN]]:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %0 = load i8, ptr %str, align 1
-  %cmp = icmp eq i8 %0, 0
-  br i1 %cmp, label %return, label %if.end
-
-if.end:
-  %incdec.ptr = getelementptr inbounds nuw i8, ptr %str, i64 1
-  %1 = load i8, ptr %incdec.ptr, align 1
-  %cmp4 = icmp eq i8 %1, 0
-  br i1 %cmp4, label %return, label %if.end7
-
-if.end7:
-  %incdec.ptr2 = getelementptr inbounds nuw i8, ptr %str, i64 2
-  %2 = load i8, ptr %incdec.ptr2, align 1
-  %cmp10 = icmp eq i8 %2, 0
-  br i1 %cmp10, label %return, label %while.cond.preheader
-
-while.cond.preheader:
-  %incdec.ptr8 = getelementptr inbounds nuw i8, ptr %str, i64 3
-  br label %while.cond
-
-while.cond:
-  %str.addr.0 = phi ptr [ %incdec.ptr14, %while.cond ], [ %incdec.ptr8, %while.cond.preheader ]
-  %3 = load i8, ptr %str.addr.0, align 1
-  %tobool.not = icmp eq i8 %3, 0
-  %incdec.ptr14 = getelementptr inbounds nuw i8, ptr %str.addr.0, i64 1
-  br i1 %tobool.not, label %while.end, label %while.cond
-
-while.end:
-  tail call void @use(ptr noundef nonnull %str.addr.0) #3
-  br label %return
-
-return:
-  ret void
-}
-
-; void valid_nested_idiom(const char** strs, int n) {
-;     for (int i = 0; i < n; ++i) {
-;         const char* s = strs[i];
-;         int count = 0;
-;         while (*s) {
-;             ++s;
-;             ++count;
-;         }
-;         usei(count);
-;     }
-; }
-define void @valid_nested_idiom(ptr %strs, i32 %n) {
-; CHECK-LABEL: define void @valid_nested_idiom(
-; CHECK-SAME: ptr [[STRS:%.*]], i32 [[N:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[CMP9:%.*]] = icmp sgt i32 [[N]], 0
-; CHECK-NEXT:    br i1 [[CMP9]], label %[[FOR_BODY_PREHEADER:.*]], label %[[FOR_COND_CLEANUP:.*]]
-; CHECK:       [[FOR_BODY_PREHEADER]]:
-; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext nneg i32 [[N]] to i64
-; CHECK-NEXT:    br label %[[FOR_BODY:.*]]
-; CHECK:       [[FOR_COND_CLEANUP_LOOPEXIT:.*]]:
-; CHECK-NEXT:    br label %[[FOR_COND_CLEANUP]]
-; CHECK:       [[FOR_COND_CLEANUP]]:
-; CHECK-NEXT:    ret void
-; CHECK:       [[FOR_BODY]]:
-; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ 0, %[[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], %[[WHILE_END:.*]] ]
-; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[STRS]], i64 [[INDVARS_IV]]
-; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8
-; CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[TMP0]], align 1
-; CHECK-NEXT:    [[TOBOOL_NOT6:%.*]] = icmp eq i8 [[TMP1]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT6]], label %[[WHILE_END]], label %[[WHILE_BODY_PREHEADER:.*]]
-; CHECK:       [[WHILE_BODY_PREHEADER]]:
-; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[TMP0]], i64 1
-; CHECK-NEXT:    [[STRLEN:%.*]] = call i64 @strlen(ptr [[SCEVGEP]])
-; CHECK-NEXT:    [[TMP2:%.*]] = trunc i64 [[STRLEN]] to i32
-; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[TMP2]], 1
-; CHECK-NEXT:    br label %[[WHILE_BODY:.*]]
-; CHECK:       [[WHILE_BODY]]:
-; CHECK-NEXT:    [[COUNT_08:%.*]] = phi i32 [ [[INC:%.*]], %[[WHILE_BODY]] ], [ 0, %[[WHILE_BODY_PREHEADER]] ]
-; CHECK-NEXT:    [[S_07:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], %[[WHILE_BODY]] ], [ [[TMP0]], %[[WHILE_BODY_PREHEADER]] ]
-; CHECK-NEXT:    [[INCDEC_PTR]] = getelementptr inbounds nuw i8, ptr [[S_07]], i64 1
-; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[COUNT_08]], 1
-; CHECK-NEXT:    [[TMP4:%.*]] = load i8, ptr [[INCDEC_PTR]], align 1
-; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i8 [[TMP4]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label %[[WHILE_END_LOOPEXIT:.*]], label %[[WHILE_BODY]]
-; CHECK:       [[WHILE_END_LOOPEXIT]]:
-; CHECK-NEXT:    br label %[[WHILE_END]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    [[COUNT_0_LCSSA:%.*]] = phi i32 [ 0, %[[FOR_BODY]] ], [ [[TMP3]], %[[WHILE_END_LOOPEXIT]] ]
-; CHECK-NEXT:    tail call void @usei(i32 [[COUNT_0_LCSSA]])
-; CHECK-NEXT:    [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
-; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
-; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[FOR_COND_CLEANUP_LOOPEXIT]], label %[[FOR_BODY]]
-;
-entry:
-  %cmp9 = icmp sgt i32 %n, 0
-  br i1 %cmp9, label %for.body.preheader, label %for.cond.cleanup
-
-for.body.preheader:
-  %wide.trip.count = zext nneg i32 %n to i64
-  br label %for.body
-
-for.cond.cleanup:
-  ret void
-
-for.body:
-  %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %while.end ]
-  %arrayidx = getelementptr inbounds ptr, ptr %strs, i64 %indvars.iv
-  %0 = load ptr, ptr %arrayidx, align 8
-  %1 = load i8, ptr %0, align 1
-  %tobool.not6 = icmp eq i8 %1, 0
-  br i1 %tobool.not6, label %while.end, label %while.body
-
-while.body:
-  %count.08 = phi i32 [ %inc, %while.body ], [ 0, %for.body ]
-  %s.07 = phi ptr [ %incdec.ptr, %while.body ], [ %0, %for.body ]
-  %incdec.ptr = getelementptr inbounds nuw i8, ptr %s.07, i64 1
-  %inc = add nuw nsw i32 %count.08, 1
-  %2 = load i8, ptr %incdec.ptr, align 1
-  %tobool.not = icmp eq i8 %2, 0
-  br i1 %tobool.not, label %while.end, label %while.body
-
-while.end:
-  %count.0.lcssa = phi i32 [ 0, %for.body ], [ %inc, %while.body ]
-  tail call void @usei(i32 %count.0.lcssa) #2
-  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
-  %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count
-  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
-}
-
-define i64 @invalid_strlen_has_side_effects(ptr %str) {
-; CHECK-LABEL: define i64 @invalid_strlen_has_side_effects(
-; CHECK-SAME: ptr [[STR:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; 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 volatile 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:    [[STR_ADDR_0_LCSSA:%.*]] = phi ptr [ [[STR_ADDR_0]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[STR_ADDR_0_LCSSA]] 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 volatile 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
-}
-
-
-define i8 @invalid_exit_phi_scev(ptr %str) {
-; CHECK-LABEL: define i8 @invalid_exit_phi_scev(
-; CHECK-SAME: ptr [[STR:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; 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:    [[STR_ADDR_0_LCSSA:%.*]] = phi ptr [ [[STR_ADDR_0]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[DOTLCSSA:%.*]] = phi i8 [ [[TMP0]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[STR_ADDR_0_LCSSA]] 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 i8 [[DOTLCSSA]]
-;
-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
-
-  ; %0.lcssa has invalid scev rec {%0} expected to be {%str,+,constant}
-  ret i8 %0
-}
-
-
-
-define i64 @invalid_branch_cond(ptr %str) {
-; CHECK-LABEL: define i64 @invalid_branch_cond(
-; CHECK-SAME: ptr [[STR:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; 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]], 10
-; 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:    [[STR_ADDR_0_LCSSA:%.*]] = phi ptr [ [[STR_ADDR_0]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[STR_ADDR_0_LCSSA]] 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
-
-  ; We compare against '\n' instead of '\0'
-  %cmp.not = icmp eq i8 %0, 10
-
-  %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
-}
-
-define i64 @invalid_unknown_step_size(ptr %str, i64 %step) {
-; CHECK-LABEL: define i64 @invalid_unknown_step_size(
-; CHECK-SAME: ptr [[STR:%.*]], i64 [[STEP:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; 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 [[STEP]]
-; CHECK-NEXT:    br i1 [[CMP_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_COND]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    [[STR_ADDR_0_LCSSA:%.*]] = phi ptr [ [[STR_ADDR_0]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[STR_ADDR_0_LCSSA]] 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 %step
-  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
-}
-
-declare ptr @pure(ptr) #0;
-attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-
-define i64 @invalid_add_rec(ptr %str) {
-; CHECK-LABEL: define i64 @invalid_add_rec(
-; CHECK-SAME: ptr [[STR:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
-; CHECK:       [[WHILE_COND]]:
-; CHECK-NEXT:    [[STR_ADDR_0:%.*]] = phi ptr [ [[STR]], %[[ENTRY]] ], [ [[INCDEC_PTR:%.*]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[INDIRECT:%.*]] = tail call ptr @pure(ptr [[STR_ADDR_0]])
-; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[INDIRECT]], 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:    [[STR_ADDR_0_LCSSA:%.*]] = phi ptr [ [[STR_ADDR_0]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[STR_ADDR_0_LCSSA]] 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 ]
-  %indirect = tail call ptr @pure(ptr %str.addr.0)
-  %0 = load i8, ptr %indirect, 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
-}
-

diff  --git a/llvm/test/Transforms/LoopIdiom/wcslen16.ll b/llvm/test/Transforms/LoopIdiom/wcslen16.ll
deleted file mode 100644
index 4f53442a9a0a4..0000000000000
--- a/llvm/test/Transforms/LoopIdiom/wcslen16.ll
+++ /dev/null
@@ -1,126 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -passes='loop(loop-idiom),verify' -enable-loop-idiom-wcslen < %s -S | FileCheck %s
-
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define i64 @valid_strlen16(ptr %src) {
-; CHECK-LABEL: define i64 @valid_strlen16(
-; CHECK-SAME: ptr [[SRC:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[SRC]], null
-; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[LOR_LHS_FALSE:.*]]
-; CHECK:       [[LOR_LHS_FALSE]]:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[SRC]], align 2
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i16 [[TMP0]], 0
-; CHECK-NEXT:    br i1 [[CMP1]], label %[[RETURN]], label %[[WHILE_COND_PREHEADER:.*]]
-; CHECK:       [[WHILE_COND_PREHEADER]]:
-; CHECK-NEXT:    [[NEWGEP:%.*]] = getelementptr i8, ptr [[SRC]], i64 2
-; CHECK-NEXT:    [[WCSLEN:%.*]] = call i64 @wcslen(ptr [[NEWGEP]])
-; CHECK-NEXT:    [[TMP1:%.*]] = shl i64 [[WCSLEN]], 1
-; CHECK-NEXT:    [[TMP2:%.*]] = add i64 [[TMP1]], 2
-; CHECK-NEXT:    [[END:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP2]]
-; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
-; CHECK:       [[WHILE_COND]]:
-; CHECK-NEXT:    [[SRC_PN:%.*]] = phi ptr [ [[CURR_0:%.*]], %[[WHILE_COND]] ], [ [[SRC]], %[[WHILE_COND_PREHEADER]] ]
-; CHECK-NEXT:    [[CURR_0]] = getelementptr inbounds i8, ptr [[SRC_PN]], i64 2
-; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[CURR_0]], align 2
-; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i16 [[TMP3]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_COND]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[END]] to i64
-; CHECK-NEXT:    [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[SRC]] to i64
-; CHECK-NEXT:    [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
-; CHECK-NEXT:    [[SUB_PTR_DIV:%.*]] = ashr exact i64 [[SUB_PTR_SUB]], 1
-; CHECK-NEXT:    br label %[[RETURN]]
-; CHECK:       [[RETURN]]:
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i64 [ [[SUB_PTR_DIV]], %[[WHILE_END]] ], [ 0, %[[LOR_LHS_FALSE]] ], [ 0, %[[ENTRY]] ]
-; CHECK-NEXT:    ret i64 [[RETVAL_0]]
-;
-entry:
-  %cmp = icmp eq ptr %src, null
-  br i1 %cmp, label %return, label %lor.lhs.false
-
-lor.lhs.false:                                    ; preds = %entry
-  %0 = load i16, ptr %src, align 2
-  %cmp1 = icmp eq i16 %0, 0
-  br i1 %cmp1, label %return, label %while.cond
-
-while.cond:                                       ; preds = %lor.lhs.false, %while.cond
-  %src.pn = phi ptr [ %curr.0, %while.cond ], [ %src, %lor.lhs.false ]
-  %curr.0 = getelementptr inbounds i8, ptr %src.pn, i64 2
-  %1 = load i16, ptr %curr.0, align 2
-  %tobool.not = icmp eq i16 %1, 0
-  br i1 %tobool.not, label %while.end, label %while.cond
-
-while.end:                                        ; preds = %while.cond
-  %sub.ptr.lhs.cast = ptrtoint ptr %curr.0 to i64
-  %sub.ptr.rhs.cast = ptrtoint ptr %src to i64
-  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
-  %sub.ptr.div = ashr exact i64 %sub.ptr.sub, 1
-  br label %return
-
-return:                                           ; preds = %entry, %lor.lhs.false, %while.end
-  %retval.0 = phi i64 [ %sub.ptr.div, %while.end ], [ 0, %lor.lhs.false ], [ 0, %entry ]
-  ret i64 %retval.0
-}
-
-define i64 @invalid_char_size(ptr %src) {
-; CHECK-LABEL: define i64 @invalid_char_size(
-; CHECK-SAME: ptr [[SRC:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[SRC]], null
-; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[LOR_LHS_FALSE:.*]]
-; CHECK:       [[LOR_LHS_FALSE]]:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[SRC]], align 2
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[TMP0]], 0
-; CHECK-NEXT:    br i1 [[CMP1]], label %[[RETURN]], label %[[WHILE_COND_PREHEADER:.*]]
-; CHECK:       [[WHILE_COND_PREHEADER]]:
-; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
-; CHECK:       [[WHILE_COND]]:
-; CHECK-NEXT:    [[SRC_PN:%.*]] = phi ptr [ [[CURR_0:%.*]], %[[WHILE_COND]] ], [ [[SRC]], %[[WHILE_COND_PREHEADER]] ]
-; CHECK-NEXT:    [[CURR_0]] = getelementptr inbounds i8, ptr [[SRC_PN]], i64 4
-; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[CURR_0]], align 4
-; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP1]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_COND]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    [[CURR_0_LCSSA:%.*]] = phi ptr [ [[CURR_0]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[CURR_0_LCSSA]] to i64
-; CHECK-NEXT:    [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[SRC]] to i64
-; CHECK-NEXT:    [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
-; CHECK-NEXT:    [[SUB_PTR_DIV:%.*]] = ashr exact i64 [[SUB_PTR_SUB]], 2
-; CHECK-NEXT:    br label %[[RETURN]]
-; CHECK:       [[RETURN]]:
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i64 [ [[SUB_PTR_DIV]], %[[WHILE_END]] ], [ 0, %[[LOR_LHS_FALSE]] ], [ 0, %[[ENTRY]] ]
-; CHECK-NEXT:    ret i64 [[RETVAL_0]]
-;
-entry:
-  %cmp = icmp eq ptr %src, null
-  br i1 %cmp, label %return, label %lor.lhs.false
-
-lor.lhs.false:                                    ; preds = %entry
-  %0 = load i32, ptr %src, align 2
-  %cmp1 = icmp eq i32 %0, 0
-  br i1 %cmp1, label %return, label %while.cond
-
-while.cond:                                       ; preds = %lor.lhs.false, %while.cond
-  %src.pn = phi ptr [ %curr.0, %while.cond ], [ %src, %lor.lhs.false ]
-  %curr.0 = getelementptr inbounds i8, ptr %src.pn, i64 4
-  %1 = load i32, ptr %curr.0, align 4
-  %tobool.not = icmp eq i32 %1, 0
-  br i1 %tobool.not, label %while.end, label %while.cond
-
-while.end:                                        ; preds = %while.cond
-  %sub.ptr.lhs.cast = ptrtoint ptr %curr.0 to i64
-  %sub.ptr.rhs.cast = ptrtoint ptr %src to i64
-  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
-  %sub.ptr.div = ashr exact i64 %sub.ptr.sub, 2
-  br label %return
-
-return:                                           ; preds = %entry, %lor.lhs.false, %while.end
-  %retval.0 = phi i64 [ %sub.ptr.div, %while.end ], [ 0, %lor.lhs.false ], [ 0, %entry ]
-  ret i64 %retval.0
-}
-!llvm.module.flags = !{!0}
-!0 = !{i32 1, !"wchar_size", i32 2}
-

diff  --git a/llvm/test/Transforms/LoopIdiom/wcslen32.ll b/llvm/test/Transforms/LoopIdiom/wcslen32.ll
deleted file mode 100644
index d083b534d660a..0000000000000
--- a/llvm/test/Transforms/LoopIdiom/wcslen32.ll
+++ /dev/null
@@ -1,134 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -passes='loop(loop-idiom),verify' -enable-loop-idiom-wcslen < %s -S | FileCheck %s
-
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
-define i64 @valid_wcslen32(ptr %src) {
-; CHECK-LABEL: define i64 @valid_wcslen32(
-; CHECK-SAME: ptr [[SRC:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[SRC]], null
-; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[LOR_LHS_FALSE:.*]]
-; CHECK:       [[LOR_LHS_FALSE]]:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[SRC]], align 4
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[TMP0]], 0
-; CHECK-NEXT:    br i1 [[CMP1]], label %[[RETURN]], label %[[WHILE_COND_PREHEADER:.*]]
-; CHECK:       [[WHILE_COND_PREHEADER]]:
-; CHECK-NEXT:    [[NEWGEP:%.*]] = getelementptr i8, ptr [[SRC]], i64 4
-; CHECK-NEXT:    [[WCSLEN:%.*]] = call i64 @wcslen(ptr [[NEWGEP]])
-; CHECK-NEXT:    [[TMP1:%.*]] = shl i64 [[WCSLEN]], 2
-; CHECK-NEXT:    [[TMP2:%.*]] = add i64 [[TMP1]], 4
-; CHECK-NEXT:    [[END:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP2]]
-; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
-; CHECK:       [[WHILE_COND]]:
-; CHECK-NEXT:    [[SRC_PN:%.*]] = phi ptr [ [[CURR_0:%.*]], %[[WHILE_COND]] ], [ [[SRC]], %[[WHILE_COND_PREHEADER]] ]
-; CHECK-NEXT:    [[CURR_0]] = getelementptr inbounds i8, ptr [[SRC_PN]], i64 4
-; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[CURR_0]], align 4
-; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP3]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_COND]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[END]] to i64
-; CHECK-NEXT:    [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[SRC]] to i64
-; CHECK-NEXT:    [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
-; CHECK-NEXT:    [[SUB_PTR_DIV:%.*]] = ashr exact i64 [[SUB_PTR_SUB]], 2
-; CHECK-NEXT:    br label %[[RETURN]]
-; CHECK:       [[RETURN]]:
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i64 [ [[SUB_PTR_DIV]], %[[WHILE_END]] ], [ 0, %[[LOR_LHS_FALSE]] ], [ 0, %[[ENTRY]] ]
-; CHECK-NEXT:    ret i64 [[RETVAL_0]]
-;
-entry:
-  %cmp = icmp eq ptr %src, null
-  br i1 %cmp, label %return, label %lor.lhs.false
-
-lor.lhs.false:                                    ; preds = %entry
-  %0 = load i32, ptr %src, align 4
-  %cmp1 = icmp eq i32 %0, 0
-  br i1 %cmp1, label %return, label %while.cond.preheader
-
-while.cond.preheader:                             ; preds = %lor.lhs.false
-  br label %while.cond
-
-while.cond:                                       ; preds = %while.cond.preheader, %while.cond
-  %src.pn = phi ptr [ %curr.0, %while.cond ], [ %src, %while.cond.preheader ]
-  %curr.0 = getelementptr inbounds i8, ptr %src.pn, i64 4
-  %1 = load i32, ptr %curr.0, align 4
-  %tobool.not = icmp eq i32 %1, 0
-  br i1 %tobool.not, label %while.end, label %while.cond
-
-while.end:                                        ; preds = %while.cond
-  %curr.0.lcssa = phi ptr [ %curr.0, %while.cond ]
-  %sub.ptr.lhs.cast = ptrtoint ptr %curr.0.lcssa to i64
-  %sub.ptr.rhs.cast = ptrtoint ptr %src to i64
-  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
-  %sub.ptr.div = ashr exact i64 %sub.ptr.sub, 2
-  br label %return
-
-return:                                           ; preds = %entry, %lor.lhs.false, %while.end
-  %retval.0 = phi i64 [ %sub.ptr.div, %while.end ], [ 0, %lor.lhs.false ], [ 0, %entry ]
-  ret i64 %retval.0
-}
-
-define i64 @invalid_char_size(ptr %src) {
-; CHECK-LABEL: define i64 @invalid_char_size(
-; CHECK-SAME: ptr [[SRC:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[SRC]], null
-; CHECK-NEXT:    br i1 [[CMP]], label %[[RETURN:.*]], label %[[LOR_LHS_FALSE:.*]]
-; CHECK:       [[LOR_LHS_FALSE]]:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[SRC]], align 2
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i16 [[TMP0]], 0
-; CHECK-NEXT:    br i1 [[CMP1]], label %[[RETURN]], label %[[WHILE_COND_PREHEADER:.*]]
-; CHECK:       [[WHILE_COND_PREHEADER]]:
-; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
-; CHECK:       [[WHILE_COND]]:
-; CHECK-NEXT:    [[SRC_PN:%.*]] = phi ptr [ [[CURR_0:%.*]], %[[WHILE_COND]] ], [ [[SRC]], %[[WHILE_COND_PREHEADER]] ]
-; CHECK-NEXT:    [[CURR_0]] = getelementptr inbounds i8, ptr [[SRC_PN]], i64 2
-; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[CURR_0]], align 2
-; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i16 [[TMP1]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label %[[WHILE_END:.*]], label %[[WHILE_COND]]
-; CHECK:       [[WHILE_END]]:
-; CHECK-NEXT:    [[CURR_0_LCSSA:%.*]] = phi ptr [ [[CURR_0]], %[[WHILE_COND]] ]
-; CHECK-NEXT:    [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint ptr [[CURR_0_LCSSA]] to i64
-; CHECK-NEXT:    [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint ptr [[SRC]] to i64
-; CHECK-NEXT:    [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
-; CHECK-NEXT:    [[SUB_PTR_DIV:%.*]] = ashr exact i64 [[SUB_PTR_SUB]], 1
-; CHECK-NEXT:    br label %[[RETURN]]
-; CHECK:       [[RETURN]]:
-; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i64 [ [[SUB_PTR_DIV]], %[[WHILE_END]] ], [ 0, %[[LOR_LHS_FALSE]] ], [ 0, %[[ENTRY]] ]
-; CHECK-NEXT:    ret i64 [[RETVAL_0]]
-;
-entry:
-  %cmp = icmp eq ptr %src, null
-  br i1 %cmp, label %return, label %lor.lhs.false
-
-lor.lhs.false:                                    ; preds = %entry
-  %0 = load i16, ptr %src, align 2
-  %cmp1 = icmp eq i16 %0, 0
-  br i1 %cmp1, label %return, label %while.cond.preheader
-
-while.cond.preheader:                             ; preds = %lor.lhs.false
-  br label %while.cond
-
-while.cond:                                       ; preds = %while.cond.preheader, %while.cond
-  %src.pn = phi ptr [ %curr.0, %while.cond ], [ %src, %while.cond.preheader ]
-  %curr.0 = getelementptr inbounds i8, ptr %src.pn, i64 2
-  %1 = load i16, ptr %curr.0, align 2
-  %tobool.not = icmp eq i16 %1, 0
-  br i1 %tobool.not, label %while.end, label %while.cond
-
-while.end:                                        ; preds = %while.cond
-  %curr.0.lcssa = phi ptr [ %curr.0, %while.cond ]
-  %sub.ptr.lhs.cast = ptrtoint ptr %curr.0.lcssa to i64
-  %sub.ptr.rhs.cast = ptrtoint ptr %src to i64
-  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
-  %sub.ptr.div = ashr exact i64 %sub.ptr.sub, 1
-  br label %return
-
-return:                                           ; preds = %entry, %lor.lhs.false, %while.end
-  %retval.0 = phi i64 [ %sub.ptr.div, %while.end ], [ 0, %lor.lhs.false ], [ 0, %entry ]
-  ret i64 %retval.0
-}
-!llvm.module.flags = !{!0}
-!0 = !{i32 1, !"wchar_size", i32 4}
-


        


More information about the llvm-commits mailing list