IMPALA-6291: disable AVX512 codegen in LLVM

Adds a whitelist of LLVM CPU attributes that I know that we routinely
test Impala with. This excludes the problematic AVX512 attributes as
well as some other flags we don't test with - e.g. AMD-only
instructions, NVM-related instructions, etc. We're unlikely to get
significant benefit from these instruction set extensions without
explicitly using them via instrinsics.

Testing:
Ran core tests on a system with AVX512 support with a prototype patch
that disabled only the AVX512 flags. Added a backend test to make sure
that the whitelisting is working as expected.

Change-Id: Ic7c3ee3e370bafc50d855113485b7e6925f7bf6a
Reviewed-on: http://gerrit.cloudera.org:8080/8802
Reviewed-by: Tim Armstrong <tarmstr...@cloudera.com>
Tested-by: Impala Public Jenkins


Project: http://git-wip-us.apache.org/repos/asf/impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/impala/commit/eeb34b65
Tree: http://git-wip-us.apache.org/repos/asf/impala/tree/eeb34b65
Diff: http://git-wip-us.apache.org/repos/asf/impala/diff/eeb34b65

Branch: refs/heads/master
Commit: eeb34b657105e87bb7ee82a4724bfc6688d54cce
Parents: e81b7c6
Author: Tim Armstrong <tarmstr...@cloudera.com>
Authored: Fri Dec 8 09:16:25 2017 -0800
Committer: Impala Public Jenkins <impala-public-jenk...@gerrit.cloudera.org>
Committed: Sat Dec 9 03:45:01 2017 +0000

----------------------------------------------------------------------
 be/src/codegen/llvm-codegen-test.cc | 20 +++++++++++++++
 be/src/codegen/llvm-codegen.cc      | 44 ++++++++++++++++++++++++++++++--
 be/src/codegen/llvm-codegen.h       |  9 +++++++
 3 files changed, 71 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/impala/blob/eeb34b65/be/src/codegen/llvm-codegen-test.cc
----------------------------------------------------------------------
diff --git a/be/src/codegen/llvm-codegen-test.cc 
b/be/src/codegen/llvm-codegen-test.cc
index af6245a..cdd2b89 100644
--- a/be/src/codegen/llvm-codegen-test.cc
+++ b/be/src/codegen/llvm-codegen-test.cc
@@ -485,6 +485,26 @@ TEST_F(LlvmCodeGenTest, HandleLinkageError) {
   codegen->Close();
 }
 
