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.
124 lines
4.7 KiB
LLVM
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
|
|
}
|