diff --git a/llvm/include/llvm/Target/TargetData.h b/llvm/include/llvm/Target/TargetData.h index aaae41c17c69..42a40dd6c4c1 100644 --- a/llvm/include/llvm/Target/TargetData.h +++ b/llvm/include/llvm/Target/TargetData.h @@ -35,15 +35,28 @@ class GlobalVariable; class TargetData : public ImmutablePass { bool LittleEndian; // Defaults to false - unsigned char BoolAlignment; // Defaults to 1 byte - unsigned char ByteAlignment; // Defaults to 1 byte - unsigned char ShortAlignment; // Defaults to 2 bytes - unsigned char IntAlignment; // Defaults to 4 bytes - unsigned char LongAlignment; // Defaults to 8 bytes - unsigned char FloatAlignment; // Defaults to 4 bytes - unsigned char DoubleAlignment; // Defaults to 8 bytes - unsigned char PointerSize; // Defaults to 8 bytes - unsigned char PointerAlignment; // Defaults to 8 bytes + + // ABI alignments + unsigned char BoolABIAlignment; // Defaults to 1 byte + unsigned char ByteABIAlignment; // Defaults to 1 byte + unsigned char ShortABIAlignment; // Defaults to 2 bytes + unsigned char IntABIAlignment; // Defaults to 4 bytes + unsigned char LongABIAlignment; // Defaults to 8 bytes + unsigned char FloatABIAlignment; // Defaults to 4 bytes + unsigned char DoubleABIAlignment; // Defaults to 8 bytes + unsigned char PointerMemSize; // Defaults to 8 bytes + unsigned char PointerABIAlignment; // Defaults to 8 bytes + + // Preferred stack/global type alignments + unsigned char BoolPrefAlignment; // Defaults to BoolABIAlignment + unsigned char BytePrefAlignment; // Defaults to ByteABIAlignment + unsigned char ShortPrefAlignment; // Defaults to ShortABIAlignment + unsigned char IntPrefAlignment; // Defaults to IntABIAlignment + unsigned char LongPrefAlignment; // Defaults to LongABIAlignment + unsigned char FloatPrefAlignment; // Defaults to FloatABIAlignment + unsigned char DoublePrefAlignment; // Defaults to DoubleABIAlignment + unsigned char PointerPrefAlignment; // Defaults to PointerABIAlignment + unsigned char AggMinPrefAlignment; // Defaults to 0 bytes public: /// Default ctor - This has to exist, because this is a pass, but it should @@ -68,15 +81,24 @@ public: TargetData(const TargetData &TD) : ImmutablePass(), LittleEndian(TD.isLittleEndian()), - BoolAlignment(TD.getBoolAlignment()), - ByteAlignment(TD.getByteAlignment()), - ShortAlignment(TD.getShortAlignment()), - IntAlignment(TD.getIntAlignment()), - LongAlignment(TD.getLongAlignment()), - FloatAlignment(TD.getFloatAlignment()), - DoubleAlignment(TD.getDoubleAlignment()), - PointerSize(TD.getPointerSize()), - PointerAlignment(TD.getPointerAlignment()) { + BoolABIAlignment(TD.getBoolABIAlignment()), + ByteABIAlignment(TD.getByteABIAlignment()), + ShortABIAlignment(TD.getShortABIAlignment()), + IntABIAlignment(TD.getIntABIAlignment()), + LongABIAlignment(TD.getLongABIAlignment()), + FloatABIAlignment(TD.getFloatABIAlignment()), + DoubleABIAlignment(TD.getDoubleABIAlignment()), + PointerMemSize(TD.getPointerSize()), + PointerABIAlignment(TD.getPointerABIAlignment()), + BoolPrefAlignment(TD.getBoolPrefAlignment()), + BytePrefAlignment(TD.getBytePrefAlignment()), + ShortPrefAlignment(TD.getShortPrefAlignment()), + IntPrefAlignment(TD.getIntPrefAlignment()), + LongPrefAlignment(TD.getLongPrefAlignment()), + FloatPrefAlignment(TD.getFloatPrefAlignment()), + DoublePrefAlignment(TD.getDoublePrefAlignment()), + PointerPrefAlignment(TD.getPointerPrefAlignment()), + AggMinPrefAlignment(TD.getAggMinPrefAlignment()) { } ~TargetData(); // Not virtual, do not subclass this class @@ -86,10 +108,16 @@ public: /// Parse a target data layout string, initializing the various TargetData /// members along the way. A TargetData specification string looks like /// "E-p:64:64-d:64-f:32-l:64-i:32-s:16-b:8-B:8" and specifies the - /// target's endianess, the alignments of various data types and - /// the size of pointers. The "-" is used as a separator and ":" - /// separates a token from its argument. Alignment is indicated in bits - /// and internally converted to the appropriate number of bytes. + /// target's endianess, the ABI alignments of various data types and + /// the size of pointers. + /// + /// "-" is used as a separator and ":" separates a token from its argument. + /// + /// Alignment is indicated in bits and internally converted to the + /// appropriate number of bytes. + /// + /// The preferred stack/global alignment specifications (":[prefalign]") are + /// optional and default to the ABI alignment. /// /// Valid tokens: ///
@@ -97,20 +125,24 @@ public: /// e specifies little endian architecture (4321)
/// p:[ptr size]:[ptr align] specifies pointer size and alignment /// [default = 64:64]
- /// d:[align] specifies double floating point alignment - /// [default = 64]
- /// f:[align] specifies single floating point alignment + /// d:[align]:[prefalign] specifies double floating + /// point alignment [default = 64]
+ /// f:[align]:[prefalign] specifies single floating + /// point alignment [default = 32]
+ /// l:[align]:[prefalign]:[globalign[ specifies long integer + /// alignment [default = 64]
+ /// i:[align]:[prefalign] specifies integer alignment /// [default = 32]
- /// l:[align] specifies long integer alignment - /// [default = 64]
- /// i:[align] specifies integer alignment - /// [default = 32]
- /// s:[align] specifies short integer alignment - /// [default = 16]
- /// b:[align] specifies byte data type alignment - /// [default = 8]
- /// B:[align] specifies boolean data type alignment - /// [default = 8]
+ /// s:[align]:[prefalign] specifies short integer + /// alignment [default = 16]
+ /// b:[align]:[prefalign] specifies byte data type + /// alignment [default = 8]
+ /// B:[align]:[prefalign] specifies boolean data type + /// alignment [default = 8]
+ /// A:[prefalign] specifies an aggregates' minimum alignment + /// on the stack and when emitted as a global. The default minimum aggregate + /// alignment defaults to 0, which causes the aggregate's "natural" internal + /// alignment calculated by llvm to be preferred. /// /// All other token types are silently ignored. void init(const std::string &TargetDescription); @@ -120,17 +152,63 @@ public: bool isLittleEndian() const { return LittleEndian; } bool isBigEndian() const { return !LittleEndian; } - /// Target alignment constraints - unsigned char getBoolAlignment() const { return BoolAlignment; } - unsigned char getByteAlignment() const { return ByteAlignment; } - unsigned char getShortAlignment() const { return ShortAlignment; } - unsigned char getIntAlignment() const { return IntAlignment; } - unsigned char getLongAlignment() const { return LongAlignment; } - unsigned char getFloatAlignment() const { return FloatAlignment; } - unsigned char getDoubleAlignment() const { return DoubleAlignment; } - unsigned char getPointerAlignment() const { return PointerAlignment; } - unsigned char getPointerSize() const { return PointerSize; } - unsigned char getPointerSizeInBits() const { return 8*PointerSize; } + /// Target boolean alignment + unsigned char getBoolABIAlignment() const { return BoolABIAlignment; } + /// Target byte alignment + unsigned char getByteABIAlignment() const { return ByteABIAlignment; } + /// Target short alignment + unsigned char getShortABIAlignment() const { return ShortABIAlignment; } + /// Target integer alignment + unsigned char getIntABIAlignment() const { return IntABIAlignment; } + /// Target long alignment + unsigned char getLongABIAlignment() const { return LongABIAlignment; } + /// Target single precision float alignment + unsigned char getFloatABIAlignment() const { return FloatABIAlignment; } + /// Target double precision float alignment + unsigned char getDoubleABIAlignment() const { return DoubleABIAlignment; } + /// Target pointer alignment + unsigned char getPointerABIAlignment() const { return PointerABIAlignment; } + /// Target pointer size + unsigned char getPointerSize() const { return PointerMemSize; } + /// Target pointer size, in bits + unsigned char getPointerSizeInBits() const { return 8*PointerMemSize; } + + /// Return target's alignment for booleans on stack + unsigned char getBoolPrefAlignment() const { + return BoolPrefAlignment; + } + /// Return target's alignment for integers on stack + unsigned char getBytePrefAlignment() const { + return BytePrefAlignment; + } + /// Return target's alignment for shorts on stack + unsigned char getShortPrefAlignment() const { + return ShortPrefAlignment; + } + /// Return target's alignment for integers on stack + unsigned char getIntPrefAlignment() const { + return IntPrefAlignment; + } + /// Return target's alignment for longs on stack + unsigned char getLongPrefAlignment() const { + return LongPrefAlignment; + } + /// Return target's alignment for single precision floats on stack + unsigned char getFloatPrefAlignment() const { + return FloatPrefAlignment; + } + /// Return target's alignment for double preceision floats on stack + unsigned char getDoublePrefAlignment() const { + return DoublePrefAlignment; + } + /// Return target's alignment for stack-based pointers + unsigned char getPointerPrefAlignment() const { + return PointerPrefAlignment; + } + /// Return target's alignment for stack-based structures + unsigned char getAggMinPrefAlignment() const { + return AggMinPrefAlignment; + } /// getStringRepresentation - Return the string representation of the /// TargetData. This representation is in the same format accepted by the @@ -142,10 +220,13 @@ public: /// uint64_t getTypeSize(const Type *Ty) const; - /// getTypeAlignment - Return the minimum required alignment for the specified - /// type. - /// - unsigned char getTypeAlignment(const Type *Ty) const; + /// getTypeAlignmentABI - Return the minimum ABI-required alignment for the + /// specified type. + unsigned char getTypeAlignmentABI(const Type *Ty) const; + + /// getTypeAlignmentPref - Return the preferred stack/global alignment for + /// the specified type. + unsigned char getTypeAlignmentPref(const Type *Ty) const; /// getTypeAlignmentShift - Return the minimum required alignment for the /// specified type, returned as log2 of the value (a shift amount). diff --git a/llvm/lib/CodeGen/ELFWriter.cpp b/llvm/lib/CodeGen/ELFWriter.cpp index 4f988070fddf..3b9653740cc0 100644 --- a/llvm/lib/CodeGen/ELFWriter.cpp +++ b/llvm/lib/CodeGen/ELFWriter.cpp @@ -241,7 +241,7 @@ void ELFWriter::EmitGlobal(GlobalVariable *GV) { } const Type *GVType = (const Type*)GV->getType(); - unsigned Align = TM.getTargetData()->getTypeAlignment(GVType); + unsigned Align = TM.getTargetData()->getTypeAlignmentPref(GVType); unsigned Size = TM.getTargetData()->getTypeSize(GVType); // If this global has a zero initializer, it is part of the .bss or common diff --git a/llvm/lib/CodeGen/MachOWriter.cpp b/llvm/lib/CodeGen/MachOWriter.cpp index 64e11010b3c5..82dcf1861b88 100644 --- a/llvm/lib/CodeGen/MachOWriter.cpp +++ b/llvm/lib/CodeGen/MachOWriter.cpp @@ -309,7 +309,7 @@ void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { unsigned Size = TM.getTargetData()->getTypeSize(Ty); unsigned Align = GV->getAlignment(); if (Align == 0) - Align = TM.getTargetData()->getTypeAlignment(Ty); + Align = TM.getTargetData()->getTypeAlignmentPref(Ty); MachOSym Sym(GV, Mang->getValueName(GV), Sec->Index, TM); diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index d26b3258fe8f..0cba1567e184 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -123,7 +123,8 @@ MachineFunction::MachineFunction(const Function *F, const TargetData &TD = *TM.getTargetData(); bool IsPic = TM.getRelocationModel() == Reloc::PIC_; unsigned EntrySize = IsPic ? 4 : TD.getPointerSize(); - unsigned Alignment = IsPic ? TD.getIntAlignment() : TD.getPointerAlignment(); + unsigned Alignment = IsPic ? TD.getIntABIAlignment() + : TD.getPointerABIAlignment(); JumpTableInfo = new MachineJumpTableInfo(EntrySize, Alignment); BasicBlocks.Parent = this; diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index d83dcc4d50b4..c8804e907ac7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -3029,7 +3029,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { // new ones, as reuse may inhibit scheduling. const Type *Ty = MVT::getTypeForValueType(ExtraVT); unsigned TySize = (unsigned)TLI.getTargetData()->getTypeSize(Ty); - unsigned Align = TLI.getTargetData()->getTypeAlignment(Ty); + unsigned Align = TLI.getTargetData()->getTypeAlignmentPref(Ty); MachineFunction &MF = DAG.getMachineFunction(); int SSFI = MF.getFrameInfo()->CreateStackObject((unsigned)TySize, Align); @@ -3937,7 +3937,9 @@ SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { SDOperand SelectionDAGLegalize::CreateStackTemporary(MVT::ValueType VT) { MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo(); unsigned ByteSize = MVT::getSizeInBits(VT)/8; - int FrameIdx = FrameInfo->CreateStackObject(ByteSize, ByteSize); + const Type *Ty = MVT::getTypeForValueType(VT); + unsigned StackAlign = (unsigned)TLI.getTargetData()->getTypeAlignmentPref(Ty); + int FrameIdx = FrameInfo->CreateStackObject(ByteSize, StackAlign); return DAG.getFrameIndex(FrameIdx, TLI.getPointerTy()); } @@ -4242,9 +4244,12 @@ SDOperand SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, if (Op0.getValueType() == MVT::i32) { // simple 32-bit [signed|unsigned] integer to float/double expansion - // get the stack frame index of a 8 byte buffer + // get the stack frame index of a 8 byte buffer, pessimistically aligned MachineFunction &MF = DAG.getMachineFunction(); - int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8); + const Type *F64Type = MVT::getTypeForValueType(MVT::f64); + unsigned StackAlign = + (unsigned)TLI.getTargetData()->getTypeAlignmentPref(F64Type); + int SSFI = MF.getFrameInfo()->CreateStackObject(8, StackAlign); // get address of 8 byte buffer SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); // word offset constant for Hi/Lo address computation diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 7e6a75d7724f..e8d58453c240 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -244,17 +244,9 @@ FunctionLoweringInfo::FunctionLoweringInfo(TargetLowering &tli, const Type *Ty = AI->getAllocatedType(); uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty); unsigned Align = - std::max((unsigned)TLI.getTargetData()->getTypeAlignment(Ty), + std::max((unsigned)TLI.getTargetData()->getTypeAlignmentPref(Ty), AI->getAlignment()); - // If the alignment of the value is smaller than the size of the - // value, and if the size of the value is particularly small - // (<= 8 bytes), round up to the size of the value for potentially - // better performance. - // - // FIXME: This could be made better with a preferred alignment hook in - // TargetData. It serves primarily to 8-byte align doubles for X86. - if (Align < TySize && TySize <= 8) Align = TySize; TySize *= CUI->getZExtValue(); // Get total allocated size. if (TySize == 0) TySize = 1; // Don't create zero-sized stack objects. StaticAllocaMap[AI] = @@ -1729,8 +1721,9 @@ void SelectionDAGLowering::visitAlloca(AllocaInst &I) { const Type *Ty = I.getAllocatedType(); uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty); - unsigned Align = std::max((unsigned)TLI.getTargetData()->getTypeAlignment(Ty), - I.getAlignment()); + unsigned Align = + std::max((unsigned)TLI.getTargetData()->getTypeAlignmentPref(Ty), + I.getAlignment()); SDOperand AllocSize = getValue(I.getArraySize()); MVT::ValueType IntPtr = TLI.getPointerTy(); diff --git a/llvm/lib/ExecutionEngine/JIT/JIT.cpp b/llvm/lib/ExecutionEngine/JIT/JIT.cpp index 7fd62cc6e0c9..c88e393d6a76 100644 --- a/llvm/lib/ExecutionEngine/JIT/JIT.cpp +++ b/llvm/lib/ExecutionEngine/JIT/JIT.cpp @@ -338,7 +338,7 @@ void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) { // compilation. const Type *GlobalType = GV->getType()->getElementType(); size_t S = getTargetData()->getTypeSize(GlobalType); - size_t A = getTargetData()->getTypeAlignment(GlobalType); + size_t A = getTargetData()->getTypeAlignmentPref(GlobalType); if (A <= 8) { Ptr = malloc(S); } else { diff --git a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp index 3bb003ad3d37..d0d34fca38fd 100644 --- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -229,7 +229,7 @@ bool SparcAsmPrinter::doFinalization(Module &M) { std::string name = Mang->getValueName(I); Constant *C = I->getInitializer(); unsigned Size = TD->getTypeSize(C->getType()); - unsigned Align = TD->getTypeAlignment(C->getType()); + unsigned Align = TD->getTypeAlignmentPref(C->getType()); if (C->isNullValue() && (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || @@ -239,7 +239,7 @@ bool SparcAsmPrinter::doFinalization(Module &M) { O << "\t.local " << name << "\n"; O << "\t.comm " << name << "," << TD->getTypeSize(C->getType()) - << "," << (unsigned)TD->getTypeAlignment(C->getType()); + << "," << Align; O << "\n"; } else { switch (I->getLinkage()) { diff --git a/llvm/lib/Target/TargetData.cpp b/llvm/lib/Target/TargetData.cpp index c0b0670b9694..b1fe43dee80f 100644 --- a/llvm/lib/Target/TargetData.cpp +++ b/llvm/lib/Target/TargetData.cpp @@ -34,8 +34,11 @@ namespace { RegisterPass X("targetdata", "Target Data Layout"); } -static inline void getTypeInfo(const Type *Ty, const TargetData *TD, - uint64_t &Size, unsigned char &Alignment); +static inline void getTypeInfoABI(const Type *Ty, const TargetData *TD, + uint64_t &Size, unsigned char &Alignment); + +static inline void getTypeInfoPref(const Type *Ty, const TargetData *TD, + uint64_t &Size, unsigned char &Alignment); //===----------------------------------------------------------------------===// // Support for StructLayout @@ -52,7 +55,7 @@ StructLayout::StructLayout(const StructType *ST, const TargetData &TD) { unsigned char A; unsigned TyAlign; uint64_t TySize; - getTypeInfo(Ty, &TD, TySize, A); + getTypeInfoABI(Ty, &TD, TySize, A); TyAlign = ST->isPacked() ? 1 : A; // Add padding if necessary to make the data element aligned properly... @@ -80,8 +83,7 @@ StructLayout::StructLayout(const StructType *ST, const TargetData &TD) { /// return the structure index that contains it. unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const { std::vector::const_iterator SI = - std::upper_bound(MemberOffsets.begin(), MemberOffsets.end(), - Offset); + std::upper_bound(MemberOffsets.begin(), MemberOffsets.end(), Offset); assert(SI != MemberOffsets.begin() && "Offset not in structure type!"); --SI; assert(*SI <= Offset && "upper_bound didn't work"); @@ -99,15 +101,24 @@ void TargetData::init(const std::string &TargetDescription) { std::string temp = TargetDescription; LittleEndian = false; - PointerSize = 8; - PointerAlignment = 8; - DoubleAlignment = 8; - FloatAlignment = 4; - LongAlignment = 8; - IntAlignment = 4; - ShortAlignment = 2; - ByteAlignment = 1; - BoolAlignment = 1; + PointerMemSize = 8; + PointerABIAlignment = 8; + DoubleABIAlignment = 8; + FloatABIAlignment = 4; + LongABIAlignment = 8; + IntABIAlignment = 4; + ShortABIAlignment = 2; + ByteABIAlignment = 1; + BoolABIAlignment = 1; + BoolPrefAlignment = BoolABIAlignment; + BytePrefAlignment = ByteABIAlignment; + ShortPrefAlignment = ShortABIAlignment; + IntPrefAlignment = IntABIAlignment; + LongPrefAlignment = LongABIAlignment; + FloatPrefAlignment = FloatABIAlignment; + DoublePrefAlignment = DoubleABIAlignment; + PointerPrefAlignment = PointerABIAlignment; + AggMinPrefAlignment = 0; while (!temp.empty()) { std::string token = getToken(temp, "-"); @@ -122,29 +133,58 @@ void TargetData::init(const std::string &TargetDescription) { LittleEndian = true; break; case 'p': - PointerSize = atoi(getToken(token,":").c_str()) / 8; - PointerAlignment = atoi(getToken(token,":").c_str()) / 8; + PointerMemSize = atoi(getToken(token,":").c_str()) / 8; + PointerABIAlignment = atoi(getToken(token,":").c_str()) / 8; + PointerPrefAlignment = atoi(getToken(token,":").c_str()) / 8; + if (PointerPrefAlignment == 0) + PointerPrefAlignment = PointerABIAlignment; break; case 'd': - DoubleAlignment = atoi(getToken(token,":").c_str()) / 8; + DoubleABIAlignment = atoi(getToken(token,":").c_str()) / 8; + DoublePrefAlignment = atoi(getToken(token,":").c_str()) / 8; + if (DoublePrefAlignment == 0) + DoublePrefAlignment = DoubleABIAlignment; break; case 'f': - FloatAlignment = atoi(getToken(token, ":").c_str()) / 8; + FloatABIAlignment = atoi(getToken(token, ":").c_str()) / 8; + FloatPrefAlignment = atoi(getToken(token,":").c_str()) / 8; + if (FloatPrefAlignment == 0) + FloatPrefAlignment = FloatABIAlignment; break; case 'l': - LongAlignment = atoi(getToken(token, ":").c_str()) / 8; + LongABIAlignment = atoi(getToken(token, ":").c_str()) / 8; + LongPrefAlignment = atoi(getToken(token,":").c_str()) / 8; + if (LongPrefAlignment == 0) + LongPrefAlignment = LongABIAlignment; break; case 'i': - IntAlignment = atoi(getToken(token, ":").c_str()) / 8; + IntABIAlignment = atoi(getToken(token, ":").c_str()) / 8; + IntPrefAlignment = atoi(getToken(token,":").c_str()) / 8; + if (IntPrefAlignment == 0) + IntPrefAlignment = IntABIAlignment; break; case 's': - ShortAlignment = atoi(getToken(token, ":").c_str()) / 8; + ShortABIAlignment = atoi(getToken(token, ":").c_str()) / 8; + ShortPrefAlignment = atoi(getToken(token,":").c_str()) / 8; + if (ShortPrefAlignment == 0) + ShortPrefAlignment = ShortABIAlignment; break; case 'b': - ByteAlignment = atoi(getToken(token, ":").c_str()) / 8; + ByteABIAlignment = atoi(getToken(token, ":").c_str()) / 8; + BytePrefAlignment = atoi(getToken(token,":").c_str()) / 8; + if (BytePrefAlignment == 0) + BytePrefAlignment = ByteABIAlignment; break; case 'B': - BoolAlignment = atoi(getToken(token, ":").c_str()) / 8; + BoolABIAlignment = atoi(getToken(token, ":").c_str()) / 8; + BoolPrefAlignment = atoi(getToken(token,":").c_str()) / 8; + if (BoolPrefAlignment == 0) + BoolPrefAlignment = BoolABIAlignment; + break; + case 'A': + AggMinPrefAlignment = atoi(getToken(token,":").c_str()) / 8; + if (AggMinPrefAlignment == 0) + AggMinPrefAlignment = 0; break; default: break; @@ -153,16 +193,25 @@ void TargetData::init(const std::string &TargetDescription) { } TargetData::TargetData(const Module *M) { - LittleEndian = M->getEndianness() != Module::BigEndian; - PointerSize = M->getPointerSize() != Module::Pointer64 ? 4 : 8; - PointerAlignment = PointerSize; - DoubleAlignment = PointerSize; - FloatAlignment = 4; - LongAlignment = PointerSize; - IntAlignment = 4; - ShortAlignment = 2; - ByteAlignment = 1; - BoolAlignment = 1; + LittleEndian = M->getEndianness() != Module::BigEndian; + PointerMemSize = M->getPointerSize() != Module::Pointer64 ? 4 : 8; + PointerABIAlignment = PointerMemSize; + DoubleABIAlignment = PointerMemSize; + FloatABIAlignment = 4; + LongABIAlignment = PointerMemSize; + IntABIAlignment = 4; + ShortABIAlignment = 2; + ByteABIAlignment = 1; + BoolABIAlignment = 1; + BoolPrefAlignment = BoolABIAlignment; + BytePrefAlignment = ByteABIAlignment; + ShortPrefAlignment = ShortABIAlignment; + IntPrefAlignment = IntABIAlignment; + LongPrefAlignment = LongABIAlignment; + FloatPrefAlignment = FloatABIAlignment; + DoublePrefAlignment = DoubleABIAlignment; + PointerPrefAlignment = PointerABIAlignment; + AggMinPrefAlignment = 0; } /// Layouts - The lazy cache of structure layout information maintained by @@ -195,14 +244,22 @@ std::string TargetData::getStringRepresentation() const { else repr << "E"; - repr << "-p:" << (PointerSize * 8) << ":" << (PointerAlignment * 8); - repr << "-d:64:" << (DoubleAlignment * 8); - repr << "-f:32:" << (FloatAlignment * 8); - repr << "-l:64:" << (LongAlignment * 8); - repr << "-i:32:" << (IntAlignment * 8); - repr << "-s:16:" << (ShortAlignment * 8); - repr << "-b:8:" << (ByteAlignment * 8); - repr << "-B:8:" << (BoolAlignment * 8); + repr << "-p:" << (PointerMemSize * 8) << ":" << (PointerABIAlignment * 8); + repr << "-d:" << (DoubleABIAlignment * 8) << ":" + << (DoublePrefAlignment * 8); + repr << "-f:" << (FloatABIAlignment * 8) << ":" + << (FloatPrefAlignment * 8); + repr << "-l:" << (LongABIAlignment * 8) << ":" + << (LongPrefAlignment * 8); + repr << "-i:" << (IntABIAlignment * 8) << ":" + << (IntPrefAlignment * 8); + repr << "-s:" << (ShortABIAlignment * 8) << ":" + << (ShortPrefAlignment * 8); + repr << "-b:" << (ByteABIAlignment * 8) << ":" + << (BytePrefAlignment * 8); + repr << "-B:" << (BoolABIAlignment * 8) << ":" + << (BoolPrefAlignment * 8); + repr << "-A:" << (AggMinPrefAlignment * 8); return repr.str(); } @@ -237,41 +294,41 @@ void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const { -static inline void getTypeInfo(const Type *Ty, const TargetData *TD, - uint64_t &Size, unsigned char &Alignment) { +static inline void getTypeInfoABI(const Type *Ty, const TargetData *TD, + uint64_t &Size, unsigned char &Alignment) { assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); switch (Ty->getTypeID()) { case Type::IntegerTyID: { unsigned BitWidth = cast(Ty)->getBitWidth(); if (BitWidth <= 8) { - Size = 1; Alignment = TD->getByteAlignment(); + Size = 1; Alignment = TD->getByteABIAlignment(); } else if (BitWidth <= 16) { - Size = 2; Alignment = TD->getShortAlignment(); + Size = 2; Alignment = TD->getShortABIAlignment(); } else if (BitWidth <= 32) { - Size = 4; Alignment = TD->getIntAlignment(); + Size = 4; Alignment = TD->getIntABIAlignment(); } else if (BitWidth <= 64) { - Size = 8; Alignment = TD->getLongAlignment(); + Size = 8; Alignment = TD->getLongABIAlignment(); } else assert(0 && "Integer types > 64 bits not supported."); return; } - case Type::VoidTyID: Size = 1; Alignment = TD->getByteAlignment(); return; - case Type::FloatTyID: Size = 4; Alignment = TD->getFloatAlignment(); return; - case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return; + case Type::VoidTyID: Size = 1; Alignment = TD->getByteABIAlignment(); return; + case Type::FloatTyID: Size = 4; Alignment = TD->getFloatABIAlignment(); return; + case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleABIAlignment(); return; case Type::LabelTyID: case Type::PointerTyID: - Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment(); + Size = TD->getPointerSize(); Alignment = TD->getPointerABIAlignment(); return; case Type::ArrayTyID: { const ArrayType *ATy = cast(Ty); - getTypeInfo(ATy->getElementType(), TD, Size, Alignment); + getTypeInfoABI(ATy->getElementType(), TD, Size, Alignment); unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment; Size = AlignedSize*ATy->getNumElements(); return; } case Type::PackedTyID: { const PackedType *PTy = cast(Ty); - getTypeInfo(PTy->getElementType(), TD, Size, Alignment); + getTypeInfoABI(PTy->getElementType(), TD, Size, Alignment); unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment; Size = AlignedSize*PTy->getNumElements(); // FIXME: The alignments of specific packed types are target dependent. @@ -292,22 +349,94 @@ static inline void getTypeInfo(const Type *Ty, const TargetData *TD, } } +static inline void getTypeInfoPref(const Type *Ty, const TargetData *TD, + uint64_t &Size, unsigned char &Alignment) { + assert(Ty->isSized() && "Cannot getTypeInfoPref() on a type that is unsized!"); + switch (Ty->getTypeID()) { + case Type::IntegerTyID: { + unsigned BitWidth = cast(Ty)->getBitWidth(); + if (BitWidth <= 8) { + Size = 1; Alignment = TD->getBytePrefAlignment(); + } else if (BitWidth <= 16) { + Size = 2; Alignment = TD->getShortPrefAlignment(); + } else if (BitWidth <= 32) { + Size = 4; Alignment = TD->getIntPrefAlignment(); + } else if (BitWidth <= 64) { + Size = 8; Alignment = TD->getLongPrefAlignment(); + } else + assert(0 && "Integer types > 64 bits not supported."); + return; + } + case Type::VoidTyID: + Size = 1; Alignment = TD->getBytePrefAlignment(); + return; + case Type::FloatTyID: + Size = 4; Alignment = TD->getFloatPrefAlignment(); + return; + case Type::DoubleTyID: + Size = 8; Alignment = TD->getDoublePrefAlignment(); + return; + case Type::LabelTyID: + case Type::PointerTyID: + Size = TD->getPointerSize(); Alignment = TD->getPointerPrefAlignment(); + return; + case Type::ArrayTyID: { + const ArrayType *ATy = cast(Ty); + getTypeInfoPref(ATy->getElementType(), TD, Size, Alignment); + unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment; + Size = AlignedSize*ATy->getNumElements(); + return; + } + case Type::PackedTyID: { + const PackedType *PTy = cast(Ty); + getTypeInfoPref(PTy->getElementType(), TD, Size, Alignment); + unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment; + Size = AlignedSize*PTy->getNumElements(); + // FIXME: The alignments of specific packed types are target dependent. + // For now, just set it to be equal to Size. + Alignment = Size; + return; + } + case Type::StructTyID: { + // Get the layout annotation... which is lazily created on demand; + // enforce minimum aggregate alignment. + const StructLayout *Layout = TD->getStructLayout(cast(Ty)); + Size = Layout->StructSize; + Alignment = std::max(Layout->StructAlignment, + (const unsigned int) TD->getAggMinPrefAlignment()); + return; + } + + default: + assert(0 && "Bad type for getTypeInfoPref!!!"); + return; + } +} + + uint64_t TargetData::getTypeSize(const Type *Ty) const { uint64_t Size; unsigned char Align; - getTypeInfo(Ty, this, Size, Align); + getTypeInfoABI(Ty, this, Size, Align); return Size; } -unsigned char TargetData::getTypeAlignment(const Type *Ty) const { +unsigned char TargetData::getTypeAlignmentABI(const Type *Ty) const { uint64_t Size; unsigned char Align; - getTypeInfo(Ty, this, Size, Align); + getTypeInfoABI(Ty, this, Size, Align); + return Align; +} + +unsigned char TargetData::getTypeAlignmentPref(const Type *Ty) const { + uint64_t Size; + unsigned char Align; + getTypeInfoPref(Ty, this, Size, Align); return Align; } unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const { - unsigned Align = getTypeAlignment(Ty); + unsigned Align = getTypeAlignmentABI(Ty); assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); return Log2_32(Align); } diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index d8283a5f220d..17bc7b14eb1e 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -109,8 +109,8 @@ X86_64TargetMachine::X86_64TargetMachine(const Module &M, const std::string &FS) X86TargetMachine::X86TargetMachine(const Module &M, const std::string &FS, bool is64Bit) : Subtarget(M, FS, is64Bit), DataLayout(Subtarget.is64Bit() ? - std::string("e-p:64:64-d:32-l:32") : - std::string("e-p:32:32-d:32-l:32")), + std::string("e-p:64:64-d:32:64-l:32") : + std::string("e-p:32:32-d:32:64-l:32")), FrameInfo(TargetFrameInfo::StackGrowsDown, Subtarget.getStackAlignment(), Subtarget.is64Bit() ? -8 : -4), InstrInfo(*this), JITInfo(*this), TLInfo(*this) { diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index 414ae794b185..04b06d28aa71 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp @@ -5779,8 +5779,8 @@ Instruction *InstCombiner::PromoteCastOfAllocation(CastInst &CI, const Type *CastElTy = PTy->getElementType(); if (!AllocElTy->isSized() || !CastElTy->isSized()) return 0; - unsigned AllocElTyAlign = TD->getTypeAlignment(AllocElTy); - unsigned CastElTyAlign = TD->getTypeAlignment(CastElTy); + unsigned AllocElTyAlign = TD->getTypeAlignmentABI(AllocElTy); + unsigned CastElTyAlign = TD->getTypeAlignmentABI(CastElTy); if (CastElTyAlign < AllocElTyAlign) return 0; // If the allocation has multiple uses, only promote it if we are strictly @@ -6878,18 +6878,22 @@ static unsigned GetKnownAlignment(Value *V, TargetData *TD) { if (GlobalVariable *GV = dyn_cast(V)) { unsigned Align = GV->getAlignment(); if (Align == 0 && TD) - Align = TD->getTypeAlignment(GV->getType()->getElementType()); + Align = TD->getTypeAlignmentPref(GV->getType()->getElementType()); return Align; } else if (AllocationInst *AI = dyn_cast(V)) { unsigned Align = AI->getAlignment(); if (Align == 0 && TD) { if (isa(AI)) - Align = TD->getTypeAlignment(AI->getType()->getElementType()); + Align = TD->getTypeAlignmentPref(AI->getType()->getElementType()); else if (isa(AI)) { // Malloc returns maximally aligned memory. - Align = TD->getTypeAlignment(AI->getType()->getElementType()); - Align = std::max(Align, (unsigned)TD->getTypeAlignment(Type::DoubleTy)); - Align = std::max(Align, (unsigned)TD->getTypeAlignment(Type::Int64Ty)); + Align = TD->getTypeAlignmentABI(AI->getType()->getElementType()); + Align = + std::max(Align, + (unsigned)TD->getTypeAlignmentABI(Type::DoubleTy)); + Align = + std::max(Align, + (unsigned)TD->getTypeAlignmentABI(Type::Int64Ty)); } } return Align; @@ -6924,10 +6928,12 @@ static unsigned GetKnownAlignment(Value *V, TargetData *TD) { if (!TD) return 0; const Type *BasePtrTy = GEPI->getOperand(0)->getType(); - if (TD->getTypeAlignment(cast(BasePtrTy)->getElementType()) + const PointerType *PtrTy = cast(BasePtrTy); + if (TD->getTypeAlignmentABI(PtrTy->getElementType()) <= BaseAlignment) { const Type *GEPTy = GEPI->getType(); - return TD->getTypeAlignment(cast(GEPTy)->getElementType()); + const PointerType *GEPPtrTy = cast(GEPTy); + return TD->getTypeAlignmentABI(GEPPtrTy->getElementType()); } return 0; } diff --git a/llvm/lib/VMCore/ValueTypes.cpp b/llvm/lib/VMCore/ValueTypes.cpp index 8732d641983f..e421d5d43036 100644 --- a/llvm/lib/VMCore/ValueTypes.cpp +++ b/llvm/lib/VMCore/ValueTypes.cpp @@ -82,8 +82,8 @@ MVT::ValueType MVT::getVectorType(ValueType VT, unsigned NumElements) { } /// MVT::getTypeForValueType - This method returns an LLVM type corresponding -/// to the specified ValueType. For integer types, this returns an unsigned -/// type. Note that this will abort for types that cannot be represented. +/// to the specified ValueType. Note that this will abort for types that cannot +/// be represented. const Type *MVT::getTypeForValueType(MVT::ValueType VT) { switch (VT) { default: assert(0 && "ValueType does not correspond to LLVM type!"); @@ -95,5 +95,14 @@ const Type *MVT::getTypeForValueType(MVT::ValueType VT) { case MVT::i64: return Type::Int64Ty; case MVT::f32: return Type::FloatTy; case MVT::f64: return Type::DoubleTy; + case MVT::v8i8: return PackedType::get(Type::Int8Ty, 8); + case MVT::v4i16: return PackedType::get(Type::Int16Ty, 4); + case MVT::v2i32: return PackedType::get(Type::Int32Ty, 2); + case MVT::v16i8: return PackedType::get(Type::Int8Ty, 16); + case MVT::v8i16: return PackedType::get(Type::Int16Ty, 8); + case MVT::v4i32: return PackedType::get(Type::Int32Ty, 4); + case MVT::v2i64: return PackedType::get(Type::Int64Ty, 2); + case MVT::v4f32: return PackedType::get(Type::FloatTy, 4); + case MVT::v2f64: return PackedType::get(Type::DoubleTy, 2); } }