OLD | NEW |
1 //===- subzero/src/IceTargetLoweringX8664Traits.h - x86-64 traits -*- C++ -*-=// | 1 //===- subzero/src/IceTargetLoweringX8664Traits.h - x86-64 traits -*- C++ -*-=// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 SSE4_1, | 294 SSE4_1, |
295 End | 295 End |
296 }; | 296 }; |
297 | 297 |
298 static const char *TargetName; | 298 static const char *TargetName; |
299 static constexpr Type WordType = IceType_i64; | 299 static constexpr Type WordType = IceType_i64; |
300 | 300 |
301 static IceString getRegName(int32_t RegNum) { | 301 static IceString getRegName(int32_t RegNum) { |
302 static const char *const RegNames[RegisterSet::Reg_NUM] = { | 302 static const char *const RegNames[RegisterSet::Reg_NUM] = { |
303 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 303 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
304 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 304 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
305 isTrunc8Rcvr, isAhRcvr, aliases) \ | 305 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
306 name, | 306 name, |
307 REGX8664_TABLE | 307 REGX8664_TABLE |
308 #undef X | 308 #undef X |
309 }; | 309 }; |
310 assert(RegNum >= 0); | 310 assert(RegNum >= 0); |
311 assert(RegNum < RegisterSet::Reg_NUM); | 311 assert(RegNum < RegisterSet::Reg_NUM); |
312 return RegNames[RegNum]; | 312 return RegNames[RegNum]; |
313 } | 313 } |
314 | 314 |
315 static GPRRegister getEncodedGPR(int32_t RegNum) { | 315 static GPRRegister getEncodedGPR(int32_t RegNum) { |
316 static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = { | 316 static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = { |
317 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 317 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
318 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 318 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
319 isTrunc8Rcvr, isAhRcvr, aliases) \ | 319 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
320 GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR), | 320 GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR), |
321 REGX8664_TABLE | 321 REGX8664_TABLE |
322 #undef X | 322 #undef X |
323 }; | 323 }; |
324 assert(RegNum >= 0); | 324 assert(RegNum >= 0); |
325 assert(RegNum < RegisterSet::Reg_NUM); | 325 assert(RegNum < RegisterSet::Reg_NUM); |
326 assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR); | 326 assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR); |
327 return GPRRegs[RegNum]; | 327 return GPRRegs[RegNum]; |
328 } | 328 } |
329 | 329 |
330 static ByteRegister getEncodedByteReg(int32_t RegNum) { | 330 static ByteRegister getEncodedByteReg(int32_t RegNum) { |
331 static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = { | 331 static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = { |
332 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 332 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
333 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 333 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
334 isTrunc8Rcvr, isAhRcvr, aliases) \ | 334 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
335 ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg), | 335 ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg), |
336 REGX8664_TABLE | 336 REGX8664_TABLE |
337 #undef X | 337 #undef X |
338 }; | 338 }; |
339 assert(RegNum >= 0); | 339 assert(RegNum >= 0); |
340 assert(RegNum < RegisterSet::Reg_NUM); | 340 assert(RegNum < RegisterSet::Reg_NUM); |
341 assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg); | 341 assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg); |
342 return ByteRegs[RegNum]; | 342 return ByteRegs[RegNum]; |
343 } | 343 } |
344 | 344 |
345 static XmmRegister getEncodedXmm(int32_t RegNum) { | 345 static XmmRegister getEncodedXmm(int32_t RegNum) { |
346 static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = { | 346 static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = { |
347 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 347 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
348 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 348 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
349 isTrunc8Rcvr, isAhRcvr, aliases) \ | 349 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
350 XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm), | 350 XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm), |
351 REGX8664_TABLE | 351 REGX8664_TABLE |
352 #undef X | 352 #undef X |
353 }; | 353 }; |
354 assert(RegNum >= 0); | 354 assert(RegNum >= 0); |
355 assert(RegNum < RegisterSet::Reg_NUM); | 355 assert(RegNum < RegisterSet::Reg_NUM); |
356 assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm); | 356 assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm); |
357 return XmmRegs[RegNum]; | 357 return XmmRegs[RegNum]; |
358 } | 358 } |
359 | 359 |
360 static uint32_t getEncoding(int32_t RegNum) { | 360 static uint32_t getEncoding(int32_t RegNum) { |
361 static const uint32_t Encoding[RegisterSet::Reg_NUM] = { | 361 static const uint32_t Encoding[RegisterSet::Reg_NUM] = { |
362 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 362 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
363 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 363 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
364 isTrunc8Rcvr, isAhRcvr, aliases) \ | 364 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
365 encode, | 365 encode, |
366 REGX8664_TABLE | 366 REGX8664_TABLE |
367 #undef X | 367 #undef X |
368 }; | 368 }; |
369 assert(RegNum >= 0); | 369 assert(RegNum >= 0); |
370 assert(RegNum < RegisterSet::Reg_NUM); | 370 assert(RegNum < RegisterSet::Reg_NUM); |
371 return Encoding[RegNum]; | 371 return Encoding[RegNum]; |
372 } | 372 } |
373 | 373 |
374 static inline int32_t getBaseReg(int32_t RegNum) { | 374 static inline int32_t getBaseReg(int32_t RegNum) { |
375 static const int32_t BaseRegs[RegisterSet::Reg_NUM] = { | 375 static const int32_t BaseRegs[RegisterSet::Reg_NUM] = { |
376 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 376 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
377 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 377 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
378 isTrunc8Rcvr, isAhRcvr, aliases) \ | 378 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
379 RegisterSet::base, | 379 encode, |
380 REGX8664_TABLE | 380 REGX8664_TABLE |
381 #undef X | 381 #undef X |
382 }; | 382 }; |
383 assert(RegNum >= 0); | 383 assert(RegNum >= 0); |
384 assert(RegNum < RegisterSet::Reg_NUM); | 384 assert(RegNum < RegisterSet::Reg_NUM); |
385 return BaseRegs[RegNum]; | 385 return BaseRegs[RegNum]; |
386 } | 386 } |
387 | 387 |
388 private: | 388 private: |
389 static int32_t getFirstGprForType(Type Ty) { | 389 static int32_t getFirstGprForType(Type Ty) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 assert(RegNum != RegisterSet::Reg_bh); | 421 assert(RegNum != RegisterSet::Reg_bh); |
422 assert(RegNum != RegisterSet::Reg_ch); | 422 assert(RegNum != RegisterSet::Reg_ch); |
423 assert(RegNum != RegisterSet::Reg_dh); | 423 assert(RegNum != RegisterSet::Reg_dh); |
424 | 424 |
425 const int32_t FirstGprForType = getFirstGprForType(Ty); | 425 const int32_t FirstGprForType = getFirstGprForType(Ty); |
426 | 426 |
427 switch (RegNum) { | 427 switch (RegNum) { |
428 default: | 428 default: |
429 llvm::report_fatal_error("Unknown register."); | 429 llvm::report_fatal_error("Unknown register."); |
430 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 430 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
431 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 431 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
432 isTrunc8Rcvr, isAhRcvr, aliases) \ | 432 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
433 case RegisterSet::val: { \ | 433 case RegisterSet::val: { \ |
434 assert(isGPR); \ | 434 if (!isGPR) \ |
| 435 return RegisterSet::val; \ |
435 assert((is64) || (is32) || (is16) || (is8) || \ | 436 assert((is64) || (is32) || (is16) || (is8) || \ |
436 getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp); \ | 437 getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp || \ |
| 438 getBaseReg(RegisterSet::val) == RegisterSet::Reg_rbp); \ |
437 constexpr int32_t FirstGprWithRegNumSize = \ | 439 constexpr int32_t FirstGprWithRegNumSize = \ |
438 ((is64) || RegisterSet::val == RegisterSet::Reg_rsp) \ | 440 ((is64) || RegisterSet::val == RegisterSet::Reg_rsp || \ |
| 441 RegisterSet::val == RegisterSet::Reg_rbp) \ |
439 ? RegisterSet::Reg_rax \ | 442 ? RegisterSet::Reg_rax \ |
440 : (((is32) || RegisterSet::val == RegisterSet::Reg_esp) \ | 443 : (((is32) || RegisterSet::val == RegisterSet::Reg_esp || \ |
| 444 RegisterSet::val == RegisterSet::Reg_ebp) \ |
441 ? RegisterSet::Reg_eax \ | 445 ? RegisterSet::Reg_eax \ |
442 : (((is16) || RegisterSet::val == RegisterSet::Reg_sp) \ | 446 : (((is16) || RegisterSet::val == RegisterSet::Reg_sp || \ |
| 447 RegisterSet::val == RegisterSet::Reg_bp) \ |
443 ? RegisterSet::Reg_ax \ | 448 ? RegisterSet::Reg_ax \ |
444 : RegisterSet::Reg_al)); \ | 449 : RegisterSet::Reg_al)); \ |
445 const int32_t NewRegNum = \ | 450 const int32_t NewRegNum = \ |
446 RegNum - FirstGprWithRegNumSize + FirstGprForType; \ | 451 RegNum - FirstGprWithRegNumSize + FirstGprForType; \ |
447 assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) && \ | 452 assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) && \ |
448 "Error involving " #val); \ | 453 "Error involving " #val); \ |
449 return NewRegNum; \ | 454 return NewRegNum; \ |
450 } | 455 } |
451 REGX8664_TABLE | 456 REGX8664_TABLE |
452 #undef X | 457 #undef X |
453 } | 458 } |
454 } | 459 } |
455 | 460 |
456 private: | 461 private: |
457 /// SizeOf is used to obtain the size of an initializer list as a constexpr | 462 /// SizeOf is used to obtain the size of an initializer list as a constexpr |
458 /// expression. This is only needed until our C++ library is updated to | 463 /// expression. This is only needed until our C++ library is updated to |
459 /// C++ 14 -- which defines constexpr members to std::initializer_list. | 464 /// C++ 14 -- which defines constexpr members to std::initializer_list. |
460 class SizeOf { | 465 class SizeOf { |
461 SizeOf(const SizeOf &) = delete; | 466 SizeOf(const SizeOf &) = delete; |
462 SizeOf &operator=(const SizeOf &) = delete; | 467 SizeOf &operator=(const SizeOf &) = delete; |
463 | 468 |
464 public: | 469 public: |
465 constexpr SizeOf() : Size(0) {} | 470 constexpr SizeOf() : Size(0) {} |
466 template <typename... T> | 471 template <typename... T> |
467 explicit constexpr SizeOf(T...) | 472 explicit constexpr SizeOf(T...) |
468 : Size(__length<T...>::value) {} | 473 : Size(length<T...>::value) {} |
469 constexpr SizeT size() const { return Size; } | 474 constexpr SizeT size() const { return Size; } |
470 | 475 |
471 private: | 476 private: |
472 template <typename T, typename... U> struct __length { | 477 template <typename T, typename... U> struct length { |
473 static constexpr std::size_t value = 1 + __length<U...>::value; | 478 static constexpr std::size_t value = 1 + length<U...>::value; |
474 }; | 479 }; |
475 | 480 |
476 template <typename T> struct __length<T> { | 481 template <typename T> struct length<T> { |
477 static constexpr std::size_t value = 1; | 482 static constexpr std::size_t value = 1; |
478 }; | 483 }; |
479 | 484 |
480 const std::size_t Size; | 485 const std::size_t Size; |
481 }; | 486 }; |
482 | 487 |
483 public: | 488 public: |
484 static void initRegisterSet( | 489 static void initRegisterSet( |
| 490 const ::Ice::ClFlags &Flags, |
485 std::array<llvm::SmallBitVector, RCX86_NUM> *TypeToRegisterSet, | 491 std::array<llvm::SmallBitVector, RCX86_NUM> *TypeToRegisterSet, |
486 std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases, | 492 std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases, |
487 llvm::SmallBitVector *ScratchRegs) { | 493 llvm::SmallBitVector *ScratchRegs) { |
488 llvm::SmallBitVector IntegerRegistersI64(RegisterSet::Reg_NUM); | 494 llvm::SmallBitVector IntegerRegistersI64(RegisterSet::Reg_NUM); |
489 llvm::SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM); | 495 llvm::SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM); |
490 llvm::SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM); | 496 llvm::SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM); |
491 llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM); | 497 llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM); |
492 llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM); | 498 llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM); |
493 llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM); | 499 llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM); |
494 llvm::SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM); | 500 llvm::SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM); |
495 llvm::SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM); | 501 llvm::SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM); |
496 llvm::SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM); | 502 llvm::SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM); |
497 llvm::SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM); | 503 llvm::SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM); |
498 llvm::SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM); | 504 llvm::SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM); |
499 llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM); | 505 llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM); |
500 ScratchRegs->resize(RegisterSet::Reg_NUM); | 506 ScratchRegs->resize(RegisterSet::Reg_NUM); |
501 | 507 |
502 static constexpr struct { | 508 static constexpr struct { |
503 uint16_t Val; | 509 uint16_t Val; |
| 510 unsigned IsReservedWhenSandboxing : 1; |
504 unsigned Is64 : 1; | 511 unsigned Is64 : 1; |
505 unsigned Is32 : 1; | 512 unsigned Is32 : 1; |
506 unsigned Is16 : 1; | 513 unsigned Is16 : 1; |
507 unsigned Is8 : 1; | 514 unsigned Is8 : 1; |
508 unsigned IsXmm : 1; | 515 unsigned IsXmm : 1; |
509 unsigned Is64To8 : 1; | 516 unsigned Is64To8 : 1; |
510 unsigned Is32To8 : 1; | 517 unsigned Is32To8 : 1; |
511 unsigned Is16To8 : 1; | 518 unsigned Is16To8 : 1; |
512 unsigned IsTrunc8Rcvr : 1; | 519 unsigned IsTrunc8Rcvr : 1; |
513 unsigned IsAhRcvr : 1; | 520 unsigned IsAhRcvr : 1; |
514 unsigned Scratch : 1; | 521 unsigned Scratch : 1; |
515 #define NUM_ALIASES_BITS 2 | 522 #define NUM_ALIASES_BITS 2 |
516 SizeT NumAliases : (NUM_ALIASES_BITS + 1); | 523 SizeT NumAliases : (NUM_ALIASES_BITS + 1); |
517 uint16_t Aliases[1 << NUM_ALIASES_BITS]; | 524 uint16_t Aliases[1 << NUM_ALIASES_BITS]; |
518 #undef NUM_ALIASES_BITS | 525 #undef NUM_ALIASES_BITS |
519 } X8664RegTable[RegisterSet::Reg_NUM] = { | 526 } X8664RegTable[RegisterSet::Reg_NUM] = { |
520 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 527 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
521 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 528 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
522 isTrunc8Rcvr, isAhRcvr, aliases) \ | 529 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
523 { \ | 530 { \ |
524 RegisterSet::val, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 531 RegisterSet::val, sboxres, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
525 isTrunc8Rcvr, isAhRcvr, scratch, (SizeOf aliases).size(), aliases, \ | 532 is16To8, isTrunc8Rcvr, isAhRcvr, scratch, (SizeOf aliases).size(), \ |
| 533 aliases, \ |
526 } \ | 534 } \ |
527 , | 535 , |
528 REGX8664_TABLE | 536 REGX8664_TABLE |
529 #undef X | 537 #undef X |
530 }; | 538 }; |
531 | 539 |
| 540 const bool NeedSandboxing = Flags.getUseSandboxing(); |
532 for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) { | 541 for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) { |
533 const auto &Entry = X8664RegTable[ii]; | 542 const auto &Entry = X8664RegTable[ii]; |
| 543 // Even though the register is disabled for register allocation, it might |
| 544 // still be used by the Target Lowering (e.g., base pointer), so the |
| 545 // register talias table still needs to be defined. |
| 546 (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM); |
| 547 for (int J = 0; J < Entry.NumAliases; ++J) { |
| 548 SizeT Alias = Entry.Aliases[J]; |
| 549 assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias"); |
| 550 (*RegisterAliases)[Entry.Val].set(Alias); |
| 551 } |
| 552 |
| 553 (*RegisterAliases)[Entry.Val].set(Entry.Val); |
| 554 const bool DisabledRegister = |
| 555 NeedSandboxing && Entry.IsReservedWhenSandboxing; |
| 556 if (DisabledRegister) { |
| 557 continue; |
| 558 } |
534 (IntegerRegistersI64)[Entry.Val] = Entry.Is64; | 559 (IntegerRegistersI64)[Entry.Val] = Entry.Is64; |
535 (IntegerRegistersI32)[Entry.Val] = Entry.Is32; | 560 (IntegerRegistersI32)[Entry.Val] = Entry.Is32; |
536 (IntegerRegistersI16)[Entry.Val] = Entry.Is16; | 561 (IntegerRegistersI16)[Entry.Val] = Entry.Is16; |
537 (IntegerRegistersI8)[Entry.Val] = Entry.Is8; | 562 (IntegerRegistersI8)[Entry.Val] = Entry.Is8; |
538 (FloatRegisters)[Entry.Val] = Entry.IsXmm; | 563 (FloatRegisters)[Entry.Val] = Entry.IsXmm; |
539 (VectorRegisters)[Entry.Val] = Entry.IsXmm; | 564 (VectorRegisters)[Entry.Val] = Entry.IsXmm; |
540 (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8; | 565 (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8; |
541 (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8; | 566 (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8; |
542 (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8; | 567 (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8; |
543 (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr; | 568 (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr; |
544 (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr; | 569 (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr; |
545 (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM); | |
546 for (int J = 0; J < Entry.NumAliases; ++J) { | |
547 SizeT Alias = Entry.Aliases[J]; | |
548 assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias"); | |
549 (*RegisterAliases)[Entry.Val].set(Alias); | |
550 } | |
551 (*RegisterAliases)[Entry.Val].set(Entry.Val); | |
552 (*ScratchRegs)[Entry.Val] = Entry.Scratch; | 570 (*ScratchRegs)[Entry.Val] = Entry.Scratch; |
553 } | 571 } |
554 | 572 |
555 (*TypeToRegisterSet)[RC_void] = InvalidRegisters; | 573 (*TypeToRegisterSet)[RC_void] = InvalidRegisters; |
556 (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8; | 574 (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8; |
557 (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8; | 575 (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8; |
558 (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16; | 576 (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16; |
559 (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32; | 577 (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32; |
560 (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64; | 578 (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64; |
561 (*TypeToRegisterSet)[RC_f32] = FloatRegisters; | 579 (*TypeToRegisterSet)[RC_f32] = FloatRegisters; |
562 (*TypeToRegisterSet)[RC_f64] = FloatRegisters; | 580 (*TypeToRegisterSet)[RC_f64] = FloatRegisters; |
563 (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters; | 581 (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters; |
564 (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters; | 582 (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters; |
565 (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters; | 583 (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters; |
566 (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters; | 584 (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters; |
567 (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters; | 585 (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters; |
568 (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters; | 586 (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters; |
569 (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters; | 587 (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters; |
570 (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers; | 588 (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers; |
571 (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers; | 589 (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers; |
572 (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers; | 590 (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers; |
573 (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters; | 591 (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters; |
574 (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters; | 592 (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters; |
575 } | 593 } |
576 | 594 |
577 static llvm::SmallBitVector | 595 static llvm::SmallBitVector |
578 getRegisterSet(TargetLowering::RegSetMask Include, | 596 getRegisterSet(const ::Ice::ClFlags &Flags, |
| 597 TargetLowering::RegSetMask Include, |
579 TargetLowering::RegSetMask Exclude) { | 598 TargetLowering::RegSetMask Exclude) { |
580 llvm::SmallBitVector Registers(RegisterSet::Reg_NUM); | 599 llvm::SmallBitVector Registers(RegisterSet::Reg_NUM); |
581 | 600 |
| 601 const bool NeedSandboxing = Flags.getUseSandboxing(); |
582 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 602 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
583 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 603 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
584 isTrunc8Rcvr, isAhRcvr, aliases) \ | 604 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
585 if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \ | 605 if (!NeedSandboxing || !(sboxres)) { \ |
586 Registers[RegisterSet::val] = true; \ | 606 if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \ |
587 if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \ | 607 Registers[RegisterSet::val] = true; \ |
588 Registers[RegisterSet::val] = true; \ | 608 if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \ |
589 if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \ | 609 Registers[RegisterSet::val] = true; \ |
590 Registers[RegisterSet::val] = true; \ | 610 if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \ |
591 if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \ | 611 Registers[RegisterSet::val] = true; \ |
592 Registers[RegisterSet::val] = true; \ | 612 if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \ |
593 if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \ | 613 Registers[RegisterSet::val] = true; \ |
594 Registers[RegisterSet::val] = false; \ | 614 if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \ |
595 if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \ | 615 Registers[RegisterSet::val] = false; \ |
596 Registers[RegisterSet::val] = false; \ | 616 if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \ |
597 if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \ | 617 Registers[RegisterSet::val] = false; \ |
598 Registers[RegisterSet::val] = false; \ | 618 if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \ |
599 if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \ | 619 Registers[RegisterSet::val] = false; \ |
600 Registers[RegisterSet::val] = false; | 620 if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \ |
| 621 Registers[RegisterSet::val] = false; \ |
| 622 } |
601 | 623 |
602 REGX8664_TABLE | 624 REGX8664_TABLE |
603 | 625 |
604 #undef X | 626 #undef X |
605 | 627 |
606 return Registers; | 628 return Registers; |
607 } | 629 } |
608 | 630 |
609 static void | 631 static void |
610 makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func, | 632 makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func, |
611 llvm::SmallVectorImpl<int32_t> &Permutation, | 633 llvm::SmallVectorImpl<int32_t> &Permutation, |
612 const llvm::SmallBitVector &ExcludeRegisters, | 634 const llvm::SmallBitVector &ExcludeRegisters, |
613 uint64_t Salt) { | 635 uint64_t Salt) { |
614 // TODO(stichnot): Declaring Permutation this way loses type/size | 636 // TODO(stichnot): Declaring Permutation this way loses type/size |
615 // information. Fix this in conjunction with the caller-side TODO. | 637 // information. Fix this in conjunction with the caller-side TODO. |
616 assert(Permutation.size() >= RegisterSet::Reg_NUM); | 638 assert(Permutation.size() >= RegisterSet::Reg_NUM); |
617 // Expected upper bound on the number of registers in a single equivalence | 639 // Expected upper bound on the number of registers in a single equivalence |
618 // class. For x86-64, this would comprise the 16 XMM registers. This is | 640 // class. For x86-64, this would comprise the 16 XMM registers. This is |
619 // for performance, not correctness. | 641 // for performance, not correctness. |
620 static const unsigned MaxEquivalenceClassSize = 8; | 642 static const unsigned MaxEquivalenceClassSize = 8; |
621 using RegisterList = llvm::SmallVector<int32_t, MaxEquivalenceClassSize>; | 643 using RegisterList = llvm::SmallVector<int32_t, MaxEquivalenceClassSize>; |
622 using EquivalenceClassMap = std::map<uint32_t, RegisterList>; | 644 using EquivalenceClassMap = std::map<uint32_t, RegisterList>; |
623 EquivalenceClassMap EquivalenceClasses; | 645 EquivalenceClassMap EquivalenceClasses; |
624 SizeT NumShuffled = 0, NumPreserved = 0; | 646 SizeT NumShuffled = 0, NumPreserved = 0; |
625 | 647 |
626 // Build up the equivalence classes of registers by looking at the register | 648 // Build up the equivalence classes of registers by looking at the register |
627 // properties as well as whether the registers should be explicitly excluded | 649 // properties as well as whether the registers should be explicitly excluded |
628 // from shuffling. | 650 // from shuffling. |
629 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ | 651 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ |
630 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ | 652 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \ |
631 isTrunc8Rcvr, isAhRcvr, aliases) \ | 653 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \ |
632 if (ExcludeRegisters[RegisterSet::val]) { \ | 654 if (ExcludeRegisters[RegisterSet::val]) { \ |
633 /* val stays the same in the resulting permutation. */ \ | 655 /* val stays the same in the resulting permutation. */ \ |
634 Permutation[RegisterSet::val] = RegisterSet::val; \ | 656 Permutation[RegisterSet::val] = RegisterSet::val; \ |
635 ++NumPreserved; \ | 657 ++NumPreserved; \ |
636 } else { \ | 658 } else { \ |
637 uint32_t AttrKey = 0; \ | 659 uint32_t AttrKey = 0; \ |
638 uint32_t Index = 0; \ | 660 uint32_t Index = 0; \ |
639 /* Combine relevant attributes into an equivalence class key. */ \ | 661 /* Combine relevant attributes into an equivalence class key. */ \ |
640 Index |= (scratch << (AttrKey++)); \ | 662 Index |= (scratch << (AttrKey++)); \ |
641 Index |= (preserved << (AttrKey++)); \ | 663 Index |= (preserved << (AttrKey++)); \ |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 X86OperandMem() = delete; | 857 X86OperandMem() = delete; |
836 X86OperandMem(const X86OperandMem &) = delete; | 858 X86OperandMem(const X86OperandMem &) = delete; |
837 X86OperandMem &operator=(const X86OperandMem &) = delete; | 859 X86OperandMem &operator=(const X86OperandMem &) = delete; |
838 | 860 |
839 public: | 861 public: |
840 enum SegmentRegisters { DefaultSegment = -1, SegReg_NUM }; | 862 enum SegmentRegisters { DefaultSegment = -1, SegReg_NUM }; |
841 static X86OperandMem * | 863 static X86OperandMem * |
842 create(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, | 864 create(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, |
843 Variable *Index = nullptr, uint16_t Shift = 0, | 865 Variable *Index = nullptr, uint16_t Shift = 0, |
844 SegmentRegisters SegmentRegister = DefaultSegment, | 866 SegmentRegisters SegmentRegister = DefaultSegment, |
845 bool IsPIC = false) { | 867 bool IsRebased = false) { |
846 assert(SegmentRegister == DefaultSegment); | 868 assert(SegmentRegister == DefaultSegment); |
847 (void)SegmentRegister; | 869 (void)SegmentRegister; |
848 return new (Func->allocate<X86OperandMem>()) | 870 return new (Func->allocate<X86OperandMem>()) |
849 X86OperandMem(Func, Ty, Base, Offset, Index, Shift, IsPIC); | 871 X86OperandMem(Func, Ty, Base, Offset, Index, Shift, IsRebased); |
| 872 } |
| 873 static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base, |
| 874 Constant *Offset, bool IsRebased) { |
| 875 constexpr Variable *NoIndex = nullptr; |
| 876 constexpr uint16_t NoShift = 0; |
| 877 return new (Func->allocate<X86OperandMem>()) |
| 878 X86OperandMem(Func, Ty, Base, Offset, NoIndex, NoShift, IsRebased); |
850 } | 879 } |
851 Variable *getBase() const { return Base; } | 880 Variable *getBase() const { return Base; } |
852 Constant *getOffset() const { return Offset; } | 881 Constant *getOffset() const { return Offset; } |
853 Variable *getIndex() const { return Index; } | 882 Variable *getIndex() const { return Index; } |
854 uint16_t getShift() const { return Shift; } | 883 uint16_t getShift() const { return Shift; } |
855 SegmentRegisters getSegmentRegister() const { return DefaultSegment; } | 884 SegmentRegisters getSegmentRegister() const { return DefaultSegment; } |
856 void emitSegmentOverride(Assembler *) const {} | 885 void emitSegmentOverride(Assembler *) const {} |
857 void setIsPIC() { IsPIC = true; } | 886 bool getIsRebased() const { return IsRebased; } |
858 bool getIsPIC() const { return IsPIC; } | 887 Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target, |
859 Address toAsmAddress(Assembler *Asm, | 888 bool IsLeaAddr = false) const; |
860 const Ice::TargetLowering *Target) const; | |
861 | 889 |
862 void emit(const Cfg *Func) const override; | 890 void emit(const Cfg *Func) const override; |
863 using X86Operand::dump; | 891 using X86Operand::dump; |
864 void dump(const Cfg *Func, Ostream &Str) const override; | 892 void dump(const Cfg *Func, Ostream &Str) const override; |
865 | 893 |
866 static bool classof(const Operand *Operand) { | 894 static bool classof(const Operand *Operand) { |
867 return Operand->getKind() == static_cast<OperandKind>(kMem); | 895 return Operand->getKind() == static_cast<OperandKind>(kMem); |
868 } | 896 } |
869 | 897 |
870 void setRandomized(bool R) { Randomized = R; } | 898 void setRandomized(bool R) { Randomized = R; } |
871 | 899 |
872 bool getRandomized() const { return Randomized; } | 900 bool getRandomized() const { return Randomized; } |
873 | 901 |
874 private: | 902 private: |
875 X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, | 903 X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, |
876 Variable *Index, uint16_t Shift, bool IsPIC); | 904 Variable *Index, uint16_t Shift, bool IsRebased); |
877 | 905 |
878 Variable *Base; | 906 Variable *const Base; |
879 Constant *Offset; | 907 Constant *const Offset; |
880 Variable *Index; | 908 Variable *const Index; |
881 uint16_t Shift; | 909 const uint16_t Shift; |
882 bool IsPIC; | 910 const bool IsRebased; |
883 /// A flag to show if this memory operand is a randomized one. Randomized | 911 /// A flag to show if this memory operand is a randomized one. Randomized |
884 /// memory operands are generated in | 912 /// memory operands are generated in |
885 /// TargetX86Base::randomizeOrPoolImmediate() | 913 /// TargetX86Base::randomizeOrPoolImmediate() |
886 bool Randomized = false; | 914 bool Randomized = false; |
887 }; | 915 }; |
888 | 916 |
889 /// VariableSplit is a way to treat an f64 memory location as a pair of i32 | 917 /// VariableSplit is a way to treat an f64 memory location as a pair of i32 |
890 /// locations (Low and High). This is needed for some cases of the Bitcast | 918 /// locations (Low and High). This is needed for some cases of the Bitcast |
891 /// instruction. Since it's not possible for integer registers to access the | 919 /// instruction. Since it's not possible for integer registers to access the |
892 /// XMM registers and vice versa, the lowering forces the f64 to be spilled to | 920 /// XMM registers and vice versa, the lowering forces the f64 to be spilled to |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 const char *FldString; // s, l, or <blank> | 1007 const char *FldString; // s, l, or <blank> |
980 } TypeAttributes[]; | 1008 } TypeAttributes[]; |
981 }; | 1009 }; |
982 | 1010 |
983 using Traits = ::Ice::X8664::TargetX8664Traits; | 1011 using Traits = ::Ice::X8664::TargetX8664Traits; |
984 } // end of namespace X8664 | 1012 } // end of namespace X8664 |
985 | 1013 |
986 } // end of namespace Ice | 1014 } // end of namespace Ice |
987 | 1015 |
988 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H | 1016 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H |
OLD | NEW |