Move instruction_set_ to CompilerOptions.

Removes CompilerDriver dependency from ImageWriter and
several other classes.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: Pixel 2 XL boots.
Test: m test-art-target-gtest
Test: testrunner.py --target --optimizing
Change-Id: I3c5b8ff73732128b9c4fad9405231a216ea72465
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 52c767f..22720ce 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -153,11 +153,7 @@
   {
     ScopedObjectAccess soa(Thread::Current());
 
-    const InstructionSet instruction_set = kRuntimeISA;
-    // Take the default set of instruction features from the build.
-    instruction_set_features_ = InstructionSetFeatures::FromCppDefines();
-
-    runtime_->SetInstructionSet(instruction_set);
+    runtime_->SetInstructionSet(instruction_set_);
     for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); ++i) {
       CalleeSaveType type = CalleeSaveType(i);
       if (!runtime_->HasCalleeSaveMethod(type)) {
@@ -165,23 +161,48 @@
       }
     }
 
-    CreateCompilerDriver(compiler_kind_, instruction_set);
+    CreateCompilerDriver();
   }
 }
 
-void CommonCompilerTest::CreateCompilerDriver(Compiler::Kind kind,
-                                              InstructionSet isa,
-                                              size_t number_of_threads) {
+void CommonCompilerTest::ApplyInstructionSet() {
+  // Copy local instruction_set_ and instruction_set_features_ to *compiler_options_;
+  CHECK(instruction_set_features_ != nullptr);
+  if (instruction_set_ == InstructionSet::kThumb2) {
+    CHECK_EQ(InstructionSet::kArm, instruction_set_features_->GetInstructionSet());
+  } else {
+    CHECK_EQ(instruction_set_, instruction_set_features_->GetInstructionSet());
+  }
+  compiler_options_->instruction_set_ = instruction_set_;
+  compiler_options_->instruction_set_features_ =
+      InstructionSetFeatures::FromBitmap(instruction_set_, instruction_set_features_->AsBitmap());
+  CHECK(compiler_options_->instruction_set_features_->Equals(instruction_set_features_.get()));
+}
+
+void CommonCompilerTest::OverrideInstructionSetFeatures(InstructionSet instruction_set,
+                                                        const std::string& variant) {
+  instruction_set_ = instruction_set;
+  std::string error_msg;
+  instruction_set_features_ =
+      InstructionSetFeatures::FromVariant(instruction_set, variant, &error_msg);
+  CHECK(instruction_set_features_ != nullptr) << error_msg;
+
+  if (compiler_options_ != nullptr) {
+    ApplyInstructionSet();
+  }
+}
+
+void CommonCompilerTest::CreateCompilerDriver() {
+  ApplyInstructionSet();
+
   compiler_options_->boot_image_ = true;
   compiler_options_->SetCompilerFilter(GetCompilerFilter());
   compiler_options_->image_classes_.swap(*GetImageClasses());
   compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
                                             verification_results_.get(),
-                                            kind,
-                                            isa,
-                                            instruction_set_features_.get(),
+                                            compiler_kind_,
                                             &compiler_options_->image_classes_,
-                                            number_of_threads,
+                                            number_of_threads_,
                                             /* swap_fd */ -1,
                                             GetProfileCompilationInfo()));
   // We typically don't generate an image in unit tests, disable this optimization by default.
@@ -207,11 +228,6 @@
   compiler_kind_ = compiler_kind;
 }
 
-InstructionSet CommonCompilerTest::GetInstructionSet() const {
-  DCHECK(compiler_driver_.get() != nullptr);
-  return compiler_driver_->GetInstructionSet();
-}
-
 void CommonCompilerTest::TearDown() {
   compiler_driver_.reset();
   callbacks_.reset();
@@ -339,4 +355,8 @@
   compiler_driver_->dex_to_dex_compiler_.SetDexFiles(dex_files);
 }
 
+void CommonCompilerTest::ClearBootImageOption() {
+  compiler_options_->boot_image_ = false;
+}
+
 }  // namespace art
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index f070bbb..db38110 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -20,6 +20,8 @@
 #include <list>
 #include <vector>
 
+#include "arch/instruction_set.h"
+#include "arch/instruction_set_features.h"
 #include "base/hash_set.h"
 #include "common_runtime_test.h"
 #include "compiler.h"
@@ -55,15 +57,13 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
  protected:
-  virtual void SetUp();
+  void SetUp() OVERRIDE;
 
-  virtual void SetUpRuntimeOptions(RuntimeOptions* options);
+  void SetUpRuntimeOptions(RuntimeOptions* options) OVERRIDE;
 
   Compiler::Kind GetCompilerKind() const;
   void SetCompilerKind(Compiler::Kind compiler_kind);
 
-  InstructionSet GetInstructionSet() const;
-
   // Get the set of image classes given to the compiler-driver in SetUp.
   virtual std::unique_ptr<HashSet<std::string>> GetImageClasses();
 
@@ -73,7 +73,7 @@
     return CompilerFilter::kDefaultCompilerFilter;
   }
 
-  virtual void TearDown();
+  void TearDown() OVERRIDE;
 
   void CompileClass(mirror::ClassLoader* class_loader, const char* class_name)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -88,7 +88,10 @@
                             const char* method_name, const char* signature)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void CreateCompilerDriver(Compiler::Kind kind, InstructionSet isa, size_t number_of_threads = 2U);
+  void ApplyInstructionSet();
+  void OverrideInstructionSetFeatures(InstructionSet instruction_set, const std::string& variant);
+
+  void CreateCompilerDriver();
 
   void ReserveImageSpace();
 
@@ -96,12 +99,20 @@
 
   void SetDexFilesForOatFile(const std::vector<const DexFile*>& dex_files);
 
+  void ClearBootImageOption();
+
   Compiler::Kind compiler_kind_ = Compiler::kOptimizing;
+  size_t number_of_threads_ = 2u;
+
+  InstructionSet instruction_set_ =
+      (kRuntimeISA == InstructionSet::kArm) ? InstructionSet::kThumb2 : kRuntimeISA;
+  // Take the default set of instruction features from the build.
+  std::unique_ptr<const InstructionSetFeatures> instruction_set_features_
+      = InstructionSetFeatures::FromCppDefines();
+
   std::unique_ptr<CompilerOptions> compiler_options_;
   std::unique_ptr<VerificationResults> verification_results_;
   std::unique_ptr<CompilerDriver> compiler_driver_;
-  std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
-
 
  private:
   std::unique_ptr<MemMap> image_reservation_;
diff --git a/compiler/debug/dwarf/dwarf_test.h b/compiler/debug/dwarf/dwarf_test.h
index 9a7c604..6b039a7 100644
--- a/compiler/debug/dwarf/dwarf_test.h
+++ b/compiler/debug/dwarf/dwarf_test.h
@@ -28,7 +28,7 @@
 
 #include "base/os.h"
 #include "base/unix_file/fd_file.h"
-#include "common_runtime_test.h"
+#include "common_compiler_test.h"
 #include "gtest/gtest.h"
 #include "linker/elf_builder.h"
 #include "linker/file_output_stream.h"
@@ -39,7 +39,7 @@
 #define DW_CHECK(substring) Check(substring, false, __FILE__, __LINE__)
 #define DW_CHECK_NEXT(substring) Check(substring, true, __FILE__, __LINE__)
 
