1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
;
; Verify that memchr calls with a string consisting of all the same
; characters are folded and those with mixed strings are not.
declare i8* @memchr(i8*, i32, i64)
@a00000 = constant [5 x i8] zeroinitializer
@a11111 = constant [5 x i8] c"\01\01\01\01\01"
@a111122 = constant [6 x i8] c"\01\01\01\01\02\02"
@a1110111 = constant [7 x i8] c"\01\01\01\00\01\01\01"
; Fold memchr(a00000, C, 5) to *a00000 == C ? a00000 : null.
; TODO: This depends on getConstantStringInfo() being able to handle
; implicitly zeroed out constants.
define i8* @fold_memchr_a00000_c_5(i32 %C) {
; CHECK-LABEL: @fold_memchr_a00000_c_5(
; CHECK-NEXT: [[RET:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @a00000, i64 0, i64 0), i32 [[C:%.*]], i64 5)
; CHECK-NEXT: ret i8* [[RET]]
;
%ptr = getelementptr [5 x i8], [5 x i8]* @a00000, i64 0, i64 0
%ret = call i8* @memchr(i8* %ptr, i32 %C, i64 5)
ret i8* %ret
}
; Fold memchr(a11111, C, 5) to *a11111 == C ? a11111 : null.
define i8* @fold_memchr_a11111_c_5(i32 %C) {
; CHECK-LABEL: @fold_memchr_a11111_c_5(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP2]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @a11111, i64 0, i64 0), i8* null
; CHECK-NEXT: ret i8* [[MEMCHR_SEL2]]
;
%ptr = getelementptr [5 x i8], [5 x i8]* @a11111, i64 0, i64 0
%ret = call i8* @memchr(i8* %ptr, i32 %C, i64 5)
ret i8* %ret
}
; Fold memchr(a11111, C, N) to N && *a11111 == C ? a11111 : null,
; on the assumption that N is in bounds.
define i8* @fold_memchr_a11111_c_n(i32 %C, i64 %N) {
; CHECK-LABEL: @fold_memchr_a11111_c_n(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[N:%.*]], 0
; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[TMP2]]
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP4]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @a11111, i64 0, i64 0), i8* null
; CHECK-NEXT: ret i8* [[MEMCHR_SEL2]]
;
%ptr = getelementptr [5 x i8], [5 x i8]* @a11111, i64 0, i64 0
%ret = call i8* @memchr(i8* %ptr, i32 %C, i64 %N)
ret i8* %ret
}
; Fold memchr(a111122, C, N) to
; N != 0 && C == 1 ? a111122 : N > 4 && C == 2 ? a111122 + 4 : null.
define i8* @fold_memchr_a111122_c_n(i32 %C, i64 %N) {
; CHECK-LABEL: @fold_memchr_a111122_c_n(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 2
; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i64 [[N:%.*]], 4
; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP2]], [[TMP3]]
; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP4]], i8* getelementptr inbounds ([6 x i8], [6 x i8]* @a111122, i64 0, i64 4), i8* null
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i64 [[N]], 0
; CHECK-NEXT: [[TMP7:%.*]] = and i1 [[TMP6]], [[TMP5]]
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP7]], i8* getelementptr inbounds ([6 x i8], [6 x i8]* @a111122, i64 0, i64 0), i8* [[MEMCHR_SEL1]]
; CHECK-NEXT: ret i8* [[MEMCHR_SEL2]]
;
%ptr = getelementptr [6 x i8], [6 x i8]* @a111122, i64 0, i64 0
%ret = call i8* @memchr(i8* %ptr, i32 %C, i64 %N)
ret i8* %ret
}
; Fold memchr(a1110111, C, 3) to a1110111[2] == C ? a1110111 : null.
define i8* @fold_memchr_a1110111_c_3(i32 %C) {
; CHECK-LABEL: @fold_memchr_a1110111_c_3(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP2]], i8* getelementptr inbounds ([7 x i8], [7 x i8]* @a1110111, i64 0, i64 0), i8* null
; CHECK-NEXT: ret i8* [[MEMCHR_SEL2]]
;
%ptr = getelementptr [7 x i8], [7 x i8]* @a1110111, i64 0, i64 0
%ret = call i8* @memchr(i8* %ptr, i32 %C, i64 3)
ret i8* %ret
}
; Don't fold memchr(a1110111, C, 4).
define i8* @call_memchr_a1110111_c_4(i32 %C) {
; CHECK-LABEL: @call_memchr_a1110111_c_4(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[C:%.*]] to i8
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: [[MEMCHR_SEL1:%.*]] = select i1 [[TMP2]], i8* getelementptr inbounds ([7 x i8], [7 x i8]* @a1110111, i64 0, i64 3), i8* null
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8 [[TMP1]], 1
; CHECK-NEXT: [[MEMCHR_SEL2:%.*]] = select i1 [[TMP3]], i8* getelementptr inbounds ([7 x i8], [7 x i8]* @a1110111, i64 0, i64 0), i8* [[MEMCHR_SEL1]]
; CHECK-NEXT: ret i8* [[MEMCHR_SEL2]]
;
%ptr = getelementptr [7 x i8], [7 x i8]* @a1110111, i64 0, i64 0
%ret = call i8* @memchr(i8* %ptr, i32 %C, i64 4)
ret i8* %ret
}
; Don't fold memchr(a1110111, C, 7).
define i8* @call_memchr_a1110111_c_7(i32 %C) {
; CHECK-LABEL: @call_memchr_a1110111_c_7(
; CHECK-NEXT: [[RET:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([7 x i8], [7 x i8]* @a1110111, i64 0, i64 0), i32 [[C:%.*]], i64 7)
; CHECK-NEXT: ret i8* [[RET]]
;
%ptr = getelementptr [7 x i8], [7 x i8]* @a1110111, i64 0, i64 0
%ret = call i8* @memchr(i8* %ptr, i32 %C, i64 7)
ret i8* %ret
}
; Don't fold memchr(a1110111, C, N).
define i8* @call_memchr_a1110111_c_n(i32 %C, i64 %N) {
; CHECK-LABEL: @call_memchr_a1110111_c_n(
; CHECK-NEXT: [[RET:%.*]] = call i8* @memchr(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @a1110111, i64 0, i64 0), i32 [[C:%.*]], i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[RET]]
;
%ptr = getelementptr [7 x i8], [7 x i8]* @a1110111, i64 0, i64 0
%ret = call i8* @memchr(i8* %ptr, i32 %C, i64 %N)
ret i8* %ret
}
|