1 //===- subzero/src/IceTargetLowering.cpp - Basic lowering implementation --===//
3 // The Subzero Code Generator
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the skeleton of the TargetLowering class,
11 // specifically invoking the appropriate lowering method for a given
12 // instruction kind and driving global register allocation. It also
13 // implements the non-deleted instruction iteration in
16 //===----------------------------------------------------------------------===//
18 #include "assembler_arm32.h"
19 #include "assembler_ia32.h"
20 #include "IceCfg.h" // setError()
21 #include "IceCfgNode.h"
22 #include "IceOperand.h"
23 #include "IceRegAlloc.h"
24 #include "IceTargetLowering.h"
25 #include "IceTargetLoweringARM32.h"
26 #include "IceTargetLoweringX8632.h"
30 void LoweringContext::init(CfgNode *N) {
32 End = getNode()->getInsts().end();
37 void LoweringContext::rewind() {
38 Begin = getNode()->getInsts().begin();
44 void LoweringContext::insert(Inst *Inst) {
45 getNode()->getInsts().insert(Next, Inst);
49 void LoweringContext::skipDeleted(InstList::iterator &I) const {
50 while (I != End && I->isDeleted())
54 void LoweringContext::advanceForward(InstList::iterator &I) const {
61 Inst *LoweringContext::getLastInserted() const {
66 TargetLowering *TargetLowering::createLowering(TargetArch Target, Cfg *Func) {
67 #define SUBZERO_TARGET(X) \
68 if (Target == Target_##X) \
69 return Target##X::create(Func);
70 #include "llvm/Config/SZTargets.def"
72 Func->setError("Unsupported target");
76 TargetLowering::TargetLowering(Cfg *Func)
77 : Func(Func), Ctx(Func->getContext()), HasComputedFrame(false),
78 CallsReturnsTwice(false), StackAdjustment(0), NextLabelNumber(0),
79 Context(), SnapshotStackAdjustment(0) {}
81 std::unique_ptr<Assembler> TargetLowering::createAssembler(TargetArch Target,
83 #define SUBZERO_TARGET(X) \
84 if (Target == Target_##X) \
85 return std::unique_ptr<Assembler>(new X::Assembler##X());
86 #include "llvm/Config/SZTargets.def"
88 Func->setError("Unsupported target assembler");
92 void TargetLowering::doAddressOpt() {
93 if (llvm::isa<InstLoad>(*Context.getCur()))
95 else if (llvm::isa<InstStore>(*Context.getCur()))
98 Context.advanceNext();
101 void TargetLowering::doNopInsertion() {
102 Inst *I = Context.getCur();
103 bool ShouldSkip = llvm::isa<InstFakeUse>(I) || llvm::isa<InstFakeDef>(I) ||
104 llvm::isa<InstFakeKill>(I) || I->isRedundantAssign() ||
107 int Probability = Ctx->getFlags().getNopProbabilityAsPercentage();
108 for (int I = 0; I < Ctx->getFlags().getMaxNopsPerInstruction(); ++I) {
109 randomlyInsertNop(Probability / 100.0);
114 // Lowers a single instruction according to the information in
115 // Context, by checking the Context.Cur instruction kind and calling
116 // the appropriate lowering method. The lowering method should insert
117 // target instructions at the Cur.Next insertion point, and should not
118 // delete the Context.Cur instruction or advance Context.Cur.
120 // The lowering method may look ahead in the instruction stream as
121 // desired, and lower additional instructions in conjunction with the
122 // current one, for example fusing a compare and branch. If it does,
123 // it should advance Context.Cur to point to the next non-deleted
124 // instruction to process, and it should delete any additional
125 // instructions it consumes.
126 void TargetLowering::lower() {
127 assert(!Context.atEnd());
128 Inst *Inst = Context.getCur();
129 Inst->deleteIfDead();
130 if (!Inst->isDeleted()) {
131 // Mark the current instruction as deleted before lowering,
132 // otherwise the Dest variable will likely get marked as non-SSA.
133 // See Variable::setDefinition().
135 switch (Inst->getKind()) {
137 lowerAlloca(llvm::cast<InstAlloca>(Inst));
139 case Inst::Arithmetic:
140 lowerArithmetic(llvm::cast<InstArithmetic>(Inst));
143 lowerAssign(llvm::cast<InstAssign>(Inst));
146 lowerBr(llvm::cast<InstBr>(Inst));
149 lowerCall(llvm::cast<InstCall>(Inst));
152 lowerCast(llvm::cast<InstCast>(Inst));
154 case Inst::ExtractElement:
155 lowerExtractElement(llvm::cast<InstExtractElement>(Inst));
158 lowerFcmp(llvm::cast<InstFcmp>(Inst));
161 lowerIcmp(llvm::cast<InstIcmp>(Inst));
163 case Inst::InsertElement:
164 lowerInsertElement(llvm::cast<InstInsertElement>(Inst));
166 case Inst::IntrinsicCall: {
167 InstIntrinsicCall *Call = llvm::cast<InstIntrinsicCall>(Inst);
168 if (Call->getIntrinsicInfo().ReturnsTwice)
169 setCallsReturnsTwice(true);
170 lowerIntrinsicCall(Call);
174 lowerLoad(llvm::cast<InstLoad>(Inst));
177 lowerPhi(llvm::cast<InstPhi>(Inst));
180 lowerRet(llvm::cast<InstRet>(Inst));
183 lowerSelect(llvm::cast<InstSelect>(Inst));
186 lowerStore(llvm::cast<InstStore>(Inst));
189 lowerSwitch(llvm::cast<InstSwitch>(Inst));
191 case Inst::Unreachable:
192 lowerUnreachable(llvm::cast<InstUnreachable>(Inst));
194 case Inst::BundleLock:
195 case Inst::BundleUnlock:
200 // These are all Target instruction types and shouldn't be
201 // encountered at this stage.
202 Func->setError("Can't lower unsupported instruction type");
209 Context.advanceCur();
210 Context.advanceNext();
213 // Drives register allocation, allowing all physical registers (except
214 // perhaps for the frame pointer) to be allocated. This set of
215 // registers could potentially be parameterized if we want to restrict
216 // registers e.g. for performance testing.
217 void TargetLowering::regAlloc(RegAllocKind Kind) {
218 TimerMarker T(TimerStack::TT_regAlloc, Func);
219 LinearScan LinearScan(Func);
220 RegSetMask RegInclude = RegSet_None;
221 RegSetMask RegExclude = RegSet_None;
222 RegInclude |= RegSet_CallerSave;
223 RegInclude |= RegSet_CalleeSave;
224 if (hasFramePointer())
225 RegExclude |= RegSet_FramePointer;
226 LinearScan.init(Kind);
227 llvm::SmallBitVector RegMask = getRegisterSet(RegInclude, RegExclude);
228 LinearScan.scan(RegMask, Ctx->getFlags().shouldRandomizeRegAlloc());
231 InstCall *TargetLowering::makeHelperCall(const IceString &Name, Variable *Dest,
233 const bool HasTailCall = false;
234 Constant *CallTarget = Ctx->getConstantExternSym(Name);
236 InstCall::create(Func, MaxSrcs, Dest, CallTarget, HasTailCall);
240 void TargetLowering::emitWithoutPrefix(const ConstantRelocatable *C) const {
243 Ostream &Str = Ctx->getStrEmit();
244 if (C->getSuppressMangling())
247 Str << Ctx->mangleName(C->getName());
248 RelocOffsetT Offset = C->getOffset();
256 void TargetLowering::emit(const ConstantRelocatable *C) const {
259 Ostream &Str = Ctx->getStrEmit();
260 Str << getConstantPrefix();
261 emitWithoutPrefix(C);
264 std::unique_ptr<TargetDataLowering>
265 TargetDataLowering::createLowering(GlobalContext *Ctx) {
266 TargetArch Target = Ctx->getFlags().getTargetArch();
267 #define SUBZERO_TARGET(X) \
268 if (Target == Target_##X) \
269 return std::unique_ptr<TargetDataLowering>(TargetData##X::create(Ctx));
270 #include "llvm/Config/SZTargets.def"
272 llvm_unreachable("Unsupported target data lowering");
276 TargetDataLowering::~TargetDataLowering() {}
278 } // end of namespace Ice