GlobalISel: Add memSizeNotByteSizePow2 legality helper
This is really a replacement for memSizeInBytesNotPow2 that actually
does what most every target wants. In particular, since s1 rounds to 1
byte, it wasn't lowered by this predicate. This results in targets
needing to think harder and add more matchers to catch all the
degenerate cases.
Also small bug fix that prevented the correct insertion of
G_ASSERT_ZEXT in the AArch64 use case.
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index 0fa5d6d..8607db1 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/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:
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp b/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp
index 1f0738a..54a82ca 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp
+++ b/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];
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index f7b1d79..516cab8 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -2995,7 +2995,7 @@
if (isa<GSExtLoad>(LoadMI)) {
auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
- } else if (isa<GZExtLoad>(LoadMI) || WideMemTy == DstTy) {
+ } else if (isa<GZExtLoad>(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.
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index e9df7e0..fbdc22a 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/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)
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir
index ca15f12..c1b1e22 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir
+++ b/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))