Skip to content

Commit e455d53

Browse files
committed
literal: auto enable SIMD on Rust stable 1.27+
This commit removes the need to use the `unstable` feature to enable SIMD optimizations. We add a "version sniffer" to the `build.rs` script to detect if Rust version 1.27 or newer is being used, and if so, enable the SIMD optimizations. The 'unstable' feature is now a no-op, but we keep it for backwards compatibility. We also may use it again some day.
1 parent a90fbd2 commit e455d53

File tree

7 files changed

+75
-17
lines changed

7 files changed

+75
-17
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ An implementation of regular expressions for Rust. This implementation uses
1212
finite automata and guarantees linear time matching on all inputs.
1313
"""
1414
categories = ["text-processing"]
15+
autotests = false
1516

1617
[badges]
1718
travis-ci = { repository = "rust-lang/regex" }

bench/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ libc = "0.2"
1818
onig = { version = "3", optional = true }
1919
libpcre-sys = { version = "0.2", optional = true }
2020
memmap = "0.6"
21-
regex = { version = "1.0.0", path = "..", features = ["unstable"] }
21+
regex = { version = "1.0.0", path = ".." }
2222
regex-syntax = { version = "0.6.0", path = "../regex-syntax" }
2323
serde = "1"
2424
serde_derive = "1"

build.rs

+67-4
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,80 @@ fn main() {
1111
.stdout;
1212
let version = String::from_utf8(output).unwrap();
1313

14+
enable_simd_optimizations(&version);
15+
}
16+
17+
fn enable_simd_optimizations(version: &str) {
1418
// If we're using nightly Rust, then we can enable vector optimizations.
1519
// Note that these aren't actually activated unless the `unstable` feature
1620
// is enabled.
1721
//
1822
// We also don't activate these if we've explicitly disabled auto
1923
// optimizations. Disabling auto optimizations is intended for use in
2024
// tests, so that we can reliably test fallback implementations.
21-
if env::var_os("CARGO_CFG_REGEX_DISABLE_AUTO_OPTIMIZATIONS").is_none() {
22-
if version.contains("nightly") {
23-
println!("cargo:rustc-cfg=regex_runtime_teddy_ssse3");
24-
println!("cargo:rustc-cfg=regex_runtime_teddy_avx2");
25+
if env::var_os("CARGO_CFG_REGEX_DISABLE_AUTO_OPTIMIZATIONS").is_some() {
26+
return;
27+
}
28+
let parsed = match Version::parse(&version) {
29+
Ok(parsed) => parsed,
30+
Err(err) => {
31+
eprintln!("failed to parse `rustc --version`: {}", err);
32+
return;
33+
}
34+
};
35+
let minimum = Version { major: 1, minor: 27, patch: 0 };
36+
if version.contains("nightly") || parsed >= minimum {
37+
println!("cargo:rustc-cfg=regex_runtime_teddy_ssse3");
38+
println!("cargo:rustc-cfg=regex_runtime_teddy_avx2");
39+
}
40+
}
41+
42+
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
43+
struct Version {
44+
major: u32,
45+
minor: u32,
46+
patch: u32,
47+
}
48+
49+
impl Version {
50+
fn parse(mut s: &str) -> Result<Version, String> {
51+
if !s.starts_with("rustc ") {
52+
return Err(format!("unrecognized version string: {}", s));
2553
}
54+
s = &s["rustc ".len()..];
55+
56+
let parts: Vec<&str> = s.split(".").collect();
57+
if parts.len() < 3 {
58+
return Err(format!("not enough version parts: {:?}", parts));
59+
}
60+
61+
let mut num = String::new();
62+
for c in parts[0].chars() {
63+
if !c.is_digit(10) {
64+
break;
65+
}
66+
num.push(c);
67+
}
68+
let major = num.parse::<u32>().map_err(|e| e.to_string())?;
69+
70+
num.clear();
71+
for c in parts[1].chars() {
72+
if !c.is_digit(10) {
73+
break;
74+
}
75+
num.push(c);
76+
}
77+
let minor = num.parse::<u32>().map_err(|e| e.to_string())?;
78+
79+
num.clear();
80+
for c in parts[2].chars() {
81+
if !c.is_digit(10) {
82+
break;
83+
}
84+
num.push(c);
85+
}
86+
let patch = num.parse::<u32>().map_err(|e| e.to_string())?;
87+
88+
Ok(Version { major, minor, patch })
2689
}
2790
}

src/lib.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -521,11 +521,9 @@ another matching engine with fixed memory requirements.
521521
#![cfg_attr(test, deny(warnings))]
522522
#![cfg_attr(feature = "pattern", feature(pattern))]
523523

524-
525524
#[cfg(not(feature = "use_std"))]
526525
compile_error!("`use_std` feature is currently required to build this crate");
527526

528-
529527
extern crate aho_corasick;
530528
extern crate memchr;
531529
extern crate thread_local;
@@ -669,7 +667,7 @@ mod re_set;
669667
mod re_trait;
670668
mod re_unicode;
671669
mod sparse;
672-
#[cfg(feature = "unstable")]
670+
#[cfg(any(regex_runtime_teddy_ssse3, regex_runtime_teddy_avx2))]
673671
mod vector;
674672

675673
/// The `internal` module exists to support suspicious activity, such as

src/literal/teddy_avx2/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
pub use self::imp::*;
22

33
#[cfg(all(
4-
feature = "unstable",
54
regex_runtime_teddy_avx2,
6-
any(target_arch = "x86_64"),
5+
target_arch = "x86_64",
76
))]
87
mod imp;
98

109
#[cfg(not(all(
11-
feature = "unstable",
1210
regex_runtime_teddy_avx2,
13-
any(target_arch = "x86_64"),
11+
target_arch = "x86_64",
1412
)))]
1513
#[path = "fallback.rs"]
1614
mod imp;

src/literal/teddy_ssse3/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
pub use self::imp::*;
22

33
#[cfg(all(
4-
feature = "unstable",
54
regex_runtime_teddy_ssse3,
6-
any(target_arch = "x86", target_arch = "x86_64"),
5+
target_arch = "x86_64",
76
))]
87
mod imp;
98

109
#[cfg(not(all(
11-
feature = "unstable",
1210
regex_runtime_teddy_ssse3,
13-
any(target_arch = "x86", target_arch = "x86_64"),
11+
target_arch = "x86_64",
1412
)))]
1513
#[path = "fallback.rs"]
1614
mod imp;

src/vector/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#[cfg(target_arch = "x86_64")]
22
pub mod avx2;
3-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3+
#[cfg(any(target_arch = "x86_64"))]
44
pub mod ssse3;

0 commit comments

Comments
 (0)