forked from OSchip/llvm-project
[InstCombine] Fold strnlen of constant strings.
Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D123817
This commit is contained in:
parent
a1bb5719ec
commit
449adafabe
|
@ -632,6 +632,7 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B,
|
||||||
unsigned CharSize,
|
unsigned CharSize,
|
||||||
Value *Bound) {
|
Value *Bound) {
|
||||||
Value *Src = CI->getArgOperand(0);
|
Value *Src = CI->getArgOperand(0);
|
||||||
|
Type *CharTy = B.getIntNTy(CharSize);
|
||||||
|
|
||||||
if (Bound) {
|
if (Bound) {
|
||||||
if (ConstantInt *BoundCst = dyn_cast<ConstantInt>(Bound)) {
|
if (ConstantInt *BoundCst = dyn_cast<ConstantInt>(Bound)) {
|
||||||
|
@ -641,20 +642,26 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B,
|
||||||
|
|
||||||
if (BoundCst->isOne()) {
|
if (BoundCst->isOne()) {
|
||||||
// Fold strnlen(s, 1) -> *s ? 1 : 0 for any s.
|
// Fold strnlen(s, 1) -> *s ? 1 : 0 for any s.
|
||||||
Type *CharTy = B.getIntNTy(CharSize);
|
|
||||||
Value *CharVal = B.CreateLoad(CharTy, Src, "strnlen.char0");
|
Value *CharVal = B.CreateLoad(CharTy, Src, "strnlen.char0");
|
||||||
Value *ZeroChar = ConstantInt::get(CharTy, 0);
|
Value *ZeroChar = ConstantInt::get(CharTy, 0);
|
||||||
Value *Cmp = B.CreateICmpNE(CharVal, ZeroChar, "strnlen.char0cmp");
|
Value *Cmp = B.CreateICmpNE(CharVal, ZeroChar, "strnlen.char0cmp");
|
||||||
return B.CreateZExt(Cmp, CI->getType());
|
return B.CreateZExt(Cmp, CI->getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise punt for strnlen for now.
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constant folding: strlen("xyz") -> 3
|
if (uint64_t Len = GetStringLength(Src, CharSize)) {
|
||||||
if (uint64_t Len = GetStringLength(Src, CharSize))
|
Value *LenC = ConstantInt::get(CI->getType(), Len - 1);
|
||||||
return ConstantInt::get(CI->getType(), Len - 1);
|
// Fold strlen("xyz") -> 3 and strnlen("xyz", 2) -> 2
|
||||||
|
// and strnlen("xyz", Bound) -> min(3, Bound) for nonconstant Bound.
|
||||||
|
if (Bound)
|
||||||
|
return B.CreateBinaryIntrinsic(Intrinsic::umin, LenC, Bound);
|
||||||
|
return LenC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Bound)
|
||||||
|
// Punt for strnlen for now.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
// If s is a constant pointer pointing to a string literal, we can fold
|
// If s is a constant pointer pointing to a string literal, we can fold
|
||||||
// strlen(s + x) to strlen(s) - x, when x is known to be in the range
|
// strlen(s + x) to strlen(s) - x, when x is known to be in the range
|
||||||
|
|
|
@ -95,8 +95,7 @@ define i64 @fold_strnlen_s5_0() {
|
||||||
|
|
||||||
define i64 @fold_strnlen_s5_4() {
|
define i64 @fold_strnlen_s5_4() {
|
||||||
; CHECK-LABEL: @fold_strnlen_s5_4(
|
; CHECK-LABEL: @fold_strnlen_s5_4(
|
||||||
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i64 4)
|
; CHECK-NEXT: ret i64 4
|
||||||
; CHECK-NEXT: ret i64 [[LEN]]
|
|
||||||
;
|
;
|
||||||
%ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0
|
%ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0
|
||||||
%len = call i64 @strnlen(i8* %ptr, i64 4)
|
%len = call i64 @strnlen(i8* %ptr, i64 4)
|
||||||
|
@ -108,8 +107,7 @@ define i64 @fold_strnlen_s5_4() {
|
||||||
|
|
||||||
define i64 @fold_strnlen_s5_5() {
|
define i64 @fold_strnlen_s5_5() {
|
||||||
; CHECK-LABEL: @fold_strnlen_s5_5(
|
; CHECK-LABEL: @fold_strnlen_s5_5(
|
||||||
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i64 5)
|
; CHECK-NEXT: ret i64 5
|
||||||
; CHECK-NEXT: ret i64 [[LEN]]
|
|
||||||
;
|
;
|
||||||
%ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0
|
%ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0
|
||||||
%len = call i64 @strnlen(i8* %ptr, i64 5)
|
%len = call i64 @strnlen(i8* %ptr, i64 5)
|
||||||
|
@ -121,8 +119,7 @@ define i64 @fold_strnlen_s5_5() {
|
||||||
|
|
||||||
define i64 @fold_strnlen_s5_m1() {
|
define i64 @fold_strnlen_s5_m1() {
|
||||||
; CHECK-LABEL: @fold_strnlen_s5_m1(
|
; CHECK-LABEL: @fold_strnlen_s5_m1(
|
||||||
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @s5, i64 0, i64 0), i64 -1)
|
; CHECK-NEXT: ret i64 5
|
||||||
; CHECK-NEXT: ret i64 [[LEN]]
|
|
||||||
;
|
;
|
||||||
%ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0
|
%ptr = getelementptr [6 x i8], [6 x i8]* @s5, i32 0, i32 0
|
||||||
%len = call i64 @strnlen(i8* %ptr, i64 -1)
|
%len = call i64 @strnlen(i8* %ptr, i64 -1)
|
||||||
|
@ -134,8 +131,7 @@ define i64 @fold_strnlen_s5_m1() {
|
||||||
|
|
||||||
define i64 @fold_strnlen_s5_3_p4_5() {
|
define i64 @fold_strnlen_s5_3_p4_5() {
|
||||||
; CHECK-LABEL: @fold_strnlen_s5_3_p4_5(
|
; CHECK-LABEL: @fold_strnlen_s5_3_p4_5(
|
||||||
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @s5_3, i64 0, i64 4), i64 5)
|
; CHECK-NEXT: ret i64 1
|
||||||
; CHECK-NEXT: ret i64 [[LEN]]
|
|
||||||
;
|
;
|
||||||
%ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 4
|
%ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 4
|
||||||
%len = call i64 @strnlen(i8* %ptr, i64 5)
|
%len = call i64 @strnlen(i8* %ptr, i64 5)
|
||||||
|
@ -143,12 +139,11 @@ define i64 @fold_strnlen_s5_3_p4_5() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
; Fold strnlen(s5_3 + 5, 5) to 1.
|
; Fold strnlen(s5_3 + 5, 5) to 0.
|
||||||
|
|
||||||
define i64 @fold_strnlen_s5_3_p5_5() {
|
define i64 @fold_strnlen_s5_3_p5_5() {
|
||||||
; CHECK-LABEL: @fold_strnlen_s5_3_p5_5(
|
; CHECK-LABEL: @fold_strnlen_s5_3_p5_5(
|
||||||
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @s5_3, i64 0, i64 5), i64 5)
|
; CHECK-NEXT: ret i64 0
|
||||||
; CHECK-NEXT: ret i64 [[LEN]]
|
|
||||||
;
|
;
|
||||||
%ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 5
|
%ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 5
|
||||||
%len = call i64 @strnlen(i8* %ptr, i64 5)
|
%len = call i64 @strnlen(i8* %ptr, i64 5)
|
||||||
|
@ -160,8 +155,7 @@ define i64 @fold_strnlen_s5_3_p5_5() {
|
||||||
|
|
||||||
define i64 @fold_strnlen_s5_3_p6_5() {
|
define i64 @fold_strnlen_s5_3_p6_5() {
|
||||||
; CHECK-LABEL: @fold_strnlen_s5_3_p6_5(
|
; CHECK-LABEL: @fold_strnlen_s5_3_p6_5(
|
||||||
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([9 x i8], [9 x i8]* @s5_3, i64 0, i64 6), i64 5)
|
; CHECK-NEXT: ret i64 3
|
||||||
; CHECK-NEXT: ret i64 [[LEN]]
|
|
||||||
;
|
;
|
||||||
%ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 6
|
%ptr = getelementptr [9 x i8], [9 x i8]* @s5_3, i32 0, i32 6
|
||||||
%len = call i64 @strnlen(i8* %ptr, i64 5)
|
%len = call i64 @strnlen(i8* %ptr, i64 5)
|
||||||
|
|
|
@ -126,8 +126,8 @@ define i64 @call_strnlen_s5_3_pi_n(i64 zeroext %i, i64 %n) {
|
||||||
|
|
||||||
define i64 @fold_strnlen_a3_n(i64 %n) {
|
define i64 @fold_strnlen_a3_n(i64 %n) {
|
||||||
; CHECK-LABEL: @fold_strnlen_a3_n(
|
; CHECK-LABEL: @fold_strnlen_a3_n(
|
||||||
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @a3, i64 0, i64 0), i64 [[N:%.*]])
|
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.umin.i64(i64 [[N:%.*]], i64 3)
|
||||||
; CHECK-NEXT: ret i64 [[LEN]]
|
; CHECK-NEXT: ret i64 [[TMP1]]
|
||||||
;
|
;
|
||||||
|
|
||||||
%ptr = getelementptr [3 x i8], [3 x i8]* @a3, i64 0, i64 0
|
%ptr = getelementptr [3 x i8], [3 x i8]* @a3, i64 0, i64 0
|
||||||
|
@ -140,8 +140,8 @@ define i64 @fold_strnlen_a3_n(i64 %n) {
|
||||||
|
|
||||||
define i64 @fold_strnlen_s3_n(i64 %n) {
|
define i64 @fold_strnlen_s3_n(i64 %n) {
|
||||||
; CHECK-LABEL: @fold_strnlen_s3_n(
|
; CHECK-LABEL: @fold_strnlen_s3_n(
|
||||||
; CHECK-NEXT: [[LEN:%.*]] = call i64 @strnlen(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @s3, i64 0, i64 0), i64 [[N:%.*]])
|
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.umin.i64(i64 [[N:%.*]], i64 3)
|
||||||
; CHECK-NEXT: ret i64 [[LEN]]
|
; CHECK-NEXT: ret i64 [[TMP1]]
|
||||||
;
|
;
|
||||||
|
|
||||||
%ptr = getelementptr [4 x i8], [4 x i8]* @s3, i64 0, i64 0
|
%ptr = getelementptr [4 x i8], [4 x i8]* @s3, i64 0, i64 0
|
||||||
|
|
Loading…
Reference in New Issue