aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMLegalizerInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM/ARMLegalizerInfo.cpp')
-rw-r--r--lib/Target/ARM/ARMLegalizerInfo.cpp71
1 files changed, 58 insertions, 13 deletions
diff --git a/lib/Target/ARM/ARMLegalizerInfo.cpp b/lib/Target/ARM/ARMLegalizerInfo.cpp
index 309430b0e9c..34186dede0d 100644
--- a/lib/Target/ARM/ARMLegalizerInfo.cpp
+++ b/lib/Target/ARM/ARMLegalizerInfo.cpp
@@ -24,6 +24,54 @@
using namespace llvm;
+/// FIXME: The following static functions are SizeChangeStrategy functions
+/// that are meant to temporarily mimic the behaviour of the old legalization
+/// based on doubling/halving non-legal types as closely as possible. This is
+/// not entirly possible as only legalizing the types that are exactly a power
+/// of 2 times the size of the legal types would require specifying all those
+/// sizes explicitly.
+/// In practice, not specifying those isn't a problem, and the below functions
+/// should disappear quickly as we add support for legalizing non-power-of-2
+/// sized types further.
+static void
+addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result,
+ const LegalizerInfo::SizeAndActionsVec &v) {
+ for (unsigned i = 0; i < v.size(); ++i) {
+ result.push_back(v[i]);
+ if (i + 1 < v[i].first && i + 1 < v.size() &&
+ v[i + 1].first != v[i].first + 1)
+ result.push_back({v[i].first + 1, LegalizerInfo::Unsupported});
+ }
+}
+
+static LegalizerInfo::SizeAndActionsVec
+widen_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
+ assert(v.size() >= 1);
+ assert(v[0].first > 17);
+ LegalizerInfo::SizeAndActionsVec result = {
+ {1, LegalizerInfo::Unsupported},
+ {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported},
+ {16, LegalizerInfo::WidenScalar}, {17, LegalizerInfo::Unsupported}};
+ addAndInterleaveWithUnsupported(result, v);
+ auto Largest = result.back().first;
+ result.push_back({Largest + 1, LegalizerInfo::Unsupported});
+ return result;
+}
+
+static LegalizerInfo::SizeAndActionsVec
+widen_1_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
+ assert(v.size() >= 1);
+ assert(v[0].first > 17);
+ LegalizerInfo::SizeAndActionsVec result = {
+ {1, LegalizerInfo::WidenScalar}, {2, LegalizerInfo::Unsupported},
+ {8, LegalizerInfo::WidenScalar}, {9, LegalizerInfo::Unsupported},
+ {16, LegalizerInfo::WidenScalar}, {17, LegalizerInfo::Unsupported}};
+ addAndInterleaveWithUnsupported(result, v);
+ auto Largest = result.back().first;
+ result.push_back({Largest + 1, LegalizerInfo::Unsupported});
+ return result;
+}
+
static bool AEABI(const ARMSubtarget &ST) {
return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI();
}
@@ -49,14 +97,15 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
}
for (unsigned Op : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) {
- for (auto Ty : {s1, s8, s16})
- setAction({Op, Ty}, WidenScalar);
+ if (Op != G_ADD)
+ setLegalizeScalarToDifferentSizeStrategy(
+ Op, 0, widenToLargerTypesUnsupportedOtherwise);
setAction({Op, s32}, Legal);
}
for (unsigned Op : {G_SDIV, G_UDIV}) {
- for (auto Ty : {s8, s16})
- setAction({Op, Ty}, WidenScalar);
+ setLegalizeScalarToDifferentSizeStrategy(Op, 0,
+ widenToLargerTypesUnsupportedOtherwise);
if (ST.hasDivideInARMMode())
setAction({Op, s32}, Legal);
else
@@ -64,8 +113,7 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
}
for (unsigned Op : {G_SREM, G_UREM}) {
- for (auto Ty : {s8, s16})
- setAction({Op, Ty}, WidenScalar);
+ setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
if (ST.hasDivideInARMMode())
setAction({Op, s32}, Lower);
else if (AEABI(ST))
@@ -74,10 +122,8 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
setAction({Op, s32}, Libcall);
}
- for (unsigned Op : {G_SEXT, G_ZEXT}) {
+ for (unsigned Op : {G_SEXT, G_ZEXT, G_ANYEXT}) {
setAction({Op, s32}, Legal);
- for (auto Ty : {s1, s8, s16})
- setAction({Op, 1, Ty}, Legal);
}
for (unsigned Op : {G_ASHR, G_LSHR, G_SHL})
@@ -93,12 +139,11 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
setAction({G_BRCOND, s1}, Legal);
setAction({G_CONSTANT, s32}, Legal);
- for (auto Ty : {s1, s8, s16})
- setAction({G_CONSTANT, Ty}, WidenScalar);
+ setLegalizeScalarToDifferentSizeStrategy(G_CONSTANT, 0, widen_1_8_16);
setAction({G_ICMP, s1}, Legal);
- for (auto Ty : {s8, s16})
- setAction({G_ICMP, 1, Ty}, WidenScalar);
+ setLegalizeScalarToDifferentSizeStrategy(G_ICMP, 1,
+ widenToLargerTypesUnsupportedOtherwise);
for (auto Ty : {s32, p0})
setAction({G_ICMP, 1, Ty}, Legal);