OLD | NEW |
1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// | 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- 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 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 Str << "%" << getRegName(Var->getRegNum(), VarType); | 884 Str << "%" << getRegName(Var->getRegNum(), VarType); |
885 return; | 885 return; |
886 } | 886 } |
887 if (Var->mustHaveReg()) { | 887 if (Var->mustHaveReg()) { |
888 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + | 888 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + |
889 ") has no register assigned - function " + | 889 ") has no register assigned - function " + |
890 Func->getFunctionName()); | 890 Func->getFunctionName()); |
891 } | 891 } |
892 const int32_t Offset = Var->getStackOffset(); | 892 const int32_t Offset = Var->getStackOffset(); |
893 auto BaseRegNum = Var->getBaseRegNum(); | 893 auto BaseRegNum = Var->getBaseRegNum(); |
894 if (BaseRegNum == RegNumT::NoRegister) | 894 if (BaseRegNum.hasNoValue()) |
895 BaseRegNum = getFrameOrStackReg(); | 895 BaseRegNum = getFrameOrStackReg(); |
896 // Print in the form "Offset(%reg)", taking care that: | 896 // Print in the form "Offset(%reg)", taking care that: |
897 // - Offset is never printed when it is 0 | 897 // - Offset is never printed when it is 0 |
898 | 898 |
899 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); | 899 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); |
900 // Only print Offset when it is nonzero, regardless of DecorateAsm. | 900 // Only print Offset when it is nonzero, regardless of DecorateAsm. |
901 if (Offset) { | 901 if (Offset) { |
902 if (DecorateAsm) { | 902 if (DecorateAsm) { |
903 Str << Var->getSymbolicStackOffset(Func); | 903 Str << Var->getSymbolicStackOffset(Func); |
904 } else { | 904 } else { |
905 Str << Offset; | 905 Str << Offset; |
906 } | 906 } |
907 } | 907 } |
908 const Type FrameSPTy = Traits::WordType; | 908 const Type FrameSPTy = Traits::WordType; |
909 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; | 909 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; |
910 } | 910 } |
911 | 911 |
912 template <typename TraitsType> | 912 template <typename TraitsType> |
913 typename TargetX86Base<TraitsType>::X86Address | 913 typename TargetX86Base<TraitsType>::X86Address |
914 TargetX86Base<TraitsType>::stackVarToAsmOperand(const Variable *Var) const { | 914 TargetX86Base<TraitsType>::stackVarToAsmOperand(const Variable *Var) const { |
915 if (Var->hasReg()) | 915 if (Var->hasReg()) |
916 llvm::report_fatal_error("Stack Variable has a register assigned"); | 916 llvm::report_fatal_error("Stack Variable has a register assigned"); |
917 if (Var->mustHaveReg()) { | 917 if (Var->mustHaveReg()) { |
918 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + | 918 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + |
919 ") has no register assigned - function " + | 919 ") has no register assigned - function " + |
920 Func->getFunctionName()); | 920 Func->getFunctionName()); |
921 } | 921 } |
922 int32_t Offset = Var->getStackOffset(); | 922 int32_t Offset = Var->getStackOffset(); |
923 auto BaseRegNum = Var->getBaseRegNum(); | 923 auto BaseRegNum = Var->getBaseRegNum(); |
924 if (Var->getBaseRegNum() == RegNumT::NoRegister) | 924 if (Var->getBaseRegNum().hasNoValue()) |
925 BaseRegNum = getFrameOrStackReg(); | 925 BaseRegNum = getFrameOrStackReg(); |
926 return X86Address(Traits::getEncodedGPR(BaseRegNum), Offset, | 926 return X86Address(Traits::getEncodedGPR(BaseRegNum), Offset, |
927 AssemblerFixup::NoFixup); | 927 AssemblerFixup::NoFixup); |
928 } | 928 } |
929 | 929 |
930 template <typename TraitsType> | 930 template <typename TraitsType> |
931 void TargetX86Base<TraitsType>::addProlog(CfgNode *Node) { | 931 void TargetX86Base<TraitsType>::addProlog(CfgNode *Node) { |
932 // Stack frame layout: | 932 // Stack frame layout: |
933 // | 933 // |
934 // +------------------------+ | 934 // +------------------------+ |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 | 1116 |
1117 emitGetIP(Node); | 1117 emitGetIP(Node); |
1118 | 1118 |
1119 const VarList &Args = Func->getArgs(); | 1119 const VarList &Args = Func->getArgs(); |
1120 size_t InArgsSizeBytes = 0; | 1120 size_t InArgsSizeBytes = 0; |
1121 unsigned NumXmmArgs = 0; | 1121 unsigned NumXmmArgs = 0; |
1122 unsigned NumGPRArgs = 0; | 1122 unsigned NumGPRArgs = 0; |
1123 for (Variable *Arg : Args) { | 1123 for (Variable *Arg : Args) { |
1124 // Skip arguments passed in registers. | 1124 // Skip arguments passed in registers. |
1125 if (isVectorType(Arg->getType())) { | 1125 if (isVectorType(Arg->getType())) { |
1126 if (Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) { | 1126 if (Traits::getRegisterForXmmArgNum(NumXmmArgs).hasValue()) { |
1127 ++NumXmmArgs; | 1127 ++NumXmmArgs; |
1128 continue; | 1128 continue; |
1129 } | 1129 } |
1130 } else if (isScalarFloatingType(Arg->getType())) { | 1130 } else if (isScalarFloatingType(Arg->getType())) { |
1131 if (Traits::X86_PASS_SCALAR_FP_IN_XMM && | 1131 if (Traits::X86_PASS_SCALAR_FP_IN_XMM && |
1132 Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) { | 1132 Traits::getRegisterForXmmArgNum(NumXmmArgs).hasValue()) { |
1133 ++NumXmmArgs; | 1133 ++NumXmmArgs; |
1134 continue; | 1134 continue; |
1135 } | 1135 } |
1136 } else { | 1136 } else { |
1137 assert(isScalarIntegerType(Arg->getType())); | 1137 assert(isScalarIntegerType(Arg->getType())); |
1138 if (Traits::getRegisterForGprArgNum(Traits::WordType, NumGPRArgs) != | 1138 if (Traits::getRegisterForGprArgNum(Traits::WordType, NumGPRArgs) |
1139 RegNumT::NoRegister) { | 1139 .hasValue()) { |
1140 ++NumGPRArgs; | 1140 ++NumGPRArgs; |
1141 continue; | 1141 continue; |
1142 } | 1142 } |
1143 } | 1143 } |
1144 // For esp-based frames where the allocas are done outside the prolog, the | 1144 // For esp-based frames where the allocas are done outside the prolog, the |
1145 // esp value may not stabilize to its home value until after all the | 1145 // esp value may not stabilize to its home value until after all the |
1146 // fixed-size alloca instructions have executed. In this case, a stack | 1146 // fixed-size alloca instructions have executed. In this case, a stack |
1147 // adjustment is needed when accessing in-args in order to copy them into | 1147 // adjustment is needed when accessing in-args in order to copy them into |
1148 // registers. | 1148 // registers. |
1149 size_t StackAdjBytes = 0; | 1149 size_t StackAdjBytes = 0; |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1469 bool GprSlotsRemain = true; | 1469 bool GprSlotsRemain = true; |
1470 | 1470 |
1471 Context.init(Func->getEntryNode()); | 1471 Context.init(Func->getEntryNode()); |
1472 Context.setInsertPoint(Context.getCur()); | 1472 Context.setInsertPoint(Context.getCur()); |
1473 | 1473 |
1474 for (SizeT i = 0, End = Args.size(); | 1474 for (SizeT i = 0, End = Args.size(); |
1475 i < End && (XmmSlotsRemain || GprSlotsRemain); ++i) { | 1475 i < End && (XmmSlotsRemain || GprSlotsRemain); ++i) { |
1476 Variable *Arg = Args[i]; | 1476 Variable *Arg = Args[i]; |
1477 Type Ty = Arg->getType(); | 1477 Type Ty = Arg->getType(); |
1478 Variable *RegisterArg = nullptr; | 1478 Variable *RegisterArg = nullptr; |
1479 auto RegNum = RegNumT::NoRegister; | 1479 RegNumT RegNum; |
1480 if (isVectorType(Ty)) { | 1480 if (isVectorType(Ty)) { |
1481 RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs); | 1481 RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs); |
1482 if (RegNum == RegNumT::NoRegister) { | 1482 if (RegNum.hasNoValue()) { |
1483 XmmSlotsRemain = false; | 1483 XmmSlotsRemain = false; |
1484 continue; | 1484 continue; |
1485 } | 1485 } |
1486 ++NumXmmArgs; | 1486 ++NumXmmArgs; |
1487 RegisterArg = Func->makeVariable(Ty); | 1487 RegisterArg = Func->makeVariable(Ty); |
1488 } else if (isScalarFloatingType(Ty)) { | 1488 } else if (isScalarFloatingType(Ty)) { |
1489 if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) { | 1489 if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) { |
1490 continue; | 1490 continue; |
1491 } | 1491 } |
1492 RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs); | 1492 RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs); |
1493 if (RegNum == RegNumT::NoRegister) { | 1493 if (RegNum.hasNoValue()) { |
1494 XmmSlotsRemain = false; | 1494 XmmSlotsRemain = false; |
1495 continue; | 1495 continue; |
1496 } | 1496 } |
1497 ++NumXmmArgs; | 1497 ++NumXmmArgs; |
1498 RegisterArg = Func->makeVariable(Ty); | 1498 RegisterArg = Func->makeVariable(Ty); |
1499 } else if (isScalarIntegerType(Ty)) { | 1499 } else if (isScalarIntegerType(Ty)) { |
1500 RegNum = Traits::getRegisterForGprArgNum(Ty, NumGprArgs); | 1500 RegNum = Traits::getRegisterForGprArgNum(Ty, NumGprArgs); |
1501 if (RegNum == RegNumT::NoRegister) { | 1501 if (RegNum.hasNoValue()) { |
1502 GprSlotsRemain = false; | 1502 GprSlotsRemain = false; |
1503 continue; | 1503 continue; |
1504 } | 1504 } |
1505 ++NumGprArgs; | 1505 ++NumGprArgs; |
1506 RegisterArg = Func->makeVariable(Ty); | 1506 RegisterArg = Func->makeVariable(Ty); |
1507 } | 1507 } |
1508 assert(RegNum != RegNumT::NoRegister); | 1508 assert(RegNum.hasValue()); |
1509 assert(RegisterArg != nullptr); | 1509 assert(RegisterArg != nullptr); |
1510 // Replace Arg in the argument list with the home register. Then generate | 1510 // Replace Arg in the argument list with the home register. Then generate |
1511 // an instruction in the prolog to copy the home register to the assigned | 1511 // an instruction in the prolog to copy the home register to the assigned |
1512 // location of Arg. | 1512 // location of Arg. |
1513 if (BuildDefs::dump()) | 1513 if (BuildDefs::dump()) |
1514 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 1514 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
1515 RegisterArg->setRegNum(RegNum); | 1515 RegisterArg->setRegNum(RegNum); |
1516 RegisterArg->setIsArg(); | 1516 RegisterArg->setIsArg(); |
1517 Arg->setIsArg(false); | 1517 Arg->setIsArg(false); |
1518 | 1518 |
(...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2483 OperandList StackArgs, StackArgLocations; | 2483 OperandList StackArgs, StackArgLocations; |
2484 uint32_t ParameterAreaSizeBytes = 0; | 2484 uint32_t ParameterAreaSizeBytes = 0; |
2485 | 2485 |
2486 // Classify each argument operand according to the location where the argument | 2486 // Classify each argument operand according to the location where the argument |
2487 // is passed. | 2487 // is passed. |
2488 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 2488 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
2489 Operand *Arg = Instr->getArg(i); | 2489 Operand *Arg = Instr->getArg(i); |
2490 const Type Ty = Arg->getType(); | 2490 const Type Ty = Arg->getType(); |
2491 // The PNaCl ABI requires the width of arguments to be at least 32 bits. | 2491 // The PNaCl ABI requires the width of arguments to be at least 32 bits. |
2492 assert(typeWidthInBytes(Ty) >= 4); | 2492 assert(typeWidthInBytes(Ty) >= 4); |
2493 if (isVectorType(Ty) && (Traits::getRegisterForXmmArgNum(XmmArgs.size()) != | 2493 if (isVectorType(Ty) && |
2494 RegNumT::NoRegister)) { | 2494 Traits::getRegisterForXmmArgNum(XmmArgs.size()).hasValue()) { |
2495 XmmArgs.push_back(Arg); | 2495 XmmArgs.push_back(Arg); |
2496 } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM && | 2496 } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM && |
2497 (Traits::getRegisterForXmmArgNum(XmmArgs.size()) != | 2497 Traits::getRegisterForXmmArgNum(XmmArgs.size()).hasValue()) { |
2498 RegNumT::NoRegister)) { | |
2499 XmmArgs.push_back(Arg); | 2498 XmmArgs.push_back(Arg); |
2500 } else if (isScalarIntegerType(Ty) && | 2499 } else if (isScalarIntegerType(Ty) && |
2501 (Traits::getRegisterForGprArgNum(Ty, GprArgs.size()) != | 2500 Traits::getRegisterForGprArgNum(Ty, GprArgs.size()).hasValue()) { |
2502 RegNumT::NoRegister)) { | |
2503 GprArgs.emplace_back(Ty, Arg); | 2501 GprArgs.emplace_back(Ty, Arg); |
2504 } else { | 2502 } else { |
2505 // Place on stack. | 2503 // Place on stack. |
2506 StackArgs.push_back(Arg); | 2504 StackArgs.push_back(Arg); |
2507 if (isVectorType(Arg->getType())) { | 2505 if (isVectorType(Arg->getType())) { |
2508 ParameterAreaSizeBytes = | 2506 ParameterAreaSizeBytes = |
2509 Traits::applyStackAlignment(ParameterAreaSizeBytes); | 2507 Traits::applyStackAlignment(ParameterAreaSizeBytes); |
2510 } | 2508 } |
2511 Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType); | 2509 Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType); |
2512 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); | 2510 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); |
(...skipping 4093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6606 _psrl(Reg, Ctx->getConstantInt8(1)); | 6604 _psrl(Reg, Ctx->getConstantInt8(1)); |
6607 return Reg; | 6605 return Reg; |
6608 } | 6606 } |
6609 | 6607 |
6610 template <typename TraitsType> | 6608 template <typename TraitsType> |
6611 typename TargetX86Base<TraitsType>::X86OperandMem * | 6609 typename TargetX86Base<TraitsType>::X86OperandMem * |
6612 TargetX86Base<TraitsType>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot, | 6610 TargetX86Base<TraitsType>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot, |
6613 uint32_t Offset) { | 6611 uint32_t Offset) { |
6614 // Ensure that Loc is a stack slot. | 6612 // Ensure that Loc is a stack slot. |
6615 assert(Slot->mustNotHaveReg()); | 6613 assert(Slot->mustNotHaveReg()); |
6616 assert(Slot->getRegNum() == RegNumT::NoRegister); | 6614 assert(Slot->getRegNum().hasNoValue()); |
6617 // Compute the location of Loc in memory. | 6615 // Compute the location of Loc in memory. |
6618 // TODO(wala,stichnot): lea should not | 6616 // TODO(wala,stichnot): lea should not |
6619 // be required. The address of the stack slot is known at compile time | 6617 // be required. The address of the stack slot is known at compile time |
6620 // (although not until after addProlog()). | 6618 // (although not until after addProlog()). |
6621 constexpr Type PointerType = IceType_i32; | 6619 constexpr Type PointerType = IceType_i32; |
6622 Variable *Loc = makeReg(PointerType); | 6620 Variable *Loc = makeReg(PointerType); |
6623 _lea(Loc, Slot); | 6621 _lea(Loc, Slot); |
6624 Constant *ConstantOffset = Ctx->getConstantInt32(Offset); | 6622 Constant *ConstantOffset = Ctx->getConstantInt32(Offset); |
6625 return X86OperandMem::create(Func, Ty, Loc, ConstantOffset); | 6623 return X86OperandMem::create(Func, Ty, Loc, ConstantOffset); |
6626 } | 6624 } |
6627 | 6625 |
6628 /// Lowering helper to copy a scalar integer source operand into some 8-bit GPR. | 6626 /// Lowering helper to copy a scalar integer source operand into some 8-bit GPR. |
6629 /// Src is assumed to already be legalized. If the source operand is known to | 6627 /// Src is assumed to already be legalized. If the source operand is known to |
6630 /// be a memory or immediate operand, a simple mov will suffice. But if the | 6628 /// be a memory or immediate operand, a simple mov will suffice. But if the |
6631 /// source operand can be a physical register, then it must first be copied into | 6629 /// source operand can be a physical register, then it must first be copied into |
6632 /// a physical register that is truncable to 8-bit, then truncated into a | 6630 /// a physical register that is truncable to 8-bit, then truncated into a |
6633 /// physical register that can receive a truncation, and finally copied into the | 6631 /// physical register that can receive a truncation, and finally copied into the |
6634 /// result 8-bit register (which in general can be any 8-bit register). For | 6632 /// result 8-bit register (which in general can be any 8-bit register). For |
6635 /// example, moving %ebp into %ah may be accomplished as: | 6633 /// example, moving %ebp into %ah may be accomplished as: |
6636 /// movl %ebp, %edx | 6634 /// movl %ebp, %edx |
6637 /// mov_trunc %edx, %dl // this redundant assignment is ultimately elided | 6635 /// mov_trunc %edx, %dl // this redundant assignment is ultimately elided |
6638 /// movb %dl, %ah | 6636 /// movb %dl, %ah |
6639 /// On the other hand, moving a memory or immediate operand into ah: | 6637 /// On the other hand, moving a memory or immediate operand into ah: |
6640 /// movb 4(%ebp), %ah | 6638 /// movb 4(%ebp), %ah |
6641 /// movb $my_imm, %ah | 6639 /// movb $my_imm, %ah |
6642 /// | 6640 /// |
6643 /// Note #1. On a 64-bit target, the "movb 4(%ebp), %ah" is likely not | 6641 /// Note #1. On a 64-bit target, the "movb 4(%ebp), %ah" is likely not |
6644 /// encodable, so RegNum=Reg_ah should NOT be given as an argument. Instead, | 6642 /// encodable, so RegNum=Reg_ah should NOT be given as an argument. Instead, |
6645 /// use RegNum=NoRegister and then let the caller do a separate copy into | 6643 /// use RegNum=RegNumT() and then let the caller do a separate copy into |
6646 /// Reg_ah. | 6644 /// Reg_ah. |
6647 /// | 6645 /// |
6648 /// Note #2. ConstantRelocatable operands are also put through this process | 6646 /// Note #2. ConstantRelocatable operands are also put through this process |
6649 /// (not truncated directly) because our ELF emitter does R_386_32 relocations | 6647 /// (not truncated directly) because our ELF emitter does R_386_32 relocations |
6650 /// but not R_386_8 relocations. | 6648 /// but not R_386_8 relocations. |
6651 /// | 6649 /// |
6652 /// Note #3. If Src is a Variable, the result will be an infinite-weight i8 | 6650 /// Note #3. If Src is a Variable, the result will be an infinite-weight i8 |
6653 /// Variable with the RCX86_IsTrunc8Rcvr register class. As such, this helper | 6651 /// Variable with the RCX86_IsTrunc8Rcvr register class. As such, this helper |
6654 /// is a convenient way to prevent ah/bh/ch/dh from being an (invalid) argument | 6652 /// is a convenient way to prevent ah/bh/ch/dh from being an (invalid) argument |
6655 /// to the pinsrb instruction. | 6653 /// to the pinsrb instruction. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6706 const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi(); | 6704 const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi(); |
6707 const Type Ty = From->getType(); | 6705 const Type Ty = From->getType(); |
6708 // Assert that a physical register is allowed. To date, all calls to | 6706 // Assert that a physical register is allowed. To date, all calls to |
6709 // legalize() allow a physical register. If a physical register needs to be | 6707 // legalize() allow a physical register. If a physical register needs to be |
6710 // explicitly disallowed, then new code will need to be written to force a | 6708 // explicitly disallowed, then new code will need to be written to force a |
6711 // spill. | 6709 // spill. |
6712 assert(Allowed & Legal_Reg); | 6710 assert(Allowed & Legal_Reg); |
6713 // If we're asking for a specific physical register, make sure we're not | 6711 // If we're asking for a specific physical register, make sure we're not |
6714 // allowing any other operand kinds. (This could be future work, e.g. allow | 6712 // allowing any other operand kinds. (This could be future work, e.g. allow |
6715 // the shl shift amount to be either an immediate or in ecx.) | 6713 // the shl shift amount to be either an immediate or in ecx.) |
6716 assert(RegNum == RegNumT::NoRegister || Allowed == Legal_Reg); | 6714 assert(RegNum.hasNoValue() || Allowed == Legal_Reg); |
6717 | 6715 |
6718 // Substitute with an available infinite-weight variable if possible. Only do | 6716 // Substitute with an available infinite-weight variable if possible. Only do |
6719 // this when we are not asking for a specific register, and when the | 6717 // this when we are not asking for a specific register, and when the |
6720 // substitution is not locked to a specific register, and when the types | 6718 // substitution is not locked to a specific register, and when the types |
6721 // match, in order to capture the vast majority of opportunities and avoid | 6719 // match, in order to capture the vast majority of opportunities and avoid |
6722 // corner cases in the lowering. | 6720 // corner cases in the lowering. |
6723 if (RegNum == RegNumT::NoRegister) { | 6721 if (RegNum.hasNoValue()) { |
6724 if (Variable *Subst = getContext().availabilityGet(From)) { | 6722 if (Variable *Subst = getContext().availabilityGet(From)) { |
6725 // At this point we know there is a potential substitution available. | 6723 // At this point we know there is a potential substitution available. |
6726 if (Subst->mustHaveReg() && !Subst->hasReg()) { | 6724 if (Subst->mustHaveReg() && !Subst->hasReg()) { |
6727 // At this point we know the substitution will have a register. | 6725 // At this point we know the substitution will have a register. |
6728 if (From->getType() == Subst->getType()) { | 6726 if (From->getType() == Subst->getType()) { |
6729 // At this point we know the substitution's register is compatible. | 6727 // At this point we know the substitution's register is compatible. |
6730 return Subst; | 6728 return Subst; |
6731 } | 6729 } |
6732 } | 6730 } |
6733 } | 6731 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6774 return From; | 6772 return From; |
6775 Const = llvm::cast<Constant>(From); | 6773 Const = llvm::cast<Constant>(From); |
6776 } | 6774 } |
6777 // There should be no constants of vector type (other than undef). | 6775 // There should be no constants of vector type (other than undef). |
6778 assert(!isVectorType(Ty)); | 6776 assert(!isVectorType(Ty)); |
6779 | 6777 |
6780 // If the operand is a 64 bit constant integer we need to legalize it to a | 6778 // If the operand is a 64 bit constant integer we need to legalize it to a |
6781 // register in x86-64. | 6779 // register in x86-64. |
6782 if (Traits::Is64Bit) { | 6780 if (Traits::Is64Bit) { |
6783 if (llvm::isa<ConstantInteger64>(Const)) { | 6781 if (llvm::isa<ConstantInteger64>(Const)) { |
6784 if (RegNum != RegNumT::NoRegister) { | 6782 if (RegNum.hasValue()) { |
6785 assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum); | 6783 assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum); |
6786 } | 6784 } |
6787 return copyToReg(Const, RegNum); | 6785 return copyToReg(Const, RegNum); |
6788 } | 6786 } |
6789 } | 6787 } |
6790 | 6788 |
6791 // If the operand is an 32 bit constant integer, we should check whether we | 6789 // If the operand is an 32 bit constant integer, we should check whether we |
6792 // need to randomize it or pool it. | 6790 // need to randomize it or pool it. |
6793 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { | 6791 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { |
6794 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); | 6792 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6857 if (MustRematerialize) { | 6855 if (MustRematerialize) { |
6858 assert(Ty == IceType_i32); | 6856 assert(Ty == IceType_i32); |
6859 Variable *NewVar = makeReg(Ty, RegNum); | 6857 Variable *NewVar = makeReg(Ty, RegNum); |
6860 // Since Var is rematerializable, the offset will be added when the lea is | 6858 // Since Var is rematerializable, the offset will be added when the lea is |
6861 // emitted. | 6859 // emitted. |
6862 constexpr Constant *NoOffset = nullptr; | 6860 constexpr Constant *NoOffset = nullptr; |
6863 auto *Mem = X86OperandMem::create(Func, Ty, Var, NoOffset); | 6861 auto *Mem = X86OperandMem::create(Func, Ty, Var, NoOffset); |
6864 _lea(NewVar, Mem); | 6862 _lea(NewVar, Mem); |
6865 From = NewVar; | 6863 From = NewVar; |
6866 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 6864 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
6867 (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) { | 6865 (RegNum.hasValue() && RegNum != Var->getRegNum())) { |
6868 From = copyToReg(From, RegNum); | 6866 From = copyToReg(From, RegNum); |
6869 } | 6867 } |
6870 return From; | 6868 return From; |
6871 } | 6869 } |
6872 | 6870 |
6873 llvm::report_fatal_error("Unhandled operand kind in legalize()"); | 6871 llvm::report_fatal_error("Unhandled operand kind in legalize()"); |
6874 return From; | 6872 return From; |
6875 } | 6873 } |
6876 | 6874 |
6877 /// Provide a trivial wrapper to legalize() for this common usage. | 6875 /// Provide a trivial wrapper to legalize() for this common usage. |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6960 // randomization/pooling. | 6958 // randomization/pooling. |
6961 return llvm::cast<X86OperandMem>(DoLegalize ? legalize(Mem) | 6959 return llvm::cast<X86OperandMem>(DoLegalize ? legalize(Mem) |
6962 : randomizeOrPoolImmediate(Mem)); | 6960 : randomizeOrPoolImmediate(Mem)); |
6963 } | 6961 } |
6964 | 6962 |
6965 template <typename TraitsType> | 6963 template <typename TraitsType> |
6966 Variable *TargetX86Base<TraitsType>::makeReg(Type Type, RegNumT RegNum) { | 6964 Variable *TargetX86Base<TraitsType>::makeReg(Type Type, RegNumT RegNum) { |
6967 // There aren't any 64-bit integer registers for x86-32. | 6965 // There aren't any 64-bit integer registers for x86-32. |
6968 assert(Traits::Is64Bit || Type != IceType_i64); | 6966 assert(Traits::Is64Bit || Type != IceType_i64); |
6969 Variable *Reg = Func->makeVariable(Type); | 6967 Variable *Reg = Func->makeVariable(Type); |
6970 if (RegNum == RegNumT::NoRegister) | 6968 if (RegNum.hasValue()) |
| 6969 Reg->setRegNum(RegNum); |
| 6970 else |
6971 Reg->setMustHaveReg(); | 6971 Reg->setMustHaveReg(); |
6972 else | |
6973 Reg->setRegNum(RegNum); | |
6974 return Reg; | 6972 return Reg; |
6975 } | 6973 } |
6976 | 6974 |
6977 template <typename TraitsType> | 6975 template <typename TraitsType> |
6978 const Type TargetX86Base<TraitsType>::TypeForSize[] = { | 6976 const Type TargetX86Base<TraitsType>::TypeForSize[] = { |
6979 IceType_i8, IceType_i16, IceType_i32, IceType_f64, IceType_v16i8}; | 6977 IceType_i8, IceType_i16, IceType_i32, IceType_f64, IceType_v16i8}; |
6980 template <typename TraitsType> | 6978 template <typename TraitsType> |
6981 Type TargetX86Base<TraitsType>::largestTypeInSize(uint32_t Size, | 6979 Type TargetX86Base<TraitsType>::largestTypeInSize(uint32_t Size, |
6982 uint32_t MaxSize) { | 6980 uint32_t MaxSize) { |
6983 assert(Size != 0); | 6981 assert(Size != 0); |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7234 // TO: | 7232 // TO: |
7235 // insert: mov $label, RegTemp | 7233 // insert: mov $label, RegTemp |
7236 // insert: lea [base, RegTemp], RegTemp | 7234 // insert: lea [base, RegTemp], RegTemp |
7237 // =>[RegTemp, index, shift] | 7235 // =>[RegTemp, index, shift] |
7238 | 7236 |
7239 // Memory operand should never exist as source operands in phi lowering | 7237 // Memory operand should never exist as source operands in phi lowering |
7240 // assignments, so there is no need to reuse any registers here. For | 7238 // assignments, so there is no need to reuse any registers here. For |
7241 // phi lowering, we should not ask for new physical registers in | 7239 // phi lowering, we should not ask for new physical registers in |
7242 // general. However, if we do meet Memory Operand during phi lowering, | 7240 // general. However, if we do meet Memory Operand during phi lowering, |
7243 // we should not blind or pool the immediates for now. | 7241 // we should not blind or pool the immediates for now. |
7244 if (RegNum != RegNumT::NoRegister) | 7242 if (RegNum.hasValue()) |
7245 return MemOperand; | 7243 return MemOperand; |
7246 Variable *RegTemp = makeReg(IceType_i32); | 7244 Variable *RegTemp = makeReg(IceType_i32); |
7247 IceString Label; | 7245 IceString Label; |
7248 llvm::raw_string_ostream Label_stream(Label); | 7246 llvm::raw_string_ostream Label_stream(Label); |
7249 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); | 7247 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); |
7250 MemOperand->getOffset()->setShouldBePooled(true); | 7248 MemOperand->getOffset()->setShouldBePooled(true); |
7251 constexpr RelocOffsetT SymOffset = 0; | 7249 constexpr RelocOffsetT SymOffset = 0; |
7252 constexpr bool SuppressMangling = true; | 7250 constexpr bool SuppressMangling = true; |
7253 Constant *Symbol = | 7251 Constant *Symbol = |
7254 Ctx->getConstantSym(SymOffset, Label_stream.str(), SuppressMangling); | 7252 Ctx->getConstantSym(SymOffset, Label_stream.str(), SuppressMangling); |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7419 emitGlobal(*Var, SectionSuffix); | 7417 emitGlobal(*Var, SectionSuffix); |
7420 } | 7418 } |
7421 } | 7419 } |
7422 } break; | 7420 } break; |
7423 } | 7421 } |
7424 } | 7422 } |
7425 } // end of namespace X86NAMESPACE | 7423 } // end of namespace X86NAMESPACE |
7426 } // end of namespace Ice | 7424 } // end of namespace Ice |
7427 | 7425 |
7428 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 7426 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
OLD | NEW |