OLD | NEW |
1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// |
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 // This file implements the TargetLoweringX8632 class, which | 10 // This file implements the TargetLoweringX8632 class, which |
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 this->FrameSizeLocals = NextStackOffset - SpillAreaPaddingBytes; | 890 this->FrameSizeLocals = NextStackOffset - SpillAreaPaddingBytes; |
891 this->HasComputedFrame = true; | 891 this->HasComputedFrame = true; |
892 | 892 |
893 // Assign stack offsets to variables that have been linked to spilled | 893 // Assign stack offsets to variables that have been linked to spilled |
894 // variables. | 894 // variables. |
895 for (Variable *Var : VariablesLinkedToSpillSlots) { | 895 for (Variable *Var : VariablesLinkedToSpillSlots) { |
896 Variable *Linked = (llvm::cast<SpillVariable>(Var))->getLinkedTo(); | 896 Variable *Linked = (llvm::cast<SpillVariable>(Var))->getLinkedTo(); |
897 Var->setStackOffset(Linked->getStackOffset()); | 897 Var->setStackOffset(Linked->getStackOffset()); |
898 } | 898 } |
899 | 899 |
900 if (ALLOW_DUMP && Func->getContext()->isVerbose(IceV_Frame)) { | 900 if (ALLOW_DUMP && Func->isVerbose(IceV_Frame)) { |
901 OstreamLocker L(Func->getContext()); | 901 OstreamLocker L(Func->getContext()); |
902 Ostream &Str = Func->getContext()->getStrDump(); | 902 Ostream &Str = Func->getContext()->getStrDump(); |
903 | 903 |
904 Str << "Stack layout:\n"; | 904 Str << "Stack layout:\n"; |
905 uint32_t EspAdjustmentPaddingSize = | 905 uint32_t EspAdjustmentPaddingSize = |
906 SpillAreaSizeBytes - LocalsSpillAreaSize - | 906 SpillAreaSizeBytes - LocalsSpillAreaSize - |
907 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes; | 907 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes; |
908 Str << " in-args = " << InArgsSizeBytes << " bytes\n" | 908 Str << " in-args = " << InArgsSizeBytes << " bytes\n" |
909 << " return address = " << X86_RET_IP_SIZE_BYTES << " bytes\n" | 909 << " return address = " << X86_RET_IP_SIZE_BYTES << " bytes\n" |
910 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" | 910 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 typedef ConstantDouble IceType; | 985 typedef ConstantDouble IceType; |
986 static const Type Ty = IceType_f64; | 986 static const Type Ty = IceType_f64; |
987 static const char *TypeName; | 987 static const char *TypeName; |
988 static const char *AsmTag; | 988 static const char *AsmTag; |
989 static const char *PrintfString; | 989 static const char *PrintfString; |
990 }; | 990 }; |
991 const char *PoolTypeConverter<double>::TypeName = "double"; | 991 const char *PoolTypeConverter<double>::TypeName = "double"; |
992 const char *PoolTypeConverter<double>::AsmTag = ".quad"; | 992 const char *PoolTypeConverter<double>::AsmTag = ".quad"; |
993 const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; | 993 const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; |
994 | 994 |
995 template <typename T> void TargetX8632::emitConstantPool() const { | 995 template <typename T> void TargetX8632::emitConstantPool(GlobalContext *Ctx) { |
996 // Note: Still used by emit IAS. | 996 // Note: Still used by emit IAS. |
997 Ostream &Str = Ctx->getStrEmit(); | 997 Ostream &Str = Ctx->getStrEmit(); |
998 Type Ty = T::Ty; | 998 Type Ty = T::Ty; |
999 SizeT Align = typeAlignInBytes(Ty); | 999 SizeT Align = typeAlignInBytes(Ty); |
1000 ConstantList Pool = Ctx->getConstantPool(Ty); | 1000 ConstantList Pool = Ctx->getConstantPool(Ty); |
1001 | 1001 |
1002 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align | 1002 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align |
1003 << "\n"; | 1003 << "\n"; |
1004 Str << "\t.align\t" << Align << "\n"; | 1004 Str << "\t.align\t" << Align << "\n"; |
1005 for (Constant *C : Pool) { | 1005 for (Constant *C : Pool) { |
1006 typename T::IceType *Const = llvm::cast<typename T::IceType>(C); | 1006 typename T::IceType *Const = llvm::cast<typename T::IceType>(C); |
1007 typename T::IceType::PrimType Value = Const->getValue(); | 1007 typename T::IceType::PrimType Value = Const->getValue(); |
1008 // Use memcpy() to copy bits from Value into RawValue in a way | 1008 // Use memcpy() to copy bits from Value into RawValue in a way |
1009 // that avoids breaking strict-aliasing rules. | 1009 // that avoids breaking strict-aliasing rules. |
1010 typename T::PrimitiveIntType RawValue; | 1010 typename T::PrimitiveIntType RawValue; |
1011 memcpy(&RawValue, &Value, sizeof(Value)); | 1011 memcpy(&RawValue, &Value, sizeof(Value)); |
1012 char buf[30]; | 1012 char buf[30]; |
1013 int CharsPrinted = | 1013 int CharsPrinted = |
1014 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); | 1014 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); |
1015 assert(CharsPrinted >= 0 && | 1015 assert(CharsPrinted >= 0 && |
1016 (size_t)CharsPrinted < llvm::array_lengthof(buf)); | 1016 (size_t)CharsPrinted < llvm::array_lengthof(buf)); |
1017 (void)CharsPrinted; // avoid warnings if asserts are disabled | 1017 (void)CharsPrinted; // avoid warnings if asserts are disabled |
1018 Const->emitPoolLabel(Str); | 1018 Const->emitPoolLabel(Str); |
1019 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " " | 1019 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " " |
1020 << Value << "\n"; | 1020 << Value << "\n"; |
1021 } | 1021 } |
1022 } | 1022 } |
1023 | 1023 |
1024 void TargetX8632::emitConstants() const { | 1024 void TargetX8632::emitConstants(GlobalContext *Ctx) { |
1025 // No need to emit constants from the int pool since (for x86) they | 1025 // No need to emit constants from the int pool since (for x86) they |
1026 // are embedded as immediates in the instructions, just emit float/double. | 1026 // are embedded as immediates in the instructions, just emit float/double. |
1027 if (Ctx->getFlags().UseELFWriter) { | 1027 if (Ctx->getFlags().UseELFWriter) { |
1028 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 1028 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
1029 Writer->writeConstantPool<ConstantFloat>(IceType_f32); | 1029 Writer->writeConstantPool<ConstantFloat>(IceType_f32); |
1030 Writer->writeConstantPool<ConstantDouble>(IceType_f64); | 1030 Writer->writeConstantPool<ConstantDouble>(IceType_f64); |
1031 } else { | 1031 } else { |
1032 OstreamLocker L(Ctx); | 1032 OstreamLocker L(Ctx); |
1033 emitConstantPool<PoolTypeConverter<float>>(); | 1033 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
1034 emitConstantPool<PoolTypeConverter<double>>(); | 1034 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
1035 } | 1035 } |
1036 } | 1036 } |
1037 | 1037 |
1038 void TargetX8632::split64(Variable *Var) { | 1038 void TargetX8632::split64(Variable *Var) { |
1039 switch (Var->getType()) { | 1039 switch (Var->getType()) { |
1040 default: | 1040 default: |
1041 return; | 1041 return; |
1042 case IceType_i64: | 1042 case IceType_i64: |
1043 // TODO: Only consider F64 if we need to push each half when | 1043 // TODO: Only consider F64 if we need to push each half when |
1044 // passing as an argument to a function call. Note that each half | 1044 // passing as an argument to a function call. Note that each half |
(...skipping 2515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3560 return (Arith->getOp() == InstArithmetic::Add); | 3560 return (Arith->getOp() == InstArithmetic::Add); |
3561 } | 3561 } |
3562 return false; | 3562 return false; |
3563 } | 3563 } |
3564 | 3564 |
3565 void dumpAddressOpt(const Cfg *Func, const Variable *Base, | 3565 void dumpAddressOpt(const Cfg *Func, const Variable *Base, |
3566 const Variable *Index, uint16_t Shift, int32_t Offset, | 3566 const Variable *Index, uint16_t Shift, int32_t Offset, |
3567 const Inst *Reason) { | 3567 const Inst *Reason) { |
3568 if (!ALLOW_DUMP) | 3568 if (!ALLOW_DUMP) |
3569 return; | 3569 return; |
3570 if (!Func->getContext()->isVerbose(IceV_AddrOpt)) | 3570 if (!Func->isVerbose(IceV_AddrOpt)) |
3571 return; | 3571 return; |
3572 OstreamLocker L(Func->getContext()); | 3572 OstreamLocker L(Func->getContext()); |
3573 Ostream &Str = Func->getContext()->getStrDump(); | 3573 Ostream &Str = Func->getContext()->getStrDump(); |
3574 Str << "Instruction: "; | 3574 Str << "Instruction: "; |
3575 Reason->dumpDecorated(Func); | 3575 Reason->dumpDecorated(Func); |
3576 Str << " results in Base="; | 3576 Str << " results in Base="; |
3577 if (Base) | 3577 if (Base) |
3578 Base->dump(Func); | 3578 Base->dump(Func); |
3579 else | 3579 else |
3580 Str << "<null>"; | 3580 Str << "<null>"; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3733 Offset += MoreOffset; | 3733 Offset += MoreOffset; |
3734 Reason = BaseInst; | 3734 Reason = BaseInst; |
3735 return true; | 3735 return true; |
3736 } | 3736 } |
3737 return false; | 3737 return false; |
3738 } | 3738 } |
3739 | 3739 |
3740 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, | 3740 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, |
3741 Variable *&Index, uint16_t &Shift, int32_t &Offset) { | 3741 Variable *&Index, uint16_t &Shift, int32_t &Offset) { |
3742 Func->resetCurrentNode(); | 3742 Func->resetCurrentNode(); |
3743 if (Func->getContext()->isVerbose(IceV_AddrOpt)) { | 3743 if (Func->isVerbose(IceV_AddrOpt)) { |
3744 OstreamLocker L(Func->getContext()); | 3744 OstreamLocker L(Func->getContext()); |
3745 Ostream &Str = Func->getContext()->getStrDump(); | 3745 Ostream &Str = Func->getContext()->getStrDump(); |
3746 Str << "\nStarting computeAddressOpt for instruction:\n "; | 3746 Str << "\nStarting computeAddressOpt for instruction:\n "; |
3747 Instr->dumpDecorated(Func); | 3747 Instr->dumpDecorated(Func); |
3748 } | 3748 } |
3749 (void)Offset; // TODO: pattern-match for non-zero offsets. | 3749 (void)Offset; // TODO: pattern-match for non-zero offsets. |
3750 if (Base == nullptr) | 3750 if (Base == nullptr) |
3751 return; | 3751 return; |
3752 // If the Base has more than one use or is live across multiple | 3752 // If the Base has more than one use or is live across multiple |
3753 // blocks, then don't go further. Alternatively (?), never consider | 3753 // blocks, then don't go further. Alternatively (?), never consider |
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4575 RegisterList Shuffled(List); | 4575 RegisterList Shuffled(List); |
4576 std::random_shuffle(Shuffled.begin(), Shuffled.end(), RNG); | 4576 std::random_shuffle(Shuffled.begin(), Shuffled.end(), RNG); |
4577 for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { | 4577 for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { |
4578 Permutation[List[SI]] = Shuffled[SI]; | 4578 Permutation[List[SI]] = Shuffled[SI]; |
4579 ++NumShuffled; | 4579 ++NumShuffled; |
4580 } | 4580 } |
4581 } | 4581 } |
4582 | 4582 |
4583 assert(NumShuffled + NumPreserved == RegX8632::Reg_NUM); | 4583 assert(NumShuffled + NumPreserved == RegX8632::Reg_NUM); |
4584 | 4584 |
4585 if (Func->getContext()->isVerbose(IceV_Random)) { | 4585 if (Func->isVerbose(IceV_Random)) { |
4586 OstreamLocker L(Func->getContext()); | 4586 OstreamLocker L(Func->getContext()); |
4587 Ostream &Str = Func->getContext()->getStrDump(); | 4587 Ostream &Str = Func->getContext()->getStrDump(); |
4588 Str << "Register equivalence classes:\n"; | 4588 Str << "Register equivalence classes:\n"; |
4589 for (auto I : EquivalenceClasses) { | 4589 for (auto I : EquivalenceClasses) { |
4590 Str << "{"; | 4590 Str << "{"; |
4591 const RegisterList &List = I.second; | 4591 const RegisterList &List = I.second; |
4592 bool First = true; | 4592 bool First = true; |
4593 for (int32_t Register : List) { | 4593 for (int32_t Register : List) { |
4594 if (!First) | 4594 if (!First) |
4595 Str << " "; | 4595 Str << " "; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4723 } else if (IsConstant || IsExternal) | 4723 } else if (IsConstant || IsExternal) |
4724 Str << "\t.zero\t" << Size << "\n"; | 4724 Str << "\t.zero\t" << Size << "\n"; |
4725 // Size is part of .comm. | 4725 // Size is part of .comm. |
4726 | 4726 |
4727 if (IsConstant || HasNonzeroInitializer || IsExternal) | 4727 if (IsConstant || HasNonzeroInitializer || IsExternal) |
4728 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; | 4728 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; |
4729 // Size is part of .comm. | 4729 // Size is part of .comm. |
4730 } | 4730 } |
4731 | 4731 |
4732 } // end of namespace Ice | 4732 } // end of namespace Ice |
OLD | NEW |