Index: llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -327,8 +327,14 @@ /// index. LegalityPredicate smallerThan(unsigned TypeIdx0, unsigned TypeIdx1); -/// True iff the specified MMO index has a size that is not a power of 2 +/// True iff the specified MMO index has a size (rounded to bytes) that is not a +/// power of 2. LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx); + +/// True iff the specified MMO index has a size that is not an even byte size, +/// or that even byte size is not a power of 2. +LegalityPredicate memSizeNotByteSizePow2(unsigned MMOIdx); + /// True iff the specified type index is a vector whose element count is not a /// power of 2. LegalityPredicate numElementsNotPow2(unsigned TypeIdx); @@ -800,11 +806,23 @@ return actionIf(LegalizeAction::Unsupported, LegalityPredicates::memSizeInBytesNotPow2(0)); } + + /// Lower a memory operation if the memory size, rounded to bytes, is not a + /// power of 2. For example, this will not trigger for s1 or s7, but will for + /// s24. LegalizeRuleSet &lowerIfMemSizeNotPow2() { return actionIf(LegalizeAction::Lower, LegalityPredicates::memSizeInBytesNotPow2(0)); } + /// Lower a memory operation if the memory access size is not a round power of + /// 2 byte size. This is stricter than lowerIfMemSizeNotPow2, and more likely + /// what you want (e.g. this will lower s1, s7 and s24). + LegalizeRuleSet &lowerIfMemSizeNotByteSizePow2() { + return actionIf(LegalizeAction::Lower, + LegalityPredicates::memSizeNotByteSizePow2(0)); + } + LegalizeRuleSet &customIf(LegalityPredicate Predicate) { // We have no choice but conservatively assume that a custom action with a // free-form user provided Predicate properly handles all type indices: Index: llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp +++ llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp @@ -188,6 +188,13 @@ }; } +LegalityPredicate LegalityPredicates::memSizeNotByteSizePow2(unsigned MMOIdx) { + return [=](const LegalityQuery &Query) { + const LLT MemTy = Query.MMODescrs[MMOIdx].MemoryTy; + return !MemTy.isByteSized() || !isPowerOf2_32(MemTy.getSizeInBytes()); + }; +} + LegalityPredicate LegalityPredicates::numElementsNotPow2(unsigned TypeIdx) { return [=](const LegalityQuery &Query) { const LLT QueryTy = Query.Types[TypeIdx]; Index: llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -2995,7 +2995,7 @@ if (isa(LoadMI)) { auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO); MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits); - } else if (isa(LoadMI) || WideMemTy == DstTy) { + } else if (isa(LoadMI) || WideMemTy == LoadTy) { auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO); // The extra bits are guaranteed to be zero, since we stored them that // way. A zext load from Wide thus automatically gives zext from MemVT. Index: llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -308,7 +308,7 @@ // These extends are also legal .legalForTypesWithMemDesc({{s32, p0, s8, 8}, {s32, p0, s16, 8}}) .widenScalarToNextPow2(0, /* MinSize = */8) - .lowerIfMemSizeNotPow2() + .lowerIfMemSizeNotByteSizePow2() .clampScalar(0, s8, s64) .narrowScalarIf([=](const LegalityQuery &Query) { // Clamp extending load results to 32-bits. @@ -317,10 +317,6 @@ Query.Types[0].getSizeInBits() > 32; }, changeTo(0, s32)) - // Lower any any-extending loads left into G_ANYEXT and G_LOAD - .lowerIf([=](const LegalityQuery &Query) { - return Query.Types[0] != Query.MMODescrs[0].MemoryTy; - }) .clampMaxNumElements(0, s8, 16) .clampMaxNumElements(0, s16, 8) .clampMaxNumElements(0, s32, 4) Index: llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir =================================================================== --- llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir +++ llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir @@ -67,8 +67,9 @@ liveins: $r0 ; CHECK: [[LD:%[0-9]+]]:_(s8) = G_LOAD %0(p0) :: (load (s8)) + ; CHECK: [[ASSERTZ:%[0-9]+]]:_(s8) = G_ASSERT_ZEXT [[LD]], 1 ; CHECK: [[ONE:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; CHECK: [[EXT:%[0-9]+]]:_(s32) = G_ANYEXT [[LD]] + ; CHECK: [[EXT:%[0-9]+]]:_(s32) = G_ANYEXT [[ASSERTZ]] ; CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[EXT]], [[ONE]] ; CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[AND]] ; CHECK: G_STORE [[TRUNC]](s8), {{%[0-9]+}}(p0) :: (store (s8))