| 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 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 TargetInstructionSet::BaseInstructionSet) { | 370 TargetInstructionSet::BaseInstructionSet) { |
| 371 InstructionSet = static_cast<InstructionSetEnum>( | 371 InstructionSet = static_cast<InstructionSetEnum>( |
| 372 (Func->getContext()->getFlags().getTargetInstructionSet() - | 372 (Func->getContext()->getFlags().getTargetInstructionSet() - |
| 373 TargetInstructionSet::X86InstructionSet_Begin) + | 373 TargetInstructionSet::X86InstructionSet_Begin) + |
| 374 Traits::InstructionSet::Begin); | 374 Traits::InstructionSet::Begin); |
| 375 } | 375 } |
| 376 } | 376 } |
| 377 | 377 |
| 378 template <typename TraitsType> | 378 template <typename TraitsType> |
| 379 void TargetX86Base<TraitsType>::staticInit(GlobalContext *Ctx) { | 379 void TargetX86Base<TraitsType>::staticInit(GlobalContext *Ctx) { |
| 380 RegNumT::setLimit(Traits::RegisterSet::Reg_NUM); |
| 380 Traits::initRegisterSet(Ctx->getFlags(), &TypeToRegisterSet, | 381 Traits::initRegisterSet(Ctx->getFlags(), &TypeToRegisterSet, |
| 381 &RegisterAliases); | 382 &RegisterAliases); |
| 382 for (size_t i = 0; i < TypeToRegisterSet.size(); ++i) | 383 for (size_t i = 0; i < TypeToRegisterSet.size(); ++i) |
| 383 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; | 384 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; |
| 384 filterTypeToRegisterSet(Ctx, Traits::RegisterSet::Reg_NUM, | 385 filterTypeToRegisterSet(Ctx, Traits::RegisterSet::Reg_NUM, |
| 385 TypeToRegisterSet.data(), TypeToRegisterSet.size(), | 386 TypeToRegisterSet.data(), TypeToRegisterSet.size(), |
| 386 Traits::getRegName, getRegClassName); | 387 Traits::getRegName, getRegClassName); |
| 387 PcRelFixup = Traits::FK_PcRel; | 388 PcRelFixup = Traits::FK_PcRel; |
| 388 AbsFixup = | 389 AbsFixup = |
| 389 Ctx->getFlags().getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; | 390 Ctx->getFlags().getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 | 836 |
| 836 template <typename TraitsType> | 837 template <typename TraitsType> |
| 837 bool TargetX86Base<TraitsType>::doBranchOpt(Inst *I, const CfgNode *NextNode) { | 838 bool TargetX86Base<TraitsType>::doBranchOpt(Inst *I, const CfgNode *NextNode) { |
| 838 if (auto *Br = llvm::dyn_cast<InstX86Br>(I)) { | 839 if (auto *Br = llvm::dyn_cast<InstX86Br>(I)) { |
| 839 return Br->optimizeBranch(NextNode); | 840 return Br->optimizeBranch(NextNode); |
| 840 } | 841 } |
| 841 return false; | 842 return false; |
| 842 } | 843 } |
| 843 | 844 |
| 844 template <typename TraitsType> | 845 template <typename TraitsType> |
| 845 Variable *TargetX86Base<TraitsType>::getPhysicalRegister(SizeT RegNum, | 846 Variable *TargetX86Base<TraitsType>::getPhysicalRegister(RegNumT RegNum, |
| 846 Type Ty) { | 847 Type Ty) { |
| 847 if (Ty == IceType_void) | 848 if (Ty == IceType_void) |
| 848 Ty = IceType_i32; | 849 Ty = IceType_i32; |
| 849 if (PhysicalRegisters[Ty].empty()) | 850 if (PhysicalRegisters[Ty].empty()) |
| 850 PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM); | 851 PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM); |
| 851 assert(RegNum < PhysicalRegisters[Ty].size()); | 852 assert(unsigned(RegNum) < PhysicalRegisters[Ty].size()); |
| 852 Variable *Reg = PhysicalRegisters[Ty][RegNum]; | 853 Variable *Reg = PhysicalRegisters[Ty][RegNum]; |
| 853 if (Reg == nullptr) { | 854 if (Reg == nullptr) { |
| 854 Reg = Func->makeVariable(Ty); | 855 Reg = Func->makeVariable(Ty); |
| 855 Reg->setRegNum(RegNum); | 856 Reg->setRegNum(RegNum); |
| 856 PhysicalRegisters[Ty][RegNum] = Reg; | 857 PhysicalRegisters[Ty][RegNum] = Reg; |
| 857 // Specially mark a named physical register as an "argument" so that it is | 858 // Specially mark a named physical register as an "argument" so that it is |
| 858 // considered live upon function entry. Otherwise it's possible to get | 859 // considered live upon function entry. Otherwise it's possible to get |
| 859 // liveness validation errors for saving callee-save registers. | 860 // liveness validation errors for saving callee-save registers. |
| 860 Func->addImplicitArg(Reg); | 861 Func->addImplicitArg(Reg); |
| 861 // Don't bother tracking the live range of a named physical register. | 862 // Don't bother tracking the live range of a named physical register. |
| 862 Reg->setIgnoreLiveness(); | 863 Reg->setIgnoreLiveness(); |
| 863 } | 864 } |
| 864 assert(Traits::getGprForType(Ty, RegNum) == static_cast<int32_t>(RegNum)); | 865 assert(Traits::getGprForType(Ty, RegNum) == RegNum); |
| 865 return Reg; | 866 return Reg; |
| 866 } | 867 } |
| 867 | 868 |
| 868 template <typename TraitsType> | 869 template <typename TraitsType> |
| 869 IceString TargetX86Base<TraitsType>::getRegName(SizeT RegNum, Type Ty) const { | 870 IceString TargetX86Base<TraitsType>::getRegName(RegNumT RegNum, Type Ty) const { |
| 870 return Traits::getRegName(Traits::getGprForType(Ty, RegNum)); | 871 return Traits::getRegName(Traits::getGprForType(Ty, RegNum)); |
| 871 } | 872 } |
| 872 | 873 |
| 873 template <typename TraitsType> | 874 template <typename TraitsType> |
| 874 void TargetX86Base<TraitsType>::emitVariable(const Variable *Var) const { | 875 void TargetX86Base<TraitsType>::emitVariable(const Variable *Var) const { |
| 875 if (!BuildDefs::dump()) | 876 if (!BuildDefs::dump()) |
| 876 return; | 877 return; |
| 877 Ostream &Str = Ctx->getStrEmit(); | 878 Ostream &Str = Ctx->getStrEmit(); |
| 878 if (Var->hasReg()) { | 879 if (Var->hasReg()) { |
| 879 const bool Is64BitSandboxing = Traits::Is64Bit && NeedSandboxing; | 880 const bool Is64BitSandboxing = Traits::Is64Bit && NeedSandboxing; |
| 880 const Type VarType = (Var->isRematerializable() && Is64BitSandboxing) | 881 const Type VarType = (Var->isRematerializable() && Is64BitSandboxing) |
| 881 ? IceType_i64 | 882 ? IceType_i64 |
| 882 : Var->getType(); | 883 : Var->getType(); |
| 883 Str << "%" << getRegName(Var->getRegNum(), VarType); | 884 Str << "%" << getRegName(Var->getRegNum(), VarType); |
| 884 return; | 885 return; |
| 885 } | 886 } |
| 886 if (Var->mustHaveReg()) { | 887 if (Var->mustHaveReg()) { |
| 887 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + | 888 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + |
| 888 ") has no register assigned - function " + | 889 ") has no register assigned - function " + |
| 889 Func->getFunctionName()); | 890 Func->getFunctionName()); |
| 890 } | 891 } |
| 891 const int32_t Offset = Var->getStackOffset(); | 892 const int32_t Offset = Var->getStackOffset(); |
| 892 int32_t BaseRegNum = Var->getBaseRegNum(); | 893 auto BaseRegNum = Var->getBaseRegNum(); |
| 893 if (BaseRegNum == Variable::NoRegister) | 894 if (BaseRegNum == RegNumT::NoRegister) |
| 894 BaseRegNum = getFrameOrStackReg(); | 895 BaseRegNum = getFrameOrStackReg(); |
| 895 // Print in the form "Offset(%reg)", taking care that: | 896 // Print in the form "Offset(%reg)", taking care that: |
| 896 // - Offset is never printed when it is 0 | 897 // - Offset is never printed when it is 0 |
| 897 | 898 |
| 898 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); | 899 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); |
| 899 // Only print Offset when it is nonzero, regardless of DecorateAsm. | 900 // Only print Offset when it is nonzero, regardless of DecorateAsm. |
| 900 if (Offset) { | 901 if (Offset) { |
| 901 if (DecorateAsm) { | 902 if (DecorateAsm) { |
| 902 Str << Var->getSymbolicStackOffset(Func); | 903 Str << Var->getSymbolicStackOffset(Func); |
| 903 } else { | 904 } else { |
| 904 Str << Offset; | 905 Str << Offset; |
| 905 } | 906 } |
| 906 } | 907 } |
| 907 const Type FrameSPTy = Traits::WordType; | 908 const Type FrameSPTy = Traits::WordType; |
| 908 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; | 909 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; |
| 909 } | 910 } |
| 910 | 911 |
| 911 template <typename TraitsType> | 912 template <typename TraitsType> |
| 912 typename TargetX86Base<TraitsType>::X86Address | 913 typename TargetX86Base<TraitsType>::X86Address |
| 913 TargetX86Base<TraitsType>::stackVarToAsmOperand(const Variable *Var) const { | 914 TargetX86Base<TraitsType>::stackVarToAsmOperand(const Variable *Var) const { |
| 914 if (Var->hasReg()) | 915 if (Var->hasReg()) |
| 915 llvm::report_fatal_error("Stack Variable has a register assigned"); | 916 llvm::report_fatal_error("Stack Variable has a register assigned"); |
| 916 if (Var->mustHaveReg()) { | 917 if (Var->mustHaveReg()) { |
| 917 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + | 918 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName(Func) + |
| 918 ") has no register assigned - function " + | 919 ") has no register assigned - function " + |
| 919 Func->getFunctionName()); | 920 Func->getFunctionName()); |
| 920 } | 921 } |
| 921 int32_t Offset = Var->getStackOffset(); | 922 int32_t Offset = Var->getStackOffset(); |
| 922 int32_t BaseRegNum = Var->getBaseRegNum(); | 923 auto BaseRegNum = Var->getBaseRegNum(); |
| 923 if (Var->getBaseRegNum() == Variable::NoRegister) | 924 if (Var->getBaseRegNum() == RegNumT::NoRegister) |
| 924 BaseRegNum = getFrameOrStackReg(); | 925 BaseRegNum = getFrameOrStackReg(); |
| 925 return X86Address(Traits::getEncodedGPR(BaseRegNum), Offset, | 926 return X86Address(Traits::getEncodedGPR(BaseRegNum), Offset, |
| 926 AssemblerFixup::NoFixup); | 927 AssemblerFixup::NoFixup); |
| 927 } | 928 } |
| 928 | 929 |
| 929 template <typename TraitsType> | 930 template <typename TraitsType> |
| 930 void TargetX86Base<TraitsType>::addProlog(CfgNode *Node) { | 931 void TargetX86Base<TraitsType>::addProlog(CfgNode *Node) { |
| 931 // Stack frame layout: | 932 // Stack frame layout: |
| 932 // | 933 // |
| 933 // +------------------------+ | 934 // +------------------------+ |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1007 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, | 1008 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, |
| 1008 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, | 1009 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, |
| 1009 &LocalsSlotsAlignmentBytes, TargetVarHook); | 1010 &LocalsSlotsAlignmentBytes, TargetVarHook); |
| 1010 uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes; | 1011 uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes; |
| 1011 SpillAreaSizeBytes += GlobalsSize; | 1012 SpillAreaSizeBytes += GlobalsSize; |
| 1012 | 1013 |
| 1013 // Add push instructions for preserved registers. | 1014 // Add push instructions for preserved registers. |
| 1014 uint32_t NumCallee = 0; | 1015 uint32_t NumCallee = 0; |
| 1015 size_t PreservedRegsSizeBytes = 0; | 1016 size_t PreservedRegsSizeBytes = 0; |
| 1016 llvm::SmallBitVector Pushed(CalleeSaves.size()); | 1017 llvm::SmallBitVector Pushed(CalleeSaves.size()); |
| 1017 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | 1018 for (RegNumT i : RegNumBVIter(CalleeSaves)) { |
| 1018 const int32_t Canonical = Traits::getBaseReg(i); | 1019 const auto Canonical = Traits::getBaseReg(i); |
| 1019 assert(Canonical == Traits::getBaseReg(Canonical)); | 1020 assert(Canonical == Traits::getBaseReg(Canonical)); |
| 1020 if (CalleeSaves[i] && RegsUsed[i]) { | 1021 if (RegsUsed[i]) { |
| 1021 Pushed[Canonical] = true; | 1022 Pushed[Canonical] = true; |
| 1022 } | 1023 } |
| 1023 } | 1024 } |
| 1024 for (SizeT i = 0; i < Pushed.size(); ++i) { | 1025 for (RegNumT RegNum : RegNumBVIter(Pushed)) { |
| 1025 if (!Pushed[i]) | 1026 assert(RegNum == Traits::getBaseReg(RegNum)); |
| 1026 continue; | |
| 1027 assert(static_cast<int32_t>(i) == Traits::getBaseReg(i)); | |
| 1028 ++NumCallee; | 1027 ++NumCallee; |
| 1029 PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType); | 1028 PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType); |
| 1030 _push_reg(getPhysicalRegister(i, Traits::WordType)); | 1029 _push_reg(getPhysicalRegister(RegNum, Traits::WordType)); |
| 1031 } | 1030 } |
| 1032 Ctx->statsUpdateRegistersSaved(NumCallee); | 1031 Ctx->statsUpdateRegistersSaved(NumCallee); |
| 1033 | 1032 |
| 1034 // Generate "push frameptr; mov frameptr, stackptr" | 1033 // Generate "push frameptr; mov frameptr, stackptr" |
| 1035 if (IsEbpBasedFrame) { | 1034 if (IsEbpBasedFrame) { |
| 1036 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) | 1035 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) |
| 1037 .count() == 0); | 1036 .count() == 0); |
| 1038 PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType); | 1037 PreservedRegsSizeBytes += typeWidthInBytes(Traits::WordType); |
| 1039 _link_bp(); | 1038 _link_bp(); |
| 1040 } | 1039 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 | 1116 |
| 1118 emitGetIP(Node); | 1117 emitGetIP(Node); |
| 1119 | 1118 |
| 1120 const VarList &Args = Func->getArgs(); | 1119 const VarList &Args = Func->getArgs(); |
| 1121 size_t InArgsSizeBytes = 0; | 1120 size_t InArgsSizeBytes = 0; |
| 1122 unsigned NumXmmArgs = 0; | 1121 unsigned NumXmmArgs = 0; |
| 1123 unsigned NumGPRArgs = 0; | 1122 unsigned NumGPRArgs = 0; |
| 1124 for (Variable *Arg : Args) { | 1123 for (Variable *Arg : Args) { |
| 1125 // Skip arguments passed in registers. | 1124 // Skip arguments passed in registers. |
| 1126 if (isVectorType(Arg->getType())) { | 1125 if (isVectorType(Arg->getType())) { |
| 1127 if (Traits::getRegisterForXmmArgNum(NumXmmArgs) != Variable::NoRegister) { | 1126 if (Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) { |
| 1128 ++NumXmmArgs; | 1127 ++NumXmmArgs; |
| 1129 continue; | 1128 continue; |
| 1130 } | 1129 } |
| 1131 } else if (isScalarFloatingType(Arg->getType())) { | 1130 } else if (isScalarFloatingType(Arg->getType())) { |
| 1132 if (Traits::X86_PASS_SCALAR_FP_IN_XMM && | 1131 if (Traits::X86_PASS_SCALAR_FP_IN_XMM && |
| 1133 Traits::getRegisterForXmmArgNum(NumXmmArgs) != Variable::NoRegister) { | 1132 Traits::getRegisterForXmmArgNum(NumXmmArgs) != RegNumT::NoRegister) { |
| 1134 ++NumXmmArgs; | 1133 ++NumXmmArgs; |
| 1135 continue; | 1134 continue; |
| 1136 } | 1135 } |
| 1137 } else { | 1136 } else { |
| 1138 assert(isScalarIntegerType(Arg->getType())); | 1137 assert(isScalarIntegerType(Arg->getType())); |
| 1139 if (Traits::getRegisterForGprArgNum(Traits::WordType, NumGPRArgs) != | 1138 if (Traits::getRegisterForGprArgNum(Traits::WordType, NumGPRArgs) != |
| 1140 Variable::NoRegister) { | 1139 RegNumT::NoRegister) { |
| 1141 ++NumGPRArgs; | 1140 ++NumGPRArgs; |
| 1142 continue; | 1141 continue; |
| 1143 } | 1142 } |
| 1144 } | 1143 } |
| 1145 // 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 |
| 1146 // 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 |
| 1147 // fixed-size alloca instructions have executed. In this case, a stack | 1146 // fixed-size alloca instructions have executed. In this case, a stack |
| 1148 // 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 |
| 1149 // registers. | 1148 // registers. |
| 1150 size_t StackAdjBytes = 0; | 1149 size_t StackAdjBytes = 0; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 if (SpillAreaSizeBytes != 0) { | 1267 if (SpillAreaSizeBytes != 0) { |
| 1269 _add_sp(Ctx->getConstantInt32(SpillAreaSizeBytes)); | 1268 _add_sp(Ctx->getConstantInt32(SpillAreaSizeBytes)); |
| 1270 } | 1269 } |
| 1271 } | 1270 } |
| 1272 | 1271 |
| 1273 // Add pop instructions for preserved registers. | 1272 // Add pop instructions for preserved registers. |
| 1274 llvm::SmallBitVector CalleeSaves = | 1273 llvm::SmallBitVector CalleeSaves = |
| 1275 getRegisterSet(RegSet_CalleeSave, RegSet_None); | 1274 getRegisterSet(RegSet_CalleeSave, RegSet_None); |
| 1276 llvm::SmallBitVector Popped(CalleeSaves.size()); | 1275 llvm::SmallBitVector Popped(CalleeSaves.size()); |
| 1277 for (int32_t i = CalleeSaves.size() - 1; i >= 0; --i) { | 1276 for (int32_t i = CalleeSaves.size() - 1; i >= 0; --i) { |
| 1278 if (static_cast<SizeT>(i) == getFrameReg() && IsEbpBasedFrame) | 1277 const auto RegNum = RegNumT::fromInt(i); |
| 1278 if (RegNum == getFrameReg() && IsEbpBasedFrame) |
| 1279 continue; | 1279 continue; |
| 1280 const SizeT Canonical = Traits::getBaseReg(i); | 1280 const RegNumT Canonical = Traits::getBaseReg(RegNum); |
| 1281 if (CalleeSaves[i] && RegsUsed[i]) { | 1281 if (CalleeSaves[i] && RegsUsed[i]) { |
| 1282 Popped[Canonical] = true; | 1282 Popped[Canonical] = true; |
| 1283 } | 1283 } |
| 1284 } | 1284 } |
| 1285 for (int32_t i = Popped.size() - 1; i >= 0; --i) { | 1285 for (int32_t i = Popped.size() - 1; i >= 0; --i) { |
| 1286 if (!Popped[i]) | 1286 if (!Popped[i]) |
| 1287 continue; | 1287 continue; |
| 1288 assert(i == Traits::getBaseReg(i)); | 1288 const auto RegNum = RegNumT::fromInt(i); |
| 1289 _pop(getPhysicalRegister(i, Traits::WordType)); | 1289 assert(RegNum == Traits::getBaseReg(RegNum)); |
| 1290 _pop(getPhysicalRegister(RegNum, Traits::WordType)); |
| 1290 } | 1291 } |
| 1291 | 1292 |
| 1292 if (!NeedSandboxing) { | 1293 if (!NeedSandboxing) { |
| 1293 return; | 1294 return; |
| 1294 } | 1295 } |
| 1295 emitSandboxedReturn(); | 1296 emitSandboxedReturn(); |
| 1296 if (RI->getSrcSize()) { | 1297 if (RI->getSrcSize()) { |
| 1297 auto *RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 1298 auto *RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
| 1298 Context.insert<InstFakeUse>(RetValue); | 1299 Context.insert<InstFakeUse>(RetValue); |
| 1299 } | 1300 } |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1468 bool GprSlotsRemain = true; | 1469 bool GprSlotsRemain = true; |
| 1469 | 1470 |
| 1470 Context.init(Func->getEntryNode()); | 1471 Context.init(Func->getEntryNode()); |
| 1471 Context.setInsertPoint(Context.getCur()); | 1472 Context.setInsertPoint(Context.getCur()); |
| 1472 | 1473 |
| 1473 for (SizeT i = 0, End = Args.size(); | 1474 for (SizeT i = 0, End = Args.size(); |
| 1474 i < End && (XmmSlotsRemain || GprSlotsRemain); ++i) { | 1475 i < End && (XmmSlotsRemain || GprSlotsRemain); ++i) { |
| 1475 Variable *Arg = Args[i]; | 1476 Variable *Arg = Args[i]; |
| 1476 Type Ty = Arg->getType(); | 1477 Type Ty = Arg->getType(); |
| 1477 Variable *RegisterArg = nullptr; | 1478 Variable *RegisterArg = nullptr; |
| 1478 int32_t RegNum = Variable::NoRegister; | 1479 auto RegNum = RegNumT::NoRegister; |
| 1479 if (isVectorType(Ty)) { | 1480 if (isVectorType(Ty)) { |
| 1480 RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs); | 1481 RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs); |
| 1481 if (RegNum == Variable::NoRegister) { | 1482 if (RegNum == RegNumT::NoRegister) { |
| 1482 XmmSlotsRemain = false; | 1483 XmmSlotsRemain = false; |
| 1483 continue; | 1484 continue; |
| 1484 } | 1485 } |
| 1485 ++NumXmmArgs; | 1486 ++NumXmmArgs; |
| 1486 RegisterArg = Func->makeVariable(Ty); | 1487 RegisterArg = Func->makeVariable(Ty); |
| 1487 } else if (isScalarFloatingType(Ty)) { | 1488 } else if (isScalarFloatingType(Ty)) { |
| 1488 if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) { | 1489 if (!Traits::X86_PASS_SCALAR_FP_IN_XMM) { |
| 1489 continue; | 1490 continue; |
| 1490 } | 1491 } |
| 1491 RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs); | 1492 RegNum = Traits::getRegisterForXmmArgNum(NumXmmArgs); |
| 1492 if (RegNum == Variable::NoRegister) { | 1493 if (RegNum == RegNumT::NoRegister) { |
| 1493 XmmSlotsRemain = false; | 1494 XmmSlotsRemain = false; |
| 1494 continue; | 1495 continue; |
| 1495 } | 1496 } |
| 1496 ++NumXmmArgs; | 1497 ++NumXmmArgs; |
| 1497 RegisterArg = Func->makeVariable(Ty); | 1498 RegisterArg = Func->makeVariable(Ty); |
| 1498 } else if (isScalarIntegerType(Ty)) { | 1499 } else if (isScalarIntegerType(Ty)) { |
| 1499 RegNum = Traits::getRegisterForGprArgNum(Ty, NumGprArgs); | 1500 RegNum = Traits::getRegisterForGprArgNum(Ty, NumGprArgs); |
| 1500 if (RegNum == Variable::NoRegister) { | 1501 if (RegNum == RegNumT::NoRegister) { |
| 1501 GprSlotsRemain = false; | 1502 GprSlotsRemain = false; |
| 1502 continue; | 1503 continue; |
| 1503 } | 1504 } |
| 1504 ++NumGprArgs; | 1505 ++NumGprArgs; |
| 1505 RegisterArg = Func->makeVariable(Ty); | 1506 RegisterArg = Func->makeVariable(Ty); |
| 1506 } | 1507 } |
| 1507 assert(RegNum != Variable::NoRegister); | 1508 assert(RegNum != RegNumT::NoRegister); |
| 1508 assert(RegisterArg != nullptr); | 1509 assert(RegisterArg != nullptr); |
| 1509 // 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 |
| 1510 // 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 |
| 1511 // location of Arg. | 1512 // location of Arg. |
| 1512 if (BuildDefs::dump()) | 1513 if (BuildDefs::dump()) |
| 1513 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 1514 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 1514 RegisterArg->setRegNum(RegNum); | 1515 RegisterArg->setRegNum(RegNum); |
| 1515 RegisterArg->setIsArg(); | 1516 RegisterArg->setIsArg(); |
| 1516 Arg->setIsArg(false); | 1517 Arg->setIsArg(false); |
| 1517 | 1518 |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 _mov(T, Src0); | 2187 _mov(T, Src0); |
| 2187 if (!llvm::isa<ConstantInteger32>(Src1)) | 2188 if (!llvm::isa<ConstantInteger32>(Src1)) |
| 2188 Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl); | 2189 Src1 = copyToReg8(Src1, Traits::RegisterSet::Reg_cl); |
| 2189 _sar(T, Src1); | 2190 _sar(T, Src1); |
| 2190 _mov(Dest, T); | 2191 _mov(Dest, T); |
| 2191 break; | 2192 break; |
| 2192 case InstArithmetic::Udiv: { | 2193 case InstArithmetic::Udiv: { |
| 2193 // div and idiv are the few arithmetic operators that do not allow | 2194 // div and idiv are the few arithmetic operators that do not allow |
| 2194 // immediates as the operand. | 2195 // immediates as the operand. |
| 2195 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); | 2196 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); |
| 2196 uint32_t Eax; | 2197 RegNumT Eax; |
| 2197 uint32_t Edx; | 2198 RegNumT Edx; |
| 2198 switch (Ty) { | 2199 switch (Ty) { |
| 2199 default: | 2200 default: |
| 2200 llvm::report_fatal_error("Bad type for udiv"); | 2201 llvm::report_fatal_error("Bad type for udiv"); |
| 2201 case IceType_i64: | 2202 case IceType_i64: |
| 2202 Eax = Traits::getRaxOrDie(); | 2203 Eax = Traits::getRaxOrDie(); |
| 2203 Edx = Traits::getRdxOrDie(); | 2204 Edx = Traits::getRdxOrDie(); |
| 2204 break; | 2205 break; |
| 2205 case IceType_i32: | 2206 case IceType_i32: |
| 2206 Eax = Traits::RegisterSet::Reg_eax; | 2207 Eax = Traits::RegisterSet::Reg_eax; |
| 2207 Edx = Traits::RegisterSet::Reg_edx; | 2208 Edx = Traits::RegisterSet::Reg_edx; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2276 T_edx = makeReg(IceType_i16, Traits::RegisterSet::Reg_ax); | 2277 T_edx = makeReg(IceType_i16, Traits::RegisterSet::Reg_ax); |
| 2277 _mov(T, Src0, Traits::RegisterSet::Reg_al); | 2278 _mov(T, Src0, Traits::RegisterSet::Reg_al); |
| 2278 break; | 2279 break; |
| 2279 } | 2280 } |
| 2280 _cbwdq(T_edx, T); | 2281 _cbwdq(T_edx, T); |
| 2281 _idiv(T, Src1, T_edx); | 2282 _idiv(T, Src1, T_edx); |
| 2282 _mov(Dest, T); | 2283 _mov(Dest, T); |
| 2283 break; | 2284 break; |
| 2284 case InstArithmetic::Urem: { | 2285 case InstArithmetic::Urem: { |
| 2285 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); | 2286 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); |
| 2286 uint32_t Eax; | 2287 RegNumT Eax; |
| 2287 uint32_t Edx; | 2288 RegNumT Edx; |
| 2288 switch (Ty) { | 2289 switch (Ty) { |
| 2289 default: | 2290 default: |
| 2290 llvm::report_fatal_error("Bad type for urem"); | 2291 llvm::report_fatal_error("Bad type for urem"); |
| 2291 case IceType_i64: | 2292 case IceType_i64: |
| 2292 Eax = Traits::getRaxOrDie(); | 2293 Eax = Traits::getRaxOrDie(); |
| 2293 Edx = Traits::getRdxOrDie(); | 2294 Edx = Traits::getRdxOrDie(); |
| 2294 break; | 2295 break; |
| 2295 case IceType_i32: | 2296 case IceType_i32: |
| 2296 Eax = Traits::RegisterSet::Reg_eax; | 2297 Eax = Traits::RegisterSet::Reg_eax; |
| 2297 Edx = Traits::RegisterSet::Reg_edx; | 2298 Edx = Traits::RegisterSet::Reg_edx; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2345 _add(T, Src0); | 2346 _add(T, Src0); |
| 2346 _and(T, Ctx->getConstantInt(Ty, -(1 << LogDiv))); | 2347 _and(T, Ctx->getConstantInt(Ty, -(1 << LogDiv))); |
| 2347 _sub(T, Src0); | 2348 _sub(T, Src0); |
| 2348 _neg(T); | 2349 _neg(T); |
| 2349 _mov(Dest, T); | 2350 _mov(Dest, T); |
| 2350 return; | 2351 return; |
| 2351 } | 2352 } |
| 2352 } | 2353 } |
| 2353 } | 2354 } |
| 2354 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); | 2355 Src1 = legalize(Src1, Legal_Reg | Legal_Mem); |
| 2355 uint32_t Eax; | 2356 RegNumT Eax; |
| 2356 uint32_t Edx; | 2357 RegNumT Edx; |
| 2357 switch (Ty) { | 2358 switch (Ty) { |
| 2358 default: | 2359 default: |
| 2359 llvm::report_fatal_error("Bad type for srem"); | 2360 llvm::report_fatal_error("Bad type for srem"); |
| 2360 case IceType_i64: | 2361 case IceType_i64: |
| 2361 Eax = Traits::getRaxOrDie(); | 2362 Eax = Traits::getRaxOrDie(); |
| 2362 Edx = Traits::getRdxOrDie(); | 2363 Edx = Traits::getRdxOrDie(); |
| 2363 break; | 2364 break; |
| 2364 case IceType_i32: | 2365 case IceType_i32: |
| 2365 Eax = Traits::RegisterSet::Reg_eax; | 2366 Eax = Traits::RegisterSet::Reg_eax; |
| 2366 Edx = Traits::RegisterSet::Reg_edx; | 2367 Edx = Traits::RegisterSet::Reg_edx; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2483 uint32_t ParameterAreaSizeBytes = 0; | 2484 uint32_t ParameterAreaSizeBytes = 0; |
| 2484 | 2485 |
| 2485 // Classify each argument operand according to the location where the argument | 2486 // Classify each argument operand according to the location where the argument |
| 2486 // is passed. | 2487 // is passed. |
| 2487 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 2488 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
| 2488 Operand *Arg = Instr->getArg(i); | 2489 Operand *Arg = Instr->getArg(i); |
| 2489 const Type Ty = Arg->getType(); | 2490 const Type Ty = Arg->getType(); |
| 2490 // 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. |
| 2491 assert(typeWidthInBytes(Ty) >= 4); | 2492 assert(typeWidthInBytes(Ty) >= 4); |
| 2492 if (isVectorType(Ty) && (Traits::getRegisterForXmmArgNum(XmmArgs.size()) != | 2493 if (isVectorType(Ty) && (Traits::getRegisterForXmmArgNum(XmmArgs.size()) != |
| 2493 Variable::NoRegister)) { | 2494 RegNumT::NoRegister)) { |
| 2494 XmmArgs.push_back(Arg); | 2495 XmmArgs.push_back(Arg); |
| 2495 } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM && | 2496 } else if (isScalarFloatingType(Ty) && Traits::X86_PASS_SCALAR_FP_IN_XMM && |
| 2496 (Traits::getRegisterForXmmArgNum(XmmArgs.size()) != | 2497 (Traits::getRegisterForXmmArgNum(XmmArgs.size()) != |
| 2497 Variable::NoRegister)) { | 2498 RegNumT::NoRegister)) { |
| 2498 XmmArgs.push_back(Arg); | 2499 XmmArgs.push_back(Arg); |
| 2499 } else if (isScalarIntegerType(Ty) && | 2500 } else if (isScalarIntegerType(Ty) && |
| 2500 (Traits::getRegisterForGprArgNum(Ty, GprArgs.size()) != | 2501 (Traits::getRegisterForGprArgNum(Ty, GprArgs.size()) != |
| 2501 Variable::NoRegister)) { | 2502 RegNumT::NoRegister)) { |
| 2502 GprArgs.emplace_back(Ty, Arg); | 2503 GprArgs.emplace_back(Ty, Arg); |
| 2503 } else { | 2504 } else { |
| 2504 // Place on stack. | 2505 // Place on stack. |
| 2505 StackArgs.push_back(Arg); | 2506 StackArgs.push_back(Arg); |
| 2506 if (isVectorType(Arg->getType())) { | 2507 if (isVectorType(Arg->getType())) { |
| 2507 ParameterAreaSizeBytes = | 2508 ParameterAreaSizeBytes = |
| 2508 Traits::applyStackAlignment(ParameterAreaSizeBytes); | 2509 Traits::applyStackAlignment(ParameterAreaSizeBytes); |
| 2509 } | 2510 } |
| 2510 Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType); | 2511 Variable *esp = getPhysicalRegister(getStackReg(), Traits::WordType); |
| 2511 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); | 2512 Constant *Loc = Ctx->getConstantInt32(ParameterAreaSizeBytes); |
| (...skipping 1755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4267 _mov(T_ecx, hiOperand(Desired)); | 4268 _mov(T_ecx, hiOperand(Desired)); |
| 4268 X86OperandMem *Addr = formMemoryOperand(Ptr, Ty); | 4269 X86OperandMem *Addr = formMemoryOperand(Ptr, Ty); |
| 4269 constexpr bool Locked = true; | 4270 constexpr bool Locked = true; |
| 4270 _cmpxchg8b(Addr, T_edx, T_eax, T_ecx, T_ebx, Locked); | 4271 _cmpxchg8b(Addr, T_edx, T_eax, T_ecx, T_ebx, Locked); |
| 4271 auto *DestLo = llvm::cast<Variable>(loOperand(DestPrev)); | 4272 auto *DestLo = llvm::cast<Variable>(loOperand(DestPrev)); |
| 4272 auto *DestHi = llvm::cast<Variable>(hiOperand(DestPrev)); | 4273 auto *DestHi = llvm::cast<Variable>(hiOperand(DestPrev)); |
| 4273 _mov(DestLo, T_eax); | 4274 _mov(DestLo, T_eax); |
| 4274 _mov(DestHi, T_edx); | 4275 _mov(DestHi, T_edx); |
| 4275 return; | 4276 return; |
| 4276 } | 4277 } |
| 4277 int32_t Eax; | 4278 RegNumT Eax; |
| 4278 switch (Ty) { | 4279 switch (Ty) { |
| 4279 default: | 4280 default: |
| 4280 llvm::report_fatal_error("Bad type for cmpxchg"); | 4281 llvm::report_fatal_error("Bad type for cmpxchg"); |
| 4281 case IceType_i64: | 4282 case IceType_i64: |
| 4282 Eax = Traits::getRaxOrDie(); | 4283 Eax = Traits::getRaxOrDie(); |
| 4283 break; | 4284 break; |
| 4284 case IceType_i32: | 4285 case IceType_i32: |
| 4285 Eax = Traits::RegisterSet::Reg_eax; | 4286 Eax = Traits::RegisterSet::Reg_eax; |
| 4286 break; | 4287 break; |
| 4287 case IceType_i16: | 4288 case IceType_i16: |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4538 // The address base (if any) is also reused in the loop. | 4539 // The address base (if any) is also reused in the loop. |
| 4539 if (Variable *Base = Addr->getBase()) | 4540 if (Variable *Base = Addr->getBase()) |
| 4540 Context.insert<InstFakeUse>(Base); | 4541 Context.insert<InstFakeUse>(Base); |
| 4541 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 4542 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 4542 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 4543 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 4543 _mov(DestLo, T_eax); | 4544 _mov(DestLo, T_eax); |
| 4544 _mov(DestHi, T_edx); | 4545 _mov(DestHi, T_edx); |
| 4545 return; | 4546 return; |
| 4546 } | 4547 } |
| 4547 X86OperandMem *Addr = formMemoryOperand(Ptr, Ty); | 4548 X86OperandMem *Addr = formMemoryOperand(Ptr, Ty); |
| 4548 int32_t Eax; | 4549 RegNumT Eax; |
| 4549 switch (Ty) { | 4550 switch (Ty) { |
| 4550 default: | 4551 default: |
| 4551 llvm::report_fatal_error("Bad type for atomicRMW"); | 4552 llvm::report_fatal_error("Bad type for atomicRMW"); |
| 4552 case IceType_i64: | 4553 case IceType_i64: |
| 4553 Eax = Traits::getRaxOrDie(); | 4554 Eax = Traits::getRaxOrDie(); |
| 4554 break; | 4555 break; |
| 4555 case IceType_i32: | 4556 case IceType_i32: |
| 4556 Eax = Traits::RegisterSet::Reg_eax; | 4557 Eax = Traits::RegisterSet::Reg_eax; |
| 4557 break; | 4558 break; |
| 4558 case IceType_i16: | 4559 case IceType_i16: |
| (...skipping 918 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5477 Opnd = Mem->getBase(); | 5478 Opnd = Mem->getBase(); |
| 5478 } | 5479 } |
| 5479 // At this point Opnd could be nullptr, or Variable, or Constant, or perhaps | 5480 // At this point Opnd could be nullptr, or Variable, or Constant, or perhaps |
| 5480 // something else. We only care if it is Variable. | 5481 // something else. We only care if it is Variable. |
| 5481 auto *Var = llvm::dyn_cast_or_null<Variable>(Opnd); | 5482 auto *Var = llvm::dyn_cast_or_null<Variable>(Opnd); |
| 5482 if (Var == nullptr) | 5483 if (Var == nullptr) |
| 5483 return; | 5484 return; |
| 5484 // We use lowerStore() to copy out-args onto the stack. This creates a memory | 5485 // We use lowerStore() to copy out-args onto the stack. This creates a memory |
| 5485 // operand with the stack pointer as the base register. Don't do bounds | 5486 // operand with the stack pointer as the base register. Don't do bounds |
| 5486 // checks on that. | 5487 // checks on that. |
| 5487 if (Var->getRegNum() == static_cast<int32_t>(getStackReg())) | 5488 if (Var->getRegNum() == getStackReg()) |
| 5488 return; | 5489 return; |
| 5489 | 5490 |
| 5490 auto *Label = InstX86Label::create(Func, this); | 5491 auto *Label = InstX86Label::create(Func, this); |
| 5491 _cmp(Opnd, Ctx->getConstantZero(IceType_i32)); | 5492 _cmp(Opnd, Ctx->getConstantZero(IceType_i32)); |
| 5492 _br(Traits::Cond::Br_e, Label); | 5493 _br(Traits::Cond::Br_e, Label); |
| 5493 _cmp(Opnd, Ctx->getConstantInt32(1)); | 5494 _cmp(Opnd, Ctx->getConstantInt32(1)); |
| 5494 _br(Traits::Cond::Br_e, Label); | 5495 _br(Traits::Cond::Br_e, Label); |
| 5495 Context.insert(Label); | 5496 Context.insert(Label); |
| 5496 } | 5497 } |
| 5497 | 5498 |
| (...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6499 // Compute the return type (if any); | 6500 // Compute the return type (if any); |
| 6500 Type ReturnType = IceType_void; | 6501 Type ReturnType = IceType_void; |
| 6501 Variable *Dest = Instr->getDest(); | 6502 Variable *Dest = Instr->getDest(); |
| 6502 if (Dest != nullptr) | 6503 if (Dest != nullptr) |
| 6503 ReturnType = Dest->getType(); | 6504 ReturnType = Dest->getType(); |
| 6504 return getCallStackArgumentsSizeBytes(ArgTypes, ReturnType); | 6505 return getCallStackArgumentsSizeBytes(ArgTypes, ReturnType); |
| 6505 } | 6506 } |
| 6506 | 6507 |
| 6507 template <typename TraitsType> | 6508 template <typename TraitsType> |
| 6508 Variable *TargetX86Base<TraitsType>::makeZeroedRegister(Type Ty, | 6509 Variable *TargetX86Base<TraitsType>::makeZeroedRegister(Type Ty, |
| 6509 int32_t RegNum) { | 6510 RegNumT RegNum) { |
| 6510 Variable *Reg = makeReg(Ty, RegNum); | 6511 Variable *Reg = makeReg(Ty, RegNum); |
| 6511 switch (Ty) { | 6512 switch (Ty) { |
| 6512 case IceType_i1: | 6513 case IceType_i1: |
| 6513 case IceType_i8: | 6514 case IceType_i8: |
| 6514 case IceType_i16: | 6515 case IceType_i16: |
| 6515 case IceType_i32: | 6516 case IceType_i32: |
| 6516 case IceType_i64: | 6517 case IceType_i64: |
| 6517 // Conservatively do "mov reg, 0" to avoid modifying FLAGS. | 6518 // Conservatively do "mov reg, 0" to avoid modifying FLAGS. |
| 6518 _mov(Reg, Ctx->getConstantZero(Ty)); | 6519 _mov(Reg, Ctx->getConstantZero(Ty)); |
| 6519 break; | 6520 break; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 6534 | 6535 |
| 6535 // There is no support for loading or emitting vector constants, so the vector | 6536 // There is no support for loading or emitting vector constants, so the vector |
| 6536 // values returned from makeVectorOfZeros, makeVectorOfOnes, etc. are | 6537 // values returned from makeVectorOfZeros, makeVectorOfOnes, etc. are |
| 6537 // initialized with register operations. | 6538 // initialized with register operations. |
| 6538 // | 6539 // |
| 6539 // TODO(wala): Add limited support for vector constants so that complex | 6540 // TODO(wala): Add limited support for vector constants so that complex |
| 6540 // initialization in registers is unnecessary. | 6541 // initialization in registers is unnecessary. |
| 6541 | 6542 |
| 6542 template <typename TraitsType> | 6543 template <typename TraitsType> |
| 6543 Variable *TargetX86Base<TraitsType>::makeVectorOfZeros(Type Ty, | 6544 Variable *TargetX86Base<TraitsType>::makeVectorOfZeros(Type Ty, |
| 6544 int32_t RegNum) { | 6545 RegNumT RegNum) { |
| 6545 return makeZeroedRegister(Ty, RegNum); | 6546 return makeZeroedRegister(Ty, RegNum); |
| 6546 } | 6547 } |
| 6547 | 6548 |
| 6548 template <typename TraitsType> | 6549 template <typename TraitsType> |
| 6549 Variable *TargetX86Base<TraitsType>::makeVectorOfMinusOnes(Type Ty, | 6550 Variable *TargetX86Base<TraitsType>::makeVectorOfMinusOnes(Type Ty, |
| 6550 int32_t RegNum) { | 6551 RegNumT RegNum) { |
| 6551 Variable *MinusOnes = makeReg(Ty, RegNum); | 6552 Variable *MinusOnes = makeReg(Ty, RegNum); |
| 6552 // Insert a FakeDef so the live range of MinusOnes is not overestimated. | 6553 // Insert a FakeDef so the live range of MinusOnes is not overestimated. |
| 6553 Context.insert<InstFakeDef>(MinusOnes); | 6554 Context.insert<InstFakeDef>(MinusOnes); |
| 6554 if (Ty == IceType_f64) | 6555 if (Ty == IceType_f64) |
| 6555 // Making a vector of minus ones of type f64 is currently only used for the | 6556 // Making a vector of minus ones of type f64 is currently only used for the |
| 6556 // fabs intrinsic. To use the f64 type to create this mask with pcmpeqq | 6557 // fabs intrinsic. To use the f64 type to create this mask with pcmpeqq |
| 6557 // requires SSE 4.1. Since we're just creating a mask, pcmpeqd does the | 6558 // requires SSE 4.1. Since we're just creating a mask, pcmpeqd does the |
| 6558 // same job and only requires SSE2. | 6559 // same job and only requires SSE2. |
| 6559 _pcmpeq(MinusOnes, MinusOnes, IceType_f32); | 6560 _pcmpeq(MinusOnes, MinusOnes, IceType_f32); |
| 6560 else | 6561 else |
| 6561 _pcmpeq(MinusOnes, MinusOnes); | 6562 _pcmpeq(MinusOnes, MinusOnes); |
| 6562 return MinusOnes; | 6563 return MinusOnes; |
| 6563 } | 6564 } |
| 6564 | 6565 |
| 6565 template <typename TraitsType> | 6566 template <typename TraitsType> |
| 6566 Variable *TargetX86Base<TraitsType>::makeVectorOfOnes(Type Ty, int32_t RegNum) { | 6567 Variable *TargetX86Base<TraitsType>::makeVectorOfOnes(Type Ty, RegNumT RegNum) { |
| 6567 Variable *Dest = makeVectorOfZeros(Ty, RegNum); | 6568 Variable *Dest = makeVectorOfZeros(Ty, RegNum); |
| 6568 Variable *MinusOne = makeVectorOfMinusOnes(Ty); | 6569 Variable *MinusOne = makeVectorOfMinusOnes(Ty); |
| 6569 _psub(Dest, MinusOne); | 6570 _psub(Dest, MinusOne); |
| 6570 return Dest; | 6571 return Dest; |
| 6571 } | 6572 } |
| 6572 | 6573 |
| 6573 template <typename TraitsType> | 6574 template <typename TraitsType> |
| 6574 Variable *TargetX86Base<TraitsType>::makeVectorOfHighOrderBits(Type Ty, | 6575 Variable *TargetX86Base<TraitsType>::makeVectorOfHighOrderBits(Type Ty, |
| 6575 int32_t RegNum) { | 6576 RegNumT RegNum) { |
| 6576 assert(Ty == IceType_v4i32 || Ty == IceType_v4f32 || Ty == IceType_v8i16 || | 6577 assert(Ty == IceType_v4i32 || Ty == IceType_v4f32 || Ty == IceType_v8i16 || |
| 6577 Ty == IceType_v16i8); | 6578 Ty == IceType_v16i8); |
| 6578 if (Ty == IceType_v4f32 || Ty == IceType_v4i32 || Ty == IceType_v8i16) { | 6579 if (Ty == IceType_v4f32 || Ty == IceType_v4i32 || Ty == IceType_v8i16) { |
| 6579 Variable *Reg = makeVectorOfOnes(Ty, RegNum); | 6580 Variable *Reg = makeVectorOfOnes(Ty, RegNum); |
| 6580 SizeT Shift = | 6581 SizeT Shift = |
| 6581 typeWidthInBytes(typeElementType(Ty)) * Traits::X86_CHAR_BIT - 1; | 6582 typeWidthInBytes(typeElementType(Ty)) * Traits::X86_CHAR_BIT - 1; |
| 6582 _psll(Reg, Ctx->getConstantInt8(Shift)); | 6583 _psll(Reg, Ctx->getConstantInt8(Shift)); |
| 6583 return Reg; | 6584 return Reg; |
| 6584 } else { | 6585 } else { |
| 6585 // SSE has no left shift operation for vectors of 8 bit integers. | 6586 // SSE has no left shift operation for vectors of 8 bit integers. |
| 6586 constexpr uint32_t HIGH_ORDER_BITS_MASK = 0x80808080; | 6587 constexpr uint32_t HIGH_ORDER_BITS_MASK = 0x80808080; |
| 6587 Constant *ConstantMask = Ctx->getConstantInt32(HIGH_ORDER_BITS_MASK); | 6588 Constant *ConstantMask = Ctx->getConstantInt32(HIGH_ORDER_BITS_MASK); |
| 6588 Variable *Reg = makeReg(Ty, RegNum); | 6589 Variable *Reg = makeReg(Ty, RegNum); |
| 6589 _movd(Reg, legalize(ConstantMask, Legal_Reg | Legal_Mem)); | 6590 _movd(Reg, legalize(ConstantMask, Legal_Reg | Legal_Mem)); |
| 6590 _pshufd(Reg, Reg, Ctx->getConstantZero(IceType_i8)); | 6591 _pshufd(Reg, Reg, Ctx->getConstantZero(IceType_i8)); |
| 6591 return Reg; | 6592 return Reg; |
| 6592 } | 6593 } |
| 6593 } | 6594 } |
| 6594 | 6595 |
| 6595 /// Construct a mask in a register that can be and'ed with a floating-point | 6596 /// Construct a mask in a register that can be and'ed with a floating-point |
| 6596 /// value to mask off its sign bit. The value will be <4 x 0x7fffffff> for f32 | 6597 /// value to mask off its sign bit. The value will be <4 x 0x7fffffff> for f32 |
| 6597 /// and v4f32, and <2 x 0x7fffffffffffffff> for f64. Construct it as vector of | 6598 /// and v4f32, and <2 x 0x7fffffffffffffff> for f64. Construct it as vector of |
| 6598 /// ones logically right shifted one bit. | 6599 /// ones logically right shifted one bit. |
| 6599 // TODO(stichnot): Fix the wala | 6600 // TODO(stichnot): Fix the wala |
| 6600 // TODO: above, to represent vector constants in memory. | 6601 // TODO: above, to represent vector constants in memory. |
| 6601 template <typename TraitsType> | 6602 template <typename TraitsType> |
| 6602 Variable *TargetX86Base<TraitsType>::makeVectorOfFabsMask(Type Ty, | 6603 Variable *TargetX86Base<TraitsType>::makeVectorOfFabsMask(Type Ty, |
| 6603 int32_t RegNum) { | 6604 RegNumT RegNum) { |
| 6604 Variable *Reg = makeVectorOfMinusOnes(Ty, RegNum); | 6605 Variable *Reg = makeVectorOfMinusOnes(Ty, RegNum); |
| 6605 _psrl(Reg, Ctx->getConstantInt8(1)); | 6606 _psrl(Reg, Ctx->getConstantInt8(1)); |
| 6606 return Reg; | 6607 return Reg; |
| 6607 } | 6608 } |
| 6608 | 6609 |
| 6609 template <typename TraitsType> | 6610 template <typename TraitsType> |
| 6610 typename TargetX86Base<TraitsType>::X86OperandMem * | 6611 typename TargetX86Base<TraitsType>::X86OperandMem * |
| 6611 TargetX86Base<TraitsType>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot, | 6612 TargetX86Base<TraitsType>::getMemoryOperandForStackSlot(Type Ty, Variable *Slot, |
| 6612 uint32_t Offset) { | 6613 uint32_t Offset) { |
| 6613 // Ensure that Loc is a stack slot. | 6614 // Ensure that Loc is a stack slot. |
| 6614 assert(Slot->mustNotHaveReg()); | 6615 assert(Slot->mustNotHaveReg()); |
| 6615 assert(Slot->getRegNum() == Variable::NoRegister); | 6616 assert(Slot->getRegNum() == RegNumT::NoRegister); |
| 6616 // Compute the location of Loc in memory. | 6617 // Compute the location of Loc in memory. |
| 6617 // TODO(wala,stichnot): lea should not | 6618 // TODO(wala,stichnot): lea should not |
| 6618 // be required. The address of the stack slot is known at compile time | 6619 // be required. The address of the stack slot is known at compile time |
| 6619 // (although not until after addProlog()). | 6620 // (although not until after addProlog()). |
| 6620 constexpr Type PointerType = IceType_i32; | 6621 constexpr Type PointerType = IceType_i32; |
| 6621 Variable *Loc = makeReg(PointerType); | 6622 Variable *Loc = makeReg(PointerType); |
| 6622 _lea(Loc, Slot); | 6623 _lea(Loc, Slot); |
| 6623 Constant *ConstantOffset = Ctx->getConstantInt32(Offset); | 6624 Constant *ConstantOffset = Ctx->getConstantInt32(Offset); |
| 6624 return X86OperandMem::create(Func, Ty, Loc, ConstantOffset); | 6625 return X86OperandMem::create(Func, Ty, Loc, ConstantOffset); |
| 6625 } | 6626 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 6646 /// | 6647 /// |
| 6647 /// Note #2. ConstantRelocatable operands are also put through this process | 6648 /// Note #2. ConstantRelocatable operands are also put through this process |
| 6648 /// (not truncated directly) because our ELF emitter does R_386_32 relocations | 6649 /// (not truncated directly) because our ELF emitter does R_386_32 relocations |
| 6649 /// but not R_386_8 relocations. | 6650 /// but not R_386_8 relocations. |
| 6650 /// | 6651 /// |
| 6651 /// Note #3. If Src is a Variable, the result will be an infinite-weight i8 | 6652 /// Note #3. If Src is a Variable, the result will be an infinite-weight i8 |
| 6652 /// Variable with the RCX86_IsTrunc8Rcvr register class. As such, this helper | 6653 /// Variable with the RCX86_IsTrunc8Rcvr register class. As such, this helper |
| 6653 /// is a convenient way to prevent ah/bh/ch/dh from being an (invalid) argument | 6654 /// is a convenient way to prevent ah/bh/ch/dh from being an (invalid) argument |
| 6654 /// to the pinsrb instruction. | 6655 /// to the pinsrb instruction. |
| 6655 template <typename TraitsType> | 6656 template <typename TraitsType> |
| 6656 Variable *TargetX86Base<TraitsType>::copyToReg8(Operand *Src, int32_t RegNum) { | 6657 Variable *TargetX86Base<TraitsType>::copyToReg8(Operand *Src, RegNumT RegNum) { |
| 6657 Type Ty = Src->getType(); | 6658 Type Ty = Src->getType(); |
| 6658 assert(isScalarIntegerType(Ty)); | 6659 assert(isScalarIntegerType(Ty)); |
| 6659 assert(Ty != IceType_i1); | 6660 assert(Ty != IceType_i1); |
| 6660 Variable *Reg = makeReg(IceType_i8, RegNum); | 6661 Variable *Reg = makeReg(IceType_i8, RegNum); |
| 6661 Reg->setRegClass(RCX86_IsTrunc8Rcvr); | 6662 Reg->setRegClass(RCX86_IsTrunc8Rcvr); |
| 6662 if (llvm::isa<Variable>(Src) || llvm::isa<ConstantRelocatable>(Src)) { | 6663 if (llvm::isa<Variable>(Src) || llvm::isa<ConstantRelocatable>(Src)) { |
| 6663 Variable *SrcTruncable = makeReg(Ty); | 6664 Variable *SrcTruncable = makeReg(Ty); |
| 6664 switch (Ty) { | 6665 switch (Ty) { |
| 6665 case IceType_i64: | 6666 case IceType_i64: |
| 6666 SrcTruncable->setRegClass(RCX86_Is64To8); | 6667 SrcTruncable->setRegClass(RCX86_Is64To8); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 6681 _mov(SrcRcvr, SrcTruncable); | 6682 _mov(SrcRcvr, SrcTruncable); |
| 6682 Src = SrcRcvr; | 6683 Src = SrcRcvr; |
| 6683 } | 6684 } |
| 6684 _mov(Reg, Src); | 6685 _mov(Reg, Src); |
| 6685 return Reg; | 6686 return Reg; |
| 6686 } | 6687 } |
| 6687 | 6688 |
| 6688 /// Helper for legalize() to emit the right code to lower an operand to a | 6689 /// Helper for legalize() to emit the right code to lower an operand to a |
| 6689 /// register of the appropriate type. | 6690 /// register of the appropriate type. |
| 6690 template <typename TraitsType> | 6691 template <typename TraitsType> |
| 6691 Variable *TargetX86Base<TraitsType>::copyToReg(Operand *Src, int32_t RegNum) { | 6692 Variable *TargetX86Base<TraitsType>::copyToReg(Operand *Src, RegNumT RegNum) { |
| 6692 Type Ty = Src->getType(); | 6693 Type Ty = Src->getType(); |
| 6693 Variable *Reg = makeReg(Ty, RegNum); | 6694 Variable *Reg = makeReg(Ty, RegNum); |
| 6694 if (isVectorType(Ty)) { | 6695 if (isVectorType(Ty)) { |
| 6695 _movp(Reg, Src); | 6696 _movp(Reg, Src); |
| 6696 } else { | 6697 } else { |
| 6697 _mov(Reg, Src); | 6698 _mov(Reg, Src); |
| 6698 } | 6699 } |
| 6699 return Reg; | 6700 return Reg; |
| 6700 } | 6701 } |
| 6701 | 6702 |
| 6702 template <typename TraitsType> | 6703 template <typename TraitsType> |
| 6703 Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, | 6704 Operand *TargetX86Base<TraitsType>::legalize(Operand *From, LegalMask Allowed, |
| 6704 int32_t RegNum) { | 6705 RegNumT RegNum) { |
| 6705 const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi(); | 6706 const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi(); |
| 6706 const Type Ty = From->getType(); | 6707 const Type Ty = From->getType(); |
| 6707 // Assert that a physical register is allowed. To date, all calls to | 6708 // Assert that a physical register is allowed. To date, all calls to |
| 6708 // legalize() allow a physical register. If a physical register needs to be | 6709 // legalize() allow a physical register. If a physical register needs to be |
| 6709 // explicitly disallowed, then new code will need to be written to force a | 6710 // explicitly disallowed, then new code will need to be written to force a |
| 6710 // spill. | 6711 // spill. |
| 6711 assert(Allowed & Legal_Reg); | 6712 assert(Allowed & Legal_Reg); |
| 6712 // If we're asking for a specific physical register, make sure we're not | 6713 // If we're asking for a specific physical register, make sure we're not |
| 6713 // allowing any other operand kinds. (This could be future work, e.g. allow | 6714 // allowing any other operand kinds. (This could be future work, e.g. allow |
| 6714 // the shl shift amount to be either an immediate or in ecx.) | 6715 // the shl shift amount to be either an immediate or in ecx.) |
| 6715 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg); | 6716 assert(RegNum == RegNumT::NoRegister || Allowed == Legal_Reg); |
| 6716 | 6717 |
| 6717 // Substitute with an available infinite-weight variable if possible. Only do | 6718 // Substitute with an available infinite-weight variable if possible. Only do |
| 6718 // this when we are not asking for a specific register, and when the | 6719 // this when we are not asking for a specific register, and when the |
| 6719 // substitution is not locked to a specific register, and when the types | 6720 // substitution is not locked to a specific register, and when the types |
| 6720 // match, in order to capture the vast majority of opportunities and avoid | 6721 // match, in order to capture the vast majority of opportunities and avoid |
| 6721 // corner cases in the lowering. | 6722 // corner cases in the lowering. |
| 6722 if (RegNum == Variable::NoRegister) { | 6723 if (RegNum == RegNumT::NoRegister) { |
| 6723 if (Variable *Subst = getContext().availabilityGet(From)) { | 6724 if (Variable *Subst = getContext().availabilityGet(From)) { |
| 6724 // At this point we know there is a potential substitution available. | 6725 // At this point we know there is a potential substitution available. |
| 6725 if (Subst->mustHaveReg() && !Subst->hasReg()) { | 6726 if (Subst->mustHaveReg() && !Subst->hasReg()) { |
| 6726 // At this point we know the substitution will have a register. | 6727 // At this point we know the substitution will have a register. |
| 6727 if (From->getType() == Subst->getType()) { | 6728 if (From->getType() == Subst->getType()) { |
| 6728 // At this point we know the substitution's register is compatible. | 6729 // At this point we know the substitution's register is compatible. |
| 6729 return Subst; | 6730 return Subst; |
| 6730 } | 6731 } |
| 6731 } | 6732 } |
| 6732 } | 6733 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6773 return From; | 6774 return From; |
| 6774 Const = llvm::cast<Constant>(From); | 6775 Const = llvm::cast<Constant>(From); |
| 6775 } | 6776 } |
| 6776 // There should be no constants of vector type (other than undef). | 6777 // There should be no constants of vector type (other than undef). |
| 6777 assert(!isVectorType(Ty)); | 6778 assert(!isVectorType(Ty)); |
| 6778 | 6779 |
| 6779 // If the operand is a 64 bit constant integer we need to legalize it to a | 6780 // If the operand is a 64 bit constant integer we need to legalize it to a |
| 6780 // register in x86-64. | 6781 // register in x86-64. |
| 6781 if (Traits::Is64Bit) { | 6782 if (Traits::Is64Bit) { |
| 6782 if (llvm::isa<ConstantInteger64>(Const)) { | 6783 if (llvm::isa<ConstantInteger64>(Const)) { |
| 6783 if (RegNum != Variable::NoRegister) { | 6784 if (RegNum != RegNumT::NoRegister) { |
| 6784 assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum); | 6785 assert(Traits::getGprForType(IceType_i64, RegNum) == RegNum); |
| 6785 } | 6786 } |
| 6786 return copyToReg(Const, RegNum); | 6787 return copyToReg(Const, RegNum); |
| 6787 } | 6788 } |
| 6788 } | 6789 } |
| 6789 | 6790 |
| 6790 // If the operand is an 32 bit constant integer, we should check whether we | 6791 // If the operand is an 32 bit constant integer, we should check whether we |
| 6791 // need to randomize it or pool it. | 6792 // need to randomize it or pool it. |
| 6792 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { | 6793 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { |
| 6793 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); | 6794 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6856 if (MustRematerialize) { | 6857 if (MustRematerialize) { |
| 6857 assert(Ty == IceType_i32); | 6858 assert(Ty == IceType_i32); |
| 6858 Variable *NewVar = makeReg(Ty, RegNum); | 6859 Variable *NewVar = makeReg(Ty, RegNum); |
| 6859 // Since Var is rematerializable, the offset will be added when the lea is | 6860 // Since Var is rematerializable, the offset will be added when the lea is |
| 6860 // emitted. | 6861 // emitted. |
| 6861 constexpr Constant *NoOffset = nullptr; | 6862 constexpr Constant *NoOffset = nullptr; |
| 6862 auto *Mem = X86OperandMem::create(Func, Ty, Var, NoOffset); | 6863 auto *Mem = X86OperandMem::create(Func, Ty, Var, NoOffset); |
| 6863 _lea(NewVar, Mem); | 6864 _lea(NewVar, Mem); |
| 6864 From = NewVar; | 6865 From = NewVar; |
| 6865 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 6866 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
| 6866 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { | 6867 (RegNum != RegNumT::NoRegister && RegNum != Var->getRegNum())) { |
| 6867 From = copyToReg(From, RegNum); | 6868 From = copyToReg(From, RegNum); |
| 6868 } | 6869 } |
| 6869 return From; | 6870 return From; |
| 6870 } | 6871 } |
| 6871 | 6872 |
| 6872 llvm::report_fatal_error("Unhandled operand kind in legalize()"); | 6873 llvm::report_fatal_error("Unhandled operand kind in legalize()"); |
| 6873 return From; | 6874 return From; |
| 6874 } | 6875 } |
| 6875 | 6876 |
| 6876 /// Provide a trivial wrapper to legalize() for this common usage. | 6877 /// Provide a trivial wrapper to legalize() for this common usage. |
| 6877 template <typename TraitsType> | 6878 template <typename TraitsType> |
| 6878 Variable *TargetX86Base<TraitsType>::legalizeToReg(Operand *From, | 6879 Variable *TargetX86Base<TraitsType>::legalizeToReg(Operand *From, |
| 6879 int32_t RegNum) { | 6880 RegNumT RegNum) { |
| 6880 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | 6881 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
| 6881 } | 6882 } |
| 6882 | 6883 |
| 6883 /// Legalize undef values to concrete values. | 6884 /// Legalize undef values to concrete values. |
| 6884 template <typename TraitsType> | 6885 template <typename TraitsType> |
| 6885 Operand *TargetX86Base<TraitsType>::legalizeUndef(Operand *From, | 6886 Operand *TargetX86Base<TraitsType>::legalizeUndef(Operand *From, |
| 6886 int32_t RegNum) { | 6887 RegNumT RegNum) { |
| 6887 Type Ty = From->getType(); | 6888 Type Ty = From->getType(); |
| 6888 if (llvm::isa<ConstantUndef>(From)) { | 6889 if (llvm::isa<ConstantUndef>(From)) { |
| 6889 // Lower undefs to zero. Another option is to lower undefs to an | 6890 // Lower undefs to zero. Another option is to lower undefs to an |
| 6890 // uninitialized register; however, using an uninitialized register results | 6891 // uninitialized register; however, using an uninitialized register results |
| 6891 // in less predictable code. | 6892 // in less predictable code. |
| 6892 // | 6893 // |
| 6893 // If in the future the implementation is changed to lower undef values to | 6894 // If in the future the implementation is changed to lower undef values to |
| 6894 // uninitialized registers, a FakeDef will be needed: | 6895 // uninitialized registers, a FakeDef will be needed: |
| 6895 // Context.insert<InstFakeDef>(Reg); | 6896 // Context.insert<InstFakeDef>(Reg); |
| 6896 // This is in order to ensure that the live range of Reg is not | 6897 // This is in order to ensure that the live range of Reg is not |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6955 // assert that PIC legalization has been applied. | 6956 // assert that PIC legalization has been applied. |
| 6956 Mem = X86OperandMem::create(Func, Ty, Base, Offset); | 6957 Mem = X86OperandMem::create(Func, Ty, Base, Offset); |
| 6957 } | 6958 } |
| 6958 // Do legalization, which contains randomization/pooling or do | 6959 // Do legalization, which contains randomization/pooling or do |
| 6959 // randomization/pooling. | 6960 // randomization/pooling. |
| 6960 return llvm::cast<X86OperandMem>(DoLegalize ? legalize(Mem) | 6961 return llvm::cast<X86OperandMem>(DoLegalize ? legalize(Mem) |
| 6961 : randomizeOrPoolImmediate(Mem)); | 6962 : randomizeOrPoolImmediate(Mem)); |
| 6962 } | 6963 } |
| 6963 | 6964 |
| 6964 template <typename TraitsType> | 6965 template <typename TraitsType> |
| 6965 Variable *TargetX86Base<TraitsType>::makeReg(Type Type, int32_t RegNum) { | 6966 Variable *TargetX86Base<TraitsType>::makeReg(Type Type, RegNumT RegNum) { |
| 6966 // There aren't any 64-bit integer registers for x86-32. | 6967 // There aren't any 64-bit integer registers for x86-32. |
| 6967 assert(Traits::Is64Bit || Type != IceType_i64); | 6968 assert(Traits::Is64Bit || Type != IceType_i64); |
| 6968 Variable *Reg = Func->makeVariable(Type); | 6969 Variable *Reg = Func->makeVariable(Type); |
| 6969 if (RegNum == Variable::NoRegister) | 6970 if (RegNum == RegNumT::NoRegister) |
| 6970 Reg->setMustHaveReg(); | 6971 Reg->setMustHaveReg(); |
| 6971 else | 6972 else |
| 6972 Reg->setRegNum(RegNum); | 6973 Reg->setRegNum(RegNum); |
| 6973 return Reg; | 6974 return Reg; |
| 6974 } | 6975 } |
| 6975 | 6976 |
| 6976 template <typename TraitsType> | 6977 template <typename TraitsType> |
| 6977 const Type TargetX86Base<TraitsType>::TypeForSize[] = { | 6978 const Type TargetX86Base<TraitsType>::TypeForSize[] = { |
| 6978 IceType_i8, IceType_i16, IceType_i32, IceType_f64, IceType_v16i8}; | 6979 IceType_i8, IceType_i16, IceType_i32, IceType_f64, IceType_v16i8}; |
| 6979 template <typename TraitsType> | 6980 template <typename TraitsType> |
| (...skipping 22 matching lines...) Expand all Loading... |
| 7002 | 7003 |
| 7003 template <typename TraitsType> void TargetX86Base<TraitsType>::postLower() { | 7004 template <typename TraitsType> void TargetX86Base<TraitsType>::postLower() { |
| 7004 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 7005 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
| 7005 return; | 7006 return; |
| 7006 markRedefinitions(); | 7007 markRedefinitions(); |
| 7007 Context.availabilityUpdate(); | 7008 Context.availabilityUpdate(); |
| 7008 } | 7009 } |
| 7009 | 7010 |
| 7010 template <typename TraitsType> | 7011 template <typename TraitsType> |
| 7011 void TargetX86Base<TraitsType>::makeRandomRegisterPermutation( | 7012 void TargetX86Base<TraitsType>::makeRandomRegisterPermutation( |
| 7012 llvm::SmallVectorImpl<int32_t> &Permutation, | 7013 llvm::SmallVectorImpl<RegNumT> &Permutation, |
| 7013 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { | 7014 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { |
| 7014 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, | 7015 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, |
| 7015 ExcludeRegisters, Salt); | 7016 ExcludeRegisters, Salt); |
| 7016 } | 7017 } |
| 7017 | 7018 |
| 7018 template <typename TraitsType> | 7019 template <typename TraitsType> |
| 7019 void TargetX86Base<TraitsType>::emit(const ConstantInteger32 *C) const { | 7020 void TargetX86Base<TraitsType>::emit(const ConstantInteger32 *C) const { |
| 7020 if (!BuildDefs::dump()) | 7021 if (!BuildDefs::dump()) |
| 7021 return; | 7022 return; |
| 7022 Ostream &Str = Ctx->getStrEmit(); | 7023 Ostream &Str = Ctx->getStrEmit(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7063 assert(!Ctx->getFlags().getUseNonsfi() || C->getName() == GlobalOffsetTable); | 7064 assert(!Ctx->getFlags().getUseNonsfi() || C->getName() == GlobalOffsetTable); |
| 7064 Ostream &Str = Ctx->getStrEmit(); | 7065 Ostream &Str = Ctx->getStrEmit(); |
| 7065 Str << "$"; | 7066 Str << "$"; |
| 7066 emitWithoutPrefix(C); | 7067 emitWithoutPrefix(C); |
| 7067 } | 7068 } |
| 7068 | 7069 |
| 7069 /// Randomize or pool an Immediate. | 7070 /// Randomize or pool an Immediate. |
| 7070 template <typename TraitsType> | 7071 template <typename TraitsType> |
| 7071 Operand * | 7072 Operand * |
| 7072 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate, | 7073 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(Constant *Immediate, |
| 7073 int32_t RegNum) { | 7074 RegNumT RegNum) { |
| 7074 assert(llvm::isa<ConstantInteger32>(Immediate) || | 7075 assert(llvm::isa<ConstantInteger32>(Immediate) || |
| 7075 llvm::isa<ConstantRelocatable>(Immediate)); | 7076 llvm::isa<ConstantRelocatable>(Immediate)); |
| 7076 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | 7077 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || |
| 7077 RandomizationPoolingPaused == true) { | 7078 RandomizationPoolingPaused == true) { |
| 7078 // Immediates randomization/pooling off or paused | 7079 // Immediates randomization/pooling off or paused |
| 7079 return Immediate; | 7080 return Immediate; |
| 7080 } | 7081 } |
| 7081 | 7082 |
| 7082 if (Traits::Is64Bit && NeedSandboxing) { | 7083 if (Traits::Is64Bit && NeedSandboxing) { |
| 7083 // Immediate randomization/pooling is currently disabled for x86-64 | 7084 // Immediate randomization/pooling is currently disabled for x86-64 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7148 X86OperandMem::create(Func, Immediate->getType(), NoBase, Symbol); | 7149 X86OperandMem::create(Func, Immediate->getType(), NoBase, Symbol); |
| 7149 _mov(Reg, MemOperand); | 7150 _mov(Reg, MemOperand); |
| 7150 return Reg; | 7151 return Reg; |
| 7151 } | 7152 } |
| 7152 } | 7153 } |
| 7153 } | 7154 } |
| 7154 | 7155 |
| 7155 template <typename TraitsType> | 7156 template <typename TraitsType> |
| 7156 typename TargetX86Base<TraitsType>::X86OperandMem * | 7157 typename TargetX86Base<TraitsType>::X86OperandMem * |
| 7157 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand, | 7158 TargetX86Base<TraitsType>::randomizeOrPoolImmediate(X86OperandMem *MemOperand, |
| 7158 int32_t RegNum) { | 7159 RegNumT RegNum) { |
| 7159 assert(MemOperand); | 7160 assert(MemOperand); |
| 7160 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | 7161 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || |
| 7161 RandomizationPoolingPaused == true) { | 7162 RandomizationPoolingPaused == true) { |
| 7162 // immediates randomization/pooling is turned off | 7163 // immediates randomization/pooling is turned off |
| 7163 return MemOperand; | 7164 return MemOperand; |
| 7164 } | 7165 } |
| 7165 | 7166 |
| 7166 if (Traits::Is64Bit && NeedSandboxing) { | 7167 if (Traits::Is64Bit && NeedSandboxing) { |
| 7167 // Immediate randomization/pooling is currently disabled for x86-64 | 7168 // Immediate randomization/pooling is currently disabled for x86-64 |
| 7168 // sandboxing for it could generate invalid memory operands. | 7169 // sandboxing for it could generate invalid memory operands. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7233 // TO: | 7234 // TO: |
| 7234 // insert: mov $label, RegTemp | 7235 // insert: mov $label, RegTemp |
| 7235 // insert: lea [base, RegTemp], RegTemp | 7236 // insert: lea [base, RegTemp], RegTemp |
| 7236 // =>[RegTemp, index, shift] | 7237 // =>[RegTemp, index, shift] |
| 7237 | 7238 |
| 7238 // Memory operand should never exist as source operands in phi lowering | 7239 // Memory operand should never exist as source operands in phi lowering |
| 7239 // assignments, so there is no need to reuse any registers here. For | 7240 // assignments, so there is no need to reuse any registers here. For |
| 7240 // phi lowering, we should not ask for new physical registers in | 7241 // phi lowering, we should not ask for new physical registers in |
| 7241 // general. However, if we do meet Memory Operand during phi lowering, | 7242 // general. However, if we do meet Memory Operand during phi lowering, |
| 7242 // we should not blind or pool the immediates for now. | 7243 // we should not blind or pool the immediates for now. |
| 7243 if (RegNum != Variable::NoRegister) | 7244 if (RegNum != RegNumT::NoRegister) |
| 7244 return MemOperand; | 7245 return MemOperand; |
| 7245 Variable *RegTemp = makeReg(IceType_i32); | 7246 Variable *RegTemp = makeReg(IceType_i32); |
| 7246 IceString Label; | 7247 IceString Label; |
| 7247 llvm::raw_string_ostream Label_stream(Label); | 7248 llvm::raw_string_ostream Label_stream(Label); |
| 7248 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); | 7249 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); |
| 7249 MemOperand->getOffset()->setShouldBePooled(true); | 7250 MemOperand->getOffset()->setShouldBePooled(true); |
| 7250 constexpr RelocOffsetT SymOffset = 0; | 7251 constexpr RelocOffsetT SymOffset = 0; |
| 7251 constexpr bool SuppressMangling = true; | 7252 constexpr bool SuppressMangling = true; |
| 7252 Constant *Symbol = | 7253 Constant *Symbol = |
| 7253 Ctx->getConstantSym(SymOffset, Label_stream.str(), SuppressMangling); | 7254 Ctx->getConstantSym(SymOffset, Label_stream.str(), SuppressMangling); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7418 emitGlobal(*Var, SectionSuffix); | 7419 emitGlobal(*Var, SectionSuffix); |
| 7419 } | 7420 } |
| 7420 } | 7421 } |
| 7421 } break; | 7422 } break; |
| 7422 } | 7423 } |
| 7423 } | 7424 } |
| 7424 } // end of namespace X86NAMESPACE | 7425 } // end of namespace X86NAMESPACE |
| 7425 } // end of namespace Ice | 7426 } // end of namespace Ice |
| 7426 | 7427 |
| 7427 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 7428 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
| OLD | NEW |