-class DwarfTest : public CommonRuntimeTest {
+class DwarfTest : public CommonCompilerTest {
  public:
   static constexpr bool kPrintObjdumpOutput = false;  // debugging.
 
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index fb6a72b..fcaa0cd 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -31,6 +31,7 @@
 #include "dex/dex_instruction-inl.h"
 #include "dex_to_dex_decompiler.h"
 #include "driver/compiler_driver.h"
+#include "driver/compiler_options.h"
 #include "driver/dex_compilation_unit.h"
 #include "mirror/dex_cache.h"
 #include "quicken_info.h"
@@ -609,7 +610,7 @@
   }
 
   // Create a `CompiledMethod`, with the quickened information in the vmap table.
-  InstructionSet instruction_set = driver_->GetInstructionSet();
+  InstructionSet instruction_set = driver_->GetCompilerOptions().GetInstructionSet();
   if (instruction_set == InstructionSet::kThumb2) {
     // Don't use the thumb2 instruction set to avoid the one off code delta.
     instruction_set = InstructionSet::kArm;
diff --git a/compiler/driver/compiled_method_storage_test.cc b/compiler/driver/compiled_method_storage_test.cc
index 42fbba5..aed04f9 100644
--- a/compiler/driver/compiled_method_storage_test.cc
+++ b/compiler/driver/compiled_method_storage_test.cc
@@ -31,8 +31,6 @@
   CompilerDriver driver(&compiler_options,
                         &verification_results,
                         Compiler::kOptimizing,
-                        /* instruction_set_ */ InstructionSet::kNone,
-                        /* instruction_set_features */ nullptr,
                         /* image_classes */ nullptr,
                         /* thread_count */ 1u,
                         /* swap_fd */ -1,
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 66a8a57..7c13894 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -261,8 +261,6 @@
     const CompilerOptions* compiler_options,
     VerificationResults* verification_results,
     Compiler::Kind compiler_kind,
-    InstructionSet instruction_set,
-    const InstructionSetFeatures* instruction_set_features,
     HashSet<std::string>* image_classes,
     size_t thread_count,
     int swap_fd,
@@ -271,9 +269,6 @@
       verification_results_(verification_results),
       compiler_(Compiler::Create(this, compiler_kind)),
       compiler_kind_(compiler_kind),
-      instruction_set_(
-          instruction_set == InstructionSet::kArm ? InstructionSet::kThumb2 : instruction_set),
-      instruction_set_features_(instruction_set_features),
       requires_constructor_barrier_lock_("constructor barrier lock"),
       non_relative_linker_patch_count_(0u),
       image_classes_(std::move(image_classes)),
@@ -309,13 +304,15 @@
 }
 
 
-#define CREATE_TRAMPOLINE(type, abi, offset) \
-    if (Is64BitInstructionSet(instruction_set_)) { \
-      return CreateTrampoline64(instruction_set_, abi, \
-                                type ## _ENTRYPOINT_OFFSET(PointerSize::k64, offset)); \
-    } else { \
-      return CreateTrampoline32(instruction_set_, abi, \
-                                type ## _ENTRYPOINT_OFFSET(PointerSize::k32, offset)); \
+#define CREATE_TRAMPOLINE(type, abi, offset)                                            \
+    if (Is64BitInstructionSet(GetCompilerOptions().GetInstructionSet())) {              \
+      return CreateTrampoline64(GetCompilerOptions().GetInstructionSet(),               \
+                                abi,                                                    \
+                                type ## _ENTRYPOINT_OFFSET(PointerSize::k64, offset));  \
+    } else {                                                                            \
+      return CreateTrampoline32(GetCompilerOptions().GetInstructionSet(),               \
+                                abi,                                                    \
+                                type ## _ENTRYPOINT_OFFSET(PointerSize::k32, offset));  \
     }
 
 std::unique_ptr<const std::vector<uint8_t>> CompilerDriver::CreateJniDlsymLookup() const {
@@ -601,7 +598,7 @@
     if ((access_flags & kAccNative) != 0) {
       // Are we extracting only and have support for generic JNI down calls?
       if (!driver->GetCompilerOptions().IsJniCompilationEnabled() &&
-          InstructionSetHasGenericJniStub(driver->GetInstructionSet())) {
+          InstructionSetHasGenericJniStub(driver->GetCompilerOptions().GetInstructionSet())) {
         // Leaving this empty will trigger the generic JNI version
       } else {
         // Query any JNI optimization annotations such as @FastNative or @CriticalNative.
@@ -2146,8 +2143,9 @@
           mirror::Class::SetStatus(klass, ClassStatus::kVerified, soa.Self());
           // Mark methods as pre-verified. If we don't do this, the interpreter will run with
           // access checks.
-          klass->SetSkipAccessChecksFlagOnAllMethods(
-              GetInstructionSetPointerSize(manager_->GetCompiler()->GetInstructionSet()));
+          InstructionSet instruction_set =
+              manager_->GetCompiler()->GetCompilerOptions().GetInstructionSet();
+          klass->SetSkipAccessChecksFlagOnAllMethods(GetInstructionSetPointerSize(instruction_set));
           klass->SetVerificationAttempted();
         }
         // Record the final class status if necessary.
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 54e1f37..8739dc3 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -97,8 +97,6 @@
   CompilerDriver(const CompilerOptions* compiler_options,
                  VerificationResults* verification_results,
                  Compiler::Kind compiler_kind,
-                 InstructionSet instruction_set,
-                 const InstructionSetFeatures* instruction_set_features,
                  HashSet<std::string>* image_classes,
                  size_t thread_count,
                  int swap_fd,
@@ -129,14 +127,6 @@
 
   VerificationResults* GetVerificationResults() const;
 
-  InstructionSet GetInstructionSet() const {
-    return instruction_set_;
-  }
-
-  const InstructionSetFeatures* GetInstructionSetFeatures() const {
-    return instruction_set_features_;
-  }
-
   const CompilerOptions& GetCompilerOptions() const {
     return *compiler_options_;
   }
@@ -451,9 +441,6 @@
   std::unique_ptr<Compiler> compiler_;
   Compiler::Kind compiler_kind_;
 
-  const InstructionSet instruction_set_;
-  const InstructionSetFeatures* const instruction_set_features_;
-
   // All class references that require constructor barriers. If the class reference is not in the
   // set then the result has not yet been computed.
   mutable ReaderWriterMutex requires_constructor_barrier_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index cc1af3e..62d547d 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -20,6 +20,8 @@
 
 #include "android-base/stringprintf.h"
 
+#include "arch/instruction_set.h"
+#include "arch/instruction_set_features.h"
 #include "base/runtime_debug.h"
 #include "base/variant_map.h"
 #include "cmdline_parser.h"
@@ -37,13 +39,14 @@
       tiny_method_threshold_(kDefaultTinyMethodThreshold),
       num_dex_methods_threshold_(kDefaultNumDexMethodsThreshold),
       inline_max_code_units_(kUnsetInlineMaxCodeUnits),
+      instruction_set_(kRuntimeISA == InstructionSet::kArm ? InstructionSet::kThumb2 : kRuntimeISA),
+      instruction_set_features_(nullptr),
       no_inline_from_(),
       dex_files_for_oat_file_(),
       image_classes_(),
       boot_image_(false),
       core_image_(false),
       app_image_(false),
-      top_k_profile_threshold_(kDefaultTopKProfileThreshold),
       debuggable_(false),
       generate_debug_info_(kDefaultGenerateDebugInfo),
       generate_mini_debug_info_(kDefaultGenerateMiniDebugInfo),
@@ -55,6 +58,7 @@
       dump_timings_(false),
       dump_pass_timings_(false),
       dump_stats_(false),
+      top_k_profile_threshold_(kDefaultTopKProfileThreshold),
       verbose_methods_(),
       abort_on_hard_verifier_failure_(false),
       abort_on_soft_verifier_failure_(false),
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 908ff33..601c914 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -17,6 +17,7 @@
 #ifndef ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
 #define ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
 
+#include <memory>
 #include <ostream>
 #include <string>
 #include <vector>
@@ -30,11 +31,17 @@
 
 namespace art {
 
+namespace jit {
+class JitCompiler;
+}  // namespace jit
+
 namespace verifier {
 class VerifierDepsTest;
 }  // namespace verifier
 
 class DexFile;
+enum class InstructionSet;
+class InstructionSetFeatures;
 
 class CompilerOptions FINAL {
  public:
@@ -231,6 +238,15 @@
     return abort_on_soft_verifier_failure_;
   }
 
+  InstructionSet GetInstructionSet() const {
+    return instruction_set_;
+  }
+
+  const InstructionSetFeatures* GetInstructionSetFeatures() const {
+    return instruction_set_features_.get();
+  }
+
+
   const std::vector<const DexFile*>& GetNoInlineFromDexFile() const {
     return no_inline_from_;
   }
@@ -312,6 +328,9 @@
   size_t num_dex_methods_threshold_;
   size_t inline_max_code_units_;
 
+  InstructionSet instruction_set_;
+  std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
+
   // Dex files from which we should not inline code. Does not own the dex files.
   // This is usually a very short list (i.e. a single dex file), so we
   // prefer vector<> over a lookup-oriented container, such as set<>.
@@ -327,8 +346,6 @@
   bool boot_image_;
   bool core_image_;
   bool app_image_;
-  // When using a profile file only the top K% of the profiled samples will be compiled.
-  double top_k_profile_threshold_;
   bool debuggable_;
   bool generate_debug_info_;
   bool generate_mini_debug_info_;
@@ -341,6 +358,9 @@
   bool dump_pass_timings_;
   bool dump_stats_;
 
+  // When using a profile file only the top K% of the profiled samples will be compiled.
+  double top_k_profile_threshold_;
+
   // Vector of methods to have verbose output enabled for.
   std::vector<std::string> verbose_methods_;
 
@@ -380,6 +400,7 @@
   friend class Dex2Oat;
   friend class DexToDexDecompilerTest;
   friend class CommonCompilerTest;
+  friend class jit::JitCompiler;
   friend class verifier::VerifierDepsTest;
 
   template <class Base>
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 0de00a8..d7bd828 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -33,6 +33,7 @@
 #include "jit/debugger_interface.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
+#include "jit/jit_logger.h"
 #include "oat_file-inl.h"
 #include "oat_quick_method_header.h"
 #include "object_lock.h"
@@ -50,7 +51,7 @@
   VLOG(jit) << "loading jit compiler";
   auto* const jit_compiler = JitCompiler::Create();
   CHECK(jit_compiler != nullptr);
-  *generate_debug_info = jit_compiler->GetCompilerOptions()->GetGenerateDebugInfo();
+  *generate_debug_info = jit_compiler->GetCompilerOptions().GetGenerateDebugInfo();
   VLOG(jit) << "Done loading jit compiler";
   return jit_compiler;
 }
@@ -72,10 +73,11 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
   DCHECK(jit_compiler != nullptr);
-  if (jit_compiler->GetCompilerOptions()->GetGenerateDebugInfo()) {
+  const CompilerOptions& compiler_options = jit_compiler->GetCompilerOptions();
+  if (compiler_options.GetGenerateDebugInfo()) {
     const ArrayRef<mirror::Class*> types_array(types, count);
     std::vector<uint8_t> elf_file = debug::WriteDebugElfFileForClasses(
-        kRuntimeISA, jit_compiler->GetCompilerDriver()->GetInstructionSetFeatures(), types_array);
+        kRuntimeISA, compiler_options.GetInstructionSetFeatures(), types_array);
     MutexLock mu(Thread::Current(), *Locks::native_debug_interface_lock_);
     // We never free debug info for types, so we don't need to provide a handle
     // (which would have been otherwise used as identifier to remove it later).
@@ -103,44 +105,50 @@
   // Set debuggability based on the runtime value.
   compiler_options_->SetDebuggable(Runtime::Current()->IsJavaDebuggable());
 
-  const InstructionSet instruction_set = kRuntimeISA;
+  const InstructionSet instruction_set = compiler_options_->GetInstructionSet();
+  if (kRuntimeISA == InstructionSet::kArm) {
+    DCHECK_EQ(instruction_set, InstructionSet::kThumb2);
+  } else {
+    DCHECK_EQ(instruction_set, kRuntimeISA);
+  }
+  std::unique_ptr<const InstructionSetFeatures> instruction_set_features;
   for (const StringPiece option : Runtime::Current()->GetCompilerOptions()) {
     VLOG(compiler) << "JIT compiler option " << option;
     std::string error_msg;
     if (option.starts_with("--instruction-set-variant=")) {
       StringPiece str = option.substr(strlen("--instruction-set-variant=")).data();
       VLOG(compiler) << "JIT instruction set variant " << str;
-      instruction_set_features_ = InstructionSetFeatures::FromVariant(
+      instruction_set_features = InstructionSetFeatures::FromVariant(
           instruction_set, str.as_string(), &error_msg);
-      if (instruction_set_features_ == nullptr) {
+      if (instruction_set_features == nullptr) {
         LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
       }
     } else if (option.starts_with("--instruction-set-features=")) {
       StringPiece str = option.substr(strlen("--instruction-set-features=")).data();
       VLOG(compiler) << "JIT instruction set features " << str;
-      if (instruction_set_features_ == nullptr) {
-        instruction_set_features_ = InstructionSetFeatures::FromVariant(
+      if (instruction_set_features == nullptr) {
+        instruction_set_features = InstructionSetFeatures::FromVariant(
             instruction_set, "default", &error_msg);
-        if (instruction_set_features_ == nullptr) {
+        if (instruction_set_features == nullptr) {
           LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
         }
       }
-      instruction_set_features_ =
-          instruction_set_features_->AddFeaturesFromString(str.as_string(), &error_msg);
-      if (instruction_set_features_ == nullptr) {
+      instruction_set_features =
+          instruction_set_features->AddFeaturesFromString(str.as_string(), &error_msg);
+      if (instruction_set_features == nullptr) {
         LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
       }
     }
   }
-  if (instruction_set_features_ == nullptr) {
-    instruction_set_features_ = InstructionSetFeatures::FromCppDefines();
+  if (instruction_set_features == nullptr) {
+    instruction_set_features = InstructionSetFeatures::FromCppDefines();
   }
+  compiler_options_->instruction_set_features_ = std::move(instruction_set_features);
+
   compiler_driver_.reset(new CompilerDriver(
       compiler_options_.get(),
       /* verification_results */ nullptr,
       Compiler::kOptimizing,
-      instruction_set,
-      instruction_set_features_.get(),
       /* image_classes */ nullptr,
       /* thread_count */ 1,
       /* swap_fd */ -1,
diff --git a/compiler/jit/jit_compiler.h b/compiler/jit/jit_compiler.h
index 31dc9e2..5840fec 100644
--- a/compiler/jit/jit_compiler.h
+++ b/compiler/jit/jit_compiler.h
@@ -18,18 +18,19 @@
 #define ART_COMPILER_JIT_JIT_COMPILER_H_
 
 #include "base/mutex.h"
-#include "compiled_method.h"
-#include "driver/compiler_driver.h"
-#include "driver/compiler_options.h"
-#include "jit_logger.h"
 
 namespace art {
 
 class ArtMethod;
-class InstructionSetFeatures;
+class CompiledMethod;
+class CompilerDriver;
+class CompilerOptions;
+class Thread;
 
 namespace jit {
 
+class JitLogger;
+
 class JitCompiler {
  public:
   static JitCompiler* Create();
@@ -39,8 +40,8 @@
   bool CompileMethod(Thread* self, ArtMethod* method, bool osr)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  CompilerOptions* GetCompilerOptions() const {
-    return compiler_options_.get();
+  const CompilerOptions& GetCompilerOptions() const {
+    return *compiler_options_.get();
   }
   CompilerDriver* GetCompilerDriver() const {
     return compiler_driver_.get();
@@ -49,7 +50,6 @@
  private:
   std::unique_ptr<CompilerOptions> compiler_options_;
   std::unique_ptr<CompilerDriver> compiler_driver_;
-  std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
   std::unique_ptr<JitLogger> jit_logger_;
 
   JitCompiler();
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 0902bf2..62e8e02 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -34,7 +34,6 @@
 #include "class_linker.h"
 #include "debug/dwarf/debug_frame_opcode_writer.h"
 #include "dex/dex_file-inl.h"
-#include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "jni/jni_env_ext.h"
@@ -115,7 +114,7 @@
 //   convention.
 //
 template <PointerSize kPointerSize>
-static JniCompiledMethod ArtJniCompileMethodInternal(CompilerDriver* driver,
+static JniCompiledMethod ArtJniCompileMethodInternal(const CompilerOptions& compiler_options,
                                                      uint32_t access_flags,
                                                      uint32_t method_idx,
                                                      const DexFile& dex_file) {
@@ -124,8 +123,9 @@
   const bool is_static = (access_flags & kAccStatic) != 0;
   const bool is_synchronized = (access_flags & kAccSynchronized) != 0;
   const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
-  InstructionSet instruction_set = driver->GetInstructionSet();
-  const InstructionSetFeatures* instruction_set_features = driver->GetInstructionSetFeatures();
+  InstructionSet instruction_set = compiler_options.GetInstructionSet();
+  const InstructionSetFeatures* instruction_set_features =
+      compiler_options.GetInstructionSetFeatures();
 
   // i.e. if the method was annotated with @FastNative
   const bool is_fast_native = (access_flags & kAccFastNative) != 0u;
@@ -216,7 +216,6 @@
   // Assembler that holds generated instructions
   std::unique_ptr<JNIMacroAssembler<kPointerSize>> jni_asm =
       GetMacroAssembler<kPointerSize>(&allocator, instruction_set, instruction_set_features);
-  const CompilerOptions& compiler_options = driver->GetCompilerOptions();
   jni_asm->cfi().SetEnabled(compiler_options.GenerateAnyDebugInfo());
   jni_asm->SetEmitRunTimeChecksInDebugMode(compiler_options.EmitRunTimeChecksInDebugMode());
 
@@ -771,16 +770,16 @@
   }
 }
 
-JniCompiledMethod ArtQuickJniCompileMethod(CompilerDriver* compiler,
+JniCompiledMethod ArtQuickJniCompileMethod(const CompilerOptions& compiler_options,
                                            uint32_t access_flags,
                                            uint32_t method_idx,
                                            const DexFile& dex_file) {
-  if (Is64BitInstructionSet(compiler->GetInstructionSet())) {
+  if (Is64BitInstructionSet(compiler_options.GetInstructionSet())) {
     return ArtJniCompileMethodInternal<PointerSize::k64>(
-        compiler, access_flags, method_idx, dex_file);
+        compiler_options, access_flags, method_idx, dex_file);
   } else {
     return ArtJniCompileMethodInternal<PointerSize::k32>(
-        compiler, access_flags, method_idx, dex_file);
+        compiler_options, access_flags, method_idx, dex_file);
   }
 }
 
diff --git a/compiler/jni/quick/jni_compiler.h b/compiler/jni/quick/jni_compiler.h
index 1141994..313fcd3 100644
--- a/compiler/jni/quick/jni_compiler.h
+++ b/compiler/jni/quick/jni_compiler.h
@@ -25,7 +25,7 @@
 namespace art {
 
 class ArtMethod;
-class CompilerDriver;
+class CompilerOptions;
 class DexFile;
 
 class JniCompiledMethod {
@@ -62,7 +62,7 @@
   std::vector<uint8_t> cfi_;
 };
 
-JniCompiledMethod ArtQuickJniCompileMethod(CompilerDriver* compiler,
+JniCompiledMethod ArtQuickJniCompileMethod(const CompilerOptions& compiler_options,
                                            uint32_t access_flags,
                                            uint32_t method_idx,
                                            const DexFile& dex_file);
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 2589869..f53e60b 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -877,53 +877,45 @@
 }
 
 std::unique_ptr<CodeGenerator> CodeGenerator::Create(HGraph* graph,
-                                                     InstructionSet instruction_set,
-                                                     const InstructionSetFeatures& isa_features,
                                                      const CompilerOptions& compiler_options,
                                                      OptimizingCompilerStats* stats) {
   ArenaAllocator* allocator = graph->GetAllocator();
-  switch (instruction_set) {
+  switch (compiler_options.GetInstructionSet()) {
 #ifdef ART_ENABLE_CODEGEN_arm
     case InstructionSet::kArm:
     case InstructionSet::kThumb2: {
       return std::unique_ptr<CodeGenerator>(
-          new (allocator) arm::CodeGeneratorARMVIXL(
-              graph, *isa_features.AsArmInstructionSetFeatures(), compiler_options, stats));
+          new (allocator) arm::CodeGeneratorARMVIXL(graph, compiler_options, stats));
     }
 #endif
 #ifdef ART_ENABLE_CODEGEN_arm64
     case InstructionSet::kArm64: {
       return std::unique_ptr<CodeGenerator>(
-          new (allocator) arm64::CodeGeneratorARM64(
-              graph, *isa_features.AsArm64InstructionSetFeatures(), compiler_options, stats));
+          new (allocator) arm64::CodeGeneratorARM64(graph, compiler_options, stats));
     }
 #endif
 #ifdef ART_ENABLE_CODEGEN_mips
     case InstructionSet::kMips: {
       return std::unique_ptr<CodeGenerator>(
-          new (allocator) mips::CodeGeneratorMIPS(
-              graph, *isa_features.AsMipsInstructionSetFeatures(), compiler_options, stats));
+          new (allocator) mips::CodeGeneratorMIPS(graph, compiler_options, stats));
     }
 #endif
 #ifdef ART_ENABLE_CODEGEN_mips64
     case InstructionSet::kMips64: {
       return std::unique_ptr<CodeGenerator>(
-          new (allocator) mips64::CodeGeneratorMIPS64(
-              graph, *isa_features.AsMips64InstructionSetFeatures(), compiler_options, stats));
+          new (allocator) mips64::CodeGeneratorMIPS64(graph, compiler_options, stats));
     }
 #endif
 #ifdef ART_ENABLE_CODEGEN_x86
     case InstructionSet::kX86: {
       return std::unique_ptr<CodeGenerator>(
-          new (allocator) x86::CodeGeneratorX86(
-              graph, *isa_features.AsX86InstructionSetFeatures(), compiler_options, stats));
+          new (allocator) x86::CodeGeneratorX86(graph, compiler_options, stats));
     }
 #endif
 #ifdef ART_ENABLE_CODEGEN_x86_64
     case InstructionSet::kX86_64: {
       return std::unique_ptr<CodeGenerator>(
-          new (allocator) x86_64::CodeGeneratorX86_64(
-              graph, *isa_features.AsX86_64InstructionSetFeatures(), compiler_options, stats));
+          new (allocator) x86_64::CodeGeneratorX86_64(graph, compiler_options, stats));
     }
 #endif
     default:
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 03ae498..59f858e 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -188,8 +188,6 @@
   // Compiles the graph to executable instructions.
   void Compile(CodeAllocator* allocator);
   static std::unique_ptr<CodeGenerator> Create(HGraph* graph,
-                                               InstructionSet instruction_set,
-                                               const InstructionSetFeatures& isa_features,
                                                const CompilerOptions& compiler_options,
                                                OptimizingCompilerStats* stats = nullptr);
   virtual ~CodeGenerator();
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 85c5659..979a5d4 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1374,7 +1374,6 @@
 }
 
 CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph,
-                                       const Arm64InstructionSetFeatures& isa_features,
                                        const CompilerOptions& compiler_options,
                                        OptimizingCompilerStats* stats)
     : CodeGenerator(graph,
@@ -1391,7 +1390,6 @@
       instruction_visitor_(graph, this),
       move_resolver_(graph->GetAllocator(), this),
       assembler_(graph->GetAllocator()),
-      isa_features_(isa_features),
       uint32_literals_(std::less<uint32_t>(),
                        graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       uint64_literals_(std::less<uint64_t>(),
@@ -1729,6 +1727,10 @@
   stream << DRegister(reg);
 }
 
+const Arm64InstructionSetFeatures& CodeGeneratorARM64::GetInstructionSetFeatures() const {
+  return *GetCompilerOptions().GetInstructionSetFeatures()->AsArm64InstructionSetFeatures();
+}
+
 void CodeGeneratorARM64::MoveConstant(CPURegister destination, HConstant* constant) {
   if (constant->IsIntConstant()) {
     __ Mov(Register(destination), constant->AsIntConstant()->GetValue());
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 11ff78b..e62c16c 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -399,7 +399,6 @@
 class CodeGeneratorARM64 : public CodeGenerator {
  public:
   CodeGeneratorARM64(HGraph* graph,
-                     const Arm64InstructionSetFeatures& isa_features,
                      const CompilerOptions& compiler_options,
                      OptimizingCompilerStats* stats = nullptr);
   virtual ~CodeGeneratorARM64() {}
@@ -472,9 +471,7 @@
     return InstructionSet::kArm64;
   }
 
-  const Arm64InstructionSetFeatures& GetInstructionSetFeatures() const {
-    return isa_features_;
-  }
+  const Arm64InstructionSetFeatures& GetInstructionSetFeatures() const;
 
   void Initialize() OVERRIDE {
     block_labels_.resize(GetGraph()->GetBlocks().size());
@@ -890,7 +887,6 @@
   InstructionCodeGeneratorARM64 instruction_visitor_;
   ParallelMoveResolverARM64 move_resolver_;
   Arm64Assembler assembler_;
-  const Arm64InstructionSetFeatures& isa_features_;
 
   // Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
   Uint32ToLiteralMap uint32_literals_;
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 6804340..6c8d563 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -1502,6 +1502,10 @@
   stream << vixl32::SRegister(reg);
 }
 
+const ArmInstructionSetFeatures& CodeGeneratorARMVIXL::GetInstructionSetFeatures() const {
+  return *GetCompilerOptions().GetInstructionSetFeatures()->AsArmInstructionSetFeatures();
+}
+
 static uint32_t ComputeSRegisterListMask(const SRegisterList& regs) {
   uint32_t mask = 0;
   for (uint32_t i = regs.GetFirstSRegister().GetCode();
@@ -2319,7 +2323,6 @@
 }
 
 CodeGeneratorARMVIXL::CodeGeneratorARMVIXL(HGraph* graph,
-                                           const ArmInstructionSetFeatures& isa_features,
                                            const CompilerOptions& compiler_options,
                                            OptimizingCompilerStats* stats)
     : CodeGenerator(graph,
@@ -2336,7 +2339,6 @@
       instruction_visitor_(graph, this),
       move_resolver_(graph->GetAllocator(), this),
       assembler_(graph->GetAllocator()),
-      isa_features_(isa_features),
       uint32_literals_(std::less<uint32_t>(),
                        graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 4893d3c..ae19cdb 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -428,7 +428,6 @@
 class CodeGeneratorARMVIXL : public CodeGenerator {
  public:
   CodeGeneratorARMVIXL(HGraph* graph,
-                       const ArmInstructionSetFeatures& isa_features,
                        const CompilerOptions& compiler_options,
                        OptimizingCompilerStats* stats = nullptr);
   virtual ~CodeGeneratorARMVIXL() {}
@@ -475,6 +474,9 @@
 
   ParallelMoveResolver* GetMoveResolver() OVERRIDE { return &move_resolver_; }
   InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kThumb2; }
+
+  const ArmInstructionSetFeatures& GetInstructionSetFeatures() const;
+
   // Helper method to move a 32-bit value between two locations.
   void Move32(Location destination, Location source);
 
@@ -523,8 +525,6 @@
 
   void Finalize(CodeAllocator* allocator) OVERRIDE;
 
-  const ArmInstructionSetFeatures& GetInstructionSetFeatures() const { return isa_features_; }
-
   bool NeedsTwoRegisters(DataType::Type type) const OVERRIDE {
     return type == DataType::Type::kFloat64 || type == DataType::Type::kInt64;
   }
@@ -888,7 +888,6 @@
   ParallelMoveResolverARMVIXL move_resolver_;
 
   ArmVIXLAssembler assembler_;
-  const ArmInstructionSetFeatures& isa_features_;
 
   // Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
   Uint32ToLiteralMap uint32_literals_;
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 112eb51..8c38824 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -997,7 +997,6 @@
 };
 
 CodeGeneratorMIPS::CodeGeneratorMIPS(HGraph* graph,
-                                     const MipsInstructionSetFeatures& isa_features,
                                      const CompilerOptions& compiler_options,
                                      OptimizingCompilerStats* stats)
     : CodeGenerator(graph,
@@ -1014,8 +1013,8 @@
       location_builder_(graph, this),
       instruction_visitor_(graph, this),
       move_resolver_(graph->GetAllocator(), this),
-      assembler_(graph->GetAllocator(), &isa_features),
-      isa_features_(isa_features),
+      assembler_(graph->GetAllocator(),
+                 compiler_options.GetInstructionSetFeatures()->AsMipsInstructionSetFeatures()),
       uint32_literals_(std::less<uint32_t>(),
                        graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -1912,6 +1911,10 @@
   stream << FRegister(reg);
 }
 
+const MipsInstructionSetFeatures& CodeGeneratorMIPS::GetInstructionSetFeatures() const {
+  return *GetCompilerOptions().GetInstructionSetFeatures()->AsMipsInstructionSetFeatures();
+}
+
 constexpr size_t kMipsDirectEntrypointRuntimeOffset = 16;
 
 void CodeGeneratorMIPS::InvokeRuntime(QuickEntrypointEnum entrypoint,
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index 9fdb385..9758d35 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -370,7 +370,6 @@
 class CodeGeneratorMIPS : public CodeGenerator {
  public:
   CodeGeneratorMIPS(HGraph* graph,
-                    const MipsInstructionSetFeatures& isa_features,
                     const CompilerOptions& compiler_options,
                     OptimizingCompilerStats* stats = nullptr);
   virtual ~CodeGeneratorMIPS() {}
@@ -509,9 +508,7 @@
 
   InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kMips; }
 
-  const MipsInstructionSetFeatures& GetInstructionSetFeatures() const {
-    return isa_features_;
-  }
+  const MipsInstructionSetFeatures& GetInstructionSetFeatures() const;
 
   MipsLabel* GetLabelOf(HBasicBlock* block) const {
     return CommonGetLabelOf<MipsLabel>(block_labels_, block);
@@ -695,7 +692,6 @@
   InstructionCodeGeneratorMIPS instruction_visitor_;
   ParallelMoveResolverMIPS move_resolver_;
   MipsAssembler assembler_;
-  const MipsInstructionSetFeatures& isa_features_;
 
   // Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
   Uint32ToLiteralMap uint32_literals_;
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 9f86364..9682377 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -940,7 +940,6 @@
 };
 
 CodeGeneratorMIPS64::CodeGeneratorMIPS64(HGraph* graph,
-                                         const Mips64InstructionSetFeatures& isa_features,
                                          const CompilerOptions& compiler_options,
                                          OptimizingCompilerStats* stats)
     : CodeGenerator(graph,
@@ -957,8 +956,8 @@
       location_builder_(graph, this),
       instruction_visitor_(graph, this),
       move_resolver_(graph->GetAllocator(), this),
-      assembler_(graph->GetAllocator(), &isa_features),
-      isa_features_(isa_features),
+      assembler_(graph->GetAllocator(),
+                 compiler_options.GetInstructionSetFeatures()->AsMips64InstructionSetFeatures()),
       uint32_literals_(std::less<uint32_t>(),
                        graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       uint64_literals_(std::less<uint64_t>(),
@@ -1772,6 +1771,10 @@
   stream << FpuRegister(reg);
 }
 
+const Mips64InstructionSetFeatures& CodeGeneratorMIPS64::GetInstructionSetFeatures() const {
+  return *GetCompilerOptions().GetInstructionSetFeatures()->AsMips64InstructionSetFeatures();
+}
+
 void CodeGeneratorMIPS64::InvokeRuntime(QuickEntrypointEnum entrypoint,
                                         HInstruction* instruction,
                                         uint32_t dex_pc,
diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h
index 25c886f..96306d1 100644
--- a/compiler/optimizing/code_generator_mips64.h
+++ b/compiler/optimizing/code_generator_mips64.h
@@ -352,7 +352,6 @@
 class CodeGeneratorMIPS64 : public CodeGenerator {
  public:
   CodeGeneratorMIPS64(HGraph* graph,
-                      const Mips64InstructionSetFeatures& isa_features,
                       const CompilerOptions& compiler_options,
                       OptimizingCompilerStats* stats = nullptr);
   virtual ~CodeGeneratorMIPS64() {}
@@ -484,9 +483,7 @@
 
   InstructionSet GetInstructionSet() const OVERRIDE { return InstructionSet::kMips64; }
 
-  const Mips64InstructionSetFeatures& GetInstructionSetFeatures() const {
-    return isa_features_;
-  }
+  const Mips64InstructionSetFeatures& GetInstructionSetFeatures() const;
 
   Mips64Label* GetLabelOf(HBasicBlock* block) const {
     return CommonGetLabelOf<Mips64Label>(block_labels_, block);
@@ -657,7 +654,6 @@
   InstructionCodeGeneratorMIPS64 instruction_visitor_;
   ParallelMoveResolverMIPS64 move_resolver_;
   Mips64Assembler assembler_;
-  const Mips64InstructionSetFeatures& isa_features_;
 
   // Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
   Uint32ToLiteralMap uint32_literals_;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 12872ed..b03d72c 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -958,6 +958,10 @@
   stream << XmmRegister(reg);
 }
 
+const X86InstructionSetFeatures& CodeGeneratorX86::GetInstructionSetFeatures() const {
+  return *GetCompilerOptions().GetInstructionSetFeatures()->AsX86InstructionSetFeatures();
+}
+
 size_t CodeGeneratorX86::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
   __ movl(Address(ESP, stack_index), static_cast<Register>(reg_id));
   return kX86WordSize;
@@ -1009,7 +1013,6 @@
 }
 
 CodeGeneratorX86::CodeGeneratorX86(HGraph* graph,
-                                   const X86InstructionSetFeatures& isa_features,
                                    const CompilerOptions& compiler_options,
                                    OptimizingCompilerStats* stats)
     : CodeGenerator(graph,
@@ -1027,7 +1030,6 @@
       instruction_visitor_(graph, this),
       move_resolver_(graph->GetAllocator(), this),
       assembler_(graph->GetAllocator()),
-      isa_features_(isa_features),
       boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
       boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 7d18e2b..e947b9d 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -316,7 +316,6 @@
 class CodeGeneratorX86 : public CodeGenerator {
  public:
   CodeGeneratorX86(HGraph* graph,
-                   const X86InstructionSetFeatures& isa_features,
                    const CompilerOptions& compiler_options,
                    OptimizingCompilerStats* stats = nullptr);
   virtual ~CodeGeneratorX86() {}
@@ -390,6 +389,8 @@
     return InstructionSet::kX86;
   }
 
+  const X86InstructionSetFeatures& GetInstructionSetFeatures() const;
+
   // Helper method to move a 32bits value between two locations.
   void Move32(Location destination, Location source);
   // Helper method to move a 64bits value between two locations.
@@ -474,10 +475,6 @@
 
   Label* GetFrameEntryLabel() { return &frame_entry_label_; }
 
-  const X86InstructionSetFeatures& GetInstructionSetFeatures() const {
-    return isa_features_;
-  }
-
   void AddMethodAddressOffset(HX86ComputeBaseMethodAddress* method_base, int32_t offset) {
     method_address_offset_.Put(method_base->GetId(), offset);
   }
@@ -640,7 +637,6 @@
   InstructionCodeGeneratorX86 instruction_visitor_;
   ParallelMoveResolverX86 move_resolver_;
   X86Assembler assembler_;
-  const X86InstructionSetFeatures& isa_features_;
 
   // PC-relative method patch info for kBootImageLinkTimePcRelative/kBootImageRelRo.
   // Also used for type/string patches for kBootImageRelRo (same linker patch as for methods).
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 9631c15..28f3abf 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1185,6 +1185,10 @@
   stream << FloatRegister(reg);
 }
 
+const X86_64InstructionSetFeatures& CodeGeneratorX86_64::GetInstructionSetFeatures() const {
+  return *GetCompilerOptions().GetInstructionSetFeatures()->AsX86_64InstructionSetFeatures();
+}
+
 size_t CodeGeneratorX86_64::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
   __ movq(Address(CpuRegister(RSP), stack_index), CpuRegister(reg_id));
   return kX86_64WordSize;
@@ -1239,7 +1243,6 @@
 // Use a fake return address register to mimic Quick.
 static constexpr Register kFakeReturnRegister = Register(kLastCpuRegister + 1);
 CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph,
-                                         const X86_64InstructionSetFeatures& isa_features,
                                          const CompilerOptions& compiler_options,
                                          OptimizingCompilerStats* stats)
       : CodeGenerator(graph,
@@ -1258,7 +1261,6 @@
         instruction_visitor_(graph, this),
         move_resolver_(graph->GetAllocator(), this),
         assembler_(graph->GetAllocator()),
-        isa_features_(isa_features),
         constant_area_start_(0),
         boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
         method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index cf862d3..0937f55 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -296,7 +296,6 @@
 class CodeGeneratorX86_64 : public CodeGenerator {
  public:
   CodeGeneratorX86_64(HGraph* graph,
-                  const X86_64InstructionSetFeatures& isa_features,
                   const CompilerOptions& compiler_options,
                   OptimizingCompilerStats* stats = nullptr);
   virtual ~CodeGeneratorX86_64() {}
@@ -370,6 +369,8 @@
     return InstructionSet::kX86_64;
   }
 
+  const X86_64InstructionSetFeatures& GetInstructionSetFeatures() const;
+
   // Emit a write barrier.
   void MarkGCCard(CpuRegister temp,
                   CpuRegister card,
@@ -440,10 +441,6 @@
 
   void EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) OVERRIDE;
 
-  const X86_64InstructionSetFeatures& GetInstructionSetFeatures() const {
-    return isa_features_;
-  }
-
   // Fast path implementation of ReadBarrier::Barrier for a heap
   // reference field load when Baker's read barriers are used.
   void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction,
@@ -606,7 +603,6 @@
   InstructionCodeGeneratorX86_64 instruction_visitor_;
   ParallelMoveResolverX86_64 move_resolver_;
   X86_64Assembler assembler_;
-  const X86_64InstructionSetFeatures& isa_features_;
 
   // Offset to the start of the constant area in the assembled code.
   // Used for fixups to the constant area.
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index a0fd5ff..86687e6 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -89,7 +89,8 @@
     HGraph* graph = CreateCFG(data);
     // Remove suspend checks, they cannot be executed in this context.
     RemoveSuspendChecks(graph);
-    RunCode(target_config, graph, [](HGraph*) {}, has_result, expected);
+    OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
+    RunCode(target_config, *compiler_options_, graph, [](HGraph*) {}, has_result, expected);
   }
 }
 
@@ -100,7 +101,8 @@
     HGraph* graph = CreateCFG(data, DataType::Type::kInt64);
     // Remove suspend checks, they cannot be executed in this context.
     RemoveSuspendChecks(graph);
-    RunCode(target_config, graph, [](HGraph*) {}, has_result, expected);
+    OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
+    RunCode(target_config, *compiler_options_, graph, [](HGraph*) {}, has_result, expected);
   }
 }
 
@@ -460,7 +462,8 @@
       block->InsertInstructionBefore(move, block->GetLastInstruction());
     };
 
-    RunCode(target_config, graph, hook_before_codegen, true, 0);
+    OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
+    RunCode(target_config, *compiler_options_, graph, hook_before_codegen, true, 0);
   }
 }
 
@@ -506,7 +509,8 @@
             new (graph_in->GetAllocator()) HParallelMove(graph_in->GetAllocator());
         block->InsertInstructionBefore(move, block->GetLastInstruction());
       };
-      RunCode(target_config, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
+      OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
+      RunCode(target_config, *compiler_options_, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
     }
   }
 }
@@ -573,7 +577,8 @@
             new (graph_in->GetAllocator()) HParallelMove(graph_in->GetAllocator());
         block->InsertInstructionBefore(move, block->GetLastInstruction());
       };
-      RunCode(target_config, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
+      OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
+      RunCode(target_config, *compiler_options_, graph, hook_before_codegen, true, lhs[i] < rhs[i]);
     }
   }
 }
@@ -682,7 +687,8 @@
   block->AddInstruction(new (GetAllocator()) HReturn(comparison));
 
   graph->BuildDominatorTree();
-  RunCode(target_config, graph, [](HGraph*) {}, true, expected_result);
+  OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
+  RunCode(target_config, *compiler_options_, graph, [](HGraph*) {}, true, expected_result);
 }
 
 TEST_F(CodegenTest, ComparisonsInt) {
@@ -713,10 +719,9 @@
 
 #ifdef ART_ENABLE_CODEGEN_arm
 TEST_F(CodegenTest, ARMVIXLParallelMoveResolver) {
-  std::unique_ptr<const ArmInstructionSetFeatures> features(
-      ArmInstructionSetFeatures::FromCppDefines());
+  OverrideInstructionSetFeatures(InstructionSet::kThumb2, "default");
   HGraph* graph = CreateGraph();
-  arm::CodeGeneratorARMVIXL codegen(graph, *features.get(), CompilerOptions());
+  arm::CodeGeneratorARMVIXL codegen(graph, *compiler_options_);
 
   codegen.Initialize();
 
@@ -737,10 +742,9 @@
 #ifdef ART_ENABLE_CODEGEN_arm64
 // Regression test for b/34760542.
 TEST_F(CodegenTest, ARM64ParallelMoveResolverB34760542) {
-  std::unique_ptr<const Arm64InstructionSetFeatures> features(
-      Arm64InstructionSetFeatures::FromCppDefines());
+  OverrideInstructionSetFeatures(InstructionSet::kArm64, "default");
   HGraph* graph = CreateGraph();
-  arm64::CodeGeneratorARM64 codegen(graph, *features.get(), CompilerOptions());
+  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options_);
 
   codegen.Initialize();
 
@@ -787,10 +791,9 @@
 
 // Check that ParallelMoveResolver works fine for ARM64 for both cases when SIMD is on and off.
 TEST_F(CodegenTest, ARM64ParallelMoveResolverSIMD) {
-  std::unique_ptr<const Arm64InstructionSetFeatures> features(
-      Arm64InstructionSetFeatures::FromCppDefines());
+  OverrideInstructionSetFeatures(InstructionSet::kArm64, "default");
   HGraph* graph = CreateGraph();
-  arm64::CodeGeneratorARM64 codegen(graph, *features.get(), CompilerOptions());
+  arm64::CodeGeneratorARM64 codegen(graph, *compiler_options_);
 
   codegen.Initialize();
 
@@ -824,9 +827,9 @@
 
 #ifdef ART_ENABLE_CODEGEN_mips
 TEST_F(CodegenTest, MipsClobberRA) {
-  std::unique_ptr<const MipsInstructionSetFeatures> features_mips(
-      MipsInstructionSetFeatures::FromCppDefines());
-  if (!CanExecute(InstructionSet::kMips) || features_mips->IsR6()) {
+  OverrideInstructionSetFeatures(InstructionSet::kMips, "mips32r");
+  CHECK(!instruction_set_features_->AsMipsInstructionSetFeatures()->IsR6());
+  if (!CanExecute(InstructionSet::kMips)) {
     // HMipsComputeBaseMethodAddress and the NAL instruction behind it
     // should only be generated on non-R6.
     return;
@@ -860,7 +863,7 @@
 
   graph->BuildDominatorTree();
 
-  mips::CodeGeneratorMIPS codegenMIPS(graph, *features_mips.get(), CompilerOptions());
+  mips::CodeGeneratorMIPS codegenMIPS(graph, *compiler_options_);
   // Since there isn't HLoadClass or HLoadString, we need to manually indicate
   // that RA is clobbered and the method entry code should generate a stack frame
   // and preserve RA in it. And this is what we're testing here.
diff --git a/compiler/optimizing/codegen_test_utils.h b/compiler/optimizing/codegen_test_utils.h
index 792cfb5..9181126 100644
--- a/compiler/optimizing/codegen_test_utils.h
+++ b/compiler/optimizing/codegen_test_utils.h
@@ -17,17 +17,11 @@
 #ifndef ART_COMPILER_OPTIMIZING_CODEGEN_TEST_UTILS_H_
 #define ART_COMPILER_OPTIMIZING_CODEGEN_TEST_UTILS_H_
 
-#include "arch/arm/instruction_set_features_arm.h"
 #include "arch/arm/registers_arm.h"
-#include "arch/arm64/instruction_set_features_arm64.h"
 #include "arch/instruction_set.h"
-#include "arch/mips/instruction_set_features_mips.h"
 #include "arch/mips/registers_mips.h"
-#include "arch/mips64/instruction_set_features_mips64.h"
 #include "arch/mips64/registers_mips64.h"
-#include "arch/x86/instruction_set_features_x86.h"
 #include "arch/x86/registers_x86.h"
-#include "arch/x86_64/instruction_set_features_x86_64.h"
 #include "code_simulator.h"
 #include "code_simulator_container.h"
 #include "common_compiler_test.h"
@@ -101,10 +95,8 @@
 // to just overwrite the code generator.
 class TestCodeGeneratorARMVIXL : public arm::CodeGeneratorARMVIXL {
  public:
-  TestCodeGeneratorARMVIXL(HGraph* graph,
-                           const ArmInstructionSetFeatures& isa_features,
-                           const CompilerOptions& compiler_options)
-      : arm::CodeGeneratorARMVIXL(graph, isa_features, compiler_options) {
+  TestCodeGeneratorARMVIXL(HGraph* graph, const CompilerOptions& compiler_options)
+      : arm::CodeGeneratorARMVIXL(graph, compiler_options) {
     AddAllocatedRegister(Location::RegisterLocation(arm::R6));
     AddAllocatedRegister(Location::RegisterLocation(arm::R7));
   }
@@ -145,10 +137,8 @@
 //   function.
 class TestCodeGeneratorARM64 : public arm64::CodeGeneratorARM64 {
  public:
-  TestCodeGeneratorARM64(HGraph* graph,
-                         const Arm64InstructionSetFeatures& isa_features,
-                         const CompilerOptions& compiler_options)
-      : arm64::CodeGeneratorARM64(graph, isa_features, compiler_options) {}
+  TestCodeGeneratorARM64(HGraph* graph, const CompilerOptions& compiler_options)
+      : arm64::CodeGeneratorARM64(graph, compiler_options) {}
 
   void MaybeGenerateMarkingRegisterCheck(int codem ATTRIBUTE_UNUSED,
                                          Location temp_loc ATTRIBUTE_UNUSED) OVERRIDE {
@@ -165,10 +155,8 @@
 #ifdef ART_ENABLE_CODEGEN_x86
 class TestCodeGeneratorX86 : public x86::CodeGeneratorX86 {
  public:
-  TestCodeGeneratorX86(HGraph* graph,
-                       const X86InstructionSetFeatures& isa_features,
-                       const CompilerOptions& compiler_options)
-      : x86::CodeGeneratorX86(graph, isa_features, compiler_options) {
+  TestCodeGeneratorX86(HGraph* graph, const CompilerOptions& compiler_options)
+      : x86::CodeGeneratorX86(graph, compiler_options) {
     // Save edi, we need it for getting enough registers for long multiplication.
     AddAllocatedRegister(Location::RegisterLocation(x86::EDI));
   }
@@ -324,11 +312,11 @@
 
 template <typename Expected>
 static void RunCode(CodegenTargetConfig target_config,
+                    const CompilerOptions& compiler_options,
                     HGraph* graph,
                     std::function<void(HGraph*)> hook_before_codegen,
                     bool has_result,
                     Expected expected) {
-  CompilerOptions compiler_options;
   std::unique_ptr<CodeGenerator> codegen(target_config.CreateCodeGenerator(graph,
                                                                            compiler_options));
   RunCode(codegen.get(), graph, hook_before_codegen, has_result, expected);
@@ -336,55 +324,37 @@
 
 #ifdef ART_ENABLE_CODEGEN_arm
 CodeGenerator* create_codegen_arm_vixl32(HGraph* graph, const CompilerOptions& compiler_options) {
-  std::unique_ptr<const ArmInstructionSetFeatures> features_arm(
-      ArmInstructionSetFeatures::FromCppDefines());
-  return new (graph->GetAllocator())
-      TestCodeGeneratorARMVIXL(graph, *features_arm.get(), compiler_options);
+  return new (graph->GetAllocator()) TestCodeGeneratorARMVIXL(graph, compiler_options);
 }
 #endif
 
 #ifdef ART_ENABLE_CODEGEN_arm64
 CodeGenerator* create_codegen_arm64(HGraph* graph, const CompilerOptions& compiler_options) {
-  std::unique_ptr<const Arm64InstructionSetFeatures> features_arm64(
-      Arm64InstructionSetFeatures::FromCppDefines());
-  return new (graph->GetAllocator())
-      TestCodeGeneratorARM64(graph, *features_arm64.get(), compiler_options);
+  return new (graph->GetAllocator()) TestCodeGeneratorARM64(graph, compiler_options);
 }
 #endif
 
 #ifdef ART_ENABLE_CODEGEN_x86
 CodeGenerator* create_codegen_x86(HGraph* graph, const CompilerOptions& compiler_options) {
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  return new (graph->GetAllocator()) TestCodeGeneratorX86(
-      graph, *features_x86.get(), compiler_options);
+  return new (graph->GetAllocator()) TestCodeGeneratorX86(graph, compiler_options);
 }
 #endif
 
 #ifdef ART_ENABLE_CODEGEN_x86_64
 CodeGenerator* create_codegen_x86_64(HGraph* graph, const CompilerOptions& compiler_options) {
-  std::unique_ptr<const X86_64InstructionSetFeatures> features_x86_64(
-     X86_64InstructionSetFeatures::FromCppDefines());
-  return new (graph->GetAllocator())
-      x86_64::CodeGeneratorX86_64(graph, *features_x86_64.get(), compiler_options);
+  return new (graph->GetAllocator()) x86_64::CodeGeneratorX86_64(graph, compiler_options);
 }
 #endif
 
 #ifdef ART_ENABLE_CODEGEN_mips
 CodeGenerator* create_codegen_mips(HGraph* graph, const CompilerOptions& compiler_options) {
-  std::unique_ptr<const MipsInstructionSetFeatures> features_mips(
-      MipsInstructionSetFeatures::FromCppDefines());
-  return new (graph->GetAllocator())
-      mips::CodeGeneratorMIPS(graph, *features_mips.get(), compiler_options);
+  return new (graph->GetAllocator()) mips::CodeGeneratorMIPS(graph, compiler_options);
 }
 #endif
 
 #ifdef ART_ENABLE_CODEGEN_mips64
 CodeGenerator* create_codegen_mips64(HGraph* graph, const CompilerOptions& compiler_options) {
-  std::unique_ptr<const Mips64InstructionSetFeatures> features_mips64(
-      Mips64InstructionSetFeatures::FromCppDefines());
-  return new (graph->GetAllocator())
-      mips64::CodeGeneratorMIPS64(graph, *features_mips64.get(), compiler_options);
+  return new (graph->GetAllocator()) mips64::CodeGeneratorMIPS64(graph, compiler_options);
 }
 #endif
 
diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc
index d271047..b1436f8 100644
--- a/compiler/optimizing/constant_folding_test.cc
+++ b/compiler/optimizing/constant_folding_test.cc
@@ -16,8 +16,6 @@
 
 #include <functional>
 
-#include "arch/x86/instruction_set_features_x86.h"
-#include "code_generator_x86.h"
 #include "constant_folding.h"
 #include "dead_code_elimination.h"
 #include "driver/compiler_options.h"
@@ -60,9 +58,6 @@
     std::string actual_before = printer_before.str();
     EXPECT_EQ(expected_before, actual_before);
 
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    x86::CodeGeneratorX86 codegenX86(graph_, *features_x86.get(), CompilerOptions());
     HConstantFolding(graph_, "constant_folding").Run();
     GraphChecker graph_checker_cf(graph_);
     graph_checker_cf.Run();
diff --git a/compiler/optimizing/dead_code_elimination_test.cc b/compiler/optimizing/dead_code_elimination_test.cc
index adb6ce1..2774535 100644
--- a/compiler/optimizing/dead_code_elimination_test.cc
+++ b/compiler/optimizing/dead_code_elimination_test.cc
@@ -16,8 +16,6 @@
 
 #include "dead_code_elimination.h"
 
-#include "arch/x86/instruction_set_features_x86.h"
-#include "code_generator_x86.h"
 #include "driver/compiler_options.h"
 #include "graph_checker.h"
 #include "optimizing_unit_test.h"
@@ -45,9 +43,6 @@
   std::string actual_before = printer_before.str();
   ASSERT_EQ(actual_before, expected_before);
 
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegenX86(graph, *features_x86.get(), CompilerOptions());
   HDeadCodeElimination(graph, nullptr /* stats */, "dead_code_elimination").Run();
   GraphChecker graph_checker(graph);
   graph_checker.Run();
diff --git a/compiler/optimizing/emit_swap_mips_test.cc b/compiler/optimizing/emit_swap_mips_test.cc
index b63914f..293c1ab 100644
--- a/compiler/optimizing/emit_swap_mips_test.cc
+++ b/compiler/optimizing/emit_swap_mips_test.cc
@@ -28,11 +28,12 @@
 class EmitSwapMipsTest : public OptimizingUnitTest {
  public:
   void SetUp() OVERRIDE {
+    instruction_set_ = InstructionSet::kMips;
+    instruction_set_features_ = MipsInstructionSetFeatures::FromCppDefines();
+    OptimizingUnitTest::SetUp();
     graph_ = CreateGraph();
-    isa_features_ = MipsInstructionSetFeatures::FromCppDefines();
-    codegen_ = new (graph_->GetAllocator()) mips::CodeGeneratorMIPS(graph_,
-                                                                    *isa_features_.get(),
-                                                                    CompilerOptions());
+    codegen_.reset(
+        new (graph_->GetAllocator()) mips::CodeGeneratorMIPS(graph_, *compiler_options_));
     moves_ = new (GetAllocator()) HParallelMove(GetAllocator());
     test_helper_.reset(
         new AssemblerTestInfrastructure(GetArchitectureString(),
@@ -47,8 +48,10 @@
 
   void TearDown() OVERRIDE {
     test_helper_.reset();
-    isa_features_.reset();
+    codegen_.reset();
+    graph_ = nullptr;
     ResetPoolAndAllocator();
+    OptimizingUnitTest::TearDown();
   }
 
   // Get the typically used name for this architecture.
@@ -106,10 +109,9 @@
  protected:
   HGraph* graph_;
   HParallelMove* moves_;
-  mips::CodeGeneratorMIPS* codegen_;
+  std::unique_ptr<mips::CodeGeneratorMIPS> codegen_;
   mips::MipsAssembler* assembler_;
   std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
-  std::unique_ptr<const MipsInstructionSetFeatures> isa_features_;
 };
 
 TEST_F(EmitSwapMipsTest, TwoRegisters) {
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 72d53d2..a104070 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -1783,7 +1783,7 @@
       graph_->GetArenaStack(),
       callee_dex_file,
       method_index,
-      compiler_driver_->GetInstructionSet(),
+      codegen_->GetCompilerOptions().GetInstructionSet(),
       invoke_type,
       graph_->IsDebuggable(),
       /* osr */ false,
@@ -1820,8 +1820,8 @@
     return false;
   }
 
-  if (!RegisterAllocator::CanAllocateRegistersFor(*callee_graph,
-                                                  compiler_driver_->GetInstructionSet())) {
+  if (!RegisterAllocator::CanAllocateRegistersFor(
+          *callee_graph, codegen_->GetCompilerOptions().GetInstructionSet())) {
     LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedRegisterAllocator)
         << "Method " << callee_dex_file.PrettyMethod(method_index)
         << " cannot be inlined because of the register allocator";
diff --git a/compiler/optimizing/linearize_test.cc b/compiler/optimizing/linearize_test.cc
index 9fa5b74..50bfe84 100644
--- a/compiler/optimizing/linearize_test.cc
+++ b/compiler/optimizing/linearize_test.cc
@@ -16,11 +16,9 @@
 
 #include <fstream>
 
-#include "arch/x86/instruction_set_features_x86.h"
 #include "base/arena_allocator.h"
 #include "builder.h"
 #include "code_generator.h"
-#include "code_generator_x86.h"
 #include "dex/dex_file.h"
 #include "dex/dex_instruction.h"
 #include "driver/compiler_options.h"
@@ -43,10 +41,8 @@
 void LinearizeTest::TestCode(const std::vector<uint16_t>& data,
                              const uint32_t (&expected_order)[number_of_blocks]) {
   HGraph* graph = CreateCFG(data);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
-  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
   ASSERT_EQ(graph->GetLinearOrder().size(), number_of_blocks);
diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc
index 6666066..0fb90fb 100644
--- a/compiler/optimizing/live_ranges_test.cc
+++ b/compiler/optimizing/live_ranges_test.cc
@@ -14,11 +14,9 @@
  * limitations under the License.
  */
 
-#include "arch/x86/instruction_set_features_x86.h"
 #include "base/arena_allocator.h"
 #include "builder.h"
 #include "code_generator.h"
-#include "code_generator_x86.h"
 #include "dex/dex_file.h"
 #include "dex/dex_instruction.h"
 #include "driver/compiler_options.h"
@@ -63,10 +61,8 @@
 
   HGraph* graph = BuildGraph(data);
 
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
-  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
   LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
@@ -109,10 +105,8 @@
     Instruction::RETURN | 0 << 8);
 
   HGraph* graph = BuildGraph(data);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
-  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
   LiveInterval* interval = liveness.GetInstructionFromSsaIndex(0)->GetLiveInterval();
@@ -158,10 +152,8 @@
     Instruction::RETURN | 0 << 8);
 
   HGraph* graph = BuildGraph(data);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
-  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
   // Test for the 4 constant.
@@ -235,10 +227,8 @@
 
   HGraph* graph = BuildGraph(data);
   RemoveSuspendChecks(graph);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
-  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
   // Test for the 0 constant.
@@ -312,10 +302,8 @@
     Instruction::RETURN | 0 << 8);
 
   HGraph* graph = BuildGraph(data);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
-  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
   // Test for the 0 constant.
@@ -388,10 +376,8 @@
     Instruction::RETURN);
 
   HGraph* graph = BuildGraph(data);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
-  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
   // Test for the 0 constant.
diff --git a/compiler/optimizing/liveness_test.cc b/compiler/optimizing/liveness_test.cc
index 6621a03..72f995e 100644
--- a/compiler/optimizing/liveness_test.cc
+++ b/compiler/optimizing/liveness_test.cc
@@ -14,11 +14,9 @@
  * limitations under the License.
  */
 
-#include "arch/x86/instruction_set_features_x86.h"
 #include "base/arena_allocator.h"
 #include "builder.h"
 #include "code_generator.h"
-#include "code_generator_x86.h"
 #include "dex/dex_file.h"
 #include "dex/dex_instruction.h"
 #include "driver/compiler_options.h"
@@ -50,10 +48,8 @@
   HGraph* graph = CreateCFG(data);
   // `Inline` conditions into ifs.
   PrepareForRegisterAllocation(graph).Run();
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
-  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
+  std::unique_ptr<CodeGenerator> codegen = CodeGenerator::Create(graph, *compiler_options_);
+  SsaLivenessAnalysis liveness(graph, codegen.get(), GetScopedAllocator());
   liveness.Analyze();
 
   std::ostringstream buffer;
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index eda6bd1..72aa253 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -23,7 +23,7 @@
 #include "arch/mips64/instruction_set_features_mips64.h"
 #include "arch/x86/instruction_set_features_x86.h"
 #include "arch/x86_64/instruction_set_features_x86_64.h"
-#include "driver/compiler_driver.h"
+#include "driver/compiler_options.h"
 #include "linear_order.h"
 #include "mirror/array-inl.h"
 #include "mirror/string.h"
@@ -427,12 +427,12 @@
 //
 
 HLoopOptimization::HLoopOptimization(HGraph* graph,
-                                     CompilerDriver* compiler_driver,
+                                     const CompilerOptions* compiler_options,
                                      HInductionVarAnalysis* induction_analysis,
                                      OptimizingCompilerStats* stats,
                                      const char* name)
     : HOptimization(graph, name, stats),
-      compiler_driver_(compiler_driver),
+      compiler_options_(compiler_options),
       induction_range_(induction_analysis),
       loop_allocator_(nullptr),
       global_allocator_(graph_->GetAllocator()),
@@ -454,8 +454,8 @@
       vector_header_(nullptr),
       vector_body_(nullptr),
       vector_index_(nullptr),
-      arch_loop_helper_(ArchNoOptsLoopHelper::Create(compiler_driver_ != nullptr
-                                                          ? compiler_driver_->GetInstructionSet()
+      arch_loop_helper_(ArchNoOptsLoopHelper::Create(compiler_options_ != nullptr
+                                                          ? compiler_options_->GetInstructionSet()
                                                           : InstructionSet::kNone,
                                                       global_allocator_)) {
 }
@@ -756,9 +756,9 @@
 //
 
 bool HLoopOptimization::TryUnrollingForBranchPenaltyReduction(LoopNode* node) {
-  // Don't run peeling/unrolling if compiler_driver_ is nullptr (i.e., running under tests)
+  // Don't run peeling/unrolling if compiler_options_ is nullptr (i.e., running under tests)
   // as InstructionSet is needed.
-  if (compiler_driver_ == nullptr) {
+  if (compiler_options_ == nullptr) {
     return false;
   }
 
@@ -802,9 +802,9 @@
 }
 
 bool HLoopOptimization::TryPeelingForLoopInvariantExitsElimination(LoopNode* node) {
-  // Don't run peeling/unrolling if compiler_driver_ is nullptr (i.e., running under tests)
+  // Don't run peeling/unrolling if compiler_options_ is nullptr (i.e., running under tests)
   // as InstructionSet is needed.
-  if (compiler_driver_ == nullptr) {
+  if (compiler_options_ == nullptr) {
     return false;
   }
 
@@ -1459,7 +1459,7 @@
 }
 
 uint32_t HLoopOptimization::GetVectorSizeInBytes() {
-  switch (compiler_driver_->GetInstructionSet()) {
+  switch (compiler_options_->GetInstructionSet()) {
     case InstructionSet::kArm:
     case InstructionSet::kThumb2:
       return 8;  // 64-bit SIMD
@@ -1469,8 +1469,8 @@
 }
 
 bool HLoopOptimization::TrySetVectorType(DataType::Type type, uint64_t* restrictions) {
-  const InstructionSetFeatures* features = compiler_driver_->GetInstructionSetFeatures();
-  switch (compiler_driver_->GetInstructionSet()) {
+  const InstructionSetFeatures* features = compiler_options_->GetInstructionSetFeatures();
+  switch (compiler_options_->GetInstructionSet()) {
     case InstructionSet::kArm:
     case InstructionSet::kThumb2:
       // Allow vectorization for all ARM devices, because Android assumes that
diff --git a/compiler/optimizing/loop_optimization.h b/compiler/optimizing/loop_optimization.h
index 191a93d..9743b25 100644
--- a/compiler/optimizing/loop_optimization.h
+++ b/compiler/optimizing/loop_optimization.h
@@ -27,7 +27,7 @@
 
 namespace art {
 
-class CompilerDriver;
+class CompilerOptions;
 class ArchNoOptsLoopHelper;
 
 /**
@@ -38,7 +38,7 @@
 class HLoopOptimization : public HOptimization {
  public:
   HLoopOptimization(HGraph* graph,
-                    CompilerDriver* compiler_driver,
+                    const CompilerOptions* compiler_options,
                     HInductionVarAnalysis* induction_analysis,
                     OptimizingCompilerStats* stats,
                     const char* name = kLoopOptimizationPassName);
@@ -243,8 +243,8 @@
   void RemoveDeadInstructions(const HInstructionList& list);
   bool CanRemoveCycle();  // Whether the current 'iset_' is removable.
 
-  // Compiler driver (to query ISA features).
-  const CompilerDriver* compiler_driver_;
+  // Compiler options (to query ISA features).
+  const CompilerOptions* compiler_options_;
 
   // Range information based on prior induction variable analysis.
   InductionVarRange induction_range_;
diff --git a/compiler/optimizing/loop_optimization_test.cc b/compiler/optimizing/loop_optimization_test.cc
index c21bd65..c7cc661 100644
--- a/compiler/optimizing/loop_optimization_test.cc
+++ b/compiler/optimizing/loop_optimization_test.cc
@@ -29,7 +29,8 @@
   LoopOptimizationTest()
       : graph_(CreateGraph()),
         iva_(new (GetAllocator()) HInductionVarAnalysis(graph_)),
-        loop_opt_(new (GetAllocator()) HLoopOptimization(graph_, nullptr, iva_, nullptr)) {
+        loop_opt_(new (GetAllocator()) HLoopOptimization(
+            graph_, /* compiler_options */ nullptr, iva_, /* stats */ nullptr)) {
     BuildGraph();
   }
 
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index d37c43d..a38bd24 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -40,6 +40,7 @@
 #include "constructor_fence_redundancy_elimination.h"
 #include "dead_code_elimination.h"
 #include "dex/code_item_accessors-inl.h"
+#include "driver/compiler_options.h"
 #include "driver/dex_compilation_unit.h"
 #include "gvn.h"
 #include "induction_var_analysis.h"
@@ -224,7 +225,7 @@
       case OptimizationPass::kLoopOptimization:
         CHECK(most_recent_induction != nullptr);
         opt = new (allocator) HLoopOptimization(
-            graph, driver, most_recent_induction, stats, pass_name);
+            graph, &codegen->GetCompilerOptions(), most_recent_induction, stats, pass_name);
         break;
       case OptimizationPass::kBoundsCheckElimination:
         CHECK(most_recent_side_effects != nullptr && most_recent_induction != nullptr);
@@ -286,7 +287,7 @@
         break;
       case OptimizationPass::kScheduling:
         opt = new (allocator) HInstructionScheduling(
-            graph, driver->GetInstructionSet(), codegen, pass_name);
+            graph, codegen->GetCompilerOptions().GetInstructionSet(), codegen, pass_name);
         break;
       //
       // Arch-specific passes.
diff --git a/compiler/optimizing/optimizing_cfi_test.cc b/compiler/optimizing/optimizing_cfi_test.cc
index 2e189fd..1c1cf28 100644
--- a/compiler/optimizing/optimizing_cfi_test.cc
+++ b/compiler/optimizing/optimizing_cfi_test.cc
@@ -47,25 +47,20 @@
   static constexpr bool kGenerateExpected = false;
 
   OptimizingCFITest()
-      : pool_and_allocator_(),
-        opts_(),
-        isa_features_(),
-        graph_(nullptr),
+      : graph_(nullptr),
         code_gen_(),
         blocks_(GetAllocator()->Adapter()) {}
 
-  ArenaAllocator* GetAllocator() { return pool_and_allocator_.GetAllocator(); }
-
   void SetUpFrame(InstructionSet isa) {
+    OverrideInstructionSetFeatures(isa, "default");
+
     // Ensure that slow-debug is off, so that there is no unexpected read-barrier check emitted.
     SetRuntimeDebugFlagsEnabled(false);
 
     // Setup simple context.
-    std::string error;
-    isa_features_ = InstructionSetFeatures::FromVariant(isa, "default", &error);
     graph_ = CreateGraph();
     // Generate simple frame with some spills.
-    code_gen_ = CodeGenerator::Create(graph_, isa, *isa_features_, opts_);
+    code_gen_ = CodeGenerator::Create(graph_, *compiler_options_);
     code_gen_->GetAssembler()->cfi().SetEnabled(true);
     code_gen_->InitializeCodeGenerationData();
     const int frame_size = 64;
@@ -148,9 +143,6 @@
     DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
   };
 
-  ArenaPoolAndAllocator pool_and_allocator_;
-  CompilerOptions opts_;
-  std::unique_ptr<const InstructionSetFeatures> isa_features_;
   HGraph* graph_;
   std::unique_ptr<CodeGenerator> code_gen_;
   ArenaVector<HBasicBlock*> blocks_;
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 79ac6b9..84863e4 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -287,7 +287,7 @@
   uintptr_t GetEntryPointOf(ArtMethod* method) const OVERRIDE
       REQUIRES_SHARED(Locks::mutator_lock_) {
     return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCodePtrSize(
-        InstructionSetPointerSize(GetCompilerDriver()->GetInstructionSet())));
+        InstructionSetPointerSize(GetCompilerDriver()->GetCompilerOptions().GetInstructionSet())));
   }
 
   void Init() OVERRIDE;
@@ -460,7 +460,7 @@
                                               const DexCompilationUnit& dex_compilation_unit,
                                               PassObserver* pass_observer,
                                               VariableSizedHandleScope* handles) const {
-  switch (GetCompilerDriver()->GetInstructionSet()) {
+  switch (codegen->GetCompilerOptions().GetInstructionSet()) {
 #if defined(ART_ENABLE_CODEGEN_arm)
     case InstructionSet::kThumb2:
     case InstructionSet::kArm: {
@@ -758,7 +758,8 @@
                                               VariableSizedHandleScope* handles) const {
   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kAttemptBytecodeCompilation);
   CompilerDriver* compiler_driver = GetCompilerDriver();
-  InstructionSet instruction_set = compiler_driver->GetInstructionSet();
+  const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions();
+  InstructionSet instruction_set = compiler_options.GetInstructionSet();
   const DexFile& dex_file = *dex_compilation_unit.GetDexFile();
   uint32_t method_idx = dex_compilation_unit.GetDexMethodIndex();
   const DexFile::CodeItem* code_item = dex_compilation_unit.GetCodeItem();
@@ -782,7 +783,6 @@
   // Implementation of the space filter: do not compile a code item whose size in
   // code units is bigger than 128.
   static constexpr size_t kSpaceFilterOptimizingThreshold = 128;
-  const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions();
   if ((compiler_options.GetCompilerFilter() == CompilerFilter::kSpace)
       && (CodeItemInstructionAccessor(dex_file, code_item).InsnsSizeInCodeUnits() >
           kSpaceFilterOptimizingThreshold)) {
@@ -796,7 +796,7 @@
       arena_stack,
       dex_file,
       method_idx,
-      compiler_driver->GetInstructionSet(),
+      compiler_options.GetInstructionSet(),
       kInvalidInvokeType,
       compiler_driver->GetCompilerOptions().GetDebuggable(),
       osr);
@@ -813,9 +813,7 @@
 
   std::unique_ptr<CodeGenerator> codegen(
       CodeGenerator::Create(graph,
-                            instruction_set,
-                            *compiler_driver->GetInstructionSetFeatures(),
-                            compiler_driver->GetCompilerOptions(),
+                            compiler_options,
                             compilation_stats_.get()));
   if (codegen.get() == nullptr) {
     MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kNotCompiledNoCodegen);
@@ -903,7 +901,8 @@
     VariableSizedHandleScope* handles) const {
   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kAttemptIntrinsicCompilation);
   CompilerDriver* compiler_driver = GetCompilerDriver();
-  InstructionSet instruction_set = compiler_driver->GetInstructionSet();
+  const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions();
+  InstructionSet instruction_set = compiler_options.GetInstructionSet();
   const DexFile& dex_file = *dex_compilation_unit.GetDexFile();
   uint32_t method_idx = dex_compilation_unit.GetDexMethodIndex();
 
@@ -921,7 +920,7 @@
       arena_stack,
       dex_file,
       method_idx,
-      compiler_driver->GetInstructionSet(),
+      compiler_driver->GetCompilerOptions().GetInstructionSet(),
       kInvalidInvokeType,
       compiler_driver->GetCompilerOptions().GetDebuggable(),
       /* osr */ false);
@@ -932,15 +931,12 @@
 
   std::unique_ptr<CodeGenerator> codegen(
       CodeGenerator::Create(graph,
-                            instruction_set,
-                            *compiler_driver->GetInstructionSetFeatures(),
-                            compiler_driver->GetCompilerOptions(),
+                            compiler_options,
                             compilation_stats_.get()));
   if (codegen.get() == nullptr) {
     return nullptr;
   }
-  codegen->GetAssembler()->cfi().SetEnabled(
-      compiler_driver->GetCompilerOptions().GenerateAnyDebugInfo());
+  codegen->GetAssembler()->cfi().SetEnabled(compiler_options.GenerateAnyDebugInfo());
 
   PassObserver pass_observer(graph,
                              codegen.get(),
@@ -1095,7 +1091,7 @@
 
   if (kIsDebugBuild &&
       IsCompilingWithCoreImage() &&
-      IsInstructionSetSupported(compiler_driver->GetInstructionSet())) {
+      IsInstructionSetSupported(compiler_driver->GetCompilerOptions().GetInstructionSet())) {
     // For testing purposes, we put a special marker on method names
     // that should be compiled with this compiler (when the
     // instruction set is supported). This makes sure we're not
@@ -1112,7 +1108,8 @@
                                                uint32_t method_idx,
                                                const DexFile& dex_file,
                                                Handle<mirror::DexCache> dex_cache) const {
-  if (GetCompilerDriver()->GetCompilerOptions().IsBootImage()) {
+  const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions();
+  if (compiler_options.IsBootImage()) {
     ScopedObjectAccess soa(Thread::Current());
     Runtime* runtime = Runtime::Current();
     ArtMethod* method = runtime->GetClassLinker()->LookupResolvedMethod(
@@ -1154,7 +1151,7 @@
   }
 
   JniCompiledMethod jni_compiled_method = ArtQuickJniCompileMethod(
-      GetCompilerDriver(), access_flags, method_idx, dex_file);
+      compiler_options, access_flags, method_idx, dex_file);
   MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kCompiledNativeStub);
   return CompiledMethod::SwapAllocCompiledMethod(
       GetCompilerDriver(),
@@ -1218,8 +1215,9 @@
   ArenaAllocator allocator(runtime->GetJitArenaPool());
 
   if (UNLIKELY(method->IsNative())) {
+    const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions();
     JniCompiledMethod jni_compiled_method = ArtQuickJniCompileMethod(
-        GetCompilerDriver(), access_flags, method_idx, *dex_file);
+        compiler_options, access_flags, method_idx, *dex_file);
     ScopedNullHandle<mirror::ObjectArray<mirror::Object>> roots;
     ArenaSet<ArtMethod*, std::less<ArtMethod*>> cha_single_implementation_list(
         allocator.Adapter(kArenaAllocCHA));
@@ -1243,7 +1241,6 @@
       return false;
     }
 
-    const CompilerOptions& compiler_options = GetCompilerDriver()->GetCompilerOptions();
     if (compiler_options.GenerateAnyDebugInfo()) {
       const auto* method_header = reinterpret_cast<const OatQuickMethodHeader*>(code);
       const uintptr_t code_address = reinterpret_cast<uintptr_t>(method_header->GetCode());
@@ -1420,8 +1417,8 @@
 
   // Create entry for the single method that we just compiled.
   std::vector<uint8_t> elf_file = debug::MakeElfFileForJIT(
-      GetCompilerDriver()->GetInstructionSet(),
-      GetCompilerDriver()->GetInstructionSetFeatures(),
+      compiler_options.GetInstructionSet(),
+      compiler_options.GetInstructionSetFeatures(),
       mini_debug_info,
       ArrayRef<const debug::MethodDebugInfo>(&info, 1));
   MutexLock mu(Thread::Current(), *Locks::native_debug_interface_lock_);
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index a70b066..7144775 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -40,6 +40,12 @@
 
 class RegisterAllocatorTest : public OptimizingUnitTest {
  protected:
+  void SetUp() OVERRIDE {
+    // This test is using the x86 ISA.
+    OverrideInstructionSetFeatures(InstructionSet::kX86, "default");
+    OptimizingUnitTest::SetUp();
+  }
+
   // These functions need to access private variables of LocationSummary, so we declare it
   // as a member of RegisterAllocatorTest, which we make a friend class.
   void SameAsFirstInputHint(Strategy strategy);
@@ -81,9 +87,7 @@
 
 bool RegisterAllocatorTest::Check(const std::vector<uint16_t>& data, Strategy strategy) {
   HGraph* graph = CreateCFG(data);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
   SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
   liveness.Analyze();
   std::unique_ptr<RegisterAllocator> register_allocator =
@@ -98,9 +102,7 @@
  */
 TEST_F(RegisterAllocatorTest, ValidateIntervals) {
   HGraph* graph = CreateGraph();
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
   ScopedArenaVector<LiveInterval*> intervals(GetScopedAllocator()->Adapter());
 
   // Test with two intervals of the same range.
@@ -324,9 +326,7 @@
     Instruction::GOTO | 0xF900);
 
   HGraph* graph = CreateCFG(data);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
   SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
   liveness.Analyze();
   std::unique_ptr<RegisterAllocator> register_allocator =
@@ -359,9 +359,7 @@
     Instruction::RETURN_VOID);
 
   HGraph* graph = CreateCFG(data);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
   SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
   liveness.Analyze();
 
@@ -412,9 +410,7 @@
 
   HGraph* graph = CreateCFG(data);
   SsaDeadPhiElimination(graph).Run();
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
   SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
   liveness.Analyze();
   std::unique_ptr<RegisterAllocator> register_allocator =
@@ -438,9 +434,7 @@
 
   HGraph* graph = CreateCFG(data);
   SsaDeadPhiElimination(graph).Run();
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
   SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
   liveness.Analyze();
   RegisterAllocatorLinearScan register_allocator(GetScopedAllocator(), &codegen, liveness);
@@ -566,9 +560,7 @@
 
   {
     HGraph* graph = BuildIfElseWithPhi(&phi, &input1, &input2);
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
     SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
     liveness.Analyze();
 
@@ -584,9 +576,7 @@
 
   {
     HGraph* graph = BuildIfElseWithPhi(&phi, &input1, &input2);
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
     SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
     liveness.Analyze();
 
@@ -604,9 +594,7 @@
 
   {
     HGraph* graph = BuildIfElseWithPhi(&phi, &input1, &input2);
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
     SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
     liveness.Analyze();
 
@@ -624,9 +612,7 @@
 
   {
     HGraph* graph = BuildIfElseWithPhi(&phi, &input1, &input2);
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
     SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
     liveness.Analyze();
 
@@ -689,9 +675,7 @@
 
   {
     HGraph* graph = BuildFieldReturn(&field, &ret);
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
     SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
     liveness.Analyze();
 
@@ -705,9 +689,7 @@
 
   {
     HGraph* graph = BuildFieldReturn(&field, &ret);
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
     SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
     liveness.Analyze();
 
@@ -761,9 +743,7 @@
 
   {
     HGraph* graph = BuildTwoSubs(&first_sub, &second_sub);
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
     SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
     liveness.Analyze();
 
@@ -778,9 +758,7 @@
 
   {
     HGraph* graph = BuildTwoSubs(&first_sub, &second_sub);
-    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-        X86InstructionSetFeatures::FromCppDefines());
-    x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
     SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
     liveness.Analyze();
 
@@ -834,9 +812,7 @@
 void RegisterAllocatorTest::ExpectedExactInRegisterAndSameOutputHint(Strategy strategy) {
   HInstruction *div;
   HGraph* graph = BuildDiv(&div);
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
   SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
   liveness.Analyze();
 
@@ -934,9 +910,7 @@
       new (GetAllocator()) LocationSummary(fourth->GetDefinedBy(), LocationSummary::kNoCall);
   locations->SetOut(Location::RequiresRegister());
 
-  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
-      X86InstructionSetFeatures::FromCppDefines());
-  x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
+  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
   SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
   // Populate the instructions in the liveness object, to please the register allocator.
   for (size_t i = 0; i < 32; ++i) {
diff --git a/compiler/optimizing/scheduler_test.cc b/compiler/optimizing/scheduler_test.cc
index d4cae72..7079e07 100644
--- a/compiler/optimizing/scheduler_test.cc
+++ b/compiler/optimizing/scheduler_test.cc
@@ -192,7 +192,9 @@
       HInstructionScheduling scheduling(graph, target_config.GetInstructionSet());
       scheduling.Run(/*only_optimize_loop_blocks*/ false, /*schedule_randomly*/ true);
 
+      OverrideInstructionSetFeatures(target_config.GetInstructionSet(), "default");
       RunCode(target_config,
+              *compiler_options_,
               graph,
               [](HGraph* graph_arg) { RemoveSuspendChecks(graph_arg); },
               has_result, expected);
diff --git a/compiler/optimizing/ssa_liveness_analysis_test.cc b/compiler/optimizing/ssa_liveness_analysis_test.cc
index ae5e4e7..a683c69 100644
--- a/compiler/optimizing/ssa_liveness_analysis_test.cc
+++ b/compiler/optimizing/ssa_liveness_analysis_test.cc
@@ -28,18 +28,11 @@
 namespace art {
 
 class SsaLivenessAnalysisTest : public OptimizingUnitTest {
- public:
-  SsaLivenessAnalysisTest()
-      : graph_(CreateGraph()),
-        compiler_options_(),
-        instruction_set_(kRuntimeISA) {
-    std::string error_msg;
-    instruction_set_features_ =
-        InstructionSetFeatures::FromVariant(instruction_set_, "default", &error_msg);
-    codegen_ = CodeGenerator::Create(graph_,
-                                     instruction_set_,
-                                     *instruction_set_features_,
-                                     compiler_options_);
+ protected:
+  void SetUp() OVERRIDE {
+    OptimizingUnitTest::SetUp();
+    graph_ = CreateGraph();
+    codegen_ = CodeGenerator::Create(graph_, *compiler_options_);
     CHECK(codegen_ != nullptr) << instruction_set_ << " is not a supported target architecture.";
     // Create entry block.
     entry_ = new (GetAllocator()) HBasicBlock(graph_);
@@ -57,9 +50,6 @@
   }
 
   HGraph* graph_;
-  CompilerOptions compiler_options_;
-  InstructionSet instruction_set_;
-  std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
   std::unique_ptr<CodeGenerator> codegen_;
   HBasicBlock* entry_;
 };