From 3309d41ac5e731816fa51c9f4281bb2c2ed043e3 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Tue, 19 Jun 2018 16:25:56 -0400 Subject: [PATCH] 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. --- Cargo.toml | 1 + bench/Cargo.toml | 2 +- build.rs | 71 ++++++++++++++++++++++++++++++++-- src/lib.rs | 4 +- src/literal/teddy_avx2/mod.rs | 2 - src/literal/teddy_ssse3/mod.rs | 2 - 6 files changed, 70 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5ff4621721..f657ed749a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ An implementation of regular expressions for Rust. This implementation uses finite automata and guarantees linear time matching on all inputs. """ categories = ["text-processing"] +autotests = false [badges] travis-ci = { repository = "rust-lang/regex" } diff --git a/bench/Cargo.toml b/bench/Cargo.toml index 2c1a2792c2..68b95af782 100644 --- a/bench/Cargo.toml +++ b/bench/Cargo.toml @@ -18,7 +18,7 @@ libc = "0.2" onig = { version = "3", optional = true } libpcre-sys = { version = "0.2", optional = true } memmap = "0.6" -regex = { version = "1.0.0", path = "..", features = ["unstable"] } +regex = { version = "1.0.0", path = ".." } regex-syntax = { version = "0.6.0", path = "../regex-syntax" } serde = "1" serde_derive = "1" diff --git a/build.rs b/build.rs index a5d12a108b..817629d656 100644 --- a/build.rs +++ b/build.rs @@ -11,6 +11,10 @@ fn main() { .stdout; let version = String::from_utf8(output).unwrap(); + enable_simd_optimizations(&version); +} + +fn enable_simd_optimizations(version: &str) { // If we're using nightly Rust, then we can enable vector optimizations. // Note that these aren't actually activated unless the `unstable` feature // is enabled. @@ -18,10 +22,69 @@ fn main() { // We also don't activate these if we've explicitly disabled auto // optimizations. Disabling auto optimizations is intended for use in // tests, so that we can reliably test fallback implementations. - if env::var_os("CARGO_CFG_REGEX_DISABLE_AUTO_OPTIMIZATIONS").is_none() { - if version.contains("nightly") { - println!("cargo:rustc-cfg=regex_runtime_teddy_ssse3"); - println!("cargo:rustc-cfg=regex_runtime_teddy_avx2"); + if env::var_os("CARGO_CFG_REGEX_DISABLE_AUTO_OPTIMIZATIONS").is_some() { + return; + } + let parsed = match Version::parse(&version) { + Ok(parsed) => parsed, + Err(err) => { + eprintln!("failed to parse `rustc --version`: {}", err); + return; + } + }; + let minimum = Version { major: 1, minor: 27, patch: 0 }; + if version.contains("nightly") || parsed >= minimum { + println!("cargo:rustc-cfg=regex_runtime_teddy_ssse3"); + println!("cargo:rustc-cfg=regex_runtime_teddy_avx2"); + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] +struct Version { + major: u32, + minor: u32, + patch: u32, +} + +impl Version { + fn parse(mut s: &str) -> Result { + if !s.starts_with("rustc ") { + return Err(format!("unrecognized version string: {}", s)); } + s = &s["rustc ".len()..]; + + let parts: Vec<&str> = s.split(".").collect(); + if parts.len() < 3 { + return Err(format!("not enough version parts: {:?}", parts)); + } + + let mut num = String::new(); + for c in parts[0].chars() { + if !c.is_digit(10) { + break; + } + num.push(c); + } + let major = num.parse::().map_err(|e| e.to_string())?; + + num.clear(); + for c in parts[1].chars() { + if !c.is_digit(10) { + break; + } + num.push(c); + } + let minor = num.parse::().map_err(|e| e.to_string())?; + + num.clear(); + for c in parts[2].chars() { + if !c.is_digit(10) { + break; + } + num.push(c); + } + let patch = num.parse::().map_err(|e| e.to_string())?; + + Ok(Version { major, minor, patch }) } } diff --git a/src/lib.rs b/src/lib.rs index 559cb51ef0..32428fe9be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -521,11 +521,9 @@ another matching engine with fixed memory requirements. #![cfg_attr(test, deny(warnings))] #![cfg_attr(feature = "pattern", feature(pattern))] - #[cfg(not(feature = "use_std"))] compile_error!("`use_std` feature is currently required to build this crate"); - extern crate aho_corasick; extern crate memchr; extern crate thread_local; @@ -669,7 +667,7 @@ mod re_set; mod re_trait; mod re_unicode; mod sparse; -#[cfg(feature = "unstable")] +#[cfg(any(regex_runtime_teddy_ssse3, regex_runtime_teddy_avx2))] mod vector; /// The `internal` module exists to support suspicious activity, such as diff --git a/src/literal/teddy_avx2/mod.rs b/src/literal/teddy_avx2/mod.rs index 78b6e20e8a..90fab0a83c 100644 --- a/src/literal/teddy_avx2/mod.rs +++ b/src/literal/teddy_avx2/mod.rs @@ -1,14 +1,12 @@ pub use self::imp::*; #[cfg(all( - feature = "unstable", regex_runtime_teddy_avx2, any(target_arch = "x86_64"), ))] mod imp; #[cfg(not(all( - feature = "unstable", regex_runtime_teddy_avx2, any(target_arch = "x86_64"), )))] diff --git a/src/literal/teddy_ssse3/mod.rs b/src/literal/teddy_ssse3/mod.rs index 2221159945..22b0203514 100644 --- a/src/literal/teddy_ssse3/mod.rs +++ b/src/literal/teddy_ssse3/mod.rs @@ -1,14 +1,12 @@ pub use self::imp::*; #[cfg(all( - feature = "unstable", regex_runtime_teddy_ssse3, any(target_arch = "x86", target_arch = "x86_64"), ))] mod imp; #[cfg(not(all( - feature = "unstable", regex_runtime_teddy_ssse3, any(target_arch = "x86", target_arch = "x86_64"), )))]