1//===-- HexagonTargetMachine.cpp - Define TargetMachine for Hexagon -------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Implements the info about Hexagon target spec.
11//
12//===----------------------------------------------------------------------===//
13
14#include "HexagonTargetMachine.h"
15#include "Hexagon.h"
16#include "HexagonISelLowering.h"
17#include "HexagonMachineScheduler.h"
18#include "HexagonTargetObjectFile.h"
19#include "HexagonTargetTransformInfo.h"
20#include "llvm/CodeGen/Passes.h"
21#include "llvm/IR/LegacyPassManager.h"
22#include "llvm/IR/Module.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/TargetRegistry.h"
25#include "llvm/Transforms/Scalar.h"
26
27using namespace llvm;
28
29
30static cl::opt<bool> EnableRDFOpt("rdf-opt", cl::Hidden, cl::ZeroOrMore,
31  cl::init(true), cl::desc("Enable RDF-based optimizations"));
32
33static cl::opt<bool> DisableHardwareLoops("disable-hexagon-hwloops",
34  cl::Hidden, cl::desc("Disable Hardware Loops for Hexagon target"));
35
36static cl::opt<bool> DisableHexagonCFGOpt("disable-hexagon-cfgopt",
37  cl::Hidden, cl::ZeroOrMore, cl::init(false),
38  cl::desc("Disable Hexagon CFG Optimization"));
39
40static cl::opt<bool> DisableStoreWidening("disable-store-widen",
41  cl::Hidden, cl::init(false), cl::desc("Disable store widening"));
42
43static cl::opt<bool> EnableExpandCondsets("hexagon-expand-condsets",
44  cl::init(true), cl::Hidden, cl::ZeroOrMore,
45  cl::desc("Early expansion of MUX"));
46
47static cl::opt<bool> EnableEarlyIf("hexagon-eif", cl::init(true), cl::Hidden,
48  cl::ZeroOrMore, cl::desc("Enable early if-conversion"));
49
50static cl::opt<bool> EnableGenInsert("hexagon-insert", cl::init(true),
51  cl::Hidden, cl::desc("Generate \"insert\" instructions"));
52
53static cl::opt<bool> EnableCommGEP("hexagon-commgep", cl::init(true),
54  cl::Hidden, cl::ZeroOrMore, cl::desc("Enable commoning of GEP instructions"));
55
56static cl::opt<bool> EnableGenExtract("hexagon-extract", cl::init(true),
57  cl::Hidden, cl::desc("Generate \"extract\" instructions"));
58
59static cl::opt<bool> EnableGenMux("hexagon-mux", cl::init(true), cl::Hidden,
60  cl::desc("Enable converting conditional transfers into MUX instructions"));
61
62static cl::opt<bool> EnableGenPred("hexagon-gen-pred", cl::init(true),
63  cl::Hidden, cl::desc("Enable conversion of arithmetic operations to "
64  "predicate instructions"));
65
66static cl::opt<bool> DisableHSDR("disable-hsdr", cl::init(false), cl::Hidden,
67  cl::desc("Disable splitting double registers"));
68
69static cl::opt<bool> EnableBitSimplify("hexagon-bit", cl::init(true),
70  cl::Hidden, cl::desc("Bit simplification"));
71
72static cl::opt<bool> EnableLoopResched("hexagon-loop-resched", cl::init(true),
73  cl::Hidden, cl::desc("Loop rescheduling"));
74
75/// HexagonTargetMachineModule - Note that this is used on hosts that
76/// cannot link in a library unless there are references into the
77/// library.  In particular, it seems that it is not possible to get
78/// things to work on Win32 without this.  Though it is unused, do not
79/// remove it.
80extern "C" int HexagonTargetMachineModule;
81int HexagonTargetMachineModule = 0;
82
83extern "C" void LLVMInitializeHexagonTarget() {
84  // Register the target.
85  RegisterTargetMachine<HexagonTargetMachine> X(TheHexagonTarget);
86}
87
88static ScheduleDAGInstrs *createVLIWMachineSched(MachineSchedContext *C) {
89  return new VLIWMachineScheduler(C, make_unique<ConvergingVLIWScheduler>());
90}
91
92static MachineSchedRegistry
93SchedCustomRegistry("hexagon", "Run Hexagon's custom scheduler",
94                    createVLIWMachineSched);
95
96namespace llvm {
97  FunctionPass *createHexagonBitSimplify();
98  FunctionPass *createHexagonCallFrameInformation();
99  FunctionPass *createHexagonCFGOptimizer();
100  FunctionPass *createHexagonCommonGEP();
101  FunctionPass *createHexagonCopyToCombine();
102  FunctionPass *createHexagonEarlyIfConversion();
103  FunctionPass *createHexagonExpandCondsets();
104  FunctionPass *createHexagonExpandPredSpillCode();
105  FunctionPass *createHexagonFixupHwLoops();
106  FunctionPass *createHexagonGenExtract();
107  FunctionPass *createHexagonGenInsert();
108  FunctionPass *createHexagonGenMux();
109  FunctionPass *createHexagonGenPredicate();
110  FunctionPass *createHexagonHardwareLoops();
111  FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM,
112                                     CodeGenOpt::Level OptLevel);
113  FunctionPass *createHexagonLoopRescheduling();
114  FunctionPass *createHexagonNewValueJump();
115  FunctionPass *createHexagonOptimizeSZextends();
116  FunctionPass *createHexagonPacketizer();
117  FunctionPass *createHexagonPeephole();
118  FunctionPass *createHexagonRDFOpt();
119  FunctionPass *createHexagonSplitConst32AndConst64();
120  FunctionPass *createHexagonSplitDoubleRegs();
121  FunctionPass *createHexagonStoreWidening();
122} // end namespace llvm;
123
124/// HexagonTargetMachine ctor - Create an ILP32 architecture model.
125///
126
127/// Hexagon_TODO: Do I need an aggregate alignment?
128///
129HexagonTargetMachine::HexagonTargetMachine(const Target &T, const Triple &TT,
130                                           StringRef CPU, StringRef FS,
131                                           const TargetOptions &Options,
132                                           Reloc::Model RM, CodeModel::Model CM,
133                                           CodeGenOpt::Level OL)
134    : LLVMTargetMachine(T, "e-m:e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-"
135                        "i1:8:8-f64:64:64-f32:32:32-v64:64:64-v32:32:32-a:0-"
136                        "n16:32", TT, CPU, FS, Options, RM, CM, OL),
137      TLOF(make_unique<HexagonTargetObjectFile>()) {
138  initAsmInfo();
139}
140
141const HexagonSubtarget *
142HexagonTargetMachine::getSubtargetImpl(const Function &F) const {
143  AttributeSet FnAttrs = F.getAttributes();
144  Attribute CPUAttr =
145      FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu");
146  Attribute FSAttr =
147      FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features");
148
149  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
150                        ? CPUAttr.getValueAsString().str()
151                        : TargetCPU;
152  std::string FS = !FSAttr.hasAttribute(Attribute::None)
153                       ? FSAttr.getValueAsString().str()
154                       : TargetFS;
155
156  auto &I = SubtargetMap[CPU + FS];
157  if (!I) {
158    // This needs to be done before we create a new subtarget since any
159    // creation will depend on the TM and the code generation flags on the
160    // function that reside in TargetOptions.
161    resetTargetOptions(F);
162    I = llvm::make_unique<HexagonSubtarget>(TargetTriple, CPU, FS, *this);
163  }
164  return I.get();
165}
166
167TargetIRAnalysis HexagonTargetMachine::getTargetIRAnalysis() {
168  return TargetIRAnalysis([this](const Function &F) {
169    return TargetTransformInfo(HexagonTTIImpl(this, F));
170  });
171}
172
173
174HexagonTargetMachine::~HexagonTargetMachine() {}
175
176namespace {
177/// Hexagon Code Generator Pass Configuration Options.
178class HexagonPassConfig : public TargetPassConfig {
179public:
180  HexagonPassConfig(HexagonTargetMachine *TM, PassManagerBase &PM)
181    : TargetPassConfig(TM, PM) {
182    bool NoOpt = (TM->getOptLevel() == CodeGenOpt::None);
183    if (!NoOpt) {
184      if (EnableExpandCondsets) {
185        Pass *Exp = createHexagonExpandCondsets();
186        insertPass(&RegisterCoalescerID, IdentifyingPassPtr(Exp));
187      }
188    }
189  }
190
191  HexagonTargetMachine &getHexagonTargetMachine() const {
192    return getTM<HexagonTargetMachine>();
193  }
194
195  ScheduleDAGInstrs *
196  createMachineScheduler(MachineSchedContext *C) const override {
197    return createVLIWMachineSched(C);
198  }
199
200  void addIRPasses() override;
201  bool addInstSelector() override;
202  void addPreRegAlloc() override;
203  void addPostRegAlloc() override;
204  void addPreSched2() override;
205  void addPreEmitPass() override;
206};
207} // namespace
208
209TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) {
210  return new HexagonPassConfig(this, PM);
211}
212
213void HexagonPassConfig::addIRPasses() {
214  TargetPassConfig::addIRPasses();
215  bool NoOpt = (getOptLevel() == CodeGenOpt::None);
216
217  addPass(createAtomicExpandPass(TM));
218  if (!NoOpt) {
219    if (EnableCommGEP)
220      addPass(createHexagonCommonGEP());
221    // Replace certain combinations of shifts and ands with extracts.
222    if (EnableGenExtract)
223      addPass(createHexagonGenExtract());
224  }
225}
226
227bool HexagonPassConfig::addInstSelector() {
228  HexagonTargetMachine &TM = getHexagonTargetMachine();
229  bool NoOpt = (getOptLevel() == CodeGenOpt::None);
230
231  if (!NoOpt)
232    addPass(createHexagonOptimizeSZextends());
233
234  addPass(createHexagonISelDag(TM, getOptLevel()));
235
236  if (!NoOpt) {
237    // Create logical operations on predicate registers.
238    if (EnableGenPred)
239      addPass(createHexagonGenPredicate(), false);
240    // Rotate loops to expose bit-simplification opportunities.
241    if (EnableLoopResched)
242      addPass(createHexagonLoopRescheduling(), false);
243    // Split double registers.
244    if (!DisableHSDR)
245      addPass(createHexagonSplitDoubleRegs());
246    // Bit simplification.
247    if (EnableBitSimplify)
248      addPass(createHexagonBitSimplify(), false);
249    addPass(createHexagonPeephole());
250    printAndVerify("After hexagon peephole pass");
251    if (EnableGenInsert)
252      addPass(createHexagonGenInsert(), false);
253    if (EnableEarlyIf)
254      addPass(createHexagonEarlyIfConversion(), false);
255  }
256
257  return false;
258}
259
260void HexagonPassConfig::addPreRegAlloc() {
261  if (getOptLevel() != CodeGenOpt::None) {
262    if (!DisableStoreWidening)
263      addPass(createHexagonStoreWidening(), false);
264    if (!DisableHardwareLoops)
265      addPass(createHexagonHardwareLoops(), false);
266  }
267}
268
269void HexagonPassConfig::addPostRegAlloc() {
270  if (getOptLevel() != CodeGenOpt::None) {
271    if (EnableRDFOpt)
272      addPass(createHexagonRDFOpt());
273    if (!DisableHexagonCFGOpt)
274      addPass(createHexagonCFGOptimizer(), false);
275  }
276}
277
278void HexagonPassConfig::addPreSched2() {
279  addPass(createHexagonCopyToCombine(), false);
280  if (getOptLevel() != CodeGenOpt::None)
281    addPass(&IfConverterID, false);
282  addPass(createHexagonSplitConst32AndConst64());
283}
284
285void HexagonPassConfig::addPreEmitPass() {
286  bool NoOpt = (getOptLevel() == CodeGenOpt::None);
287
288  if (!NoOpt)
289    addPass(createHexagonNewValueJump(), false);
290
291  // Expand Spill code for predicate registers.
292  addPass(createHexagonExpandPredSpillCode(), false);
293
294  // Create Packets.
295  if (!NoOpt) {
296    if (!DisableHardwareLoops)
297      addPass(createHexagonFixupHwLoops(), false);
298    // Generate MUX from pairs of conditional transfers.
299    if (EnableGenMux)
300      addPass(createHexagonGenMux(), false);
301
302    addPass(createHexagonPacketizer(), false);
303  }
304
305  // Add CFI instructions if necessary.
306  addPass(createHexagonCallFrameInformation(), false);
307}
308