CompilerConfig.cpp revision ae3184b98e2ff4a786979423e59b5c0ae6c16bd5
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/Support/CompilerConfig.h"
18#include "bcc/Config/Config.h"
19#include "bcc/Support/Properties.h"
20
21#include <llvm/CodeGen/SchedulerRegistry.h>
22#include <llvm/MC/SubtargetFeature.h>
23#include <llvm/Support/Host.h>
24#include <llvm/Support/TargetRegistry.h>
25
26#include "bcc/Support/Log.h"
27
28using namespace bcc;
29
30#if defined (PROVIDE_X86_CODEGEN) && !defined(__HOST__)
31
32namespace {
33
34// Utility function to test for f16c feature.  This function is only needed for
35// on-device bcc for x86
36bool HasF16C() {
37  llvm::StringMap<bool> features;
38  if (!llvm::sys::getHostCPUFeatures(features))
39    return false;
40
41  if (features.count("f16c") && features["f16c"])
42    return true;
43  else
44    return false;
45}
46
47}
48#endif // (PROVIDE_X86_CODEGEN) && !defined(__HOST__)
49
50CompilerConfig::CompilerConfig(const std::string &pTriple)
51  : mTriple(pTriple), mFullPrecision(true), mTarget(nullptr) {
52  //===--------------------------------------------------------------------===//
53  // Default setting of target options
54  //===--------------------------------------------------------------------===//
55
56  // Use soft-float ABI.  This only selects the ABI (and is applicable only to
57  // ARM targets).  Codegen still uses hardware FPU by default.  To use software
58  // floating point, add 'soft-float' feature to mFeatureString below.
59  mTargetOpts.FloatABIType = llvm::FloatABI::Soft;
60
61  //===--------------------------------------------------------------------===//
62  // Default setting for code model
63  //===--------------------------------------------------------------------===//
64  mCodeModel = llvm::CodeModel::Small;
65
66  //===--------------------------------------------------------------------===//
67  // Default setting for relocation model
68  //===--------------------------------------------------------------------===//
69  mRelocModel = llvm::Reloc::Default;
70
71  //===--------------------------------------------------------------------===//
72  // Default setting for optimization level (-O2)
73  //===--------------------------------------------------------------------===//
74  mOptLevel = llvm::CodeGenOpt::Default;
75
76  //===--------------------------------------------------------------------===//
77  // Default setting for architecture type
78  //===--------------------------------------------------------------------===//
79  mArchType = llvm::Triple::UnknownArch;
80
81  initializeTarget();
82  initializeArch();
83
84  return;
85}
86
87bool CompilerConfig::initializeTarget() {
88  std::string error;
89  mTarget = llvm::TargetRegistry::lookupTarget(mTriple, error);
90  if (mTarget != nullptr) {
91    return true;
92  } else {
93    ALOGE("Cannot initialize llvm::Target for given triple '%s'! (%s)",
94          mTriple.c_str(), error.c_str());
95    return false;
96  }
97}
98
99bool CompilerConfig::initializeArch() {
100  if (mTarget != nullptr) {
101    mArchType = llvm::Triple::getArchTypeForLLVMName(mTarget->getName());
102  } else {
103    mArchType = llvm::Triple::UnknownArch;
104    return false;
105  }
106
107  // Configure each architecture for any necessary additional flags.
108  std::vector<std::string> attributes;
109  switch (mArchType) {
110#if defined(PROVIDE_ARM_CODEGEN)
111  case llvm::Triple::arm: {
112    llvm::StringMap<bool> features;
113    llvm::sys::getHostCPUFeatures(features);
114
115#if defined(__HOST__) || defined(ARCH_ARM_HAVE_VFP)
116    attributes.push_back("+vfp3");
117#if !defined(__HOST__) && !defined(ARCH_ARM_HAVE_VFP_D32)
118    attributes.push_back("+d16");
119#endif  // !__HOST__ && !ARCH_ARM_HAVE_VFP_D32
120#endif  // __HOST__ || ARCH_ARM_HAVE_VFP
121
122#if defined(__HOST__) || defined(ARCH_ARM_HAVE_NEON)
123    // Only enable NEON on ARM if we have relaxed precision floats.
124    if (!mFullPrecision) {
125      attributes.push_back("+neon");
126    } else {
127#endif  // __HOST__ || ARCH_ARM_HAVE_NEON
128      attributes.push_back("-neon");
129      attributes.push_back("-neonfp");
130#if defined(__HOST__) || defined(ARCH_ARM_HAVE_NEON)
131    }
132#endif  // __HOST__ || ARCH_ARM_HAVE_NEON
133
134    if (!getProperty("debug.rs.arm-no-hwdiv")) {
135      if (features.count("hwdiv-arm") && features["hwdiv-arm"])
136        attributes.push_back("+hwdiv-arm");
137
138      if (features.count("hwdiv") && features["hwdiv"])
139        attributes.push_back("+hwdiv");
140    }
141
142    // Enable fp16 attribute if available in the feature list.  This feature
143    // will not be added in the host version of bcc or bcc_compat since
144    // 'features' would correspond to features in an x86 host.
145    if (features.count("fp16") && features["fp16"])
146      attributes.push_back("+fp16");
147
148#if defined(PROVIDE_ARM64_CODEGEN)
149    // On AArch64, asimd in /proc/cpuinfo signals the presence of hardware
150    // half-precision conversion instructions.  getHostCPUFeatures translates
151    // this to "neon".  If PROVIDE_ARM64_CODEGEN is set, enable "+fp16" for ARM
152    // codegen if "neon" is present in features.
153    if (features.count("neon") && features["neon"])
154      attributes.push_back("+fp16");
155#endif // PROVIDE_ARM64_CODEGEN
156
157#if defined(TARGET_BUILD)
158    if (!getProperty("debug.rs.arm-no-tune-for-cpu")) {
159#ifndef FORCE_CPU_VARIANT_32
160#ifdef DEFAULT_ARM_CODEGEN
161      setCPU(llvm::sys::getHostCPUName());
162#endif
163#else
164#define XSTR(S) #S
165#define STR(S) XSTR(S)
166      setCPU(STR(FORCE_CPU_VARIANT_32));
167#undef STR
168#undef XSTR
169#endif
170    }
171#endif  // TARGET_BUILD
172
173    break;
174  }
175#endif  // PROVIDE_ARM_CODEGEN
176
177#if defined(PROVIDE_ARM64_CODEGEN)
178  case llvm::Triple::aarch64:
179#if defined(TARGET_BUILD)
180    if (!getProperty("debug.rs.arm-no-tune-for-cpu")) {
181#ifndef FORCE_CPU_VARIANT_64
182#ifdef DEFAULT_ARM64_CODEGEN
183      setCPU(llvm::sys::getHostCPUName());
184#endif
185#else
186#define XSTR(S) #S
187#define STR(S) XSTR(S)
188      setCPU(STR(FORCE_CPU_VARIANT_64));
189#undef STR
190#undef XSTR
191#endif
192
193    }
194#endif  // TARGET_BUILD
195    break;
196#endif  // PROVIDE_ARM64_CODEGEN
197
198#if defined (PROVIDE_MIPS_CODEGEN)
199  case llvm::Triple::mips:
200  case llvm::Triple::mipsel:
201    if (getRelocationModel() == llvm::Reloc::Default) {
202      setRelocationModel(llvm::Reloc::Static);
203    }
204    break;
205#endif  // PROVIDE_MIPS_CODEGEN
206
207#if defined (PROVIDE_MIPS64_CODEGEN)
208  case llvm::Triple::mips64:
209  case llvm::Triple::mips64el:
210    // Default revision for MIPS64 Android is R6.
211    setCPU("mips64r6");
212    break;
213#endif // PROVIDE_MIPS64_CODEGEN
214
215#if defined (PROVIDE_X86_CODEGEN)
216  case llvm::Triple::x86:
217    getTargetOptions().UseInitArray = true;
218#if defined (DEFAULT_X86_CODEGEN) && !defined (DEFAULT_X86_64_CODEGEN)
219    setCPU(llvm::sys::getHostCPUName());
220#else
221    // generic fallback for 32bit x86 targets
222    setCPU("atom");
223#endif // DEFAULT_X86_CODEGEN && !DEFAULT_X86_64_CODEGEN
224
225#ifndef __HOST__
226    // If not running on the host, and f16c is available, set it in the feature
227    // string
228    if (HasF16C())
229      attributes.push_back("+f16c");
230#if defined(__SSE3__)
231    attributes.push_back("+sse3");
232    attributes.push_back("+ssse3");
233#endif
234#if defined(__SSE4_1__)
235    attributes.push_back("+sse4.1");
236#endif
237#if defined(__SSE4_2__)
238    attributes.push_back("+sse4.2");
239#endif
240#endif // __HOST__
241    break;
242#endif  // PROVIDE_X86_CODEGEN
243
244#if defined (PROVIDE_X86_CODEGEN)
245// PROVIDE_X86_CODEGEN is defined for both x86 and x86_64
246  case llvm::Triple::x86_64:
247#if defined(DEFAULT_X86_64_CODEGEN)
248    setCPU(llvm::sys::getHostCPUName());
249#else
250    // generic fallback for 64bit x86 targets
251    setCPU("core2");
252#endif
253    // x86_64 needs small CodeModel if use PIC_ reloc, or else dlopen failed with TEXTREL.
254    if (getRelocationModel() == llvm::Reloc::PIC_) {
255      setCodeModel(llvm::CodeModel::Small);
256    } else {
257      setCodeModel(llvm::CodeModel::Medium);
258    }
259    getTargetOptions().UseInitArray = true;
260
261#ifndef __HOST__
262    // If not running on the host, and f16c is available, set it in the feature
263    // string
264    if (HasF16C())
265      attributes.push_back("+f16c");
266#endif // __HOST__
267
268    break;
269#endif  // PROVIDE_X86_CODEGEN
270
271  default:
272    ALOGE("Unsupported architecture type: %s", mTarget->getName());
273    return false;
274  }
275
276  setFeatureString(attributes);
277  return true;
278}
279
280void CompilerConfig::setFeatureString(const std::vector<std::string> &pAttrs) {
281  llvm::SubtargetFeatures f;
282
283  for (std::vector<std::string>::const_iterator attr_iter = pAttrs.begin(),
284           attr_end = pAttrs.end();
285       attr_iter != attr_end; attr_iter++) {
286    f.AddFeature(*attr_iter);
287  }
288
289  mFeatureString = f.getString();
290  return;
291}
292