+// Test that the default whitelisting disables the expected attributes.
+TEST_F(LlvmCodeGenTest, CpuAttrWhitelist) {
+  // Non-existent attributes should be disabled regardless of initial states.
+  // Whitelisted attributes like sse2 and lzcnt should retain their initial
+  // state.
+  EXPECT_EQ(vector<string>(
+          {"-dummy1", "-dummy2", "-dummy3", "-dummy4", "+sse2", "-lzcnt"}),
+      LlvmCodeGen::ApplyCpuAttrWhitelist(
+          {"+dummy1", "+dummy2", "-dummy3", "+dummy4", "+sse2", "-lzcnt"}));
+
+  // IMPALA-6291: Test that all AVX512 attributes are disabled.
+  vector<string> avx512_attrs;
+  EXPECT_EQ(vector<string>(
+        {"-avx512ifma", "-avx512dqavx512er", "-avx512f", "-avx512bw", 
"-avx512vl",
+         "-avx512cd", "-avx512vbmi", "-avx512pf"}),
+      LlvmCodeGen::ApplyCpuAttrWhitelist(
+        {"+avx512ifma", "+avx512dqavx512er", "+avx512f", "+avx512bw", 
"+avx512vl",
+         "+avx512cd", "+avx512vbmi", "+avx512pf"}));
+}
+
 }
 
 int main(int argc, char **argv) {

http://git-wip-us.apache.org/repos/asf/impala/blob/eeb34b65/be/src/codegen/llvm-codegen.cc
----------------------------------------------------------------------
diff --git a/be/src/codegen/llvm-codegen.cc b/be/src/codegen/llvm-codegen.cc
index 0dcbd1c..ca78bbb 100644
--- a/be/src/codegen/llvm-codegen.cc
+++ b/be/src/codegen/llvm-codegen.cc
@@ -101,6 +101,19 @@ DEFINE_string(opt_module_dir, "",
 DEFINE_string(asm_module_dir, "",
     "if set, saves disassembly for generated IR modules to the specified 
directory.");
 DECLARE_string(local_library_dir);
+// IMPALA-6291: AVX-512 and other CPU attrs the community doesn't routinely 
test are
+// disabled. AVX-512 is affected by known bugs in LLVM 3.9.1. The following 
attrs that
+// exist in LLVM 3.9.1 are disabled: 
avx512bw,avx512cd,avx512dq,avx512er,avx512f,
+// 
avx512ifma,avx512pf,avx512vbmi,avx512vl,clflushopt,clwb,fma4,mwaitx.1.2,pcommit,pku,
+// prefetchwt1,sgx,sha,sse4a,tbm,xop,xsavec,xsaves. If new attrs are added to 
LLVM,
+// they will be disabled until added to this whitelist.
+DEFINE_string_hidden(llvm_cpu_attr_whitelist, 
"adx,aes,avx,avx2,bmi,bmi2,cmov,cx16,f16c,"
+    
"fma,fsgsbase,hle,invpcid,lzcnt,mmx,movbe,pclmul,popcnt,prfchw,rdrnd,rdseed,rtm,smap,"
+    "sse,sse2,sse3,sse4.1,sse4.2,ssse3,xsave,xsaveopt",
+    "(Experimental) a comma-separated list of LLVM CPU attribute flags that 
are enabled "
+    "for runtime code generation. The default flags are a known-good set that 
are "
+    "routinely tested. This flag is provided to enable additional LLVM CPU 
attribute "
+    "flags for testing.");
 
 namespace impala {
 
@@ -138,8 +151,10 @@ Status LlvmCodeGen::InitializeLlvm(bool load_backend) {
   cpu_name_ = llvm::sys::getHostCPUName().str();
   LOG(INFO) << "CPU class for runtime code generation: " << cpu_name_;
   GetHostCPUAttrs(&cpu_attrs_);
-  target_features_attr_ = boost::algorithm::join(cpu_attrs_, ",");
-  LOG(INFO) << "CPU flags for runtime code generation: " << 
target_features_attr_;
+  LOG(INFO) << "Detected CPU flags: " << boost::join(cpu_attrs_, ",");
+  cpu_attrs_ = ApplyCpuAttrWhitelist(cpu_attrs_);
+  target_features_attr_ = boost::join(cpu_attrs_, ",");
+  LOG(INFO) << "CPU flags enabled for runtime code generation: " << 
target_features_attr_;
 
   // Write an empty map file for perf to find.
   if (FLAGS_perf_map) CodegenSymbolEmitter::WritePerfMap();
@@ -1637,6 +1652,31 @@ llvm::Constant* 
LlvmCodeGen::ConstantsToGVArrayPtr(llvm::Type* element_type,
   return ConstantToGVPtr(array_type, array_const, name);
 }
 
+vector<string> LlvmCodeGen::ApplyCpuAttrWhitelist(const vector<string>& 
cpu_attrs) {
+  vector<string> result;
+  vector<string> attr_whitelist;
+  boost::split(attr_whitelist, FLAGS_llvm_cpu_attr_whitelist, 
boost::is_any_of(","));
+  for (const string& attr : cpu_attrs) {
+    DCHECK_GE(attr.size(), 1);
+    DCHECK(attr[0] == '-' || attr[0] == '+') << attr;
+    if (attr[0] == '-') {
+      // Already disabled - copy it over unmodified.
+      result.push_back(attr);
+      continue;
+    }
+    const string attr_name = attr.substr(1);
+    auto it = std::find(attr_whitelist.begin(), attr_whitelist.end(), 
attr_name);
+    if (it != attr_whitelist.end()) {
+      // In whitelist - copy it over unmodified.
+      result.push_back(attr);
+    } else {
+      // Not in whitelist - disable it.
+      result.push_back("-" + attr_name);
+    }
+  }
+  return result;
+}
+
 void LlvmCodeGen::DiagnosticHandler::DiagnosticHandlerFn(
     const llvm::DiagnosticInfo& info, void* context) {
   if (info.getSeverity() == llvm::DiagnosticSeverity::DS_Error) {

http://git-wip-us.apache.org/repos/asf/impala/blob/eeb34b65/be/src/codegen/llvm-codegen.h
----------------------------------------------------------------------
diff --git a/be/src/codegen/llvm-codegen.h b/be/src/codegen/llvm-codegen.h
index bbfda3e..672ed27 100644
--- a/be/src/codegen/llvm-codegen.h
+++ b/be/src/codegen/llvm-codegen.h
@@ -540,6 +540,7 @@ class LlvmCodeGen {
  private:
   friend class ExprCodegenTest;
   friend class LlvmCodeGenTest;
+  friend class LlvmCodeGenTest_CpuAttrWhitelist_Test;
   friend class SubExprElimination;
 
   /// Top level codegen object. 'module_id' is used for debugging when 
outputting the IR.
@@ -659,6 +660,14 @@ class LlvmCodeGen {
   /// generated is retained by the execution engine.
   void DestroyModule();
 
+  /// Disable CPU attributes in 'cpu_attrs' that are not present in
+  /// the '--llvm_cpu_attr_whitelist' flag. The same attributes in the input 
are
+  /// always present in the output, except "+" is flipped to "-" for the 
disabled
+  /// attributes. E.g. if 'cpu_attrs' is {"+x", "+y", "-z"} and the whitelist 
is
+  /// {"x", "z"}, returns {"+x", "-y", "-z"}.
+  static std::vector<std::string> ApplyCpuAttrWhitelist(
+      const std::vector<std::string>& cpu_attrs);
+
   /// Whether InitializeLlvm() has been called.
   static bool llvm_initialized_;
 

Reply via email to