[llvm] efa0f12 - [InstCombine] Fold strnlen calls in equality to zero.
Martin Sebor via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 27 11:06:01 PDT 2022
Author: Martin Sebor
Date: 2022-04-27T12:03:24-06:00
New Revision: efa0f12c0beb20e0c7103efed3c5e0400c525811
URL: https://github.com/llvm/llvm-project/commit/efa0f12c0beb20e0c7103efed3c5e0400c525811
DIFF: https://github.com/llvm/llvm-project/commit/efa0f12c0beb20e0c7103efed3c5e0400c525811.diff
LOG: [InstCombine] Fold strnlen calls in equality to zero.
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D123818
Added:
Modified:
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
llvm/test/Transforms/InstCombine/strnlen-5.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 4e170e830c7ef..38dca391b6789 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -637,6 +637,18 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B,
Value *Src = CI->getArgOperand(0);
Type *CharTy = B.getIntNTy(CharSize);
+ if (isOnlyUsedInZeroEqualityComparison(CI) &&
+ (!Bound || isKnownNonZero(Bound, DL))) {
+ // Fold strlen:
+ // strlen(x) != 0 --> *x != 0
+ // strlen(x) == 0 --> *x == 0
+ // and likewise strnlen with constant N > 0:
+ // strnlen(x, N) != 0 --> *x != 0
+ // strnlen(x, N) == 0 --> *x == 0
+ return B.CreateZExt(B.CreateLoad(CharTy, Src, "char0"),
+ CI->getType());
+ }
+
if (Bound) {
if (ConstantInt *BoundCst = dyn_cast<ConstantInt>(Bound)) {
if (BoundCst->isZero())
@@ -731,12 +743,6 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B,
}
}
- // strlen(x) != 0 --> *x != 0
- // strlen(x) == 0 --> *x == 0
- if (isOnlyUsedInZeroEqualityComparison(CI))
- return B.CreateZExt(B.CreateLoad(B.getIntNTy(CharSize), Src, "strlenfirst"),
- CI->getType());
-
return nullptr;
}
diff --git a/llvm/test/Transforms/InstCombine/strnlen-5.ll b/llvm/test/Transforms/InstCombine/strnlen-5.ll
index 790ad12ea4e63..15e951cb11e8d 100644
--- a/llvm/test/Transforms/InstCombine/strnlen-5.ll
+++ b/llvm/test/Transforms/InstCombine/strnlen-5.ll
@@ -43,6 +43,22 @@ define i1 @fold_strnlen_ax_0_gtz() {
define i1 @fold_strnlen_ax_1_eqz() {
; CHECK-LABEL: @fold_strnlen_ax_1_eqz(
+; CHECK-NEXT: [[CHAR0:%.*]] = load i8, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), align 1
+; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0
+; CHECK-NEXT: ret i1 [[EQZ]]
+;
+
+ %ptr = getelementptr [0 x i8], [0 x i8]* @ax, i64 0, i64 0
+ %len = tail call i64 @strnlen(i8* %ptr, i64 1)
+ %eqz = icmp eq i64 %len, 0
+ ret i1 %eqz
+}
+
+
+; Likewise, fold strnlen(ax, 1) < 1 to *ax == 0.
+
+define i1 @fold_strnlen_ax_1_lt1() {
+; CHECK-LABEL: @fold_strnlen_ax_1_lt1(
; CHECK-NEXT: [[STRNLEN_CHAR0:%.*]] = load i8, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), align 1
; CHECK-NEXT: [[STRNLEN_CHAR0CMP_NOT:%.*]] = icmp eq i8 [[STRNLEN_CHAR0]], 0
; CHECK-NEXT: ret i1 [[STRNLEN_CHAR0CMP_NOT]]
@@ -50,8 +66,8 @@ define i1 @fold_strnlen_ax_1_eqz() {
%ptr = getelementptr [0 x i8], [0 x i8]* @ax, i64 0, i64 0
%len = tail call i64 @strnlen(i8* %ptr, i64 1)
- %eqz = icmp eq i64 %len, 0
- ret i1 %eqz
+ %nez = icmp ult i64 %len, 1
+ ret i1 %nez
}
@@ -59,6 +75,22 @@ define i1 @fold_strnlen_ax_1_eqz() {
define i1 @fold_strnlen_ax_1_neqz() {
; CHECK-LABEL: @fold_strnlen_ax_1_neqz(
+; CHECK-NEXT: [[CHAR0:%.*]] = load i8, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), align 1
+; CHECK-NEXT: [[NEZ:%.*]] = icmp ne i8 [[CHAR0]], 0
+; CHECK-NEXT: ret i1 [[NEZ]]
+;
+
+ %ptr = getelementptr [0 x i8], [0 x i8]* @ax, i64 0, i64 0
+ %len = tail call i64 @strnlen(i8* %ptr, i64 1)
+ %nez = icmp ne i64 %len, 0
+ ret i1 %nez
+}
+
+
+; Likewise, fold strnlen(ax, 1) > 0 to *ax != 0.
+
+define i1 @fold_strnlen_ax_1_gtz() {
+; CHECK-LABEL: @fold_strnlen_ax_1_gtz(
; CHECK-NEXT: [[STRNLEN_CHAR0:%.*]] = load i8, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), align 1
; CHECK-NEXT: [[STRNLEN_CHAR0CMP:%.*]] = icmp ne i8 [[STRNLEN_CHAR0]], 0
; CHECK-NEXT: ret i1 [[STRNLEN_CHAR0CMP]]
@@ -66,7 +98,7 @@ define i1 @fold_strnlen_ax_1_neqz() {
%ptr = getelementptr [0 x i8], [0 x i8]* @ax, i64 0, i64 0
%len = tail call i64 @strnlen(i8* %ptr, i64 1)
- %nez = icmp ne i64 %len, 0
+ %nez = icmp ugt i64 %len, 0
ret i1 %nez
}
@@ -75,8 +107,8 @@ define i1 @fold_strnlen_ax_1_neqz() {
define i1 @fold_strnlen_ax_9_eqz() {
; CHECK-LABEL: @fold_strnlen_ax_9_eqz(
-; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 9)
-; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0
+; CHECK-NEXT: [[CHAR0:%.*]] = load i8, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), align 1
+; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0
; CHECK-NEXT: ret i1 [[EQZ]]
;
@@ -107,9 +139,8 @@ define i1 @call_strnlen_ax_n_eqz(i64 %n) {
define i1 @fold_strnlen_ax_nz_eqz(i64 %n) {
; CHECK-LABEL: @fold_strnlen_ax_nz_eqz(
-; CHECK-NEXT: [[MAX:%.*]] = or i64 [[N:%.*]], 1
-; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 [[MAX]])
-; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0
+; CHECK-NEXT: [[CHAR0:%.*]] = load i8, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), align 1
+; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0
; CHECK-NEXT: ret i1 [[EQZ]]
;
@@ -125,9 +156,8 @@ define i1 @fold_strnlen_ax_nz_eqz(i64 %n) {
define i1 @fold_strnlen_ax_nz_gtz(i64 %n) {
; CHECK-LABEL: @fold_strnlen_ax_nz_gtz(
-; CHECK-NEXT: [[MAX:%.*]] = or i64 [[N:%.*]], 1
-; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), i64 [[MAX]])
-; CHECK-NEXT: [[GTZ:%.*]] = icmp ne i64 [[LEN]], 0
+; CHECK-NEXT: [[CHAR0:%.*]] = load i8, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @ax, i64 0, i64 0), align 1
+; CHECK-NEXT: [[GTZ:%.*]] = icmp ne i8 [[CHAR0]], 0
; CHECK-NEXT: ret i1 [[GTZ]]
;
@@ -144,10 +174,9 @@ define i1 @fold_strnlen_ax_nz_gtz(i64 %n) {
define i1 @fold_strnlen_a5_pi_nz_eqz(i64 %i, i64 %n) {
; CHECK-LABEL: @fold_strnlen_a5_pi_nz_eqz(
-; CHECK-NEXT: [[NZ:%.*]] = or i64 [[N:%.*]], 1
; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [5 x i8], [5 x i8]* @a5, i64 0, i64 [[I:%.*]]
-; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 [[NZ]])
-; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0
+; CHECK-NEXT: [[CHAR0:%.*]] = load i8, i8* [[PTR]], align 1
+; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i8 [[CHAR0]], 0
; CHECK-NEXT: ret i1 [[EQZ]]
;
@@ -165,10 +194,7 @@ define i1 @fold_strnlen_a5_pi_nz_eqz(i64 %i, i64 %n) {
define i1 @fold_strnlen_s5_pi_nz_eqz(i64 %i, i64 %n) {
; CHECK-LABEL: @fold_strnlen_s5_pi_nz_eqz(
-; CHECK-NEXT: [[NZ:%.*]] = or i64 [[N:%.*]], 1
-; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [6 x i8], [6 x i8]* @s5, i64 0, i64 [[I:%.*]]
-; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull [[PTR]], i64 [[NZ]])
-; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[LEN]], 0
+; CHECK-NEXT: [[EQZ:%.*]] = icmp eq i64 [[I:%.*]], 5
; CHECK-NEXT: ret i1 [[EQZ]]
;
More information about the llvm-commits
mailing list