diff options
Diffstat (limited to 'lib/Target/ARM/ARMLegalizerInfo.cpp')
-rw-r--r-- | lib/Target/ARM/ARMLegalizerInfo.cpp | 71 |
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); |