Files
clang-p2996/llvm/test/Transforms/InstCombine/strchr-3.ll
Nikita Popov 635f93dff7 [SimplifyLibCalls] Place deref attr even if nonnull already set
If nonnull is already set, we currently skip setting both nonnull
and dereferenceable. Make these independent, to avoid regressions
when additional nonnull attributes are inferred earlier.
2022-10-04 11:26:15 +02:00

124 lines
4.7 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
;
; Verify that strchr calls with a string consisting of one or two sequences
; of all the same characters are folded and those with mixed strings are not.
@s1 = constant [2 x i8] c"\01\00"
@s11 = constant [3 x i8] c"\01\01\00"
@s111 = constant [4 x i8] c"\01\01\01\00"
@s000 = constant [4 x i8] c"\00\00\00\00"
@s11102 = constant [6 x i8] c"\01\01\01\00\02\00"
@s21111 = constant [6 x i8] c"\02\01\01\01\01\00"
declare ptr @strchr(ptr, i32)
; Fold strchr(S = "\01", C) to C == '\01' ? S : C == '\0' ? S + 1 : null.
define ptr @fold_strchr_s1_C(i32 %C) {
; CHECK-LABEL: @fold_strchr_s1_C(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([2 x i8], ptr @s1, i64 0, i64 1), ptr null
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @s1, ptr [[MEMCHR_SEL1]]
; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]]
;
%ret = call ptr @strchr(ptr @s1, i32 %C)
ret ptr %ret
}
; Fold strchr(S = "\01\01", C) to C == '\01' ? S : C == '\0' ? S + 2 : null.
define ptr @fold_strchr_s11_C(i32 %C) {
; CHECK-LABEL: @fold_strchr_s11_C(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([3 x i8], ptr @s11, i64 0, i64 2), ptr null
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @s11, ptr [[MEMCHR_SEL1]]
; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]]
;
%ret = call ptr @strchr(ptr @s11, i32 %C)
ret ptr %ret
}
; Fold strchr(S = "\01\01\01", C) to C == '\01' ? S : C == '\0' ? S + 3 : null.
define ptr @fold_strchr_s111_C(i32 %C) {
; CHECK-LABEL: @fold_strchr_s111_C(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([4 x i8], ptr @s111, i64 0, i64 3), ptr null
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @s111, ptr [[MEMCHR_SEL1]]
; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]]
;
%ret = call ptr @strchr(ptr @s111, i32 %C)
ret ptr %ret
}
; Fold strchr(S = "\00\00\00", C) to C == '\0' ? S : null.
define ptr @fold_strchr_s000_C(i32 %C) {
; CHECK-LABEL: @fold_strchr_s000_C(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[MEMCHR_CHAR0CMP:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: [[MEMCHR_SEL:%.*]] = select i1 [[MEMCHR_CHAR0CMP]], ptr @s000, ptr null
; CHECK-NEXT: ret ptr [[MEMCHR_SEL]]
;
%ret = call ptr @strchr(ptr @s000, i32 %C)
ret ptr %ret
}
; Do not fold strchr(S = "\02\01\01\01\01", C). It's transformed to
; memchr(S, C, 6).
define ptr @xform_strchr_s21111_C(i32 %C) {
; CHECK-LABEL: @xform_strchr_s21111_C(
; CHECK-NEXT: [[MEMCHR:%.*]] = call ptr @memchr(ptr noundef nonnull dereferenceable(1) @s21111, i32 [[C:%.*]], i64 6)
; CHECK-NEXT: ret ptr [[MEMCHR]]
;
%ret = call ptr @strchr(ptr @s21111, i32 %C)
ret ptr %ret
}
; Fold strchr(S = "\02\01\01\01\01" + 1, C) to
; C == '\01' ? S + 1 : C == '\0' ? S + 5 : null.
define ptr @fold_strchr_s21111p1_C(i32 %C) {
; CHECK-LABEL: @fold_strchr_s21111p1_C(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([6 x i8], ptr @s21111, i64 0, i64 5), ptr null
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr getelementptr inbounds ([6 x i8], ptr @s21111, i64 0, i64 1), ptr [[MEMCHR_SEL1]]
; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]]
;
%ptr = getelementptr inbounds [6 x i8], ptr @s21111, i64 0, i64 1
%ret = call ptr @strchr(ptr %ptr, i32 %C)
ret ptr %ret
}
; Fold strchr(S = "\01\01\01\00\02", C) to
; C == '\01' ? S : C == '\0' ? S + 3 : null.
define ptr @fold_strchr_s11102_C(i32 %C) {
; CHECK-LABEL: @fold_strchr_s11102_C(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], ptr getelementptr inbounds ([6 x i8], ptr @s11102, i64 0, i64 3), ptr null
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], ptr @s11102, ptr [[MEMCHR_SEL1]]
; CHECK-NEXT: ret ptr [[MEMCHR_SEL2]]
;
%ret = call ptr @strchr(ptr @s11102, i32 %C)
ret ptr %ret
}