Index: include/llvm/CodeGen/GlobalISel/LegalizerInfo.h =================================================================== --- include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -123,6 +123,7 @@ struct MemDesc { uint64_t SizeInBits; AtomicOrdering Ordering; + uint32_t AlignInBits; }; /// Operations which require memory can use this to place requirements on the @@ -164,13 +165,21 @@ std::function(const LegalityQuery &)>; namespace LegalityPredicates { -struct TypePairAndMemSize { +struct TypePairAndMemDesc { LLT Type0; LLT Type1; uint64_t MemSize; + uint32_t Align; - bool operator==(const TypePairAndMemSize &Other) const { + bool operator==(const TypePairAndMemDesc &Other) const { return Type0 == Other.Type0 && Type1 == Other.Type1 && + Align == Other.Align && + MemSize == Other.MemSize; + } + + bool isCompatible(const TypePairAndMemDesc &Other) const { + return Type0 == Other.Type0 && Type1 == Other.Type1 && + Align >= Other.Align && MemSize == Other.MemSize; } }; @@ -199,9 +208,9 @@ std::initializer_list> TypesInit); /// True iff the given types for the given pair of type indexes is one of the /// specified type pairs. -LegalityPredicate typePairAndMemSizeInSet( +LegalityPredicate typePairAndMemDescInSet( unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, - std::initializer_list TypesAndMemSizeInit); + std::initializer_list TypesAndMemDescInit); /// True iff the specified type index is a scalar. LegalityPredicate isScalar(unsigned TypeIdx); /// True iff the specified type index is a vector. @@ -430,13 +439,13 @@ return actionFor(LegalizeAction::Legal, Types); } /// The instruction is legal when type indexes 0 and 1 along with the memory - /// size is any type and size tuple in the given list. - LegalizeRuleSet &legalForTypesWithMemSize( - std::initializer_list - TypesAndMemSize) { + /// size and minimum alignment is any type and size tuple in the given list. + LegalizeRuleSet &legalForTypesWithMemDesc( + std::initializer_list + TypesAndMemDesc) { return actionIf(LegalizeAction::Legal, - LegalityPredicates::typePairAndMemSizeInSet( - typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemSize)); + LegalityPredicates::typePairAndMemDescInSet( + typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc)); } /// The instruction is legal when type indexes 0 and 1 are both in the given /// list. That is, the type pair is in the cartesian product of the list. Index: lib/CodeGen/GlobalISel/LegalityPredicates.cpp =================================================================== --- lib/CodeGen/GlobalISel/LegalityPredicates.cpp +++ lib/CodeGen/GlobalISel/LegalityPredicates.cpp @@ -38,15 +38,19 @@ }; } -LegalityPredicate LegalityPredicates::typePairAndMemSizeInSet( +LegalityPredicate LegalityPredicates::typePairAndMemDescInSet( unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, - std::initializer_list TypesAndMemSizeInit) { - SmallVector TypesAndMemSize = TypesAndMemSizeInit; + std::initializer_list TypesAndMemDescInit) { + SmallVector TypesAndMemDesc = TypesAndMemDescInit; return [=](const LegalityQuery &Query) { - TypePairAndMemSize Match = {Query.Types[TypeIdx0], Query.Types[TypeIdx1], - Query.MMODescrs[MMOIdx].SizeInBits}; - return std::find(TypesAndMemSize.begin(), TypesAndMemSize.end(), Match) != - TypesAndMemSize.end(); + TypePairAndMemDesc Match = {Query.Types[TypeIdx0], Query.Types[TypeIdx1], + Query.MMODescrs[MMOIdx].SizeInBits, + Query.MMODescrs[MMOIdx].AlignInBits}; + return std::find_if( + TypesAndMemDesc.begin(), TypesAndMemDesc.end(), + [=](const TypePairAndMemDesc &Entry) ->bool { + return Match.isCompatible(Entry); + }) != TypesAndMemDesc.end(); }; } Index: lib/CodeGen/GlobalISel/LegalizerInfo.cpp =================================================================== --- lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -424,7 +424,9 @@ SmallVector MemDescrs; for (const auto &MMO : MI.memoperands()) MemDescrs.push_back( - {MMO->getSize() /* in bytes */ * 8, MMO->getOrdering()}); + {MMO->getSize() /* in bytes */ * 8, + MMO->getOrdering(), + static_cast(MMO->getAlignment() * 8)}); return getAction({MI.getOpcode(), Types, MemDescrs}); } Index: lib/Target/AArch64/AArch64LegalizerInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -189,12 +189,12 @@ .widenScalarToNextPow2(0); getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD}) - .legalForTypesWithMemSize({{s32, p0, 8}, - {s32, p0, 16}, - {s32, p0, 32}, - {s64, p0, 64}, - {p0, p0, 64}, - {v2s32, p0, 64}}) + .legalForTypesWithMemDesc({{s32, p0, 8, 8}, + {s32, p0, 16, 8}, + {s32, p0, 32, 8}, + {s64, p0, 64, 8}, + {p0, p0, 64, 8}, + {v2s32, p0, 64, 8}}) .clampScalar(0, s32, s64) .widenScalarToNextPow2(0) // TODO: We could support sum-of-pow2's but the lowering code doesn't know @@ -204,15 +204,15 @@ .lower(); getActionDefinitionsBuilder(G_LOAD) - .legalForTypesWithMemSize({{s8, p0, 8}, - {s16, p0, 16}, - {s32, p0, 32}, - {s64, p0, 64}, - {p0, p0, 64}, - {v2s32, p0, 64}}) + .legalForTypesWithMemDesc({{s8, p0, 8, 8}, + {s16, p0, 16, 8}, + {s32, p0, 32, 8}, + {s64, p0, 64, 8}, + {p0, p0, 64, 8}, + {v2s32, p0, 64, 8}}) // These extends are also legal - .legalForTypesWithMemSize({{s32, p0, 8}, - {s32, p0, 16}}) + .legalForTypesWithMemDesc({{s32, p0, 8, 8}, + {s32, p0, 16, 8}}) .clampScalar(0, s8, s64) .widenScalarToNextPow2(0) // TODO: We could support sum-of-pow2's but the lowering code doesn't know @@ -226,12 +226,12 @@ .clampMaxNumElements(0, s64, 1); getActionDefinitionsBuilder(G_STORE) - .legalForTypesWithMemSize({{s8, p0, 8}, - {s16, p0, 16}, - {s32, p0, 32}, - {s64, p0, 64}, - {p0, p0, 64}, - {v2s32, p0, 64}}) + .legalForTypesWithMemDesc({{s8, p0, 8, 8}, + {s16, p0, 16, 8}, + {s32, p0, 32, 8}, + {s64, p0, 64, 8}, + {p0, p0, 64, 8}, + {v2s32, p0, 64, 8}}) .clampScalar(0, s8, s64) .widenScalarToNextPow2(0) // TODO: We could support sum-of-pow2's but the lowering code doesn't know Index: lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -352,17 +352,18 @@ .clampScalar(0, S32, S64); + // FIXME: Handle alignment requirements. auto &ExtLoads = getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD}) - .legalForTypesWithMemSize({ - {S32, GlobalPtr, 8}, - {S32, GlobalPtr, 16}, - {S32, LocalPtr, 8}, - {S32, LocalPtr, 16}, - {S32, PrivatePtr, 8}, - {S32, PrivatePtr, 16}}); + .legalForTypesWithMemDesc({ + {S32, GlobalPtr, 8, 8}, + {S32, GlobalPtr, 16, 8}, + {S32, LocalPtr, 8, 8}, + {S32, LocalPtr, 16, 8}, + {S32, PrivatePtr, 8, 8}, + {S32, PrivatePtr, 16, 8}}); if (ST.hasFlatAddressSpace()) { - ExtLoads.legalForTypesWithMemSize({{S32, FlatPtr, 8}, - {S32, FlatPtr, 16}}); + ExtLoads.legalForTypesWithMemDesc({{S32, FlatPtr, 8, 8}, + {S32, FlatPtr, 16, 8}}); } ExtLoads.clampScalar(0, S32, S32) Index: lib/Target/ARM/ARMLegalizerInfo.cpp =================================================================== --- lib/Target/ARM/ARMLegalizerInfo.cpp +++ lib/Target/ARM/ARMLegalizerInfo.cpp @@ -124,12 +124,12 @@ // floating point to them. auto &LoadStoreBuilder = getActionDefinitionsBuilder({G_LOAD, G_STORE}) - .legalForTypesWithMemSize({ - {s1, p0, 8}, - {s8, p0, 8}, - {s16, p0, 16}, - {s32, p0, 32}, - {p0, p0, 32}}); + .legalForTypesWithMemDesc({ + {s1, p0, 8, 8}, + {s8, p0, 8, 8}, + {s16, p0, 16, 8}, + {s32, p0, 32, 8}, + {p0, p0, 32, 8}}); if (ST.isThumb()) { // FIXME: merge with the code for non-Thumb. Index: lib/Target/Mips/MipsLegalizerInfo.cpp =================================================================== --- lib/Target/Mips/MipsLegalizerInfo.cpp +++ lib/Target/Mips/MipsLegalizerInfo.cpp @@ -35,8 +35,8 @@ .legalForCartesianProduct({p0, s32}, {p0}); getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD}) - .legalForTypesWithMemSize({{s32, p0, 8}, - {s32, p0, 16}}) + .legalForTypesWithMemDesc({{s32, p0, 8, 8}, + {s32, p0, 16, 8}}) .minScalar(0, s32); getActionDefinitionsBuilder(G_SELECT)