diff --git a/tests/codegen-llvm/slice-range-indexing.rs b/tests/codegen-llvm/slice-range-indexing.rs new file mode 100644 index 000000000000..5c47cab6234e --- /dev/null +++ b/tests/codegen-llvm/slice-range-indexing.rs @@ -0,0 +1,96 @@ +//@ compile-flags: -Copt-level=3 +//@ min-llvm-version: 21 + +#![crate_type = "lib"] + +use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}; + +macro_rules! tests { + ($range_ty:ty, $get_func_name:ident, $index_func_name:ident) => { + #[no_mangle] + pub fn $get_func_name(slice: &[u32], range: $range_ty) -> Option<&[u32]> { + slice.get(range) + } + + #[no_mangle] + pub fn $index_func_name(slice: &[u32], range: $range_ty) -> &[u32] { + &slice[range] + } + }; +} + +// 2 comparisons required: +// end <= len && start <= end + +// CHECK-LABEL: @get_range +// CHECK-COUNT-2: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range +// CHECK-COUNT-2: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(Range, get_range, index_range); + +// 3 comparisons required: +// end != usize::MAX && end + 1 <= len && start <= end + 1 + +// CHECK-LABEL: @get_range_inclusive +// CHECK-COUNT-3: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// 2 comparisons required: +// end < len && start <= end + 1 + +// CHECK-LABEL: @index_range_inclusive +// CHECK-COUNT-2: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeInclusive, get_range_inclusive, index_range_inclusive); + +// 1 comparison required: +// end <= len + +// CHECK-LABEL: @get_range_to +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_to +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeTo, get_range_to, index_range_to); + +// 2 comparisons required: +// end != usize::MAX && end + 1 <= len + +// CHECK-LABEL: @get_range_to_inclusive +// CHECK-COUNT-2: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// 1 comparison required: +// end < len + +// CHECK-LABEL: @index_range_to_inclusive +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeToInclusive, get_range_to_inclusive, index_range_to_inclusive); + +// 1 comparison required: +// start <= len + +// CHECK-LABEL: @get_range_from +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_from +// CHECK-COUNT-1: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeFrom, get_range_from, index_range_from); diff --git a/tests/codegen-llvm/str-range-indexing.rs b/tests/codegen-llvm/str-range-indexing.rs new file mode 100644 index 000000000000..3c35b26773cb --- /dev/null +++ b/tests/codegen-llvm/str-range-indexing.rs @@ -0,0 +1,94 @@ +//@ compile-flags: -Copt-level=3 +//@ min-llvm-version: 21 + +#![crate_type = "lib"] + +use std::ops::{Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}; + +macro_rules! tests { + ($range_ty:ty, $get_func_name:ident, $index_func_name:ident) => { + #[no_mangle] + pub fn $get_func_name(slice: &str, range: $range_ty) -> Option<&str> { + slice.get(range) + } + + #[no_mangle] + pub fn $index_func_name(slice: &str, range: $range_ty) -> &str { + &slice[range] + } + }; +} + +// 9 comparisons required: +// start <= end +// && (start == 0 || (start >= len && start == len) || bytes[start] >= -0x40) +// && (end == 0 || (end >= len && end == len) || bytes[end] >= -0x40) + +// CHECK-LABEL: @get_range +// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range +// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(Range, get_range, index_range); + +// 9 comparisons required: +// end != usize::MAX && start <= end + 1 +// && (start == 0 || (start >= len && start == len) || bytes[start] >= -0x40) +// && ( (end + 1 >= len && end + 1 == len) || bytes[end + 1] >= -0x40) + +// CHECK-LABEL: @get_range_inclusive +// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_inclusive +// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeInclusive, get_range_inclusive, index_range_inclusive); + +// 4 comparisons required: +// end == 0 || (end >= len && end == len) || bytes[end] >= -0x40 + +// CHECK-LABEL: @get_range_to +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_to +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeTo, get_range_to, index_range_to); + +// 4 comparisons required: +// end != usize::MAX && (end + 1 >= len && end + 1 == len) || bytes[end + 1] >= -0x40) + +// CHECK-LABEL: @get_range_to_inclusive +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_to_inclusive +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeToInclusive, get_range_to_inclusive, index_range_to_inclusive); + +// 4 comparisons required: +// start == 0 || (start >= len && start == len) || bytes[start] >= -0x40) + +// CHECK-LABEL: @get_range_from +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret + +// CHECK-LABEL: @index_range_from +// CHECK-COUNT-4: %{{.+}} = icmp +// CHECK-NOT: %{{.+}} = icmp +// CHECK: ret +tests!(RangeFrom, get_range_from, index_range_from);