Skip to content

Commit

Permalink
literal: auto enable SIMD on Rust stable 1.27+
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
BurntSushi committed Jun 19, 2018
1 parent a90fbd2 commit e455d53
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 17 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -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" }
Expand Down
2 changes: 1 addition & 1 deletion bench/Cargo.toml
Expand Up @@ -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"
Expand Down
71 changes: 67 additions & 4 deletions build.rs
Expand Up @@ -11,17 +11,80 @@ 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.
//
// 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<Version, String> {
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::<u32>().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::<u32>().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::<u32>().map_err(|e| e.to_string())?;

Ok(Version { major, minor, patch })
}
}
4 changes: 1 addition & 3 deletions src/lib.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
6 changes: 2 additions & 4 deletions src/literal/teddy_avx2/mod.rs
@@ -1,16 +1,14 @@
pub use self::imp::*;

#[cfg(all(
feature = "unstable",
regex_runtime_teddy_avx2,
any(target_arch = "x86_64"),
target_arch = "x86_64",
))]
mod imp;

#[cfg(not(all(
feature = "unstable",
regex_runtime_teddy_avx2,
any(target_arch = "x86_64"),
target_arch = "x86_64",
)))]
#[path = "fallback.rs"]
mod imp;
6 changes: 2 additions & 4 deletions src/literal/teddy_ssse3/mod.rs
@@ -1,16 +1,14 @@
pub use self::imp::*;

#[cfg(all(
feature = "unstable",
regex_runtime_teddy_ssse3,
any(target_arch = "x86", target_arch = "x86_64"),
target_arch = "x86_64",
))]
mod imp;

#[cfg(not(all(
feature = "unstable",
regex_runtime_teddy_ssse3,
any(target_arch = "x86", target_arch = "x86_64"),
target_arch = "x86_64",
)))]
#[path = "fallback.rs"]
mod imp;
2 changes: 1 addition & 1 deletion src/vector/mod.rs
@@ -1,4 +1,4 @@
#[cfg(target_arch = "x86_64")]
pub mod avx2;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[cfg(any(target_arch = "x86_64"))]
pub mod ssse3;

0 comments on commit e455d53

Please sign in to comment.