Home | History | Annotate | Download | only in lib
      1 /*
      2  * Copyright 2012, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "bcc/CompilerConfig.h"
     18 
     19 #include "Log.h"
     20 #include "Properties.h"
     21 
     22 #include "bcc/Config.h"
     23 
     24 #include <llvm/CodeGen/SchedulerRegistry.h>
     25 #include <llvm/MC/SubtargetFeature.h>
     26 #include <llvm/Support/Host.h>
     27 #include <llvm/Support/TargetRegistry.h>
     28 
     29 using namespace bcc;
     30 
     31 #if defined (PROVIDE_X86_CODEGEN) && !defined(__HOST__)
     32 
     33 namespace {
     34 
     35 // Utility function to add feature flags supported by the running CPU.
     36 // This function is only needed for on-device bcc for x86.
     37 void AddX86NativeCPUFeatures(std::vector<std::string>* attributes) {
     38   llvm::StringMap<bool> features;
     39   if (llvm::sys::getHostCPUFeatures(features)) {
     40     for (const auto& f : features)
     41       attributes->push_back((f.second ? '+' : '-') + f.first().str());
     42   }
     43 
     44   // LLVM generates AVX code that treats a long3 as 256 bits, while
     45   // RenderScript considers a long3 192 bits (http://b/28879581)
     46   attributes->push_back("-avx");
     47 }
     48 
     49 }
     50 #endif // (PROVIDE_X86_CODEGEN) && !defined(__HOST__)
     51 
     52 CompilerConfig::CompilerConfig(const std::string &pTriple)
     53   : mTriple(pTriple), mFullPrecision(true), mTarget(nullptr) {
     54   //===--------------------------------------------------------------------===//
     55   // Default setting of target options
     56   //===--------------------------------------------------------------------===//
     57 
     58   // Use soft-float ABI.  This only selects the ABI (and is applicable only to
     59   // ARM targets).  Codegen still uses hardware FPU by default.  To use software
     60   // floating point, add 'soft-float' feature to mFeatureString below.
     61   mTargetOpts.FloatABIType = llvm::FloatABI::Soft;
     62 
     63   //===--------------------------------------------------------------------===//
     64   // Default setting for code model
     65   //===--------------------------------------------------------------------===//
     66   mCodeModel = llvm::CodeModel::Small;
     67 
     68   //===--------------------------------------------------------------------===//
     69   // Default setting for optimization level (-O2)
     70   //===--------------------------------------------------------------------===//
     71   mOptLevel = llvm::CodeGenOpt::Default;
     72 
     73   //===--------------------------------------------------------------------===//
     74   // Default setting for architecture type
     75   //===--------------------------------------------------------------------===//
     76   mArchType = llvm::Triple::UnknownArch;
     77 
     78   initializeTarget();
     79   initializeArch();
     80 
     81   return;
     82 }
     83 
     84 bool CompilerConfig::initializeTarget() {
     85   std::string error;
     86   mTarget = llvm::TargetRegistry::lookupTarget(mTriple, error);
     87   if (mTarget != nullptr) {
     88     return true;
     89   } else {
     90     ALOGE("Cannot initialize llvm::Target for given triple '%s'! (%s)",
     91           mTriple.c_str(), error.c_str());
     92     return false;
     93   }
     94 }
     95 
     96 bool CompilerConfig::initializeArch() {
     97   if (mTarget != nullptr) {
     98     mArchType = llvm::Triple::getArchTypeForLLVMName(mTarget->getName());
     99   } else {
    100     mArchType = llvm::Triple::UnknownArch;
    101     return false;
    102   }
    103 
    104   // Configure each architecture for any necessary additional flags.
    105   std::vector<std::string> attributes;
    106   switch (mArchType) {
    107 #if defined(PROVIDE_ARM_CODEGEN)
    108   case llvm::Triple::arm: {
    109     llvm::StringMap<bool> features;
    110     llvm::sys::getHostCPUFeatures(features);
    111 
    112 #if defined(__HOST__) || defined(ARCH_ARM_HAVE_VFP)
    113     attributes.push_back("+vfp3");
    114 #if !defined(__HOST__) && !defined(ARCH_ARM_HAVE_VFP_D32)
    115     attributes.push_back("+d16");
    116 #endif  // !__HOST__ && !ARCH_ARM_HAVE_VFP_D32
    117 #endif  // __HOST__ || ARCH_ARM_HAVE_VFP
    118 
    119 #if defined(__HOST__) || defined(ARCH_ARM_HAVE_NEON)
    120     // Only enable NEON on ARM if we have relaxed precision floats.
    121     if (!mFullPrecision) {
    122       attributes.push_back("+neon");
    123     } else {
    124 #endif  // __HOST__ || ARCH_ARM_HAVE_NEON
    125       attributes.push_back("-neon");
    126       attributes.push_back("-neonfp");
    127 #if defined(__HOST__) || defined(ARCH_ARM_HAVE_NEON)
    128     }
    129 #endif  // __HOST__ || ARCH_ARM_HAVE_NEON
    130 
    131     if (!getProperty("debug.rs.arm-no-hwdiv")) {
    132       if (features.count("hwdiv-arm") && features["hwdiv-arm"])
    133         attributes.push_back("+hwdiv-arm");
    134 
    135       if (features.count("hwdiv") && features["hwdiv"])
    136         attributes.push_back("+hwdiv");
    137     }
    138 
    139     // Enable fp16 attribute if available in the feature list.  This feature
    140     // will not be added in the host version of bcc or bcc_compat since
    141     // 'features' would correspond to features in an x86 host.
    142     if (features.count("fp16") && features["fp16"])
    143       attributes.push_back("+fp16");
    144 
    145 #if defined(PROVIDE_ARM64_CODEGEN)
    146     // On AArch64, asimd in /proc/cpuinfo signals the presence of hardware
    147     // half-precision conversion instructions.  getHostCPUFeatures translates
    148     // this to "neon".  If PROVIDE_ARM64_CODEGEN is set, enable "+fp16" for ARM
    149     // codegen if "neon" is present in features.
    150     if (features.count("neon") && features["neon"])
    151       attributes.push_back("+fp16");
    152 #endif // PROVIDE_ARM64_CODEGEN
    153 
    154 #if defined(TARGET_BUILD)
    155     if (!getProperty("debug.rs.arm-no-tune-for-cpu")) {
    156 #ifdef DEFAULT_ARM_CODEGEN
    157       setCPU(llvm::sys::getHostCPUName());
    158 #endif
    159     }
    160 #endif  // TARGET_BUILD
    161 
    162     break;
    163   }
    164 #endif  // PROVIDE_ARM_CODEGEN
    165 
    166 #if defined(PROVIDE_ARM64_CODEGEN)
    167   case llvm::Triple::aarch64:
    168 #if defined(TARGET_BUILD)
    169     if (!getProperty("debug.rs.arm-no-tune-for-cpu")) {
    170 #ifdef DEFAULT_ARM64_CODEGEN
    171       setCPU(llvm::sys::getHostCPUName());
    172 #endif
    173     }
    174 #endif  // TARGET_BUILD
    175     break;
    176 #endif  // PROVIDE_ARM64_CODEGEN
    177 
    178 #if defined (PROVIDE_MIPS_CODEGEN)
    179   case llvm::Triple::mips:
    180   case llvm::Triple::mipsel:
    181     if (!mRelocModel.hasValue()) {
    182       mRelocModel = llvm::Reloc::Static;
    183     }
    184     break;
    185 #endif  // PROVIDE_MIPS_CODEGEN
    186 
    187 #if defined (PROVIDE_MIPS64_CODEGEN)
    188   case llvm::Triple::mips64:
    189   case llvm::Triple::mips64el:
    190     // Default revision for MIPS64 Android is R6.
    191     setCPU("mips64r6");
    192     break;
    193 #endif // PROVIDE_MIPS64_CODEGEN
    194 
    195 #if defined (PROVIDE_X86_CODEGEN)
    196   case llvm::Triple::x86:
    197     getTargetOptions().UseInitArray = true;
    198 #if defined (DEFAULT_X86_CODEGEN) && !defined (__HOST__)
    199     setCPU(llvm::sys::getHostCPUName());
    200     AddX86NativeCPUFeatures(&attributes);
    201 #else
    202     // generic fallback for 32bit x86 targets
    203     setCPU("atom");
    204 #endif // DEFAULT_X86_CODEGEN && !__HOST__
    205     break;
    206 #endif  // PROVIDE_X86_CODEGEN
    207 
    208 #if defined (PROVIDE_X86_CODEGEN)
    209 // PROVIDE_X86_CODEGEN is defined for both x86 and x86_64
    210   case llvm::Triple::x86_64:
    211 #if defined(DEFAULT_X86_64_CODEGEN) && !defined(__HOST__)
    212     setCPU(llvm::sys::getHostCPUName());
    213     AddX86NativeCPUFeatures(&attributes);
    214 #else
    215     // generic fallback for 64bit x86 targets
    216     setCPU("core2");
    217 #endif
    218     // x86_64 needs small CodeModel if use PIC_ reloc, or else dlopen failed with TEXTREL.
    219     if (mRelocModel.hasValue() && mRelocModel.getValue() == llvm::Reloc::PIC_) {
    220       setCodeModel(llvm::CodeModel::Small);
    221     } else {
    222       setCodeModel(llvm::CodeModel::Medium);
    223     }
    224     getTargetOptions().UseInitArray = true;
    225     break;
    226 #endif  // PROVIDE_X86_CODEGEN
    227 
    228   default:
    229     ALOGE("Unsupported architecture type: %s", mTarget->getName());
    230     return false;
    231   }
    232 
    233   setFeatureString(attributes);
    234   return true;
    235 }
    236 
    237 void CompilerConfig::setFeatureString(const std::vector<std::string> &pAttrs) {
    238   llvm::SubtargetFeatures f;
    239 
    240   for (std::vector<std::string>::const_iterator attr_iter = pAttrs.begin(),
    241            attr_end = pAttrs.end();
    242        attr_iter != attr_end; attr_iter++) {
    243     f.AddFeature(*attr_iter);
    244   }
    245 
    246   mFeatureString = f.getString();
    247   return;
    248 }
    249