blob: f1b8c25097a151564c54f72d6190b7846d311cde [file] [log] [blame]
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001//===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===//
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 TargetLoweringX8632 class, which
11// consists almost entirely of the lowering sequence for each
12// high-level instruction. It also implements
13// TargetX8632Fast::postLower() which does the simplest possible
14// register allocation for the "fast" target.
15//
16//===----------------------------------------------------------------------===//
17
18#include "IceDefs.h"
19#include "IceCfg.h"
20#include "IceCfgNode.h"
21#include "IceInstX8632.h"
22#include "IceOperand.h"
23#include "IceTargetLoweringX8632.def"
24#include "IceTargetLoweringX8632.h"
25
26namespace Ice {
27
28namespace {
29
30// The following table summarizes the logic for lowering the fcmp instruction.
31// There is one table entry for each of the 16 conditions. A comment in
32// lowerFcmp() describes the lowering template. In the most general case, there
33// is a compare followed by two conditional branches, because some fcmp
34// conditions don't map to a single x86 conditional branch. However, in many
35// cases it is possible to swap the operands in the comparison and have a single
36// conditional branch. Since it's quite tedious to validate the table by hand,
37// good execution tests are helpful.
38
39const struct TableFcmp_ {
40 uint32_t Default;
41 bool SwapOperands;
42 InstX8632Br::BrCond C1, C2;
43} TableFcmp[] = {
44#define X(val, dflt, swap, C1, C2) \
45 { dflt, swap, InstX8632Br::C1, InstX8632Br::C2 } \
46 ,
47 FCMPX8632_TABLE
48#undef X
49 };
50const size_t TableFcmpSize = llvm::array_lengthof(TableFcmp);
51
52// The following table summarizes the logic for lowering the icmp instruction
53// for i32 and narrower types. Each icmp condition has a clear mapping to an
54// x86 conditional branch instruction.
55
56const struct TableIcmp32_ {
57 InstX8632Br::BrCond Mapping;
58} TableIcmp32[] = {
59#define X(val, C_32, C1_64, C2_64, C3_64) \
60 { InstX8632Br::C_32 } \
61 ,
62 ICMPX8632_TABLE
63#undef X
64 };
65const size_t TableIcmp32Size = llvm::array_lengthof(TableIcmp32);
66
67// The following table summarizes the logic for lowering the icmp instruction
68// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
69// conditional branches are needed. For the other conditions, three separate
70// conditional branches are needed.
71const struct TableIcmp64_ {
72 InstX8632Br::BrCond C1, C2, C3;
73} TableIcmp64[] = {
74#define X(val, C_32, C1_64, C2_64, C3_64) \
75 { InstX8632Br::C1_64, InstX8632Br::C2_64, InstX8632Br::C3_64 } \
76 ,
77 ICMPX8632_TABLE
78#undef X
79 };
80const size_t TableIcmp64Size = llvm::array_lengthof(TableIcmp64);
81
82InstX8632Br::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
83 size_t Index = static_cast<size_t>(Cond);
84 assert(Index < TableIcmp32Size);
85 return TableIcmp32[Index].Mapping;
86}
87
Matt Wala45a06232014-07-09 16:33:22 -070088// The maximum number of arguments to pass in XMM registers
89const unsigned X86_MAX_XMM_ARGS = 4;
90
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070091// In some cases, there are x-macros tables for both high-level and
92// low-level instructions/operands that use the same enum key value.
93// The tables are kept separate to maintain a proper separation
94// between abstraction layers. There is a risk that the tables
95// could get out of sync if enum values are reordered or if entries
96// are added or deleted. This dummy function uses static_assert to
97// ensure everything is kept in sync.
98void xMacroIntegrityCheck() {
99 // Validate the enum values in FCMPX8632_TABLE.
100 {
101 // Define a temporary set of enum values based on low-level
102 // table entries.
103 enum _tmp_enum {
104#define X(val, dflt, swap, C1, C2) _tmp_##val,
105 FCMPX8632_TABLE
106#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700107 _num
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700108 };
109// Define a set of constants based on high-level table entries.
110#define X(tag, str) static const int _table1_##tag = InstFcmp::tag;
111 ICEINSTFCMP_TABLE;
112#undef X
113// Define a set of constants based on low-level table entries,
114// and ensure the table entry keys are consistent.
115#define X(val, dflt, swap, C1, C2) \
116 static const int _table2_##val = _tmp_##val; \
117 STATIC_ASSERT(_table1_##val == _table2_##val);
118 FCMPX8632_TABLE;
119#undef X
120// Repeat the static asserts with respect to the high-level
121// table entries in case the high-level table has extra entries.
122#define X(tag, str) STATIC_ASSERT(_table1_##tag == _table2_##tag);
123 ICEINSTFCMP_TABLE;
124#undef X
125 }
126
127 // Validate the enum values in ICMPX8632_TABLE.
128 {
129 // Define a temporary set of enum values based on low-level
130 // table entries.
131 enum _tmp_enum {
132#define X(val, C_32, C1_64, C2_64, C3_64) _tmp_##val,
133 ICMPX8632_TABLE
134#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700135 _num
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700136 };
137// Define a set of constants based on high-level table entries.
138#define X(tag, str) static const int _table1_##tag = InstIcmp::tag;
139 ICEINSTICMP_TABLE;
140#undef X
141// Define a set of constants based on low-level table entries,
142// and ensure the table entry keys are consistent.
143#define X(val, C_32, C1_64, C2_64, C3_64) \
144 static const int _table2_##val = _tmp_##val; \
145 STATIC_ASSERT(_table1_##val == _table2_##val);
146 ICMPX8632_TABLE;
147#undef X
148// Repeat the static asserts with respect to the high-level
149// table entries in case the high-level table has extra entries.
150#define X(tag, str) STATIC_ASSERT(_table1_##tag == _table2_##tag);
151 ICEINSTICMP_TABLE;
152#undef X
153 }
154
155 // Validate the enum values in ICETYPEX8632_TABLE.
156 {
157 // Define a temporary set of enum values based on low-level
158 // table entries.
159 enum _tmp_enum {
160#define X(tag, cvt, sdss, width) _tmp_##tag,
161 ICETYPEX8632_TABLE
162#undef X
Jim Stichnoth4376d292014-05-23 13:39:02 -0700163 _num
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700164 };
165// Define a set of constants based on high-level table entries.
Matt Wala928f1292014-07-07 16:50:46 -0700166#define X(tag, size, align, elts, elty, str) \
167 static const int _table1_##tag = tag;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700168 ICETYPE_TABLE;
169#undef X
170// Define a set of constants based on low-level table entries,
171// and ensure the table entry keys are consistent.
172#define X(tag, cvt, sdss, width) \
173 static const int _table2_##tag = _tmp_##tag; \
174 STATIC_ASSERT(_table1_##tag == _table2_##tag);
175 ICETYPEX8632_TABLE;
176#undef X
177// Repeat the static asserts with respect to the high-level
178// table entries in case the high-level table has extra entries.
Matt Wala928f1292014-07-07 16:50:46 -0700179#define X(tag, size, align, elts, elty, str) \
180 STATIC_ASSERT(_table1_##tag == _table2_##tag);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700181 ICETYPE_TABLE;
182#undef X
183 }
184}
185
186} // end of anonymous namespace
187
188TargetX8632::TargetX8632(Cfg *Func)
189 : TargetLowering(Func), IsEbpBasedFrame(false), FrameSizeLocals(0),
190 LocalsSizeBytes(0), NextLabelNumber(0), ComputedLiveRanges(false),
191 PhysicalRegisters(VarList(Reg_NUM)) {
192 // TODO: Don't initialize IntegerRegisters and friends every time.
193 // Instead, initialize in some sort of static initializer for the
194 // class.
195 llvm::SmallBitVector IntegerRegisters(Reg_NUM);
196 llvm::SmallBitVector IntegerRegistersI8(Reg_NUM);
197 llvm::SmallBitVector FloatRegisters(Reg_NUM);
Matt Wala928f1292014-07-07 16:50:46 -0700198 llvm::SmallBitVector VectorRegisters(Reg_NUM);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700199 llvm::SmallBitVector InvalidRegisters(Reg_NUM);
200 ScratchRegs.resize(Reg_NUM);
201#define X(val, init, name, name16, name8, scratch, preserved, stackptr, \
202 frameptr, isI8, isInt, isFP) \
203 IntegerRegisters[val] = isInt; \
204 IntegerRegistersI8[val] = isI8; \
205 FloatRegisters[val] = isFP; \
Matt Wala928f1292014-07-07 16:50:46 -0700206 VectorRegisters[val] = isFP; \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700207 ScratchRegs[val] = scratch;
208 REGX8632_TABLE;
209#undef X
210 TypeToRegisterSet[IceType_void] = InvalidRegisters;
211 TypeToRegisterSet[IceType_i1] = IntegerRegistersI8;
212 TypeToRegisterSet[IceType_i8] = IntegerRegistersI8;
213 TypeToRegisterSet[IceType_i16] = IntegerRegisters;
214 TypeToRegisterSet[IceType_i32] = IntegerRegisters;
215 TypeToRegisterSet[IceType_i64] = IntegerRegisters;
216 TypeToRegisterSet[IceType_f32] = FloatRegisters;
217 TypeToRegisterSet[IceType_f64] = FloatRegisters;
Matt Wala928f1292014-07-07 16:50:46 -0700218 TypeToRegisterSet[IceType_v4i1] = VectorRegisters;
219 TypeToRegisterSet[IceType_v8i1] = VectorRegisters;
220 TypeToRegisterSet[IceType_v16i1] = VectorRegisters;
221 TypeToRegisterSet[IceType_v16i8] = VectorRegisters;
222 TypeToRegisterSet[IceType_v8i16] = VectorRegisters;
223 TypeToRegisterSet[IceType_v4i32] = VectorRegisters;
224 TypeToRegisterSet[IceType_v4f32] = VectorRegisters;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700225}
226
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700227void TargetX8632::translateO2() {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700228 GlobalContext *Context = Func->getContext();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700229
230 // Lower Phi instructions.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700231 Timer T_placePhiLoads;
232 Func->placePhiLoads();
233 if (Func->hasError())
234 return;
235 T_placePhiLoads.printElapsedUs(Context, "placePhiLoads()");
236 Timer T_placePhiStores;
237 Func->placePhiStores();
238 if (Func->hasError())
239 return;
240 T_placePhiStores.printElapsedUs(Context, "placePhiStores()");
241 Timer T_deletePhis;
242 Func->deletePhis();
243 if (Func->hasError())
244 return;
245 T_deletePhis.printElapsedUs(Context, "deletePhis()");
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700246 Func->dump("After Phi lowering");
247
248 // Address mode optimization.
249 Timer T_doAddressOpt;
250 Func->doAddressOpt();
251 T_doAddressOpt.printElapsedUs(Context, "doAddressOpt()");
252
Matt Wala45a06232014-07-09 16:33:22 -0700253 // Argument lowering
254 Timer T_argLowering;
255 Func->doArgLowering();
256 T_argLowering.printElapsedUs(Context, "lowerArguments()");
257
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700258 // Target lowering. This requires liveness analysis for some parts
259 // of the lowering decisions, such as compare/branch fusing. If
260 // non-lightweight liveness analysis is used, the instructions need
261 // to be renumbered first. TODO: This renumbering should only be
262 // necessary if we're actually calculating live intervals, which we
263 // only do for register allocation.
264 Timer T_renumber1;
265 Func->renumberInstructions();
266 if (Func->hasError())
267 return;
268 T_renumber1.printElapsedUs(Context, "renumberInstructions()");
Matt Wala45a06232014-07-09 16:33:22 -0700269
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700270 // TODO: It should be sufficient to use the fastest liveness
271 // calculation, i.e. livenessLightweight(). However, for some
272 // reason that slows down the rest of the translation. Investigate.
273 Timer T_liveness1;
274 Func->liveness(Liveness_Basic);
275 if (Func->hasError())
276 return;
277 T_liveness1.printElapsedUs(Context, "liveness()");
278 Func->dump("After x86 address mode opt");
Matt Wala45a06232014-07-09 16:33:22 -0700279
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700280 Timer T_genCode;
281 Func->genCode();
282 if (Func->hasError())
283 return;
284 T_genCode.printElapsedUs(Context, "genCode()");
285
286 // Register allocation. This requires instruction renumbering and
287 // full liveness analysis.
288 Timer T_renumber2;
289 Func->renumberInstructions();
290 if (Func->hasError())
291 return;
292 T_renumber2.printElapsedUs(Context, "renumberInstructions()");
293 Timer T_liveness2;
294 Func->liveness(Liveness_Intervals);
295 if (Func->hasError())
296 return;
297 T_liveness2.printElapsedUs(Context, "liveness()");
298 // Validate the live range computations. Do it outside the timing
299 // code. TODO: Put this under a flag.
300 bool ValidLiveness = Func->validateLiveness();
301 assert(ValidLiveness);
302 (void)ValidLiveness; // used only in assert()
303 ComputedLiveRanges = true;
304 // The post-codegen dump is done here, after liveness analysis and
305 // associated cleanup, to make the dump cleaner and more useful.
306 Func->dump("After initial x8632 codegen");
307 Timer T_regAlloc;
308 regAlloc();
309 if (Func->hasError())
310 return;
311 T_regAlloc.printElapsedUs(Context, "regAlloc()");
312 Func->dump("After linear scan regalloc");
313
314 // Stack frame mapping.
315 Timer T_genFrame;
316 Func->genFrame();
317 if (Func->hasError())
318 return;
319 T_genFrame.printElapsedUs(Context, "genFrame()");
320 Func->dump("After stack frame mapping");
321}
322
323void TargetX8632::translateOm1() {
324 GlobalContext *Context = Func->getContext();
325 Timer T_placePhiLoads;
326 Func->placePhiLoads();
327 if (Func->hasError())
328 return;
329 T_placePhiLoads.printElapsedUs(Context, "placePhiLoads()");
330 Timer T_placePhiStores;
331 Func->placePhiStores();
332 if (Func->hasError())
333 return;
334 T_placePhiStores.printElapsedUs(Context, "placePhiStores()");
335 Timer T_deletePhis;
336 Func->deletePhis();
337 if (Func->hasError())
338 return;
339 T_deletePhis.printElapsedUs(Context, "deletePhis()");
340 Func->dump("After Phi lowering");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700341
Matt Wala45a06232014-07-09 16:33:22 -0700342 Timer T_argLowering;
343 Func->doArgLowering();
344 T_argLowering.printElapsedUs(Context, "lowerArguments()");
345
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700346 Timer T_genCode;
347 Func->genCode();
348 if (Func->hasError())
349 return;
350 T_genCode.printElapsedUs(Context, "genCode()");
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700351 Func->dump("After initial x8632 codegen");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700352
353 Timer T_genFrame;
354 Func->genFrame();
355 if (Func->hasError())
356 return;
357 T_genFrame.printElapsedUs(Context, "genFrame()");
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700358 Func->dump("After stack frame mapping");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700359}
360
361IceString TargetX8632::RegNames[] = {
362#define X(val, init, name, name16, name8, scratch, preserved, stackptr, \
363 frameptr, isI8, isInt, isFP) \
364 name,
365 REGX8632_TABLE
366#undef X
367};
368
369Variable *TargetX8632::getPhysicalRegister(SizeT RegNum) {
370 assert(RegNum < PhysicalRegisters.size());
371 Variable *Reg = PhysicalRegisters[RegNum];
372 if (Reg == NULL) {
373 CfgNode *Node = NULL; // NULL means multi-block lifetime
374 Reg = Func->makeVariable(IceType_i32, Node);
375 Reg->setRegNum(RegNum);
376 PhysicalRegisters[RegNum] = Reg;
377 }
378 return Reg;
379}
380
381IceString TargetX8632::getRegName(SizeT RegNum, Type Ty) const {
382 assert(RegNum < Reg_NUM);
383 static IceString RegNames8[] = {
384#define X(val, init, name, name16, name8, scratch, preserved, stackptr, \
385 frameptr, isI8, isInt, isFP) \
Jim Stichnoth4376d292014-05-23 13:39:02 -0700386 name8,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700387 REGX8632_TABLE
388#undef X
389 };
390 static IceString RegNames16[] = {
391#define X(val, init, name, name16, name8, scratch, preserved, stackptr, \
392 frameptr, isI8, isInt, isFP) \
Jim Stichnoth4376d292014-05-23 13:39:02 -0700393 name16,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700394 REGX8632_TABLE
395#undef X
396 };
397 switch (Ty) {
398 case IceType_i1:
399 case IceType_i8:
400 return RegNames8[RegNum];
401 case IceType_i16:
402 return RegNames16[RegNum];
403 default:
404 return RegNames[RegNum];
405 }
406}
407
408void TargetX8632::emitVariable(const Variable *Var, const Cfg *Func) const {
409 Ostream &Str = Ctx->getStrEmit();
410 assert(Var->getLocalUseNode() == NULL ||
411 Var->getLocalUseNode() == Func->getCurrentNode());
412 if (Var->hasReg()) {
413 Str << getRegName(Var->getRegNum(), Var->getType());
414 return;
415 }
416 Str << InstX8632::getWidthString(Var->getType());
417 Str << " [" << getRegName(getFrameOrStackReg(), IceType_i32);
Jim Stichnothb0e142b2014-06-12 15:28:56 -0700418 int32_t Offset = Var->getStackOffset();
419 if (!hasFramePointer())
420 Offset += getStackAdjustment();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700421 if (Offset) {
422 if (Offset > 0)
423 Str << "+";
424 Str << Offset;
425 }
426 Str << "]";
427}
428
Matt Wala45a06232014-07-09 16:33:22 -0700429void TargetX8632::lowerArguments() {
430 VarList &Args = Func->getArgs();
431 // The first four arguments of vector type, regardless of their
432 // position relative to the other arguments in the argument list, are
433 // passed in registers xmm0 - xmm3.
434 unsigned NumXmmArgs = 0;
435
436 Context.init(Func->getEntryNode());
437 Context.setInsertPoint(Context.getCur());
438
439 for (SizeT I = 0, E = Args.size(); I < E && NumXmmArgs < X86_MAX_XMM_ARGS;
440 ++I) {
441 Variable *Arg = Args[I];
442 Type Ty = Arg->getType();
443 if (!isVectorType(Ty))
444 continue;
445 // Replace Arg in the argument list with the home register. Then
446 // generate an instruction in the prolog to copy the home register
447 // to the assigned location of Arg.
448 int32_t RegNum = Reg_xmm0 + NumXmmArgs;
449 ++NumXmmArgs;
450 IceString Name = "home_reg:" + Arg->getName();
451 const CfgNode *DefNode = NULL;
452 Variable *RegisterArg = Func->makeVariable(Ty, DefNode, Name);
453 RegisterArg->setRegNum(RegNum);
454 RegisterArg->setIsArg(Func);
455 Arg->setIsArg(Func, false);
456
457 Args[I] = RegisterArg;
458 Context.insert(InstAssign::create(Func, Arg, RegisterArg));
459 }
460}
461
462// Helper function for addProlog().
463//
464// This assumes Arg is an argument passed on the stack. This sets the
465// frame offset for Arg and updates InArgsSizeBytes according to Arg's
466// width. For an I64 arg that has been split into Lo and Hi components,
467// it calls itself recursively on the components, taking care to handle
468// Lo first because of the little-endian architecture. Lastly, this
469// function generates an instruction to copy Arg into its assigned
470// register if applicable.
471void TargetX8632::finishArgumentLowering(Variable *Arg, Variable *FramePtr,
472 size_t BasicFrameOffset,
473 size_t &InArgsSizeBytes) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700474 Variable *Lo = Arg->getLo();
475 Variable *Hi = Arg->getHi();
476 Type Ty = Arg->getType();
477 if (Lo && Hi && Ty == IceType_i64) {
478 assert(Lo->getType() != IceType_i64); // don't want infinite recursion
479 assert(Hi->getType() != IceType_i64); // don't want infinite recursion
Matt Wala45a06232014-07-09 16:33:22 -0700480 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes);
481 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700482 return;
483 }
484 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes);
Matt Wala45a06232014-07-09 16:33:22 -0700485 InArgsSizeBytes += typeWidthInBytesOnStack(Ty);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700486 if (Arg->hasReg()) {
487 assert(Ty != IceType_i64);
488 OperandX8632Mem *Mem = OperandX8632Mem::create(
489 Func, Ty, FramePtr,
490 Ctx->getConstantInt(IceType_i32, Arg->getStackOffset()));
Matt Wala45a06232014-07-09 16:33:22 -0700491 if (isVectorType(Arg->getType())) {
492 _movp(Arg, Mem);
493 } else {
494 _mov(Arg, Mem);
495 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700496 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700497}
498
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700499Type TargetX8632::stackSlotType() { return IceType_i32; }
500
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700501void TargetX8632::addProlog(CfgNode *Node) {
502 // If SimpleCoalescing is false, each variable without a register
503 // gets its own unique stack slot, which leads to large stack
504 // frames. If SimpleCoalescing is true, then each "global" variable
505 // without a register gets its own slot, but "local" variable slots
506 // are reused across basic blocks. E.g., if A and B are local to
507 // block 1 and C is local to block 2, then C may share a slot with A
508 // or B.
509 const bool SimpleCoalescing = true;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700510 size_t InArgsSizeBytes = 0;
511 size_t RetIpSizeBytes = 4;
512 size_t PreservedRegsSizeBytes = 0;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700513 LocalsSizeBytes = 0;
514 Context.init(Node);
515 Context.setInsertPoint(Context.getCur());
516
517 // Determine stack frame offsets for each Variable without a
518 // register assignment. This can be done as one variable per stack
519 // slot. Or, do coalescing by running the register allocator again
520 // with an infinite set of registers (as a side effect, this gives
521 // variables a second chance at physical register assignment).
522 //
523 // A middle ground approach is to leverage sparsity and allocate one
524 // block of space on the frame for globals (variables with
525 // multi-block lifetime), and one block to share for locals
526 // (single-block lifetime).
527
528 llvm::SmallBitVector CalleeSaves =
529 getRegisterSet(RegSet_CalleeSave, RegSet_None);
530
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700531 size_t GlobalsSize = 0;
532 std::vector<size_t> LocalsSize(Func->getNumNodes());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700533
534 // Prepass. Compute RegsUsed, PreservedRegsSizeBytes, and
535 // LocalsSizeBytes.
536 RegsUsed = llvm::SmallBitVector(CalleeSaves.size());
537 const VarList &Variables = Func->getVariables();
538 const VarList &Args = Func->getArgs();
539 for (VarList::const_iterator I = Variables.begin(), E = Variables.end();
540 I != E; ++I) {
541 Variable *Var = *I;
542 if (Var->hasReg()) {
543 RegsUsed[Var->getRegNum()] = true;
544 continue;
545 }
Matt Wala45a06232014-07-09 16:33:22 -0700546 // An argument either does not need a stack slot (if passed in a
547 // register) or already has one (if passed on the stack).
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700548 if (Var->getIsArg())
549 continue;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700550 // An unreferenced variable doesn't need a stack slot.
551 if (ComputedLiveRanges && Var->getLiveRange().isEmpty())
552 continue;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700553 // A spill slot linked to a variable with a stack slot should reuse
554 // that stack slot.
555 if (Var->getWeight() == RegWeight::Zero && Var->getRegisterOverlap()) {
556 if (Variable *Linked = Var->getPreferredRegister()) {
557 if (!Linked->hasReg())
558 continue;
559 }
560 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700561 size_t Increment = typeWidthInBytesOnStack(Var->getType());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700562 if (SimpleCoalescing) {
563 if (Var->isMultiblockLife()) {
564 GlobalsSize += Increment;
565 } else {
566 SizeT NodeIndex = Var->getLocalUseNode()->getIndex();
567 LocalsSize[NodeIndex] += Increment;
568 if (LocalsSize[NodeIndex] > LocalsSizeBytes)
569 LocalsSizeBytes = LocalsSize[NodeIndex];
570 }
571 } else {
572 LocalsSizeBytes += Increment;
573 }
574 }
575 LocalsSizeBytes += GlobalsSize;
576
577 // Add push instructions for preserved registers.
578 for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
579 if (CalleeSaves[i] && RegsUsed[i]) {
580 PreservedRegsSizeBytes += 4;
581 const bool SuppressStackAdjustment = true;
582 _push(getPhysicalRegister(i), SuppressStackAdjustment);
583 }
584 }
585
586 // Generate "push ebp; mov ebp, esp"
587 if (IsEbpBasedFrame) {
588 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None))
589 .count() == 0);
590 PreservedRegsSizeBytes += 4;
591 Variable *ebp = getPhysicalRegister(Reg_ebp);
592 Variable *esp = getPhysicalRegister(Reg_esp);
593 const bool SuppressStackAdjustment = true;
594 _push(ebp, SuppressStackAdjustment);
595 _mov(ebp, esp);
596 }
597
598 // Generate "sub esp, LocalsSizeBytes"
599 if (LocalsSizeBytes)
600 _sub(getPhysicalRegister(Reg_esp),
601 Ctx->getConstantInt(IceType_i32, LocalsSizeBytes));
602
603 resetStackAdjustment();
604
Matt Wala45a06232014-07-09 16:33:22 -0700605 // Fill in stack offsets for stack args, and copy args into registers
606 // for those that were register-allocated. Args are pushed right to
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700607 // left, so Arg[0] is closest to the stack/frame pointer.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700608 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700609 size_t BasicFrameOffset = PreservedRegsSizeBytes + RetIpSizeBytes;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700610 if (!IsEbpBasedFrame)
611 BasicFrameOffset += LocalsSizeBytes;
Matt Wala45a06232014-07-09 16:33:22 -0700612
613 unsigned NumXmmArgs = 0;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700614 for (SizeT i = 0; i < Args.size(); ++i) {
615 Variable *Arg = Args[i];
Matt Wala45a06232014-07-09 16:33:22 -0700616 // Skip arguments passed in registers.
617 if (isVectorType(Arg->getType()) && NumXmmArgs < X86_MAX_XMM_ARGS) {
618 ++NumXmmArgs;
619 continue;
620 }
621 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700622 }
623
624 // Fill in stack offsets for locals.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700625 size_t TotalGlobalsSize = GlobalsSize;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700626 GlobalsSize = 0;
627 LocalsSize.assign(LocalsSize.size(), 0);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700628 size_t NextStackOffset = 0;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700629 for (VarList::const_iterator I = Variables.begin(), E = Variables.end();
630 I != E; ++I) {
631 Variable *Var = *I;
632 if (Var->hasReg()) {
633 RegsUsed[Var->getRegNum()] = true;
634 continue;
635 }
636 if (Var->getIsArg())
637 continue;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700638 if (ComputedLiveRanges && Var->getLiveRange().isEmpty())
639 continue;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700640 if (Var->getWeight() == RegWeight::Zero && Var->getRegisterOverlap()) {
641 if (Variable *Linked = Var->getPreferredRegister()) {
642 if (!Linked->hasReg()) {
643 // TODO: Make sure Linked has already been assigned a stack
644 // slot.
645 Var->setStackOffset(Linked->getStackOffset());
646 continue;
647 }
648 }
649 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700650 size_t Increment = typeWidthInBytesOnStack(Var->getType());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700651 if (SimpleCoalescing) {
652 if (Var->isMultiblockLife()) {
653 GlobalsSize += Increment;
654 NextStackOffset = GlobalsSize;
655 } else {
656 SizeT NodeIndex = Var->getLocalUseNode()->getIndex();
657 LocalsSize[NodeIndex] += Increment;
658 NextStackOffset = TotalGlobalsSize + LocalsSize[NodeIndex];
659 }
660 } else {
661 NextStackOffset += Increment;
662 }
663 if (IsEbpBasedFrame)
664 Var->setStackOffset(-NextStackOffset);
665 else
666 Var->setStackOffset(LocalsSizeBytes - NextStackOffset);
667 }
668 this->FrameSizeLocals = NextStackOffset;
669 this->HasComputedFrame = true;
670
671 if (Func->getContext()->isVerbose(IceV_Frame)) {
672 Func->getContext()->getStrDump() << "LocalsSizeBytes=" << LocalsSizeBytes
673 << "\n"
674 << "InArgsSizeBytes=" << InArgsSizeBytes
675 << "\n"
676 << "PreservedRegsSizeBytes="
677 << PreservedRegsSizeBytes << "\n";
678 }
679}
680
681void TargetX8632::addEpilog(CfgNode *Node) {
682 InstList &Insts = Node->getInsts();
683 InstList::reverse_iterator RI, E;
684 for (RI = Insts.rbegin(), E = Insts.rend(); RI != E; ++RI) {
685 if (llvm::isa<InstX8632Ret>(*RI))
686 break;
687 }
688 if (RI == E)
689 return;
690
691 // Convert the reverse_iterator position into its corresponding
692 // (forward) iterator position.
693 InstList::iterator InsertPoint = RI.base();
694 --InsertPoint;
695 Context.init(Node);
696 Context.setInsertPoint(InsertPoint);
697
698 Variable *esp = getPhysicalRegister(Reg_esp);
699 if (IsEbpBasedFrame) {
700 Variable *ebp = getPhysicalRegister(Reg_ebp);
701 _mov(esp, ebp);
702 _pop(ebp);
703 } else {
704 // add esp, LocalsSizeBytes
705 if (LocalsSizeBytes)
706 _add(esp, Ctx->getConstantInt(IceType_i32, LocalsSizeBytes));
707 }
708
709 // Add pop instructions for preserved registers.
710 llvm::SmallBitVector CalleeSaves =
711 getRegisterSet(RegSet_CalleeSave, RegSet_None);
712 for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
713 SizeT j = CalleeSaves.size() - i - 1;
714 if (j == Reg_ebp && IsEbpBasedFrame)
715 continue;
716 if (CalleeSaves[j] && RegsUsed[j]) {
717 _pop(getPhysicalRegister(j));
718 }
719 }
720}
721
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700722template <typename T> struct PoolTypeConverter {};
723
724template <> struct PoolTypeConverter<float> {
725 typedef float PrimitiveFpType;
726 typedef uint32_t PrimitiveIntType;
727 typedef ConstantFloat IceType;
728 static const Type Ty = IceType_f32;
729 static const char *TypeName;
730 static const char *AsmTag;
731 static const char *PrintfString;
732};
733const char *PoolTypeConverter<float>::TypeName = "float";
734const char *PoolTypeConverter<float>::AsmTag = ".long";
735const char *PoolTypeConverter<float>::PrintfString = "0x%x";
736
737template <> struct PoolTypeConverter<double> {
738 typedef double PrimitiveFpType;
739 typedef uint64_t PrimitiveIntType;
740 typedef ConstantDouble IceType;
741 static const Type Ty = IceType_f64;
742 static const char *TypeName;
743 static const char *AsmTag;
744 static const char *PrintfString;
745};
746const char *PoolTypeConverter<double>::TypeName = "double";
747const char *PoolTypeConverter<double>::AsmTag = ".quad";
748const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
749
750template <typename T> void TargetX8632::emitConstantPool() const {
751 Ostream &Str = Ctx->getStrEmit();
752 Type Ty = T::Ty;
753 SizeT Align = typeAlignInBytes(Ty);
754 ConstantList Pool = Ctx->getConstantPool(Ty);
755
756 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
757 << "\n";
758 Str << "\t.align\t" << Align << "\n";
759 for (ConstantList::const_iterator I = Pool.begin(), E = Pool.end(); I != E;
760 ++I) {
761 typename T::IceType *Const = llvm::cast<typename T::IceType>(*I);
762 typename T::PrimitiveFpType Value = Const->getValue();
763 // Use memcpy() to copy bits from Value into RawValue in a way
764 // that avoids breaking strict-aliasing rules.
765 typename T::PrimitiveIntType RawValue;
766 memcpy(&RawValue, &Value, sizeof(Value));
767 char buf[30];
768 int CharsPrinted =
769 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue);
770 assert(CharsPrinted >= 0 &&
771 (size_t)CharsPrinted < llvm::array_lengthof(buf));
772 (void)CharsPrinted; // avoid warnings if asserts are disabled
773 Str << "L$" << Ty << "$" << Const->getPoolEntryID() << ":\n";
774 Str << "\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " "
775 << Value << "\n";
776 }
777}
778
779void TargetX8632::emitConstants() const {
780 emitConstantPool<PoolTypeConverter<float> >();
781 emitConstantPool<PoolTypeConverter<double> >();
782
783 // No need to emit constants from the int pool since (for x86) they
784 // are embedded as immediates in the instructions.
785}
786
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700787void TargetX8632::split64(Variable *Var) {
788 switch (Var->getType()) {
789 default:
790 return;
791 case IceType_i64:
792 // TODO: Only consider F64 if we need to push each half when
793 // passing as an argument to a function call. Note that each half
794 // is still typed as I32.
795 case IceType_f64:
796 break;
797 }
798 Variable *Lo = Var->getLo();
799 Variable *Hi = Var->getHi();
800 if (Lo) {
801 assert(Hi);
802 return;
803 }
804 assert(Hi == NULL);
805 Lo = Func->makeVariable(IceType_i32, Context.getNode(),
806 Var->getName() + "__lo");
807 Hi = Func->makeVariable(IceType_i32, Context.getNode(),
808 Var->getName() + "__hi");
809 Var->setLoHi(Lo, Hi);
810 if (Var->getIsArg()) {
811 Lo->setIsArg(Func);
812 Hi->setIsArg(Func);
813 }
814}
815
816Operand *TargetX8632::loOperand(Operand *Operand) {
817 assert(Operand->getType() == IceType_i64);
818 if (Operand->getType() != IceType_i64)
819 return Operand;
820 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) {
821 split64(Var);
822 return Var->getLo();
823 }
824 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) {
825 uint64_t Mask = (1ull << 32) - 1;
826 return Ctx->getConstantInt(IceType_i32, Const->getValue() & Mask);
827 }
828 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) {
829 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(),
830 Mem->getOffset(), Mem->getIndex(),
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700831 Mem->getShift(), Mem->getSegmentRegister());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700832 }
833 llvm_unreachable("Unsupported operand type");
834 return NULL;
835}
836
837Operand *TargetX8632::hiOperand(Operand *Operand) {
838 assert(Operand->getType() == IceType_i64);
839 if (Operand->getType() != IceType_i64)
840 return Operand;
841 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) {
842 split64(Var);
843 return Var->getHi();
844 }
845 if (ConstantInteger *Const = llvm::dyn_cast<ConstantInteger>(Operand)) {
846 return Ctx->getConstantInt(IceType_i32, Const->getValue() >> 32);
847 }
848 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) {
849 Constant *Offset = Mem->getOffset();
850 if (Offset == NULL)
851 Offset = Ctx->getConstantInt(IceType_i32, 4);
852 else if (ConstantInteger *IntOffset =
853 llvm::dyn_cast<ConstantInteger>(Offset)) {
854 Offset = Ctx->getConstantInt(IceType_i32, 4 + IntOffset->getValue());
855 } else if (ConstantRelocatable *SymOffset =
856 llvm::dyn_cast<ConstantRelocatable>(Offset)) {
857 Offset = Ctx->getConstantSym(IceType_i32, 4 + SymOffset->getOffset(),
858 SymOffset->getName());
859 }
860 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), Offset,
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700861 Mem->getIndex(), Mem->getShift(),
862 Mem->getSegmentRegister());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700863 }
864 llvm_unreachable("Unsupported operand type");
865 return NULL;
866}
867
868llvm::SmallBitVector TargetX8632::getRegisterSet(RegSetMask Include,
869 RegSetMask Exclude) const {
870 llvm::SmallBitVector Registers(Reg_NUM);
871
872#define X(val, init, name, name16, name8, scratch, preserved, stackptr, \
873 frameptr, isI8, isInt, isFP) \
874 if (scratch && (Include & RegSet_CallerSave)) \
875 Registers[val] = true; \
876 if (preserved && (Include & RegSet_CalleeSave)) \
877 Registers[val] = true; \
878 if (stackptr && (Include & RegSet_StackPointer)) \
879 Registers[val] = true; \
880 if (frameptr && (Include & RegSet_FramePointer)) \
881 Registers[val] = true; \
882 if (scratch && (Exclude & RegSet_CallerSave)) \
883 Registers[val] = false; \
884 if (preserved && (Exclude & RegSet_CalleeSave)) \
885 Registers[val] = false; \
886 if (stackptr && (Exclude & RegSet_StackPointer)) \
887 Registers[val] = false; \
888 if (frameptr && (Exclude & RegSet_FramePointer)) \
889 Registers[val] = false;
890
891 REGX8632_TABLE
892
893#undef X
894
895 return Registers;
896}
897
898void TargetX8632::lowerAlloca(const InstAlloca *Inst) {
899 IsEbpBasedFrame = true;
900 // TODO(sehr,stichnot): align allocated memory, keep stack aligned, minimize
901 // the number of adjustments of esp, etc.
902 Variable *esp = getPhysicalRegister(Reg_esp);
903 Operand *TotalSize = legalize(Inst->getSizeInBytes());
904 Variable *Dest = Inst->getDest();
905 _sub(esp, TotalSize);
906 _mov(Dest, esp);
907}
908
909void TargetX8632::lowerArithmetic(const InstArithmetic *Inst) {
910 Variable *Dest = Inst->getDest();
911 Operand *Src0 = legalize(Inst->getSrc(0));
912 Operand *Src1 = legalize(Inst->getSrc(1));
913 if (Dest->getType() == IceType_i64) {
914 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
915 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
916 Operand *Src0Lo = loOperand(Src0);
917 Operand *Src0Hi = hiOperand(Src0);
918 Operand *Src1Lo = loOperand(Src1);
919 Operand *Src1Hi = hiOperand(Src1);
920 Variable *T_Lo = NULL, *T_Hi = NULL;
921 switch (Inst->getOp()) {
Jim Stichnoth4376d292014-05-23 13:39:02 -0700922 case InstArithmetic::_num:
923 llvm_unreachable("Unknown arithmetic operator");
924 break;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700925 case InstArithmetic::Add:
926 _mov(T_Lo, Src0Lo);
927 _add(T_Lo, Src1Lo);
928 _mov(DestLo, T_Lo);
929 _mov(T_Hi, Src0Hi);
930 _adc(T_Hi, Src1Hi);
931 _mov(DestHi, T_Hi);
932 break;
933 case InstArithmetic::And:
934 _mov(T_Lo, Src0Lo);
935 _and(T_Lo, Src1Lo);
936 _mov(DestLo, T_Lo);
937 _mov(T_Hi, Src0Hi);
938 _and(T_Hi, Src1Hi);
939 _mov(DestHi, T_Hi);
940 break;
941 case InstArithmetic::Or:
942 _mov(T_Lo, Src0Lo);
943 _or(T_Lo, Src1Lo);
944 _mov(DestLo, T_Lo);
945 _mov(T_Hi, Src0Hi);
946 _or(T_Hi, Src1Hi);
947 _mov(DestHi, T_Hi);
948 break;
949 case InstArithmetic::Xor:
950 _mov(T_Lo, Src0Lo);
951 _xor(T_Lo, Src1Lo);
952 _mov(DestLo, T_Lo);
953 _mov(T_Hi, Src0Hi);
954 _xor(T_Hi, Src1Hi);
955 _mov(DestHi, T_Hi);
956 break;
957 case InstArithmetic::Sub:
958 _mov(T_Lo, Src0Lo);
959 _sub(T_Lo, Src1Lo);
960 _mov(DestLo, T_Lo);
961 _mov(T_Hi, Src0Hi);
962 _sbb(T_Hi, Src1Hi);
963 _mov(DestHi, T_Hi);
964 break;
965 case InstArithmetic::Mul: {
966 Variable *T_1 = NULL, *T_2 = NULL, *T_3 = NULL;
967 Variable *T_4Lo = makeReg(IceType_i32, Reg_eax);
968 Variable *T_4Hi = makeReg(IceType_i32, Reg_edx);
969 // gcc does the following:
970 // a=b*c ==>
971 // t1 = b.hi; t1 *=(imul) c.lo
972 // t2 = c.hi; t2 *=(imul) b.lo
973 // t3:eax = b.lo
974 // t4.hi:edx,t4.lo:eax = t3:eax *(mul) c.lo
975 // a.lo = t4.lo
976 // t4.hi += t1
977 // t4.hi += t2
978 // a.hi = t4.hi
979 _mov(T_1, Src0Hi);
980 _imul(T_1, Src1Lo);
981 _mov(T_2, Src1Hi);
982 _imul(T_2, Src0Lo);
983 _mov(T_3, Src0Lo, Reg_eax);
984 _mul(T_4Lo, T_3, Src1Lo);
985 // The mul instruction produces two dest variables, edx:eax. We
986 // create a fake definition of edx to account for this.
987 Context.insert(InstFakeDef::create(Func, T_4Hi, T_4Lo));
988 _mov(DestLo, T_4Lo);
989 _add(T_4Hi, T_1);
990 _add(T_4Hi, T_2);
991 _mov(DestHi, T_4Hi);
992 } break;
993 case InstArithmetic::Shl: {
994 // TODO: Refactor the similarities between Shl, Lshr, and Ashr.
995 // gcc does the following:
996 // a=b<<c ==>
997 // t1:ecx = c.lo & 0xff
998 // t2 = b.lo
999 // t3 = b.hi
1000 // t3 = shld t3, t2, t1
1001 // t2 = shl t2, t1
1002 // test t1, 0x20
1003 // je L1
1004 // use(t3)
1005 // t3 = t2
1006 // t2 = 0
1007 // L1:
1008 // a.lo = t2
1009 // a.hi = t3
1010 Variable *T_1 = NULL, *T_2 = NULL, *T_3 = NULL;
1011 Constant *BitTest = Ctx->getConstantInt(IceType_i32, 0x20);
Matt Wala43ff7eb2014-06-18 10:30:07 -07001012 Constant *Zero = Ctx->getConstantZero(IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001013 InstX8632Label *Label = InstX8632Label::create(Func, this);
1014 _mov(T_1, Src1Lo, Reg_ecx);
1015 _mov(T_2, Src0Lo);
1016 _mov(T_3, Src0Hi);
1017 _shld(T_3, T_2, T_1);
1018 _shl(T_2, T_1);
1019 _test(T_1, BitTest);
1020 _br(InstX8632Br::Br_e, Label);
1021 // Because of the intra-block control flow, we need to fake a use
1022 // of T_3 to prevent its earlier definition from being dead-code
1023 // eliminated in the presence of its later definition.
1024 Context.insert(InstFakeUse::create(Func, T_3));
1025 _mov(T_3, T_2);
1026 _mov(T_2, Zero);
1027 Context.insert(Label);
1028 _mov(DestLo, T_2);
1029 _mov(DestHi, T_3);
1030 } break;
1031 case InstArithmetic::Lshr: {
1032 // a=b>>c (unsigned) ==>
1033 // t1:ecx = c.lo & 0xff
1034 // t2 = b.lo
1035 // t3 = b.hi
1036 // t2 = shrd t2, t3, t1
1037 // t3 = shr t3, t1
1038 // test t1, 0x20
1039 // je L1
1040 // use(t2)
1041 // t2 = t3
1042 // t3 = 0
1043 // L1:
1044 // a.lo = t2
1045 // a.hi = t3
1046 Variable *T_1 = NULL, *T_2 = NULL, *T_3 = NULL;
1047 Constant *BitTest = Ctx->getConstantInt(IceType_i32, 0x20);
Matt Wala43ff7eb2014-06-18 10:30:07 -07001048 Constant *Zero = Ctx->getConstantZero(IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001049 InstX8632Label *Label = InstX8632Label::create(Func, this);
1050 _mov(T_1, Src1Lo, Reg_ecx);
1051 _mov(T_2, Src0Lo);
1052 _mov(T_3, Src0Hi);
1053 _shrd(T_2, T_3, T_1);
1054 _shr(T_3, T_1);
1055 _test(T_1, BitTest);
1056 _br(InstX8632Br::Br_e, Label);
1057 // Because of the intra-block control flow, we need to fake a use
1058 // of T_3 to prevent its earlier definition from being dead-code
1059 // eliminated in the presence of its later definition.
1060 Context.insert(InstFakeUse::create(Func, T_2));
1061 _mov(T_2, T_3);
1062 _mov(T_3, Zero);
1063 Context.insert(Label);
1064 _mov(DestLo, T_2);
1065 _mov(DestHi, T_3);
1066 } break;
1067 case InstArithmetic::Ashr: {
1068 // a=b>>c (signed) ==>
1069 // t1:ecx = c.lo & 0xff
1070 // t2 = b.lo
1071 // t3 = b.hi
1072 // t2 = shrd t2, t3, t1
1073 // t3 = sar t3, t1
1074 // test t1, 0x20
1075 // je L1
1076 // use(t2)
1077 // t2 = t3
1078 // t3 = sar t3, 0x1f
1079 // L1:
1080 // a.lo = t2
1081 // a.hi = t3
1082 Variable *T_1 = NULL, *T_2 = NULL, *T_3 = NULL;
1083 Constant *BitTest = Ctx->getConstantInt(IceType_i32, 0x20);
1084 Constant *SignExtend = Ctx->getConstantInt(IceType_i32, 0x1f);
1085 InstX8632Label *Label = InstX8632Label::create(Func, this);
1086 _mov(T_1, Src1Lo, Reg_ecx);
1087 _mov(T_2, Src0Lo);
1088 _mov(T_3, Src0Hi);
1089 _shrd(T_2, T_3, T_1);
1090 _sar(T_3, T_1);
1091 _test(T_1, BitTest);
1092 _br(InstX8632Br::Br_e, Label);
1093 // Because of the intra-block control flow, we need to fake a use
1094 // of T_3 to prevent its earlier definition from being dead-code
1095 // eliminated in the presence of its later definition.
1096 Context.insert(InstFakeUse::create(Func, T_2));
1097 _mov(T_2, T_3);
1098 _sar(T_3, SignExtend);
1099 Context.insert(Label);
1100 _mov(DestLo, T_2);
1101 _mov(DestHi, T_3);
1102 } break;
1103 case InstArithmetic::Udiv: {
1104 const SizeT MaxSrcs = 2;
1105 InstCall *Call = makeHelperCall("__udivdi3", Dest, MaxSrcs);
1106 Call->addArg(Inst->getSrc(0));
1107 Call->addArg(Inst->getSrc(1));
1108 lowerCall(Call);
1109 } break;
1110 case InstArithmetic::Sdiv: {
1111 const SizeT MaxSrcs = 2;
1112 InstCall *Call = makeHelperCall("__divdi3", Dest, MaxSrcs);
1113 Call->addArg(Inst->getSrc(0));
1114 Call->addArg(Inst->getSrc(1));
1115 lowerCall(Call);
1116 } break;
1117 case InstArithmetic::Urem: {
1118 const SizeT MaxSrcs = 2;
1119 InstCall *Call = makeHelperCall("__umoddi3", Dest, MaxSrcs);
1120 Call->addArg(Inst->getSrc(0));
1121 Call->addArg(Inst->getSrc(1));
1122 lowerCall(Call);
1123 } break;
1124 case InstArithmetic::Srem: {
1125 const SizeT MaxSrcs = 2;
1126 InstCall *Call = makeHelperCall("__moddi3", Dest, MaxSrcs);
1127 Call->addArg(Inst->getSrc(0));
1128 Call->addArg(Inst->getSrc(1));
1129 lowerCall(Call);
1130 } break;
1131 case InstArithmetic::Fadd:
1132 case InstArithmetic::Fsub:
1133 case InstArithmetic::Fmul:
1134 case InstArithmetic::Fdiv:
1135 case InstArithmetic::Frem:
1136 llvm_unreachable("FP instruction with i64 type");
1137 break;
1138 }
Matt Wala8d1072e2014-07-11 15:43:51 -07001139 } else if (isVectorType(Dest->getType())) {
1140 switch (Inst->getOp()) {
1141 case InstArithmetic::_num:
1142 llvm_unreachable("Unknown arithmetic operator");
1143 break;
1144 case InstArithmetic::Add:
1145 case InstArithmetic::And:
1146 case InstArithmetic::Or:
1147 case InstArithmetic::Xor:
1148 case InstArithmetic::Sub:
1149 case InstArithmetic::Mul:
1150 case InstArithmetic::Shl:
1151 case InstArithmetic::Lshr:
1152 case InstArithmetic::Ashr:
1153 case InstArithmetic::Udiv:
1154 case InstArithmetic::Sdiv:
1155 case InstArithmetic::Urem:
1156 case InstArithmetic::Srem:
1157 // TODO(wala): Handle these.
1158 Func->setError("Unhandled instruction");
1159 break;
1160 case InstArithmetic::Fadd: {
1161 Variable *T = makeReg(Dest->getType());
1162 _movp(T, Src0);
1163 _addps(T, Src1);
1164 _movp(Dest, T);
1165 } break;
1166 case InstArithmetic::Fsub: {
1167 Variable *T = makeReg(Dest->getType());
1168 _movp(T, Src0);
1169 _subps(T, Src1);
1170 _movp(Dest, T);
1171 } break;
1172 case InstArithmetic::Fmul: {
1173 Variable *T = makeReg(Dest->getType());
1174 _movp(T, Src0);
1175 _mulps(T, Src1);
1176 _movp(Dest, T);
1177 } break;
1178 case InstArithmetic::Fdiv: {
1179 Variable *T = makeReg(Dest->getType());
1180 _movp(T, Src0);
1181 _divps(T, Src1);
1182 _movp(Dest, T);
1183 } break;
1184 case InstArithmetic::Frem: {
1185 const SizeT MaxSrcs = 1;
1186 InstCall *Call = makeHelperCall("__frem_v4f32", Dest, MaxSrcs);
1187 Call->addArg(Src0);
1188 lowerCall(Call);
1189 } break;
1190 }
1191 } else { // Dest->getType() is non-i64 scalar
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001192 Variable *T_edx = NULL;
1193 Variable *T = NULL;
1194 switch (Inst->getOp()) {
Jim Stichnoth4376d292014-05-23 13:39:02 -07001195 case InstArithmetic::_num:
1196 llvm_unreachable("Unknown arithmetic operator");
1197 break;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001198 case InstArithmetic::Add:
1199 _mov(T, Src0);
1200 _add(T, Src1);
1201 _mov(Dest, T);
1202 break;
1203 case InstArithmetic::And:
1204 _mov(T, Src0);
1205 _and(T, Src1);
1206 _mov(Dest, T);
1207 break;
1208 case InstArithmetic::Or:
1209 _mov(T, Src0);
1210 _or(T, Src1);
1211 _mov(Dest, T);
1212 break;
1213 case InstArithmetic::Xor:
1214 _mov(T, Src0);
1215 _xor(T, Src1);
1216 _mov(Dest, T);
1217 break;
1218 case InstArithmetic::Sub:
1219 _mov(T, Src0);
1220 _sub(T, Src1);
1221 _mov(Dest, T);
1222 break;
1223 case InstArithmetic::Mul:
1224 // TODO: Optimize for llvm::isa<Constant>(Src1)
1225 // TODO: Strength-reduce multiplications by a constant,
1226 // particularly -1 and powers of 2. Advanced: use lea to
1227 // multiply by 3, 5, 9.
1228 //
1229 // The 8-bit version of imul only allows the form "imul r/m8"
1230 // where T must be in eax.
1231 if (Dest->getType() == IceType_i8)
1232 _mov(T, Src0, Reg_eax);
1233 else
1234 _mov(T, Src0);
1235 _imul(T, Src1);
1236 _mov(Dest, T);
1237 break;
1238 case InstArithmetic::Shl:
1239 _mov(T, Src0);
1240 if (!llvm::isa<Constant>(Src1))
1241 Src1 = legalizeToVar(Src1, false, Reg_ecx);
1242 _shl(T, Src1);
1243 _mov(Dest, T);
1244 break;
1245 case InstArithmetic::Lshr:
1246 _mov(T, Src0);
1247 if (!llvm::isa<Constant>(Src1))
1248 Src1 = legalizeToVar(Src1, false, Reg_ecx);
1249 _shr(T, Src1);
1250 _mov(Dest, T);
1251 break;
1252 case InstArithmetic::Ashr:
1253 _mov(T, Src0);
1254 if (!llvm::isa<Constant>(Src1))
1255 Src1 = legalizeToVar(Src1, false, Reg_ecx);
1256 _sar(T, Src1);
1257 _mov(Dest, T);
1258 break;
1259 case InstArithmetic::Udiv:
Jan Voung70d68832014-06-17 10:02:37 -07001260 // div and idiv are the few arithmetic operators that do not allow
1261 // immediates as the operand.
1262 Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001263 if (Dest->getType() == IceType_i8) {
1264 Variable *T_ah = NULL;
Matt Wala43ff7eb2014-06-18 10:30:07 -07001265 Constant *Zero = Ctx->getConstantZero(IceType_i8);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001266 _mov(T, Src0, Reg_eax);
1267 _mov(T_ah, Zero, Reg_ah);
1268 _div(T, Src1, T_ah);
1269 _mov(Dest, T);
1270 } else {
Matt Wala43ff7eb2014-06-18 10:30:07 -07001271 Constant *Zero = Ctx->getConstantZero(IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001272 _mov(T, Src0, Reg_eax);
1273 _mov(T_edx, Zero, Reg_edx);
1274 _div(T, Src1, T_edx);
1275 _mov(Dest, T);
1276 }
1277 break;
1278 case InstArithmetic::Sdiv:
Jan Voung70d68832014-06-17 10:02:37 -07001279 Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001280 T_edx = makeReg(IceType_i32, Reg_edx);
1281 _mov(T, Src0, Reg_eax);
1282 _cdq(T_edx, T);
1283 _idiv(T, Src1, T_edx);
1284 _mov(Dest, T);
1285 break;
1286 case InstArithmetic::Urem:
Jan Voung70d68832014-06-17 10:02:37 -07001287 Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001288 if (Dest->getType() == IceType_i8) {
1289 Variable *T_ah = NULL;
Matt Wala43ff7eb2014-06-18 10:30:07 -07001290 Constant *Zero = Ctx->getConstantZero(IceType_i8);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001291 _mov(T, Src0, Reg_eax);
1292 _mov(T_ah, Zero, Reg_ah);
1293 _div(T_ah, Src1, T);
1294 _mov(Dest, T_ah);
1295 } else {
Matt Wala43ff7eb2014-06-18 10:30:07 -07001296 Constant *Zero = Ctx->getConstantZero(IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001297 _mov(T_edx, Zero, Reg_edx);
1298 _mov(T, Src0, Reg_eax);
1299 _div(T_edx, Src1, T);
1300 _mov(Dest, T_edx);
1301 }
1302 break;
1303 case InstArithmetic::Srem:
Jan Voung70d68832014-06-17 10:02:37 -07001304 Src1 = legalize(Src1, Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001305 T_edx = makeReg(IceType_i32, Reg_edx);
1306 _mov(T, Src0, Reg_eax);
1307 _cdq(T_edx, T);
1308 _idiv(T_edx, Src1, T);
1309 _mov(Dest, T_edx);
1310 break;
1311 case InstArithmetic::Fadd:
1312 _mov(T, Src0);
1313 _addss(T, Src1);
1314 _mov(Dest, T);
1315 break;
1316 case InstArithmetic::Fsub:
1317 _mov(T, Src0);
1318 _subss(T, Src1);
1319 _mov(Dest, T);
1320 break;
1321 case InstArithmetic::Fmul:
1322 _mov(T, Src0);
1323 _mulss(T, Src1);
1324 _mov(Dest, T);
1325 break;
1326 case InstArithmetic::Fdiv:
1327 _mov(T, Src0);
1328 _divss(T, Src1);
1329 _mov(Dest, T);
1330 break;
1331 case InstArithmetic::Frem: {
1332 const SizeT MaxSrcs = 2;
1333 Type Ty = Dest->getType();
1334 InstCall *Call =
1335 makeHelperCall(Ty == IceType_f32 ? "fmodf" : "fmod", Dest, MaxSrcs);
1336 Call->addArg(Src0);
1337 Call->addArg(Src1);
1338 return lowerCall(Call);
1339 } break;
1340 }
1341 }
1342}
1343
1344void TargetX8632::lowerAssign(const InstAssign *Inst) {
1345 Variable *Dest = Inst->getDest();
1346 Operand *Src0 = Inst->getSrc(0);
1347 assert(Dest->getType() == Src0->getType());
1348 if (Dest->getType() == IceType_i64) {
1349 Src0 = legalize(Src0);
1350 Operand *Src0Lo = loOperand(Src0);
1351 Operand *Src0Hi = hiOperand(Src0);
1352 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
1353 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
1354 Variable *T_Lo = NULL, *T_Hi = NULL;
1355 _mov(T_Lo, Src0Lo);
1356 _mov(DestLo, T_Lo);
1357 _mov(T_Hi, Src0Hi);
1358 _mov(DestHi, T_Hi);
1359 } else {
1360 const bool AllowOverlap = true;
1361 // RI is either a physical register or an immediate.
1362 Operand *RI = legalize(Src0, Legal_Reg | Legal_Imm, AllowOverlap);
Matt Wala45a06232014-07-09 16:33:22 -07001363 if (isVectorType(Dest->getType()))
1364 _movp(Dest, RI);
1365 else
1366 _mov(Dest, RI);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001367 }
1368}
1369
1370void TargetX8632::lowerBr(const InstBr *Inst) {
1371 if (Inst->isUnconditional()) {
1372 _br(Inst->getTargetUnconditional());
1373 } else {
1374 Operand *Src0 = legalize(Inst->getCondition());
Matt Wala43ff7eb2014-06-18 10:30:07 -07001375 Constant *Zero = Ctx->getConstantZero(IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001376 _cmp(Src0, Zero);
1377 _br(InstX8632Br::Br_ne, Inst->getTargetTrue(), Inst->getTargetFalse());
1378 }
1379}
1380
1381void TargetX8632::lowerCall(const InstCall *Instr) {
Matt Wala45a06232014-07-09 16:33:22 -07001382 // Classify each argument operand according to the location where the
1383 // argument is passed.
1384 OperandList XmmArgs;
1385 OperandList StackArgs;
1386 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) {
1387 Operand *Arg = Instr->getArg(i);
1388 if (isVectorType(Arg->getType()) && XmmArgs.size() < X86_MAX_XMM_ARGS) {
1389 XmmArgs.push_back(Arg);
1390 } else {
1391 StackArgs.push_back(Arg);
1392 }
1393 }
1394 // For stack arguments, generate a sequence of push instructions,
1395 // pushing right to left, keeping track of stack offsets in case a
1396 // push involves a stack operand and we are using an esp-based frame.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001397 uint32_t StackOffset = 0;
Matt Wala45a06232014-07-09 16:33:22 -07001398 // TODO: Consolidate the stack adjustment for function calls by
1399 // reserving enough space for the arguments only once.
1400 //
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001401 // TODO: If for some reason the call instruction gets dead-code
1402 // eliminated after lowering, we would need to ensure that the
1403 // pre-call push instructions and the post-call esp adjustment get
1404 // eliminated as well.
Matt Wala45a06232014-07-09 16:33:22 -07001405 for (OperandList::reverse_iterator I = StackArgs.rbegin(),
1406 E = StackArgs.rend(); I != E; ++I) {
1407 Operand *Arg = legalize(*I);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001408 if (Arg->getType() == IceType_i64) {
1409 _push(hiOperand(Arg));
1410 _push(loOperand(Arg));
Matt Wala45a06232014-07-09 16:33:22 -07001411 } else if (Arg->getType() == IceType_f64 || isVectorType(Arg->getType())) {
1412 // If the Arg turns out to be a memory operand, more than one push
1413 // instruction is required. This ends up being somewhat clumsy in
1414 // the current IR, so we use a workaround. Force the operand into
1415 // a (xmm) register, and then push the register. An xmm register
1416 // push is actually not possible in x86, but the Push instruction
1417 // emitter handles this by decrementing the stack pointer and
1418 // directly writing the xmm register value.
1419 _push(legalize(Arg, Legal_Reg));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001420 } else {
Jan Voungbdbe4022014-06-17 17:12:26 -07001421 // Otherwise PNaCl requires parameter types to be at least 32-bits.
1422 assert(Arg->getType() == IceType_f32 || Arg->getType() == IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001423 _push(Arg);
1424 }
1425 StackOffset += typeWidthInBytesOnStack(Arg->getType());
1426 }
Matt Wala45a06232014-07-09 16:33:22 -07001427 // Copy arguments to be passed in registers to the appropriate
1428 // registers.
1429 // TODO: Investigate the impact of lowering arguments passed in
1430 // registers after lowering stack arguments as opposed to the other
1431 // way around. Lowering register arguments after stack arguments may
1432 // reduce register pressure. On the other hand, lowering register
1433 // arguments first (before stack arguments) may result in more compact
1434 // code, as the memory operand displacements may end up being smaller
1435 // before any stack adjustment is done.
1436 for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) {
1437 Variable *Reg = legalizeToVar(XmmArgs[i], false, Reg_xmm0 + i);
1438 // Generate a FakeUse of register arguments so that they do not get
1439 // dead code eliminated as a result of the FakeKill of scratch
1440 // registers after the call.
1441 Context.insert(InstFakeUse::create(Func, Reg));
1442 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001443 // Generate the call instruction. Assign its result to a temporary
1444 // with high register allocation weight.
1445 Variable *Dest = Instr->getDest();
Matt Wala45a06232014-07-09 16:33:22 -07001446 // ReturnReg doubles as ReturnRegLo as necessary.
1447 Variable *ReturnReg = NULL;
1448 Variable *ReturnRegHi = NULL;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001449 if (Dest) {
1450 switch (Dest->getType()) {
1451 case IceType_NUM:
1452 llvm_unreachable("Invalid Call dest type");
1453 break;
1454 case IceType_void:
1455 break;
1456 case IceType_i1:
1457 case IceType_i8:
1458 case IceType_i16:
1459 case IceType_i32:
Matt Wala45a06232014-07-09 16:33:22 -07001460 ReturnReg = makeReg(Dest->getType(), Reg_eax);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001461 break;
1462 case IceType_i64:
Matt Wala45a06232014-07-09 16:33:22 -07001463 ReturnReg = makeReg(IceType_i32, Reg_eax);
1464 ReturnRegHi = makeReg(IceType_i32, Reg_edx);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001465 break;
1466 case IceType_f32:
1467 case IceType_f64:
Matt Wala45a06232014-07-09 16:33:22 -07001468 // Leave ReturnReg==ReturnRegHi==NULL, and capture the result with
1469 // the fstp instruction.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001470 break;
Matt Wala928f1292014-07-07 16:50:46 -07001471 case IceType_v4i1:
1472 case IceType_v8i1:
1473 case IceType_v16i1:
1474 case IceType_v16i8:
1475 case IceType_v8i16:
1476 case IceType_v4i32:
Matt Wala45a06232014-07-09 16:33:22 -07001477 case IceType_v4f32:
1478 ReturnReg = makeReg(Dest->getType(), Reg_xmm0);
1479 break;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001480 }
1481 }
Jim Stichnothde4ca712014-06-29 08:13:48 -07001482 // TODO(stichnot): LEAHACK: remove Legal_All (and use default) once
1483 // a proper emitter is used.
1484 Operand *CallTarget = legalize(Instr->getCallTarget(), Legal_All);
Matt Wala45a06232014-07-09 16:33:22 -07001485 Inst *NewCall = InstX8632Call::create(Func, ReturnReg, CallTarget);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001486 Context.insert(NewCall);
Matt Wala45a06232014-07-09 16:33:22 -07001487 if (ReturnRegHi)
1488 Context.insert(InstFakeDef::create(Func, ReturnRegHi));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001489
1490 // Add the appropriate offset to esp.
1491 if (StackOffset) {
1492 Variable *esp = Func->getTarget()->getPhysicalRegister(Reg_esp);
1493 _add(esp, Ctx->getConstantInt(IceType_i32, StackOffset));
1494 }
1495
1496 // Insert a register-kill pseudo instruction.
1497 VarList KilledRegs;
1498 for (SizeT i = 0; i < ScratchRegs.size(); ++i) {
1499 if (ScratchRegs[i])
1500 KilledRegs.push_back(Func->getTarget()->getPhysicalRegister(i));
1501 }
1502 Context.insert(InstFakeKill::create(Func, KilledRegs, NewCall));
1503
1504 // Generate a FakeUse to keep the call live if necessary.
Matt Wala45a06232014-07-09 16:33:22 -07001505 if (Instr->hasSideEffects() && ReturnReg) {
1506 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001507 Context.insert(FakeUse);
1508 }
Matt Wala8d1072e2014-07-11 15:43:51 -07001509
Matt Wala45a06232014-07-09 16:33:22 -07001510 if (!Dest)
1511 return;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001512
Matt Wala45a06232014-07-09 16:33:22 -07001513 // Assign the result of the call to Dest.
1514 if (ReturnReg) {
1515 if (ReturnRegHi) {
1516 assert(Dest->getType() == IceType_i64);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001517 split64(Dest);
1518 Variable *DestLo = Dest->getLo();
1519 Variable *DestHi = Dest->getHi();
Matt Wala45a06232014-07-09 16:33:22 -07001520 DestLo->setPreferredRegister(ReturnReg, false);
1521 DestHi->setPreferredRegister(ReturnRegHi, false);
1522 _mov(DestLo, ReturnReg);
1523 _mov(DestHi, ReturnRegHi);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001524 } else {
Matt Wala45a06232014-07-09 16:33:22 -07001525 assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 ||
1526 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 ||
1527 isVectorType(Dest->getType()));
1528 Dest->setPreferredRegister(ReturnReg, false);
1529 if (isVectorType(Dest->getType())) {
1530 _movp(Dest, ReturnReg);
1531 } else {
1532 _mov(Dest, ReturnReg);
1533 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001534 }
Matt Wala45a06232014-07-09 16:33:22 -07001535 } else if (Dest->getType() == IceType_f32 || Dest->getType() == IceType_f64) {
1536 // Special treatment for an FP function which returns its result in
1537 // st(0).
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001538 _fstp(Dest);
Matt Wala45a06232014-07-09 16:33:22 -07001539 // If Dest ends up being a physical xmm register, the fstp emit code
1540 // will route st(0) through a temporary stack slot.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001541 }
1542}
1543
1544void TargetX8632::lowerCast(const InstCast *Inst) {
1545 // a = cast(b) ==> t=cast(b); a=t; (link t->b, link a->t, no overlap)
1546 InstCast::OpKind CastKind = Inst->getCastKind();
1547 Variable *Dest = Inst->getDest();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001548 switch (CastKind) {
1549 default:
1550 Func->setError("Cast type not supported");
1551 return;
Jan Voung1ee34162014-06-24 13:43:30 -07001552 case InstCast::Sext: {
1553 // Src0RM is the source operand legalized to physical register or memory,
1554 // but not immediate, since the relevant x86 native instructions don't
1555 // allow an immediate operand. If the operand is an immediate, we could
1556 // consider computing the strength-reduced result at translation time,
1557 // but we're unlikely to see something like that in the bitcode that
1558 // the optimizer wouldn't have already taken care of.
1559 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001560 if (Dest->getType() == IceType_i64) {
1561 // t1=movsx src; t2=t1; t2=sar t2, 31; dst.lo=t1; dst.hi=t2
1562 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
1563 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
1564 Variable *T_Lo = makeReg(DestLo->getType());
1565 if (Src0RM->getType() == IceType_i32)
1566 _mov(T_Lo, Src0RM);
1567 else
1568 _movsx(T_Lo, Src0RM);
1569 _mov(DestLo, T_Lo);
1570 Variable *T_Hi = NULL;
1571 Constant *Shift = Ctx->getConstantInt(IceType_i32, 31);
1572 _mov(T_Hi, T_Lo);
1573 _sar(T_Hi, Shift);
1574 _mov(DestHi, T_Hi);
1575 } else {
1576 // TODO: Sign-extend an i1 via "shl reg, 31; sar reg, 31", and
1577 // also copy to the high operand of a 64-bit variable.
1578 // t1 = movsx src; dst = t1
1579 Variable *T = makeReg(Dest->getType());
1580 _movsx(T, Src0RM);
1581 _mov(Dest, T);
1582 }
1583 break;
Jan Voung1ee34162014-06-24 13:43:30 -07001584 }
1585 case InstCast::Zext: {
1586 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001587 if (Dest->getType() == IceType_i64) {
1588 // t1=movzx src; dst.lo=t1; dst.hi=0
Matt Wala43ff7eb2014-06-18 10:30:07 -07001589 Constant *Zero = Ctx->getConstantZero(IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001590 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
1591 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
1592 Variable *Tmp = makeReg(DestLo->getType());
1593 if (Src0RM->getType() == IceType_i32)
1594 _mov(Tmp, Src0RM);
1595 else
1596 _movzx(Tmp, Src0RM);
1597 _mov(DestLo, Tmp);
1598 _mov(DestHi, Zero);
1599 } else if (Src0RM->getType() == IceType_i1) {
1600 // t = Src0RM; t &= 1; Dest = t
1601 Operand *One = Ctx->getConstantInt(IceType_i32, 1);
1602 Variable *T = makeReg(IceType_i32);
1603 _movzx(T, Src0RM);
1604 _and(T, One);
1605 _mov(Dest, T);
1606 } else {
1607 // t1 = movzx src; dst = t1
1608 Variable *T = makeReg(Dest->getType());
1609 _movzx(T, Src0RM);
1610 _mov(Dest, T);
1611 }
1612 break;
Jan Voung1ee34162014-06-24 13:43:30 -07001613 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001614 case InstCast::Trunc: {
Jan Voung1ee34162014-06-24 13:43:30 -07001615 Operand *Src0 = Inst->getSrc(0);
1616 if (Src0->getType() == IceType_i64)
1617 Src0 = loOperand(Src0);
1618 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001619 // t1 = trunc Src0RM; Dest = t1
1620 Variable *T = NULL;
1621 _mov(T, Src0RM);
1622 _mov(Dest, T);
1623 break;
1624 }
1625 case InstCast::Fptrunc:
1626 case InstCast::Fpext: {
Jan Voung1ee34162014-06-24 13:43:30 -07001627 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001628 // t1 = cvt Src0RM; Dest = t1
1629 Variable *T = makeReg(Dest->getType());
1630 _cvt(T, Src0RM);
1631 _mov(Dest, T);
1632 break;
1633 }
1634 case InstCast::Fptosi:
1635 if (Dest->getType() == IceType_i64) {
1636 // Use a helper for converting floating-point values to 64-bit
1637 // integers. SSE2 appears to have no way to convert from xmm
1638 // registers to something like the edx:eax register pair, and
1639 // gcc and clang both want to use x87 instructions complete with
1640 // temporary manipulation of the status word. This helper is
1641 // not needed for x86-64.
1642 split64(Dest);
1643 const SizeT MaxSrcs = 1;
1644 Type SrcType = Inst->getSrc(0)->getType();
1645 InstCall *Call = makeHelperCall(
1646 SrcType == IceType_f32 ? "cvtftosi64" : "cvtdtosi64", Dest, MaxSrcs);
1647 // TODO: Call the correct compiler-rt helper function.
1648 Call->addArg(Inst->getSrc(0));
1649 lowerCall(Call);
1650 } else {
Jan Voung1ee34162014-06-24 13:43:30 -07001651 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001652 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type
1653 Variable *T_1 = makeReg(IceType_i32);
1654 Variable *T_2 = makeReg(Dest->getType());
1655 _cvt(T_1, Src0RM);
1656 _mov(T_2, T_1); // T_1 and T_2 may have different integer types
1657 _mov(Dest, T_2);
1658 T_2->setPreferredRegister(T_1, true);
1659 }
1660 break;
1661 case InstCast::Fptoui:
1662 if (Dest->getType() == IceType_i64 || Dest->getType() == IceType_i32) {
1663 // Use a helper for both x86-32 and x86-64.
1664 split64(Dest);
1665 const SizeT MaxSrcs = 1;
1666 Type DestType = Dest->getType();
Jan Voung1ee34162014-06-24 13:43:30 -07001667 Type SrcType = Inst->getSrc(0)->getType();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001668 IceString DstSubstring = (DestType == IceType_i64 ? "64" : "32");
1669 IceString SrcSubstring = (SrcType == IceType_f32 ? "f" : "d");
1670 // Possibilities are cvtftoui32, cvtdtoui32, cvtftoui64, cvtdtoui64
1671 IceString TargetString = "cvt" + SrcSubstring + "toui" + DstSubstring;
1672 // TODO: Call the correct compiler-rt helper function.
1673 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs);
1674 Call->addArg(Inst->getSrc(0));
1675 lowerCall(Call);
1676 return;
1677 } else {
Jan Voung1ee34162014-06-24 13:43:30 -07001678 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001679 // t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type
1680 Variable *T_1 = makeReg(IceType_i32);
1681 Variable *T_2 = makeReg(Dest->getType());
1682 _cvt(T_1, Src0RM);
1683 _mov(T_2, T_1); // T_1 and T_2 may have different integer types
1684 _mov(Dest, T_2);
1685 T_2->setPreferredRegister(T_1, true);
1686 }
1687 break;
1688 case InstCast::Sitofp:
Jan Voung1ee34162014-06-24 13:43:30 -07001689 if (Inst->getSrc(0)->getType() == IceType_i64) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001690 // Use a helper for x86-32.
1691 const SizeT MaxSrcs = 1;
1692 Type DestType = Dest->getType();
1693 InstCall *Call = makeHelperCall(
1694 DestType == IceType_f32 ? "cvtsi64tof" : "cvtsi64tod", Dest, MaxSrcs);
1695 // TODO: Call the correct compiler-rt helper function.
1696 Call->addArg(Inst->getSrc(0));
1697 lowerCall(Call);
1698 return;
1699 } else {
Jan Voung1ee34162014-06-24 13:43:30 -07001700 Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001701 // Sign-extend the operand.
1702 // t1.i32 = movsx Src0RM; t2 = Cvt t1.i32; Dest = t2
1703 Variable *T_1 = makeReg(IceType_i32);
1704 Variable *T_2 = makeReg(Dest->getType());
1705 if (Src0RM->getType() == IceType_i32)
1706 _mov(T_1, Src0RM);
1707 else
1708 _movsx(T_1, Src0RM);
1709 _cvt(T_2, T_1);
1710 _mov(Dest, T_2);
1711 }
1712 break;
Jan Voung1ee34162014-06-24 13:43:30 -07001713 case InstCast::Uitofp: {
1714 Operand *Src0 = Inst->getSrc(0);
1715 if (Src0->getType() == IceType_i64 || Src0->getType() == IceType_i32) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001716 // Use a helper for x86-32 and x86-64. Also use a helper for
1717 // i32 on x86-32.
1718 const SizeT MaxSrcs = 1;
1719 Type DestType = Dest->getType();
Jan Voung1ee34162014-06-24 13:43:30 -07001720 IceString SrcSubstring = (Src0->getType() == IceType_i64 ? "64" : "32");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001721 IceString DstSubstring = (DestType == IceType_f32 ? "f" : "d");
1722 // Possibilities are cvtui32tof, cvtui32tod, cvtui64tof, cvtui64tod
1723 IceString TargetString = "cvtui" + SrcSubstring + "to" + DstSubstring;
1724 // TODO: Call the correct compiler-rt helper function.
1725 InstCall *Call = makeHelperCall(TargetString, Dest, MaxSrcs);
Jan Voung1ee34162014-06-24 13:43:30 -07001726 Call->addArg(Src0);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001727 lowerCall(Call);
1728 return;
1729 } else {
Jan Voung1ee34162014-06-24 13:43:30 -07001730 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001731 // Zero-extend the operand.
1732 // t1.i32 = movzx Src0RM; t2 = Cvt t1.i32; Dest = t2
1733 Variable *T_1 = makeReg(IceType_i32);
1734 Variable *T_2 = makeReg(Dest->getType());
1735 if (Src0RM->getType() == IceType_i32)
1736 _mov(T_1, Src0RM);
1737 else
1738 _movzx(T_1, Src0RM);
1739 _cvt(T_2, T_1);
1740 _mov(Dest, T_2);
1741 }
1742 break;
Jan Voung1ee34162014-06-24 13:43:30 -07001743 }
1744 case InstCast::Bitcast: {
1745 Operand *Src0 = Inst->getSrc(0);
1746 if (Dest->getType() == Src0->getType()) {
1747 InstAssign *Assign = InstAssign::create(Func, Dest, Src0);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001748 lowerAssign(Assign);
1749 return;
1750 }
1751 switch (Dest->getType()) {
1752 default:
1753 llvm_unreachable("Unexpected Bitcast dest type");
1754 case IceType_i32:
1755 case IceType_f32: {
Jan Voung1ee34162014-06-24 13:43:30 -07001756 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001757 Type DestType = Dest->getType();
1758 Type SrcType = Src0RM->getType();
1759 assert((DestType == IceType_i32 && SrcType == IceType_f32) ||
1760 (DestType == IceType_f32 && SrcType == IceType_i32));
1761 // a.i32 = bitcast b.f32 ==>
1762 // t.f32 = b.f32
1763 // s.f32 = spill t.f32
1764 // a.i32 = s.f32
1765 Variable *T = NULL;
1766 // TODO: Should be able to force a spill setup by calling legalize() with
1767 // Legal_Mem and not Legal_Reg or Legal_Imm.
1768 Variable *Spill = Func->makeVariable(SrcType, Context.getNode());
1769 Spill->setWeight(RegWeight::Zero);
1770 Spill->setPreferredRegister(Dest, true);
1771 _mov(T, Src0RM);
1772 _mov(Spill, T);
1773 _mov(Dest, Spill);
1774 } break;
1775 case IceType_i64: {
Jan Voung1ee34162014-06-24 13:43:30 -07001776 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001777 assert(Src0RM->getType() == IceType_f64);
1778 // a.i64 = bitcast b.f64 ==>
1779 // s.f64 = spill b.f64
1780 // t_lo.i32 = lo(s.f64)
1781 // a_lo.i32 = t_lo.i32
1782 // t_hi.i32 = hi(s.f64)
1783 // a_hi.i32 = t_hi.i32
1784 Variable *Spill = Func->makeVariable(IceType_f64, Context.getNode());
1785 Spill->setWeight(RegWeight::Zero);
1786 Spill->setPreferredRegister(llvm::dyn_cast<Variable>(Src0RM), true);
Jan Voung5cd240d2014-06-25 10:36:46 -07001787 _movq(Spill, Src0RM);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001788
1789 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
1790 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
1791 Variable *T_Lo = makeReg(IceType_i32);
1792 Variable *T_Hi = makeReg(IceType_i32);
1793 VariableSplit *SpillLo =
1794 VariableSplit::create(Func, Spill, VariableSplit::Low);
1795 VariableSplit *SpillHi =
1796 VariableSplit::create(Func, Spill, VariableSplit::High);
1797
1798 _mov(T_Lo, SpillLo);
1799 _mov(DestLo, T_Lo);
1800 _mov(T_Hi, SpillHi);
1801 _mov(DestHi, T_Hi);
1802 } break;
1803 case IceType_f64: {
Jan Voung1ee34162014-06-24 13:43:30 -07001804 Src0 = legalize(Src0);
1805 assert(Src0->getType() == IceType_i64);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001806 // a.f64 = bitcast b.i64 ==>
1807 // t_lo.i32 = b_lo.i32
Jan Voung1ee34162014-06-24 13:43:30 -07001808 // FakeDef(s.f64)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001809 // lo(s.f64) = t_lo.i32
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001810 // t_hi.i32 = b_hi.i32
1811 // hi(s.f64) = t_hi.i32
1812 // a.f64 = s.f64
1813 Variable *Spill = Func->makeVariable(IceType_f64, Context.getNode());
1814 Spill->setWeight(RegWeight::Zero);
1815 Spill->setPreferredRegister(Dest, true);
1816
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001817 Variable *T_Lo = NULL, *T_Hi = NULL;
1818 VariableSplit *SpillLo =
1819 VariableSplit::create(Func, Spill, VariableSplit::Low);
1820 VariableSplit *SpillHi =
1821 VariableSplit::create(Func, Spill, VariableSplit::High);
Jan Voung1ee34162014-06-24 13:43:30 -07001822 _mov(T_Lo, loOperand(Src0));
1823 // Technically, the Spill is defined after the _store happens, but
1824 // SpillLo is considered a "use" of Spill so define Spill before it
1825 // is used.
1826 Context.insert(InstFakeDef::create(Func, Spill));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001827 _store(T_Lo, SpillLo);
Jan Voung1ee34162014-06-24 13:43:30 -07001828 _mov(T_Hi, hiOperand(Src0));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001829 _store(T_Hi, SpillHi);
Jan Voung5cd240d2014-06-25 10:36:46 -07001830 _movq(Dest, Spill);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001831 } break;
1832 }
1833 break;
1834 }
Jan Voung1ee34162014-06-24 13:43:30 -07001835 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001836}
1837
1838void TargetX8632::lowerFcmp(const InstFcmp *Inst) {
1839 Operand *Src0 = Inst->getSrc(0);
1840 Operand *Src1 = Inst->getSrc(1);
1841 Variable *Dest = Inst->getDest();
1842 // Lowering a = fcmp cond, b, c
1843 // ucomiss b, c /* only if C1 != Br_None */
1844 // /* but swap b,c order if SwapOperands==true */
1845 // mov a, <default>
1846 // j<C1> label /* only if C1 != Br_None */
1847 // j<C2> label /* only if C2 != Br_None */
1848 // FakeUse(a) /* only if C1 != Br_None */
1849 // mov a, !<default> /* only if C1 != Br_None */
1850 // label: /* only if C1 != Br_None */
1851 InstFcmp::FCond Condition = Inst->getCondition();
1852 size_t Index = static_cast<size_t>(Condition);
1853 assert(Index < TableFcmpSize);
1854 if (TableFcmp[Index].SwapOperands) {
1855 Operand *Tmp = Src0;
1856 Src0 = Src1;
1857 Src1 = Tmp;
1858 }
1859 bool HasC1 = (TableFcmp[Index].C1 != InstX8632Br::Br_None);
1860 bool HasC2 = (TableFcmp[Index].C2 != InstX8632Br::Br_None);
1861 if (HasC1) {
1862 Src0 = legalize(Src0);
1863 Operand *Src1RM = legalize(Src1, Legal_Reg | Legal_Mem);
1864 Variable *T = NULL;
1865 _mov(T, Src0);
1866 _ucomiss(T, Src1RM);
1867 }
1868 Constant *Default =
1869 Ctx->getConstantInt(IceType_i32, TableFcmp[Index].Default);
1870 _mov(Dest, Default);
1871 if (HasC1) {
1872 InstX8632Label *Label = InstX8632Label::create(Func, this);
1873 _br(TableFcmp[Index].C1, Label);
1874 if (HasC2) {
1875 _br(TableFcmp[Index].C2, Label);
1876 }
1877 Context.insert(InstFakeUse::create(Func, Dest));
1878 Constant *NonDefault =
1879 Ctx->getConstantInt(IceType_i32, !TableFcmp[Index].Default);
1880 _mov(Dest, NonDefault);
1881 Context.insert(Label);
1882 }
1883}
1884
1885void TargetX8632::lowerIcmp(const InstIcmp *Inst) {
1886 Operand *Src0 = legalize(Inst->getSrc(0));
1887 Operand *Src1 = legalize(Inst->getSrc(1));
1888 Variable *Dest = Inst->getDest();
1889
Jim Stichnothd97c7df2014-06-04 11:57:08 -07001890 // If Src1 is an immediate, or known to be a physical register, we can
1891 // allow Src0 to be a memory operand. Otherwise, Src0 must be copied into
1892 // a physical register. (Actually, either Src0 or Src1 can be chosen for
1893 // the physical register, but unfortunately we have to commit to one or
1894 // the other before register allocation.)
1895 bool IsSrc1ImmOrReg = false;
1896 if (llvm::isa<Constant>(Src1)) {
1897 IsSrc1ImmOrReg = true;
1898 } else if (Variable *Var = llvm::dyn_cast<Variable>(Src1)) {
1899 if (Var->hasReg())
1900 IsSrc1ImmOrReg = true;
1901 }
1902
1903 // Try to fuse a compare immediately followed by a conditional branch. This
1904 // is possible when the compare dest and the branch source operands are the
1905 // same, and are their only uses. TODO: implement this optimization for i64.
1906 if (InstBr *NextBr = llvm::dyn_cast_or_null<InstBr>(Context.getNextInst())) {
1907 if (Src0->getType() != IceType_i64 && !NextBr->isUnconditional() &&
1908 Dest == NextBr->getSrc(0) && NextBr->isLastUse(Dest)) {
1909 Operand *Src0New =
1910 legalize(Src0, IsSrc1ImmOrReg ? Legal_All : Legal_Reg, true);
1911 _cmp(Src0New, Src1);
1912 _br(getIcmp32Mapping(Inst->getCondition()), NextBr->getTargetTrue(),
1913 NextBr->getTargetFalse());
1914 // Skip over the following branch instruction.
1915 NextBr->setDeleted();
1916 Context.advanceNext();
1917 return;
1918 }
1919 }
1920
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001921 // a=icmp cond, b, c ==> cmp b,c; a=1; br cond,L1; FakeUse(a); a=0; L1:
Matt Wala43ff7eb2014-06-18 10:30:07 -07001922 Constant *Zero = Ctx->getConstantZero(IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001923 Constant *One = Ctx->getConstantInt(IceType_i32, 1);
1924 if (Src0->getType() == IceType_i64) {
1925 InstIcmp::ICond Condition = Inst->getCondition();
1926 size_t Index = static_cast<size_t>(Condition);
1927 assert(Index < TableIcmp64Size);
1928 Operand *Src1LoRI = legalize(loOperand(Src1), Legal_Reg | Legal_Imm);
1929 Operand *Src1HiRI = legalize(hiOperand(Src1), Legal_Reg | Legal_Imm);
1930 if (Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) {
1931 InstX8632Label *Label = InstX8632Label::create(Func, this);
1932 _mov(Dest, (Condition == InstIcmp::Eq ? Zero : One));
1933 _cmp(loOperand(Src0), Src1LoRI);
1934 _br(InstX8632Br::Br_ne, Label);
1935 _cmp(hiOperand(Src0), Src1HiRI);
1936 _br(InstX8632Br::Br_ne, Label);
1937 Context.insert(InstFakeUse::create(Func, Dest));
1938 _mov(Dest, (Condition == InstIcmp::Eq ? One : Zero));
1939 Context.insert(Label);
1940 } else {
1941 InstX8632Label *LabelFalse = InstX8632Label::create(Func, this);
1942 InstX8632Label *LabelTrue = InstX8632Label::create(Func, this);
1943 _mov(Dest, One);
1944 _cmp(hiOperand(Src0), Src1HiRI);
1945 _br(TableIcmp64[Index].C1, LabelTrue);
1946 _br(TableIcmp64[Index].C2, LabelFalse);
1947 _cmp(loOperand(Src0), Src1LoRI);
1948 _br(TableIcmp64[Index].C3, LabelTrue);
1949 Context.insert(LabelFalse);
1950 Context.insert(InstFakeUse::create(Func, Dest));
1951 _mov(Dest, Zero);
1952 Context.insert(LabelTrue);
1953 }
1954 return;
1955 }
1956
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001957 // cmp b, c
1958 Operand *Src0New =
1959 legalize(Src0, IsSrc1ImmOrReg ? Legal_All : Legal_Reg, true);
1960 InstX8632Label *Label = InstX8632Label::create(Func, this);
1961 _cmp(Src0New, Src1);
1962 _mov(Dest, One);
1963 _br(getIcmp32Mapping(Inst->getCondition()), Label);
1964 Context.insert(InstFakeUse::create(Func, Dest));
1965 _mov(Dest, Zero);
1966 Context.insert(Label);
1967}
1968
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001969void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
1970 switch (Instr->getIntrinsicInfo().ID) {
1971 case Intrinsics::AtomicCmpxchg:
Jan Voung5cd240d2014-06-25 10:36:46 -07001972 if (!Intrinsics::VerifyMemoryOrder(
1973 llvm::cast<ConstantInteger>(Instr->getArg(3))->getValue())) {
1974 Func->setError("Unexpected memory ordering (success) for AtomicCmpxchg");
1975 return;
1976 }
1977 if (!Intrinsics::VerifyMemoryOrder(
1978 llvm::cast<ConstantInteger>(Instr->getArg(4))->getValue())) {
1979 Func->setError("Unexpected memory ordering (failure) for AtomicCmpxchg");
1980 return;
1981 }
1982 // TODO(jvoung): fill it in.
1983 Func->setError("Unhandled intrinsic");
1984 return;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001985 case Intrinsics::AtomicFence:
Jan Voung5cd240d2014-06-25 10:36:46 -07001986 if (!Intrinsics::VerifyMemoryOrder(
1987 llvm::cast<ConstantInteger>(Instr->getArg(0))->getValue())) {
1988 Func->setError("Unexpected memory ordering for AtomicFence");
1989 return;
1990 }
1991 _mfence();
1992 return;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07001993 case Intrinsics::AtomicFenceAll:
Jan Voung5cd240d2014-06-25 10:36:46 -07001994 // NOTE: FenceAll should prevent and load/store from being moved
1995 // across the fence (both atomic and non-atomic). The InstX8632Mfence
1996 // instruction is currently marked coarsely as "HasSideEffects".
1997 _mfence();
1998 return;
1999 case Intrinsics::AtomicIsLockFree: {
2000 // X86 is always lock free for 8/16/32/64 bit accesses.
2001 // TODO(jvoung): Since the result is constant when given a constant
2002 // byte size, this opens up DCE opportunities.
2003 Operand *ByteSize = Instr->getArg(0);
2004 Variable *Dest = Instr->getDest();
2005 if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(ByteSize)) {
2006 Constant *Result;
2007 switch (CI->getValue()) {
2008 default:
2009 // Some x86-64 processors support the cmpxchg16b intruction, which
2010 // can make 16-byte operations lock free (when used with the LOCK
2011 // prefix). However, that's not supported in 32-bit mode, so just
2012 // return 0 even for large sizes.
2013 Result = Ctx->getConstantZero(IceType_i32);
2014 break;
2015 case 1:
2016 case 2:
2017 case 4:
2018 case 8:
2019 Result = Ctx->getConstantInt(IceType_i32, 1);
2020 break;
2021 }
2022 _mov(Dest, Result);
2023 return;
2024 }
2025 // The PNaCl ABI requires the byte size to be a compile-time constant.
2026 Func->setError("AtomicIsLockFree byte size should be compile-time const");
2027 return;
2028 }
2029 case Intrinsics::AtomicLoad: {
2030 // We require the memory address to be naturally aligned.
2031 // Given that is the case, then normal loads are atomic.
2032 if (!Intrinsics::VerifyMemoryOrder(
2033 llvm::cast<ConstantInteger>(Instr->getArg(1))->getValue())) {
2034 Func->setError("Unexpected memory ordering for AtomicLoad");
2035 return;
2036 }
2037 Variable *Dest = Instr->getDest();
2038 if (Dest->getType() == IceType_i64) {
2039 // Follow what GCC does and use a movq instead of what lowerLoad()
2040 // normally does (split the load into two).
2041 // Thus, this skips load/arithmetic op folding. Load/arithmetic folding
2042 // can't happen anyway, since this is x86-32 and integer arithmetic only
2043 // happens on 32-bit quantities.
2044 Variable *T = makeReg(IceType_f64);
2045 OperandX8632Mem *Addr = FormMemoryOperand(Instr->getArg(0), IceType_f64);
2046 _movq(T, Addr);
2047 // Then cast the bits back out of the XMM register to the i64 Dest.
2048 InstCast *Cast = InstCast::create(Func, InstCast::Bitcast, Dest, T);
2049 lowerCast(Cast);
2050 // Make sure that the atomic load isn't elided.
2051 Context.insert(InstFakeUse::create(Func, Dest->getLo()));
2052 Context.insert(InstFakeUse::create(Func, Dest->getHi()));
2053 return;
2054 }
2055 InstLoad *Load = InstLoad::create(Func, Dest, Instr->getArg(0));
2056 lowerLoad(Load);
2057 // Make sure the atomic load isn't elided.
2058 Context.insert(InstFakeUse::create(Func, Dest));
2059 return;
2060 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002061 case Intrinsics::AtomicRMW:
Jan Voung5cd240d2014-06-25 10:36:46 -07002062 if (!Intrinsics::VerifyMemoryOrder(
2063 llvm::cast<ConstantInteger>(Instr->getArg(3))->getValue())) {
2064 Func->setError("Unexpected memory ordering for AtomicRMW");
2065 return;
2066 }
2067 lowerAtomicRMW(Instr->getDest(),
2068 static_cast<uint32_t>(llvm::cast<ConstantInteger>(
2069 Instr->getArg(0))->getValue()),
2070 Instr->getArg(1), Instr->getArg(2));
2071 return;
2072 case Intrinsics::AtomicStore: {
2073 if (!Intrinsics::VerifyMemoryOrder(
2074 llvm::cast<ConstantInteger>(Instr->getArg(2))->getValue())) {
2075 Func->setError("Unexpected memory ordering for AtomicStore");
2076 return;
2077 }
2078 // We require the memory address to be naturally aligned.
2079 // Given that is the case, then normal stores are atomic.
2080 // Add a fence after the store to make it visible.
2081 Operand *Value = Instr->getArg(0);
2082 Operand *Ptr = Instr->getArg(1);
2083 if (Value->getType() == IceType_i64) {
2084 // Use a movq instead of what lowerStore() normally does
2085 // (split the store into two), following what GCC does.
2086 // Cast the bits from int -> to an xmm register first.
2087 Variable *T = makeReg(IceType_f64);
2088 InstCast *Cast = InstCast::create(Func, InstCast::Bitcast, T, Value);
2089 lowerCast(Cast);
2090 // Then store XMM w/ a movq.
2091 OperandX8632Mem *Addr = FormMemoryOperand(Ptr, IceType_f64);
2092 _storeq(T, Addr);
2093 _mfence();
2094 return;
2095 }
2096 InstStore *Store = InstStore::create(Func, Value, Ptr);
2097 lowerStore(Store);
2098 _mfence();
2099 return;
2100 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002101 case Intrinsics::Bswap:
2102 case Intrinsics::Ctlz:
2103 case Intrinsics::Ctpop:
2104 case Intrinsics::Cttz:
Jan Voung5cd240d2014-06-25 10:36:46 -07002105 // TODO(jvoung): fill it in.
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002106 Func->setError("Unhandled intrinsic");
2107 return;
2108 case Intrinsics::Longjmp: {
2109 InstCall *Call = makeHelperCall("longjmp", NULL, 2);
2110 Call->addArg(Instr->getArg(0));
2111 Call->addArg(Instr->getArg(1));
2112 lowerCall(Call);
Jan Voung5cd240d2014-06-25 10:36:46 -07002113 return;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002114 }
2115 case Intrinsics::Memcpy: {
2116 // In the future, we could potentially emit an inline memcpy/memset, etc.
2117 // for intrinsic calls w/ a known length.
2118 InstCall *Call = makeHelperCall("memcpy", NULL, 3);
2119 Call->addArg(Instr->getArg(0));
2120 Call->addArg(Instr->getArg(1));
2121 Call->addArg(Instr->getArg(2));
2122 lowerCall(Call);
Jan Voung5cd240d2014-06-25 10:36:46 -07002123 return;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002124 }
2125 case Intrinsics::Memmove: {
2126 InstCall *Call = makeHelperCall("memmove", NULL, 3);
2127 Call->addArg(Instr->getArg(0));
2128 Call->addArg(Instr->getArg(1));
2129 Call->addArg(Instr->getArg(2));
2130 lowerCall(Call);
Jan Voung5cd240d2014-06-25 10:36:46 -07002131 return;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002132 }
2133 case Intrinsics::Memset: {
2134 // The value operand needs to be extended to a stack slot size
2135 // because we "push" only works for a specific operand size.
2136 Operand *ValOp = Instr->getArg(1);
2137 assert(ValOp->getType() == IceType_i8);
2138 Variable *ValExt = makeReg(stackSlotType());
2139 _movzx(ValExt, ValOp);
2140 InstCall *Call = makeHelperCall("memset", NULL, 3);
2141 Call->addArg(Instr->getArg(0));
2142 Call->addArg(ValExt);
2143 Call->addArg(Instr->getArg(2));
2144 lowerCall(Call);
Jan Voung5cd240d2014-06-25 10:36:46 -07002145 return;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002146 }
2147 case Intrinsics::NaClReadTP: {
Jan Voung5cd240d2014-06-25 10:36:46 -07002148 Constant *Zero = Ctx->getConstantZero(IceType_i32);
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002149 Operand *Src = OperandX8632Mem::create(Func, IceType_i32, NULL, Zero, NULL,
2150 0, OperandX8632Mem::SegReg_GS);
2151 Variable *Dest = Instr->getDest();
2152 Variable *T = NULL;
2153 _mov(T, Src);
2154 _mov(Dest, T);
Jan Voung5cd240d2014-06-25 10:36:46 -07002155 return;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002156 }
2157 case Intrinsics::Setjmp: {
2158 InstCall *Call = makeHelperCall("setjmp", Instr->getDest(), 1);
2159 Call->addArg(Instr->getArg(0));
2160 lowerCall(Call);
Jan Voung5cd240d2014-06-25 10:36:46 -07002161 return;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002162 }
Jan Voungf37fbbe2014-07-09 16:13:13 -07002163 case Intrinsics::Sqrt: {
2164 Operand *Src = legalize(Instr->getArg(0));
2165 Variable *Dest = Instr->getDest();
2166 Variable *T = makeReg(Dest->getType());
2167 _sqrtss(T, Src);
2168 _mov(Dest, T);
2169 return;
2170 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002171 case Intrinsics::Stacksave:
2172 case Intrinsics::Stackrestore:
Jan Voung5cd240d2014-06-25 10:36:46 -07002173 // TODO(jvoung): fill it in.
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002174 Func->setError("Unhandled intrinsic");
2175 return;
2176 case Intrinsics::Trap:
2177 _ud2();
Jan Voung5cd240d2014-06-25 10:36:46 -07002178 return;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002179 case Intrinsics::UnknownIntrinsic:
2180 Func->setError("Should not be lowering UnknownIntrinsic");
2181 return;
2182 }
2183 return;
2184}
2185
Jan Voung5cd240d2014-06-25 10:36:46 -07002186void TargetX8632::lowerAtomicRMW(Variable *Dest, uint32_t Operation,
2187 Operand *Ptr, Operand *Val) {
2188 switch (Operation) {
2189 default:
2190 Func->setError("Unknown AtomicRMW operation");
2191 return;
2192 case Intrinsics::AtomicAdd: {
2193 if (Dest->getType() == IceType_i64) {
2194 // Do a nasty cmpxchg8b loop. Factor this into a function.
2195 // TODO(jvoung): fill it in.
2196 Func->setError("Unhandled AtomicRMW operation");
2197 return;
2198 }
2199 OperandX8632Mem *Addr = FormMemoryOperand(Ptr, Dest->getType());
2200 const bool Locked = true;
2201 Variable *T = NULL;
2202 _mov(T, Val);
2203 _xadd(Addr, T, Locked);
2204 _mov(Dest, T);
2205 return;
2206 }
2207 case Intrinsics::AtomicSub: {
2208 if (Dest->getType() == IceType_i64) {
2209 // Do a nasty cmpxchg8b loop.
2210 // TODO(jvoung): fill it in.
2211 Func->setError("Unhandled AtomicRMW operation");
2212 return;
2213 }
2214 // Generate a memory operand from Ptr.
2215 // neg...
2216 // Then do the same as AtomicAdd.
2217 // TODO(jvoung): fill it in.
2218 Func->setError("Unhandled AtomicRMW operation");
2219 return;
2220 }
2221 case Intrinsics::AtomicOr:
2222 case Intrinsics::AtomicAnd:
2223 case Intrinsics::AtomicXor:
2224 case Intrinsics::AtomicExchange:
2225 // TODO(jvoung): fill it in.
2226 Func->setError("Unhandled AtomicRMW operation");
2227 return;
2228 }
2229}
2230
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002231namespace {
2232
2233bool isAdd(const Inst *Inst) {
2234 if (const InstArithmetic *Arith =
2235 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) {
2236 return (Arith->getOp() == InstArithmetic::Add);
2237 }
2238 return false;
2239}
2240
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002241void computeAddressOpt(Variable *&Base, Variable *&Index, uint16_t &Shift,
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002242 int32_t &Offset) {
2243 (void)Offset; // TODO: pattern-match for non-zero offsets.
2244 if (Base == NULL)
2245 return;
2246 // If the Base has more than one use or is live across multiple
2247 // blocks, then don't go further. Alternatively (?), never consider
2248 // a transformation that would change a variable that is currently
2249 // *not* live across basic block boundaries into one that *is*.
2250 if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/)
2251 return;
2252
2253 while (true) {
2254 // Base is Base=Var ==>
2255 // set Base=Var
2256 const Inst *BaseInst = Base->getDefinition();
2257 Operand *BaseOperand0 = BaseInst ? BaseInst->getSrc(0) : NULL;
2258 Variable *BaseVariable0 = llvm::dyn_cast_or_null<Variable>(BaseOperand0);
2259 // TODO: Helper function for all instances of assignment
2260 // transitivity.
2261 if (BaseInst && llvm::isa<InstAssign>(BaseInst) && BaseVariable0 &&
2262 // TODO: ensure BaseVariable0 stays single-BB
2263 true) {
2264 Base = BaseVariable0;
2265 continue;
2266 }
2267
2268 // Index is Index=Var ==>
2269 // set Index=Var
2270
2271 // Index==NULL && Base is Base=Var1+Var2 ==>
2272 // set Base=Var1, Index=Var2, Shift=0
2273 Operand *BaseOperand1 =
2274 BaseInst && BaseInst->getSrcSize() >= 2 ? BaseInst->getSrc(1) : NULL;
2275 Variable *BaseVariable1 = llvm::dyn_cast_or_null<Variable>(BaseOperand1);
2276 if (Index == NULL && isAdd(BaseInst) && BaseVariable0 && BaseVariable1 &&
2277 // TODO: ensure BaseVariable0 and BaseVariable1 stay single-BB
2278 true) {
2279 Base = BaseVariable0;
2280 Index = BaseVariable1;
2281 Shift = 0; // should already have been 0
2282 continue;
2283 }
2284
2285 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==>
2286 // Index=Var, Shift+=log2(Const)
2287 const Inst *IndexInst = Index ? Index->getDefinition() : NULL;
2288 if (const InstArithmetic *ArithInst =
2289 llvm::dyn_cast_or_null<InstArithmetic>(IndexInst)) {
2290 Operand *IndexOperand0 = ArithInst->getSrc(0);
2291 Variable *IndexVariable0 = llvm::dyn_cast<Variable>(IndexOperand0);
2292 Operand *IndexOperand1 = ArithInst->getSrc(1);
2293 ConstantInteger *IndexConstant1 =
2294 llvm::dyn_cast<ConstantInteger>(IndexOperand1);
2295 if (ArithInst->getOp() == InstArithmetic::Mul && IndexVariable0 &&
2296 IndexOperand1->getType() == IceType_i32 && IndexConstant1) {
2297 uint64_t Mult = IndexConstant1->getValue();
2298 uint32_t LogMult;
2299 switch (Mult) {
2300 case 1:
2301 LogMult = 0;
2302 break;
2303 case 2:
2304 LogMult = 1;
2305 break;
2306 case 4:
2307 LogMult = 2;
2308 break;
2309 case 8:
2310 LogMult = 3;
2311 break;
2312 default:
2313 LogMult = 4;
2314 break;
2315 }
2316 if (Shift + LogMult <= 3) {
2317 Index = IndexVariable0;
2318 Shift += LogMult;
2319 continue;
2320 }
2321 }
2322 }
2323
2324 // Index is Index=Var<<Const && Const+Shift<=3 ==>
2325 // Index=Var, Shift+=Const
2326
2327 // Index is Index=Const*Var && log2(Const)+Shift<=3 ==>
2328 // Index=Var, Shift+=log2(Const)
2329
2330 // Index && Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==>
2331 // swap(Index,Base)
2332 // Similar for Base=Const*Var and Base=Var<<Const
2333
2334 // Base is Base=Var+Const ==>
2335 // set Base=Var, Offset+=Const
2336
2337 // Base is Base=Const+Var ==>
2338 // set Base=Var, Offset+=Const
2339
2340 // Base is Base=Var-Const ==>
2341 // set Base=Var, Offset-=Const
2342
2343 // Index is Index=Var+Const ==>
2344 // set Index=Var, Offset+=(Const<<Shift)
2345
2346 // Index is Index=Const+Var ==>
2347 // set Index=Var, Offset+=(Const<<Shift)
2348
2349 // Index is Index=Var-Const ==>
2350 // set Index=Var, Offset-=(Const<<Shift)
2351
2352 // TODO: consider overflow issues with respect to Offset.
2353 // TODO: handle symbolic constants.
2354 break;
2355 }
2356}
2357
2358} // anonymous namespace
2359
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002360void TargetX8632::lowerLoad(const InstLoad *Inst) {
2361 // A Load instruction can be treated the same as an Assign
2362 // instruction, after the source operand is transformed into an
2363 // OperandX8632Mem operand. Note that the address mode
2364 // optimization already creates an OperandX8632Mem operand, so it
2365 // doesn't need another level of transformation.
2366 Type Ty = Inst->getDest()->getType();
Jan Voung5cd240d2014-06-25 10:36:46 -07002367 Operand *Src0 = FormMemoryOperand(Inst->getSourceAddress(), Ty);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002368
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002369 // Fuse this load with a subsequent Arithmetic instruction in the
2370 // following situations:
2371 // a=[mem]; c=b+a ==> c=b+[mem] if last use of a and a not in b
2372 // a=[mem]; c=a+b ==> c=b+[mem] if commutative and above is true
2373 //
2374 // TODO: Clean up and test thoroughly.
Jan Voung5cd240d2014-06-25 10:36:46 -07002375 // (E.g., if there is an mfence-all make sure the load ends up on the
2376 // same side of the fence).
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002377 //
2378 // TODO: Why limit to Arithmetic instructions? This could probably be
2379 // applied to most any instruction type. Look at all source operands
2380 // in the following instruction, and if there is one instance of the
2381 // load instruction's dest variable, and that instruction ends that
2382 // variable's live range, then make the substitution. Deal with
2383 // commutativity optimization in the arithmetic instruction lowering.
2384 InstArithmetic *NewArith = NULL;
2385 if (InstArithmetic *Arith =
2386 llvm::dyn_cast_or_null<InstArithmetic>(Context.getNextInst())) {
2387 Variable *DestLoad = Inst->getDest();
2388 Variable *Src0Arith = llvm::dyn_cast<Variable>(Arith->getSrc(0));
2389 Variable *Src1Arith = llvm::dyn_cast<Variable>(Arith->getSrc(1));
2390 if (Src1Arith == DestLoad && Arith->isLastUse(Src1Arith) &&
2391 DestLoad != Src0Arith) {
2392 NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(),
2393 Arith->getSrc(0), Src0);
2394 } else if (Src0Arith == DestLoad && Arith->isCommutative() &&
2395 Arith->isLastUse(Src0Arith) && DestLoad != Src1Arith) {
2396 NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(),
2397 Arith->getSrc(1), Src0);
2398 }
2399 if (NewArith) {
2400 Arith->setDeleted();
2401 Context.advanceNext();
2402 lowerArithmetic(NewArith);
2403 return;
2404 }
2405 }
2406
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002407 InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0);
2408 lowerAssign(Assign);
2409}
2410
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002411void TargetX8632::doAddressOptLoad() {
2412 Inst *Inst = *Context.getCur();
2413 Variable *Dest = Inst->getDest();
2414 Operand *Addr = Inst->getSrc(0);
2415 Variable *Index = NULL;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002416 uint16_t Shift = 0;
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002417 int32_t Offset = 0; // TODO: make Constant
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002418 // Vanilla ICE load instructions should not use the segment registers,
2419 // and computeAddressOpt only works at the level of Variables and Constants,
2420 // not other OperandX8632Mem, so there should be no mention of segment
2421 // registers there either.
2422 const OperandX8632Mem::SegmentRegisters SegmentReg =
2423 OperandX8632Mem::DefaultSegment;
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002424 Variable *Base = llvm::dyn_cast<Variable>(Addr);
2425 computeAddressOpt(Base, Index, Shift, Offset);
2426 if (Base && Addr != Base) {
2427 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset);
2428 Addr = OperandX8632Mem::create(Func, Dest->getType(), Base, OffsetOp, Index,
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002429 Shift, SegmentReg);
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002430 Inst->setDeleted();
2431 Context.insert(InstLoad::create(Func, Dest, Addr));
2432 }
2433}
2434
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002435void TargetX8632::lowerPhi(const InstPhi * /*Inst*/) {
2436 Func->setError("Phi found in regular instruction list");
2437}
2438
2439void TargetX8632::lowerRet(const InstRet *Inst) {
2440 Variable *Reg = NULL;
2441 if (Inst->hasRetValue()) {
2442 Operand *Src0 = legalize(Inst->getRetValue());
2443 if (Src0->getType() == IceType_i64) {
2444 Variable *eax = legalizeToVar(loOperand(Src0), false, Reg_eax);
2445 Variable *edx = legalizeToVar(hiOperand(Src0), false, Reg_edx);
2446 Reg = eax;
2447 Context.insert(InstFakeUse::create(Func, edx));
2448 } else if (Src0->getType() == IceType_f32 ||
2449 Src0->getType() == IceType_f64) {
2450 _fld(Src0);
Matt Wala928f1292014-07-07 16:50:46 -07002451 } else if (isVectorType(Src0->getType())) {
2452 Reg = legalizeToVar(Src0, false, Reg_xmm0);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002453 } else {
2454 _mov(Reg, Src0, Reg_eax);
2455 }
2456 }
2457 _ret(Reg);
2458 // Add a fake use of esp to make sure esp stays alive for the entire
2459 // function. Otherwise post-call esp adjustments get dead-code
2460 // eliminated. TODO: Are there more places where the fake use
2461 // should be inserted? E.g. "void f(int n){while(1) g(n);}" may not
2462 // have a ret instruction.
2463 Variable *esp = Func->getTarget()->getPhysicalRegister(Reg_esp);
2464 Context.insert(InstFakeUse::create(Func, esp));
2465}
2466
2467void TargetX8632::lowerSelect(const InstSelect *Inst) {
2468 // a=d?b:c ==> cmp d,0; a=b; jne L1; FakeUse(a); a=c; L1:
2469 Variable *Dest = Inst->getDest();
2470 Operand *SrcT = Inst->getTrueOperand();
2471 Operand *SrcF = Inst->getFalseOperand();
2472 Operand *Condition = legalize(Inst->getCondition());
Matt Wala43ff7eb2014-06-18 10:30:07 -07002473 Constant *Zero = Ctx->getConstantZero(IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002474 InstX8632Label *Label = InstX8632Label::create(Func, this);
2475
2476 if (Dest->getType() == IceType_i64) {
2477 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
2478 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
2479 Operand *SrcLoRI = legalize(loOperand(SrcT), Legal_Reg | Legal_Imm, true);
2480 Operand *SrcHiRI = legalize(hiOperand(SrcT), Legal_Reg | Legal_Imm, true);
2481 _cmp(Condition, Zero);
2482 _mov(DestLo, SrcLoRI);
2483 _mov(DestHi, SrcHiRI);
2484 _br(InstX8632Br::Br_ne, Label);
2485 Context.insert(InstFakeUse::create(Func, DestLo));
2486 Context.insert(InstFakeUse::create(Func, DestHi));
2487 Operand *SrcFLo = loOperand(SrcF);
2488 Operand *SrcFHi = hiOperand(SrcF);
2489 SrcLoRI = legalize(SrcFLo, Legal_Reg | Legal_Imm, true);
2490 SrcHiRI = legalize(SrcFHi, Legal_Reg | Legal_Imm, true);
2491 _mov(DestLo, SrcLoRI);
2492 _mov(DestHi, SrcHiRI);
2493 } else {
2494 _cmp(Condition, Zero);
2495 SrcT = legalize(SrcT, Legal_Reg | Legal_Imm, true);
2496 _mov(Dest, SrcT);
2497 _br(InstX8632Br::Br_ne, Label);
2498 Context.insert(InstFakeUse::create(Func, Dest));
2499 SrcF = legalize(SrcF, Legal_Reg | Legal_Imm, true);
2500 _mov(Dest, SrcF);
2501 }
2502
2503 Context.insert(Label);
2504}
2505
2506void TargetX8632::lowerStore(const InstStore *Inst) {
2507 Operand *Value = Inst->getData();
2508 Operand *Addr = Inst->getAddr();
Jan Voung5cd240d2014-06-25 10:36:46 -07002509 OperandX8632Mem *NewAddr = FormMemoryOperand(Addr, Value->getType());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002510
2511 if (NewAddr->getType() == IceType_i64) {
2512 Value = legalize(Value);
2513 Operand *ValueHi = legalize(hiOperand(Value), Legal_Reg | Legal_Imm, true);
2514 Operand *ValueLo = legalize(loOperand(Value), Legal_Reg | Legal_Imm, true);
2515 _store(ValueHi, llvm::cast<OperandX8632Mem>(hiOperand(NewAddr)));
2516 _store(ValueLo, llvm::cast<OperandX8632Mem>(loOperand(NewAddr)));
2517 } else {
2518 Value = legalize(Value, Legal_Reg | Legal_Imm, true);
2519 _store(Value, NewAddr);
2520 }
2521}
2522
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002523void TargetX8632::doAddressOptStore() {
2524 InstStore *Inst = llvm::cast<InstStore>(*Context.getCur());
2525 Operand *Data = Inst->getData();
2526 Operand *Addr = Inst->getAddr();
2527 Variable *Index = NULL;
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002528 uint16_t Shift = 0;
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002529 int32_t Offset = 0; // TODO: make Constant
2530 Variable *Base = llvm::dyn_cast<Variable>(Addr);
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002531 // Vanilla ICE store instructions should not use the segment registers,
2532 // and computeAddressOpt only works at the level of Variables and Constants,
2533 // not other OperandX8632Mem, so there should be no mention of segment
2534 // registers there either.
2535 const OperandX8632Mem::SegmentRegisters SegmentReg =
2536 OperandX8632Mem::DefaultSegment;
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002537 computeAddressOpt(Base, Index, Shift, Offset);
2538 if (Base && Addr != Base) {
2539 Constant *OffsetOp = Ctx->getConstantInt(IceType_i32, Offset);
2540 Addr = OperandX8632Mem::create(Func, Data->getType(), Base, OffsetOp, Index,
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002541 Shift, SegmentReg);
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002542 Inst->setDeleted();
2543 Context.insert(InstStore::create(Func, Data, Addr));
2544 }
2545}
2546
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002547void TargetX8632::lowerSwitch(const InstSwitch *Inst) {
2548 // This implements the most naive possible lowering.
2549 // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default
2550 Operand *Src0 = Inst->getComparison();
2551 SizeT NumCases = Inst->getNumCases();
2552 // OK, we'll be slightly less naive by forcing Src into a physical
2553 // register if there are 2 or more uses.
2554 if (NumCases >= 2)
2555 Src0 = legalizeToVar(Src0, true);
2556 else
2557 Src0 = legalize(Src0, Legal_All, true);
2558 for (SizeT I = 0; I < NumCases; ++I) {
2559 Operand *Value = Ctx->getConstantInt(IceType_i32, Inst->getValue(I));
2560 _cmp(Src0, Value);
2561 _br(InstX8632Br::Br_e, Inst->getLabel(I));
2562 }
2563
2564 _br(Inst->getLabelDefault());
2565}
2566
2567void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) {
2568 const SizeT MaxSrcs = 0;
2569 Variable *Dest = NULL;
2570 InstCall *Call = makeHelperCall("ice_unreachable", Dest, MaxSrcs);
2571 lowerCall(Call);
2572}
2573
Matt Wala928f1292014-07-07 16:50:46 -07002574// Helper for legalize() to emit the right code to lower an operand to a
2575// register of the appropriate type.
2576Variable *TargetX8632::copyToReg(Operand *Src, int32_t RegNum) {
2577 Type Ty = Src->getType();
2578 Variable *Reg = makeReg(Ty, RegNum);
2579 if (isVectorType(Src->getType())) {
2580 _movp(Reg, Src);
2581 } else {
2582 _mov(Reg, Src);
2583 }
2584 return Reg;
2585}
2586
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002587Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
2588 bool AllowOverlap, int32_t RegNum) {
2589 // Assert that a physical register is allowed. To date, all calls
2590 // to legalize() allow a physical register. If a physical register
2591 // needs to be explicitly disallowed, then new code will need to be
2592 // written to force a spill.
2593 assert(Allowed & Legal_Reg);
2594 // If we're asking for a specific physical register, make sure we're
2595 // not allowing any other operand kinds. (This could be future
2596 // work, e.g. allow the shl shift amount to be either an immediate
2597 // or in ecx.)
2598 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg);
2599 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(From)) {
2600 // Before doing anything with a Mem operand, we need to ensure
2601 // that the Base and Index components are in physical registers.
2602 Variable *Base = Mem->getBase();
2603 Variable *Index = Mem->getIndex();
2604 Variable *RegBase = NULL;
2605 Variable *RegIndex = NULL;
2606 if (Base) {
2607 RegBase = legalizeToVar(Base, true);
2608 }
2609 if (Index) {
2610 RegIndex = legalizeToVar(Index, true);
2611 }
2612 if (Base != RegBase || Index != RegIndex) {
Jan Voung3bd9f1a2014-06-18 10:50:57 -07002613 From = OperandX8632Mem::create(
2614 Func, Mem->getType(), RegBase, Mem->getOffset(), RegIndex,
2615 Mem->getShift(), Mem->getSegmentRegister());
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002616 }
2617
2618 if (!(Allowed & Legal_Mem)) {
Matt Wala928f1292014-07-07 16:50:46 -07002619 From = copyToReg(From, RegNum);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002620 }
2621 return From;
2622 }
2623 if (llvm::isa<Constant>(From)) {
Matt Walad8f4a7d2014-06-18 09:55:03 -07002624 if (llvm::isa<ConstantUndef>(From)) {
2625 // Lower undefs to zero. Another option is to lower undefs to an
2626 // uninitialized register; however, using an uninitialized register
2627 // results in less predictable code.
2628 //
2629 // If in the future the implementation is changed to lower undef
2630 // values to uninitialized registers, a FakeDef will be needed:
2631 // Context.insert(InstFakeDef::create(Func, Reg));
2632 // This is in order to ensure that the live range of Reg is not
2633 // overestimated. If the constant being lowered is a 64 bit value,
2634 // then the result should be split and the lo and hi components will
2635 // need to go in uninitialized registers.
Matt Wala928f1292014-07-07 16:50:46 -07002636
2637 if (isVectorType(From->getType())) {
2638 // There is no support for loading or emitting vector constants, so
2639 // undef values are instead initialized in registers.
2640 Variable *Reg = makeReg(From->getType(), RegNum);
2641 // Insert a FakeDef, since otherwise the live range of Reg might
2642 // be overestimated.
2643 Context.insert(InstFakeDef::create(Func, Reg));
2644 _pxor(Reg, Reg);
2645 return Reg;
2646 } else {
2647 From = Ctx->getConstantZero(From->getType());
2648 }
Matt Walad8f4a7d2014-06-18 09:55:03 -07002649 }
Jim Stichnothde4ca712014-06-29 08:13:48 -07002650 bool NeedsReg = false;
2651 if (!(Allowed & Legal_Imm))
2652 // Immediate specifically not allowed
2653 NeedsReg = true;
2654 // TODO(stichnot): LEAHACK: remove Legal_Reloc once a proper
2655 // emitter is used.
2656 if (!(Allowed & Legal_Reloc) && llvm::isa<ConstantRelocatable>(From))
2657 // Relocatable specifically not allowed
2658 NeedsReg = true;
2659 if (!(Allowed & Legal_Mem) &&
2660 (From->getType() == IceType_f32 || From->getType() == IceType_f64))
2661 // On x86, FP constants are lowered to mem operands.
2662 NeedsReg = true;
Jan Voung5a13f452014-06-18 10:42:02 -07002663 if (NeedsReg) {
Matt Wala928f1292014-07-07 16:50:46 -07002664 From = copyToReg(From, RegNum);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002665 }
2666 return From;
2667 }
2668 if (Variable *Var = llvm::dyn_cast<Variable>(From)) {
2669 // We need a new physical register for the operand if:
Jim Stichnothca662e92014-07-10 15:32:36 -07002670 // Mem is not allowed and Var isn't guaranteed a physical
2671 // register, or
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002672 // RegNum is required and Var->getRegNum() doesn't match.
Jim Stichnothca662e92014-07-10 15:32:36 -07002673 bool WillHaveRegister =
2674 (Var->hasReg() || Var->getWeight() == RegWeight::Inf);
2675 if ((!(Allowed & Legal_Mem) && !WillHaveRegister) ||
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002676 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) {
Matt Wala928f1292014-07-07 16:50:46 -07002677 Variable *Reg = copyToReg(From, RegNum);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002678 if (RegNum == Variable::NoRegister) {
2679 Reg->setPreferredRegister(Var, AllowOverlap);
2680 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002681 From = Reg;
2682 }
2683 return From;
2684 }
2685 llvm_unreachable("Unhandled operand kind in legalize()");
2686 return From;
2687}
2688
2689// Provide a trivial wrapper to legalize() for this common usage.
2690Variable *TargetX8632::legalizeToVar(Operand *From, bool AllowOverlap,
2691 int32_t RegNum) {
2692 return llvm::cast<Variable>(legalize(From, Legal_Reg, AllowOverlap, RegNum));
2693}
2694
Jan Voung5cd240d2014-06-25 10:36:46 -07002695OperandX8632Mem *TargetX8632::FormMemoryOperand(Operand *Operand, Type Ty) {
2696 OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand);
2697 // It may be the case that address mode optimization already creates
2698 // an OperandX8632Mem, so in that case it wouldn't need another level
2699 // of transformation.
2700 if (!Mem) {
2701 Variable *Base = llvm::dyn_cast<Variable>(Operand);
2702 Constant *Offset = llvm::dyn_cast<Constant>(Operand);
2703 assert(Base || Offset);
2704 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset);
2705 }
2706 return llvm::cast<OperandX8632Mem>(legalize(Mem));
2707}
2708
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002709Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) {
Jan Voung1ee34162014-06-24 13:43:30 -07002710 // There aren't any 64-bit integer registers for x86-32.
2711 assert(Type != IceType_i64);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002712 Variable *Reg = Func->makeVariable(Type, Context.getNode());
2713 if (RegNum == Variable::NoRegister)
2714 Reg->setWeightInfinite();
2715 else
2716 Reg->setRegNum(RegNum);
2717 return Reg;
2718}
2719
2720void TargetX8632::postLower() {
2721 if (Ctx->getOptLevel() != Opt_m1)
2722 return;
2723 // TODO: Avoid recomputing WhiteList every instruction.
Jan Voung95598992014-07-09 09:54:25 -07002724 RegSetMask RegInclude = RegSet_All;
2725 RegSetMask RegExclude = RegSet_None;
2726 if (hasFramePointer())
2727 RegExclude |= RegSet_FramePointer;
2728 llvm::SmallBitVector WhiteList = getRegisterSet(RegInclude, RegExclude);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002729 // Make one pass to black-list pre-colored registers. TODO: If
2730 // there was some prior register allocation pass that made register
2731 // assignments, those registers need to be black-listed here as
2732 // well.
2733 for (InstList::iterator I = Context.getCur(), E = Context.getEnd(); I != E;
2734 ++I) {
2735 const Inst *Inst = *I;
2736 if (Inst->isDeleted())
2737 continue;
2738 if (llvm::isa<InstFakeKill>(Inst))
2739 continue;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002740 for (SizeT SrcNum = 0; SrcNum < Inst->getSrcSize(); ++SrcNum) {
2741 Operand *Src = Inst->getSrc(SrcNum);
2742 SizeT NumVars = Src->getNumVars();
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002743 for (SizeT J = 0; J < NumVars; ++J) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002744 const Variable *Var = Src->getVar(J);
2745 if (!Var->hasReg())
2746 continue;
2747 WhiteList[Var->getRegNum()] = false;
2748 }
2749 }
2750 }
2751 // The second pass colors infinite-weight variables.
2752 llvm::SmallBitVector AvailableRegisters = WhiteList;
2753 for (InstList::iterator I = Context.getCur(), E = Context.getEnd(); I != E;
2754 ++I) {
2755 const Inst *Inst = *I;
2756 if (Inst->isDeleted())
2757 continue;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002758 for (SizeT SrcNum = 0; SrcNum < Inst->getSrcSize(); ++SrcNum) {
2759 Operand *Src = Inst->getSrc(SrcNum);
2760 SizeT NumVars = Src->getNumVars();
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002761 for (SizeT J = 0; J < NumVars; ++J) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002762 Variable *Var = Src->getVar(J);
2763 if (Var->hasReg())
2764 continue;
2765 if (!Var->getWeight().isInf())
2766 continue;
2767 llvm::SmallBitVector AvailableTypedRegisters =
2768 AvailableRegisters & getRegisterSetForType(Var->getType());
2769 if (!AvailableTypedRegisters.any()) {
2770 // This is a hack in case we run out of physical registers
2771 // due to an excessive number of "push" instructions from
2772 // lowering a call.
2773 AvailableRegisters = WhiteList;
2774 AvailableTypedRegisters =
2775 AvailableRegisters & getRegisterSetForType(Var->getType());
2776 }
2777 assert(AvailableTypedRegisters.any());
2778 int32_t RegNum = AvailableTypedRegisters.find_first();
2779 Var->setRegNum(RegNum);
2780 AvailableRegisters[RegNum] = false;
2781 }
2782 }
2783 }
2784}
2785
Matt Wala928f1292014-07-07 16:50:46 -07002786template <> void ConstantInteger::emit(GlobalContext *Ctx) const {
2787 Ostream &Str = Ctx->getStrEmit();
2788 Str << getValue();
2789}
2790
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002791template <> void ConstantFloat::emit(GlobalContext *Ctx) const {
2792 Ostream &Str = Ctx->getStrEmit();
Jim Stichnothf61d5b22014-05-23 13:31:24 -07002793 // It would be better to prefix with ".L$" instead of "L$", but
2794 // llvm-mc doesn't parse "dword ptr [.L$foo]".
2795 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]";
2796}
2797
Jim Stichnothd97c7df2014-06-04 11:57:08 -07002798template <> void ConstantDouble::emit(GlobalContext *Ctx) const {
2799 Ostream &Str = Ctx->getStrEmit();
Jim Stichnothf61d5b22014-05-23 13:31:24 -07002800 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]";
2801}
2802
Jim Stichnothde4ca712014-06-29 08:13:48 -07002803TargetGlobalInitX8632::TargetGlobalInitX8632(GlobalContext *Ctx)
2804 : TargetGlobalInitLowering(Ctx) {}
2805
2806namespace {
2807char hexdigit(unsigned X) { return X < 10 ? '0' + X : 'A' + X - 10; }
2808}
2809
2810void TargetGlobalInitX8632::lower(const IceString &Name, SizeT Align,
2811 bool IsInternal, bool IsConst,
2812 bool IsZeroInitializer, SizeT Size,
2813 const char *Data, bool DisableTranslation) {
2814 if (Ctx->isVerbose()) {
2815 // TODO: Consider moving the dump output into the driver to be
2816 // reused for all targets.
2817 Ostream &Str = Ctx->getStrDump();
2818 Str << "@" << Name << " = " << (IsInternal ? "internal" : "external");
2819 Str << (IsConst ? " constant" : " global");
2820 Str << " [" << Size << " x i8] ";
2821 if (IsZeroInitializer) {
2822 Str << "zeroinitializer";
2823 } else {
2824 Str << "c\"";
2825 // Code taken from PrintEscapedString() in AsmWriter.cpp. Keep
2826 // the strings in the same format as the .ll file for practical
2827 // diffing.
2828 for (uint64_t i = 0; i < Size; ++i) {
2829 unsigned char C = Data[i];
2830 if (isprint(C) && C != '\\' && C != '"')
2831 Str << C;
2832 else
2833 Str << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
2834 }
2835 Str << "\"";
2836 }
2837 Str << ", align " << Align << "\n";
2838 }
2839
2840 if (DisableTranslation)
2841 return;
2842
2843 Ostream &Str = Ctx->getStrEmit();
2844 // constant:
2845 // .section .rodata,"a",@progbits
2846 // .align ALIGN
2847 // .byte ...
2848 // .size NAME, SIZE
2849
2850 // non-constant:
2851 // .data
2852 // .align ALIGN
2853 // .byte ...
2854 // .size NAME, SIZE
2855
2856 // zeroinitializer (constant):
2857 // (.section or .data as above)
2858 // .align ALIGN
2859 // .zero SIZE
2860 // .size NAME, SIZE
2861
2862 // zeroinitializer (non-constant):
2863 // (.section or .data as above)
2864 // .comm NAME, SIZE, ALIGN
2865 // .local NAME
2866
2867 IceString MangledName = Ctx->mangleName(Name);
2868 // Start a new section.
2869 if (IsConst) {
2870 Str << "\t.section\t.rodata,\"a\",@progbits\n";
2871 } else {
2872 Str << "\t.type\t" << MangledName << ",@object\n";
2873 Str << "\t.data\n";
2874 }
2875 if (IsZeroInitializer) {
2876 if (IsConst) {
2877 Str << "\t.align\t" << Align << "\n";
2878 Str << MangledName << ":\n";
2879 Str << "\t.zero\t" << Size << "\n";
2880 Str << "\t.size\t" << MangledName << ", " << Size << "\n";
2881 } else {
2882 // TODO(stichnot): Put the appropriate non-constant
2883 // zeroinitializers in a .bss section to reduce object size.
2884 Str << "\t.comm\t" << MangledName << ", " << Size << ", " << Align
2885 << "\n";
2886 }
2887 } else {
2888 Str << "\t.align\t" << Align << "\n";
2889 Str << MangledName << ":\n";
2890 for (SizeT i = 0; i < Size; ++i) {
2891 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n";
2892 }
2893 Str << "\t.size\t" << MangledName << ", " << Size << "\n";
2894 }
2895 Str << "\t" << (IsInternal ? ".local" : ".global") << "\t" << MangledName
2896 << "\n";
2897}
2898
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07002899} // end of namespace Ice