[llvm] [Transforms] Mirror optimizeStrRChr with optimizeStrChr (PR #77685)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 11 07:54:52 PST 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/77685
>From 791e4974781c340436a135f2ae0ca51e985aa8c5 Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Wed, 10 Jan 2024 15:44:36 -0500
Subject: [PATCH 1/3] [Transforms] Mirror optimizeStrRChr with optimizeStrChr
strchr and strrchr have a lot in common. Basically, they can have most optimizations applied to them, only difference being we work backwards, and the "end" of the string being the first argument, and the "start" being the null terminator. Basically, we can do similar transformations with the same transformations and checks, especially if memrchr does the same as memchr but backwards from the null terminator.
---
.../lib/Transforms/Utils/SimplifyLibCalls.cpp | 55 +++++++++++++++----
1 file changed, 44 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index a7cd68e860e467b..d0da4771f698e66 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -483,8 +483,7 @@ Value *LibCallSimplifier::optimizeStrChr(CallInst *CI, IRBuilderBase &B) {
Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits);
return copyFlags(*CI,
emitMemChr(SrcStr, CharVal, // include nul.
- ConstantInt::get(SizeTTy, Len), B,
- DL, TLI));
+ ConstantInt::get(SizeTTy, Len), B, DL, TLI));
}
if (CharC->isZero()) {
@@ -523,22 +522,56 @@ Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilderBase &B) {
ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal);
annotateNonNullNoUndefBasedOnAccess(CI, 0);
+ if (!CharC) {
+ uint64_t Len = GetStringLength(SrcStr);
+ if (Len)
+ annotateDereferenceableBytes(CI, 0, Len);
+ else
+ return nullptr;
+
+ Function *Callee = CI->getCalledFunction();
+ FunctionType *FT = Callee->getFunctionType();
+ unsigned IntBits = TLI->getIntSize();
+ if (!FT->getParamType(1)->isIntegerTy(IntBits)) // memrchr needs 'int'.
+ return nullptr;
+
+ unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());
+ Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits);
+
+ // Try to expand strrchr to the memrchr nonstandard extension if it's
+ // available, or simply fail otherwise.
+ return copyFlags(*CI,
+ emitMemRChr(SrcStr, CharVal, // include nul.
+ ConstantInt::get(SizeTTy, Len), B, DL, TLI));
+ }
+
+ if (CharC->isZero()) {
+ Value *NullPtr = Constant::getNullValue(CI->getType());
+ if (isOnlyUsedInEqualityComparison(CI, NullPtr))
+ // Pre-empt the transformation to strlen below and fold
+ // strrchr(A, '\0') == null to false.
+ return B.CreateIntToPtr(B.getTrue(), CI->getType());
+ }
+
+ // Otherwise, the character is a constant, see if the first argument is
+ // a string literal. If so, we can constant fold.
StringRef Str;
if (!getConstantStringInfo(SrcStr, Str)) {
- // strrchr(s, 0) -> strchr(s, 0)
- if (CharC && CharC->isZero())
+ if (CharC->isZero()) // strrchr(p, 0) -> strchr(p, 0)
return copyFlags(*CI, emitStrChr(SrcStr, '\0', B, TLI));
return nullptr;
}
- unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());
- Type *SizeTTy = IntegerType::get(CI->getContext(), SizeTBits);
+ // Compute the offset, make sure to handle the case when we're searching for
+ // zero (a weird way to spell strlen).
+ size_t I = (0xFF & CharC->getSExtValue()) == 0
+ ? Str.size()
+ : Str.rfind(CharC->getSExtValue());
+ if (I == StringRef::npos) // Didn't find the char. strrchr returns null.
+ return Constant::getNullValue(CI->getType());
- // Try to expand strrchr to the memrchr nonstandard extension if it's
- // available, or simply fail otherwise.
- uint64_t NBytes = Str.size() + 1; // Include the terminating nul.
- Value *Size = ConstantInt::get(SizeTTy, NBytes);
- return copyFlags(*CI, emitMemRChr(SrcStr, CharVal, Size, B, DL, TLI));
+ // strrchr(s+n,c) -> gep(s+n+i,c)
+ return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "strrchr");
}
Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilderBase &B) {
>From 2170e6c0f9e7a25120a4dee84f46b8d8dd228f53 Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Thu, 11 Jan 2024 10:23:13 -0500
Subject: [PATCH 2/3] test
---
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index d0da4771f698e66..39ea0ff03396c2f 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -557,18 +557,19 @@ Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilderBase &B) {
// a string literal. If so, we can constant fold.
StringRef Str;
if (!getConstantStringInfo(SrcStr, Str)) {
- if (CharC->isZero()) // strrchr(p, 0) -> strchr(p, 0)
- return copyFlags(*CI, emitStrChr(SrcStr, '\0', B, TLI));
+ if (CharC->isZero()) // strrchr(p, 0) -> p + strlen(p)
+ if (Value *StrLen = emitStrLen(SrcStr, B, DL, TLI))
+ return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, StrLen, "strrchr");
return nullptr;
}
// Compute the offset, make sure to handle the case when we're searching for
// zero (a weird way to spell strlen).
- size_t I = (0xFF & CharC->getSExtValue()) == 0
- ? Str.size()
- : Str.rfind(CharC->getSExtValue());
- if (I == StringRef::npos) // Didn't find the char. strrchr returns null.
- return Constant::getNullValue(CI->getType());
+ // size_t I = (0xFF & CharC->getSExtValue()) == 0
+ // ? Str.size()
+ // : Str.rfind(CharC->getSExtValue());
+ // if (I == StringRef::npos) // Didn't find the char. strrchr returns null.
+ // return Constant::getNullValue(CI->getType());
// strrchr(s+n,c) -> gep(s+n+i,c)
return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "strrchr");
>From 7f4d77db496d4264ba8d5d06a5dc59d9a2cb5953 Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Thu, 11 Jan 2024 10:53:47 -0500
Subject: [PATCH 3/3] Update SimplifyLibCalls.cpp
---
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 39ea0ff03396c2f..a16a8d80c54ba45 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -565,11 +565,11 @@ Value *LibCallSimplifier::optimizeStrRChr(CallInst *CI, IRBuilderBase &B) {
// Compute the offset, make sure to handle the case when we're searching for
// zero (a weird way to spell strlen).
- // size_t I = (0xFF & CharC->getSExtValue()) == 0
- // ? Str.size()
- // : Str.rfind(CharC->getSExtValue());
- // if (I == StringRef::npos) // Didn't find the char. strrchr returns null.
- // return Constant::getNullValue(CI->getType());
+ size_t I = (0xFF & CharC->getSExtValue()) == 0
+ ? Str.size()
+ : Str.rfind(CharC->getSExtValue());
+ if (I == StringRef::npos) // Didn't find the char. strrchr returns null.
+ return Constant::getNullValue(CI->getType());
// strrchr(s+n,c) -> gep(s+n+i,c)
return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "strrchr");
More information about the llvm-commits
mailing list