blob: db332cbd0e8babeda952b8507e869202a14f9ed9 [file] [log] [blame]
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001//===- subzero/src/IceTargetLowering.cpp - Basic lowering implementation --===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
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
14// LoweringContext.
15//
16//===----------------------------------------------------------------------===//
17
Jan Voungb36ad9b2015-04-21 17:01:49 -070018#include "assembler_arm32.h"
Jan Voung8acded02014-09-22 18:02:25 -070019#include "assembler_ia32.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070020#include "IceCfg.h" // setError()
21#include "IceCfgNode.h"
22#include "IceOperand.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070023#include "IceRegAlloc.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070024#include "IceTargetLowering.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070025#include "IceTargetLoweringARM32.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070026#include "IceTargetLoweringX8632.h"
27
28namespace Ice {
29
30void LoweringContext::init(CfgNode *N) {
31 Node = N;
Jim Stichnoth336f6c42014-10-30 15:01:31 -070032 End = getNode()->getInsts().end();
33 rewind();
34 advanceForward(Next);
35}
36
37void LoweringContext::rewind() {
Jan Vounge6e497d2014-07-30 10:06:03 -070038 Begin = getNode()->getInsts().begin();
39 Cur = Begin;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070040 skipDeleted(Cur);
41 Next = Cur;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070042}
43
44void LoweringContext::insert(Inst *Inst) {
45 getNode()->getInsts().insert(Next, Inst);
Jim Stichnoth98712a32014-10-24 10:59:02 -070046 LastInserted = Inst;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070047}
48
Jan Voungc820ddf2014-07-29 14:38:51 -070049void LoweringContext::skipDeleted(InstList::iterator &I) const {
Jim Stichnoth607e9f02014-11-06 13:32:05 -080050 while (I != End && I->isDeleted())
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070051 ++I;
52}
53
Jan Vounge6e497d2014-07-30 10:06:03 -070054void LoweringContext::advanceForward(InstList::iterator &I) const {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070055 if (I != End) {
56 ++I;
57 skipDeleted(I);
58 }
59}
60
Jan Vounge6e497d2014-07-30 10:06:03 -070061Inst *LoweringContext::getLastInserted() const {
Jim Stichnoth98712a32014-10-24 10:59:02 -070062 assert(LastInserted);
63 return LastInserted;
Jan Vounge6e497d2014-07-30 10:06:03 -070064}
65
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070066TargetLowering *TargetLowering::createLowering(TargetArch Target, Cfg *Func) {
Jan Voungb36ad9b2015-04-21 17:01:49 -070067#define SUBZERO_TARGET(X) \
68 if (Target == Target_##X) \
69 return Target##X::create(Func);
70#include "llvm/Config/SZTargets.def"
71
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070072 Func->setError("Unsupported target");
Jim Stichnothae953202014-12-20 06:17:49 -080073 return nullptr;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070074}
75
Jim Stichnothe6d24782014-12-19 05:42:24 -080076TargetLowering::TargetLowering(Cfg *Func)
Jan Voung1f47ad02015-03-20 15:01:26 -070077 : Func(Func), Ctx(Func->getContext()), HasComputedFrame(false),
Jan Voungb36ad9b2015-04-21 17:01:49 -070078 CallsReturnsTwice(false), StackAdjustment(0), NextLabelNumber(0),
79 Context(), SnapshotStackAdjustment(0) {}
Jim Stichnothe6d24782014-12-19 05:42:24 -080080
Jan Voungec270732015-01-12 17:00:22 -080081std::unique_ptr<Assembler> TargetLowering::createAssembler(TargetArch Target,
82 Cfg *Func) {
Jan Voung90ccc3f2015-04-30 14:15:10 -070083#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"
Jan Voungb36ad9b2015-04-21 17:01:49 -070087
88 Func->setError("Unsupported target assembler");
Jim Stichnothae953202014-12-20 06:17:49 -080089 return nullptr;
Jan Voung8acded02014-09-22 18:02:25 -070090}
91
Jim Stichnothd97c7df2014-06-04 11:57:08 -070092void TargetLowering::doAddressOpt() {
93 if (llvm::isa<InstLoad>(*Context.getCur()))
94 doAddressOptLoad();
95 else if (llvm::isa<InstStore>(*Context.getCur()))
96 doAddressOptStore();
97 Context.advanceCur();
98 Context.advanceNext();
99}
100
Matt Walac3302742014-08-15 16:21:56 -0700101void TargetLowering::doNopInsertion() {
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800102 Inst *I = Context.getCur();
Matt Walac3302742014-08-15 16:21:56 -0700103 bool ShouldSkip = llvm::isa<InstFakeUse>(I) || llvm::isa<InstFakeDef>(I) ||
104 llvm::isa<InstFakeKill>(I) || I->isRedundantAssign() ||
105 I->isDeleted();
106 if (!ShouldSkip) {
Jan Voung1f47ad02015-03-20 15:01:26 -0700107 int Probability = Ctx->getFlags().getNopProbabilityAsPercentage();
108 for (int I = 0; I < Ctx->getFlags().getMaxNopsPerInstruction(); ++I) {
109 randomlyInsertNop(Probability / 100.0);
Matt Walac3302742014-08-15 16:21:56 -0700110 }
111 }
112}
113
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700114// 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.
119//
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.
126void TargetLowering::lower() {
127 assert(!Context.atEnd());
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800128 Inst *Inst = Context.getCur();
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700129 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().
134 Inst->setDeleted();
135 switch (Inst->getKind()) {
136 case Inst::Alloca:
137 lowerAlloca(llvm::cast<InstAlloca>(Inst));
138 break;
139 case Inst::Arithmetic:
140 lowerArithmetic(llvm::cast<InstArithmetic>(Inst));
141 break;
142 case Inst::Assign:
143 lowerAssign(llvm::cast<InstAssign>(Inst));
144 break;
145 case Inst::Br:
146 lowerBr(llvm::cast<InstBr>(Inst));
147 break;
148 case Inst::Call:
149 lowerCall(llvm::cast<InstCall>(Inst));
150 break;
151 case Inst::Cast:
152 lowerCast(llvm::cast<InstCast>(Inst));
153 break;
154 case Inst::ExtractElement:
155 lowerExtractElement(llvm::cast<InstExtractElement>(Inst));
156 break;
157 case Inst::Fcmp:
158 lowerFcmp(llvm::cast<InstFcmp>(Inst));
159 break;
160 case Inst::Icmp:
161 lowerIcmp(llvm::cast<InstIcmp>(Inst));
162 break;
163 case Inst::InsertElement:
164 lowerInsertElement(llvm::cast<InstInsertElement>(Inst));
165 break;
166 case Inst::IntrinsicCall: {
167 InstIntrinsicCall *Call = llvm::cast<InstIntrinsicCall>(Inst);
168 if (Call->getIntrinsicInfo().ReturnsTwice)
169 setCallsReturnsTwice(true);
170 lowerIntrinsicCall(Call);
171 break;
172 }
173 case Inst::Load:
174 lowerLoad(llvm::cast<InstLoad>(Inst));
175 break;
176 case Inst::Phi:
177 lowerPhi(llvm::cast<InstPhi>(Inst));
178 break;
179 case Inst::Ret:
180 lowerRet(llvm::cast<InstRet>(Inst));
181 break;
182 case Inst::Select:
183 lowerSelect(llvm::cast<InstSelect>(Inst));
184 break;
185 case Inst::Store:
186 lowerStore(llvm::cast<InstStore>(Inst));
187 break;
188 case Inst::Switch:
189 lowerSwitch(llvm::cast<InstSwitch>(Inst));
190 break;
191 case Inst::Unreachable:
192 lowerUnreachable(llvm::cast<InstUnreachable>(Inst));
193 break;
194 case Inst::BundleLock:
195 case Inst::BundleUnlock:
196 case Inst::FakeDef:
197 case Inst::FakeUse:
198 case Inst::FakeKill:
199 case Inst::Target:
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");
203 break;
204 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700205
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700206 postLower();
207 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700208
209 Context.advanceCur();
210 Context.advanceNext();
211}
212
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700213// 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.
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800217void TargetLowering::regAlloc(RegAllocKind Kind) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700218 TimerMarker T(TimerStack::TT_regAlloc, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700219 LinearScan LinearScan(Func);
220 RegSetMask RegInclude = RegSet_None;
221 RegSetMask RegExclude = RegSet_None;
222 RegInclude |= RegSet_CallerSave;
223 RegInclude |= RegSet_CalleeSave;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700224 if (hasFramePointer())
225 RegExclude |= RegSet_FramePointer;
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800226 LinearScan.init(Kind);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700227 llvm::SmallBitVector RegMask = getRegisterSet(RegInclude, RegExclude);
Jan Voung1f47ad02015-03-20 15:01:26 -0700228 LinearScan.scan(RegMask, Ctx->getFlags().shouldRandomizeRegAlloc());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700229}
230
Jan Voungb3401d22015-05-18 09:38:21 -0700231void TargetLowering::inferTwoAddress() {
232 // Find two-address non-SSA instructions where Dest==Src0, and set
233 // the DestNonKillable flag to keep liveness analysis consistent.
234 for (auto Inst = Context.getCur(), E = Context.getNext(); Inst != E; ++Inst) {
235 if (Inst->isDeleted())
236 continue;
237 if (Variable *Dest = Inst->getDest()) {
238 // TODO(stichnot): We may need to consider all source
239 // operands, not just the first one, if using 3-address
240 // instructions.
241 if (Inst->getSrcSize() > 0 && Inst->getSrc(0) == Dest)
242 Inst->setDestNonKillable();
243 }
244 }
245}
246
Jan Voungb36ad9b2015-04-21 17:01:49 -0700247InstCall *TargetLowering::makeHelperCall(const IceString &Name, Variable *Dest,
248 SizeT MaxSrcs) {
249 const bool HasTailCall = false;
250 Constant *CallTarget = Ctx->getConstantExternSym(Name);
251 InstCall *Call =
252 InstCall::create(Func, MaxSrcs, Dest, CallTarget, HasTailCall);
253 return Call;
254}
255
Jan Voung76bb0be2015-05-14 09:26:19 -0700256void TargetLowering::emitWithoutPrefix(const ConstantRelocatable *C) const {
257 if (!ALLOW_DUMP)
258 return;
259 Ostream &Str = Ctx->getStrEmit();
260 if (C->getSuppressMangling())
261 Str << C->getName();
262 else
263 Str << Ctx->mangleName(C->getName());
264 RelocOffsetT Offset = C->getOffset();
265 if (Offset) {
266 if (Offset > 0)
267 Str << "+";
268 Str << Offset;
269 }
270}
271
272void TargetLowering::emit(const ConstantRelocatable *C) const {
273 if (!ALLOW_DUMP)
274 return;
275 Ostream &Str = Ctx->getStrEmit();
276 Str << getConstantPrefix();
277 emitWithoutPrefix(C);
278}
279
Jim Stichnothbbca7542015-02-11 16:08:31 -0800280std::unique_ptr<TargetDataLowering>
281TargetDataLowering::createLowering(GlobalContext *Ctx) {
Jan Voung1f47ad02015-03-20 15:01:26 -0700282 TargetArch Target = Ctx->getFlags().getTargetArch();
Jan Voungb36ad9b2015-04-21 17:01:49 -0700283#define SUBZERO_TARGET(X) \
284 if (Target == Target_##X) \
285 return std::unique_ptr<TargetDataLowering>(TargetData##X::create(Ctx));
286#include "llvm/Config/SZTargets.def"
287
288 llvm_unreachable("Unsupported target data lowering");
Jim Stichnothae953202014-12-20 06:17:49 -0800289 return nullptr;
Jim Stichnothde4ca712014-06-29 08:13:48 -0700290}
291
Jan Voung72984d82015-01-29 14:42:38 -0800292TargetDataLowering::~TargetDataLowering() {}
Jan Voung839c4ce2014-07-28 15:19:43 -0700293
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700294} // end of namespace Ice