[llvm] [Transform] Clean up strlen loop idiom (PR #132421)

Henry Jiang via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 21 10:54:25 PDT 2025


https://github.com/mustartt updated https://github.com/llvm/llvm-project/pull/132421

>From b212a292b810254e984efe5dfa2d638b4600874e Mon Sep 17 00:00:00 2001
From: Henry Jiang <henry.jiang1 at ibm.com>
Date: Fri, 21 Mar 2025 12:54:50 -0400
Subject: [PATCH 1/2] bail out before modifing cfg

---
 .../Transforms/Scalar/LoopIdiomRecognize.cpp  | 39 +++++++------------
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index b91cdc0748581..7f92f5f65a972 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -1515,16 +1515,6 @@ bool LoopIdiomRecognize::runOnNoncountableLoop() {
          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;
-}
-
 /// Check if the given conditional branch is based on the comparison between
 /// a variable and zero, and if the variable is non-zero or zero (JmpOnZero is
 /// true), the control yields to the loop entry. If the branch matches the
@@ -1540,7 +1530,8 @@ static Value *matchCondition(BranchInst *BI, BasicBlock *LoopEntry,
   if (!Cond)
     return nullptr;
 
-  if (!isZeroConstant(Cond->getOperand(1)))
+  const ConstantInt *CmpZero = dyn_cast<ConstantInt>(Cond->getOperand(1));
+  if (!CmpZero || !CmpZero->isZero())
     return nullptr;
 
   BasicBlock *TrueSucc = BI->getSuccessor(0);
@@ -1656,11 +1647,7 @@ class StrlenVerifier {
       if (!Ev)
         return false;
 
-      LLVM_DEBUG({
-        dbgs() << "loop exit phi scev: ";
-        Ev->print(dbgs());
-        dbgs() << "\n";
-      });
+      LLVM_DEBUG(dbgs() << "loop exit phi scev: " << *Ev << "\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
@@ -1763,6 +1750,18 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
   BasicBlock *Preheader = CurLoop->getLoopPreheader();
   BasicBlock *LoopExitBB = CurLoop->getExitBlock();
 
+  if (Verifier.OpWidth == 8) {
+    if (DisableLIRP::Strlen)
+      return false;
+    if (!isLibFuncEmittable(Preheader->getModule(), TLI, LibFunc_strlen))
+      return false;
+  } else {
+    if (DisableLIRP::Wcslen)
+      return false;
+    if (!isLibFuncEmittable(Preheader->getModule(), TLI, LibFunc_wcslen))
+      return false;
+  }
+
   IRBuilder<> Builder(Preheader->getTerminator());
   SCEVExpander Expander(*SE, Preheader->getModule()->getDataLayout(),
                         "strlen_idiom");
@@ -1772,16 +1771,8 @@ bool LoopIdiomRecognize::recognizeAndInsertStrLen() {
 
   Value *StrLenFunc = nullptr;
   if (Verifier.OpWidth == 8) {
-    if (DisableLIRP::Strlen)
-      return false;
-    if (!isLibFuncEmittable(Preheader->getModule(), TLI, LibFunc_strlen))
-      return false;
     StrLenFunc = emitStrLen(MaterialzedBase, Builder, *DL, TLI);
   } else {
-    if (DisableLIRP::Wcslen)
-      return false;
-    if (!isLibFuncEmittable(Preheader->getModule(), TLI, LibFunc_wcslen))
-      return false;
     StrLenFunc = emitWcsLen(MaterialzedBase, Builder, *DL, TLI);
   }
   assert(StrLenFunc && "Failed to emit strlen function.");

>From b1f81d054f76af609d3fc4544688ea2d686b0bcd Mon Sep 17 00:00:00 2001
From: Henry Jiang <henry.jiang1 at ibm.com>
Date: Fri, 21 Mar 2025 12:55:02 -0400
Subject: [PATCH 2/2] remove verify pass

---
 llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp      | 6 +-----
 llvm/test/Transforms/LoopIdiom/strlen-not-emittable.ll | 2 +-
 llvm/test/Transforms/LoopIdiom/strlen.ll               | 2 +-
 llvm/test/Transforms/LoopIdiom/wcslen16.ll             | 2 +-
 llvm/test/Transforms/LoopIdiom/wcslen32.ll             | 2 +-
 5 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index 7f92f5f65a972..d754e6b09bbe5 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -1602,11 +1602,7 @@ class StrlenVerifier {
       return false;
     LoadBaseEv = LoadEv->getStart();
 
-    LLVM_DEBUG({
-      dbgs() << "pointer load scev: ";
-      LoadEv->print(outs());
-      dbgs() << "\n";
-    });
+    LLVM_DEBUG(dbgs() << "pointer load scev: " << *LoadEv << "\n");
 
     const SCEVConstant *Step =
         dyn_cast<SCEVConstant>(LoadEv->getStepRecurrence(*SE));
diff --git a/llvm/test/Transforms/LoopIdiom/strlen-not-emittable.ll b/llvm/test/Transforms/LoopIdiom/strlen-not-emittable.ll
index 0be76cbd42a72..00fbe89846a30 100644
--- a/llvm/test/Transforms/LoopIdiom/strlen-not-emittable.ll
+++ b/llvm/test/Transforms/LoopIdiom/strlen-not-emittable.ll
@@ -1,4 +1,4 @@
-; RUN: opt -passes='loop(loop-idiom),verify' < %s -S | FileCheck %s
+; RUN: opt -passes='loop(loop-idiom)' < %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"
diff --git a/llvm/test/Transforms/LoopIdiom/strlen.ll b/llvm/test/Transforms/LoopIdiom/strlen.ll
index 137a17f541cd4..c1141177c659f 100644
--- a/llvm/test/Transforms/LoopIdiom/strlen.ll
+++ b/llvm/test/Transforms/LoopIdiom/strlen.ll
@@ -1,5 +1,5 @@
 ; 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
+; RUN: opt -passes='loop(loop-idiom)' < %s -S | FileCheck %s
 
 declare void @other()
 declare void @use(ptr)
diff --git a/llvm/test/Transforms/LoopIdiom/wcslen16.ll b/llvm/test/Transforms/LoopIdiom/wcslen16.ll
index d3b0b8d208cd8..8be51869f1f2e 100644
--- a/llvm/test/Transforms/LoopIdiom/wcslen16.ll
+++ b/llvm/test/Transforms/LoopIdiom/wcslen16.ll
@@ -1,5 +1,5 @@
 ; 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
+; RUN: opt -passes='loop(loop-idiom)' < %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"
diff --git a/llvm/test/Transforms/LoopIdiom/wcslen32.ll b/llvm/test/Transforms/LoopIdiom/wcslen32.ll
index 488afff86c245..2c7ceb4d187e6 100644
--- a/llvm/test/Transforms/LoopIdiom/wcslen32.ll
+++ b/llvm/test/Transforms/LoopIdiom/wcslen32.ll
@@ -1,5 +1,5 @@
 ; 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
+; RUN: opt -passes='loop(loop-idiom)' < %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"



More information about the llvm-commits mailing list