summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lib/Target/X86/X86LegalizerInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lib/Target/X86/X86LegalizerInfo.cpp')
-rw-r--r--gnu/llvm/lib/Target/X86/X86LegalizerInfo.cpp202
1 files changed, 145 insertions, 57 deletions
diff --git a/gnu/llvm/lib/Target/X86/X86LegalizerInfo.cpp b/gnu/llvm/lib/Target/X86/X86LegalizerInfo.cpp
index 744ba21011a..4108a58fa7a 100644
--- a/gnu/llvm/lib/Target/X86/X86LegalizerInfo.cpp
+++ b/gnu/llvm/lib/Target/X86/X86LegalizerInfo.cpp
@@ -14,17 +14,45 @@
#include "X86LegalizerInfo.h"
#include "X86Subtarget.h"
#include "X86TargetMachine.h"
+#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Type.h"
-#include "llvm/Target/TargetOpcodes.h"
using namespace llvm;
using namespace TargetOpcode;
-#ifndef LLVM_BUILD_GLOBAL_ISEL
-#error "You shouldn't build this"
-#endif
+/// 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_1(const LegalizerInfo::SizeAndActionsVec &v) {
+ assert(v.size() >= 1);
+ assert(v[0].first > 1);
+ LegalizerInfo::SizeAndActionsVec result = {{1, LegalizerInfo::WidenScalar},
+ {2, LegalizerInfo::Unsupported}};
+ addAndInterleaveWithUnsupported(result, v);
+ auto Largest = result.back().first;
+ result.push_back({Largest + 1, LegalizerInfo::Unsupported});
+ return result;
+}
X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
const X86TargetMachine &TM)
@@ -41,21 +69,35 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
setLegalizerInfoAVX512DQ();
setLegalizerInfoAVX512BW();
+ setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1);
+ for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR})
+ setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1);
+ for (unsigned MemOp : {G_LOAD, G_STORE})
+ setLegalizeScalarToDifferentSizeStrategy(MemOp, 0,
+ narrowToSmallerAndWidenToSmallest);
+ setLegalizeScalarToDifferentSizeStrategy(
+ G_GEP, 1, widenToLargerTypesUnsupportedOtherwise);
+ setLegalizeScalarToDifferentSizeStrategy(
+ G_CONSTANT, 0, widenToLargerTypesAndNarrowToLargest);
+
computeTables();
}
void X86LegalizerInfo::setLegalizerInfo32bit() {
- if (Subtarget.is64Bit())
- return;
-
- const LLT p0 = LLT::pointer(0, 32);
+ const LLT p0 = LLT::pointer(0, TM.getPointerSize() * 8);
const LLT s1 = LLT::scalar(1);
const LLT s8 = LLT::scalar(8);
const LLT s16 = LLT::scalar(16);
const LLT s32 = LLT::scalar(32);
const LLT s64 = LLT::scalar(64);
+ for (auto Ty : {p0, s1, s8, s16, s32})
+ setAction({G_IMPLICIT_DEF, Ty}, Legal);
+
+ for (auto Ty : {s8, s16, s32, p0})
+ setAction({G_PHI, Ty}, Legal);
+
for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
for (auto Ty : {s8, s16, s32})
setAction({BinOp, Ty}, Legal);
@@ -69,7 +111,6 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
for (auto Ty : {s8, s16, s32, p0})
setAction({MemOp, Ty}, Legal);
- setAction({MemOp, s1}, WidenScalar);
// And everything's fine in addrspace 0.
setAction({MemOp, 1, p0}, Legal);
}
@@ -81,25 +122,18 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
setAction({G_GEP, p0}, Legal);
setAction({G_GEP, 1, s32}, Legal);
- for (auto Ty : {s1, s8, s16})
- setAction({G_GEP, 1, Ty}, WidenScalar);
+ // Control-flow
+ setAction({G_BRCOND, s1}, Legal);
// Constants
for (auto Ty : {s8, s16, s32, p0})
setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
- setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar);
- setAction({TargetOpcode::G_CONSTANT, s64}, NarrowScalar);
-
// Extensions
for (auto Ty : {s8, s16, s32}) {
setAction({G_ZEXT, Ty}, Legal);
setAction({G_SEXT, Ty}, Legal);
- }
-
- for (auto Ty : {s1, s8, s16}) {
- setAction({G_ZEXT, 1, Ty}, Legal);
- setAction({G_SEXT, 1, Ty}, Legal);
+ setAction({G_ANYEXT, Ty}, Legal);
}
// Comparison
@@ -107,6 +141,16 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
for (auto Ty : {s8, s16, s32, p0})
setAction({G_ICMP, 1, Ty}, Legal);
+
+ // Merge/Unmerge
+ for (const auto &Ty : {s16, s32, s64}) {
+ setAction({G_MERGE_VALUES, Ty}, Legal);
+ setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
+ }
+ for (const auto &Ty : {s8, s16, s32}) {
+ setAction({G_MERGE_VALUES, 1, Ty}, Legal);
+ setAction({G_UNMERGE_VALUES, Ty}, Legal);
+ }
}
void X86LegalizerInfo::setLegalizerInfo64bit() {
@@ -114,59 +158,38 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
if (!Subtarget.is64Bit())
return;
- const LLT p0 = LLT::pointer(0, TM.getPointerSize() * 8);
- const LLT s1 = LLT::scalar(1);
- const LLT s8 = LLT::scalar(8);
- const LLT s16 = LLT::scalar(16);
- const LLT s32 = LLT::scalar(32);
const LLT s64 = LLT::scalar(64);
+ const LLT s128 = LLT::scalar(128);
- for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
- for (auto Ty : {s8, s16, s32, s64})
- setAction({BinOp, Ty}, Legal);
+ setAction({G_IMPLICIT_DEF, s64}, Legal);
- for (unsigned MemOp : {G_LOAD, G_STORE}) {
- for (auto Ty : {s8, s16, s32, s64, p0})
- setAction({MemOp, Ty}, Legal);
+ setAction({G_PHI, s64}, Legal);
- setAction({MemOp, s1}, WidenScalar);
- // And everything's fine in addrspace 0.
- setAction({MemOp, 1, p0}, Legal);
- }
+ for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
+ setAction({BinOp, s64}, Legal);
- // Pointer-handling
- setAction({G_FRAME_INDEX, p0}, Legal);
- setAction({G_GLOBAL_VALUE, p0}, Legal);
+ for (unsigned MemOp : {G_LOAD, G_STORE})
+ setAction({MemOp, s64}, Legal);
- setAction({G_GEP, p0}, Legal);
- setAction({G_GEP, 1, s32}, Legal);
+ // Pointer-handling
setAction({G_GEP, 1, s64}, Legal);
- for (auto Ty : {s1, s8, s16})
- setAction({G_GEP, 1, Ty}, WidenScalar);
-
// Constants
- for (auto Ty : {s8, s16, s32, s64, p0})
- setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
-
- setAction({TargetOpcode::G_CONSTANT, s1}, WidenScalar);
+ setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
// Extensions
- for (auto Ty : {s8, s16, s32, s64}) {
- setAction({G_ZEXT, Ty}, Legal);
- setAction({G_SEXT, Ty}, Legal);
- }
-
- for (auto Ty : {s1, s8, s16, s32}) {
- setAction({G_ZEXT, 1, Ty}, Legal);
- setAction({G_SEXT, 1, Ty}, Legal);
+ for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
+ setAction({extOp, s64}, Legal);
}
// Comparison
- setAction({G_ICMP, s1}, Legal);
+ setAction({G_ICMP, 1, s64}, Legal);
- for (auto Ty : {s8, s16, s32, s64, p0})
- setAction({G_ICMP, 1, Ty}, Legal);
+ // Merge/Unmerge
+ setAction({G_MERGE_VALUES, s128}, Legal);
+ setAction({G_UNMERGE_VALUES, 1, s128}, Legal);
+ setAction({G_MERGE_VALUES, 1, s128}, Legal);
+ setAction({G_UNMERGE_VALUES, s128}, Legal);
}
void X86LegalizerInfo::setLegalizerInfoSSE1() {
@@ -174,6 +197,7 @@ void X86LegalizerInfo::setLegalizerInfoSSE1() {
return;
const LLT s32 = LLT::scalar(32);
+ const LLT s64 = LLT::scalar(64);
const LLT v4s32 = LLT::vector(4, 32);
const LLT v2s64 = LLT::vector(2, 64);
@@ -184,18 +208,35 @@ void X86LegalizerInfo::setLegalizerInfoSSE1() {
for (unsigned MemOp : {G_LOAD, G_STORE})
for (auto Ty : {v4s32, v2s64})
setAction({MemOp, Ty}, Legal);
+
+ // Constants
+ setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
+
+ // Merge/Unmerge
+ for (const auto &Ty : {v4s32, v2s64}) {
+ setAction({G_MERGE_VALUES, Ty}, Legal);
+ setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
+ }
+ setAction({G_MERGE_VALUES, 1, s64}, Legal);
+ setAction({G_UNMERGE_VALUES, s64}, Legal);
}
void X86LegalizerInfo::setLegalizerInfoSSE2() {
if (!Subtarget.hasSSE2())
return;
+ const LLT s32 = LLT::scalar(32);
const LLT s64 = LLT::scalar(64);
const LLT v16s8 = LLT::vector(16, 8);
const LLT v8s16 = LLT::vector(8, 16);
const LLT v4s32 = LLT::vector(4, 32);
const LLT v2s64 = LLT::vector(2, 64);
+ const LLT v32s8 = LLT::vector(32, 8);
+ const LLT v16s16 = LLT::vector(16, 16);
+ const LLT v8s32 = LLT::vector(8, 32);
+ const LLT v4s64 = LLT::vector(4, 64);
+
for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
for (auto Ty : {s64, v2s64})
setAction({BinOp, Ty}, Legal);
@@ -205,6 +246,23 @@ void X86LegalizerInfo::setLegalizerInfoSSE2() {
setAction({BinOp, Ty}, Legal);
setAction({G_MUL, v8s16}, Legal);
+
+ setAction({G_FPEXT, s64}, Legal);
+ setAction({G_FPEXT, 1, s32}, Legal);
+
+ // Constants
+ setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
+
+ // Merge/Unmerge
+ for (const auto &Ty :
+ {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
+ setAction({G_MERGE_VALUES, Ty}, Legal);
+ setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
+ }
+ for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) {
+ setAction({G_MERGE_VALUES, 1, Ty}, Legal);
+ setAction({G_UNMERGE_VALUES, Ty}, Legal);
+ }
}
void X86LegalizerInfo::setLegalizerInfoSSE41() {
@@ -226,9 +284,13 @@ void X86LegalizerInfo::setLegalizerInfoAVX() {
const LLT v2s64 = LLT::vector(2, 64);
const LLT v32s8 = LLT::vector(32, 8);
+ const LLT v64s8 = LLT::vector(64, 8);
const LLT v16s16 = LLT::vector(16, 16);
+ const LLT v32s16 = LLT::vector(32, 16);
const LLT v8s32 = LLT::vector(8, 32);
+ const LLT v16s32 = LLT::vector(16, 32);
const LLT v4s64 = LLT::vector(4, 64);
+ const LLT v8s64 = LLT::vector(8, 64);
for (unsigned MemOp : {G_LOAD, G_STORE})
for (auto Ty : {v8s32, v4s64})
@@ -242,6 +304,17 @@ void X86LegalizerInfo::setLegalizerInfoAVX() {
setAction({G_INSERT, 1, Ty}, Legal);
setAction({G_EXTRACT, Ty}, Legal);
}
+ // Merge/Unmerge
+ for (const auto &Ty :
+ {v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) {
+ setAction({G_MERGE_VALUES, Ty}, Legal);
+ setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
+ }
+ for (const auto &Ty :
+ {v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
+ setAction({G_MERGE_VALUES, 1, Ty}, Legal);
+ setAction({G_UNMERGE_VALUES, Ty}, Legal);
+ }
}
void X86LegalizerInfo::setLegalizerInfoAVX2() {
@@ -253,12 +326,27 @@ void X86LegalizerInfo::setLegalizerInfoAVX2() {
const LLT v8s32 = LLT::vector(8, 32);
const LLT v4s64 = LLT::vector(4, 64);
+ const LLT v64s8 = LLT::vector(64, 8);
+ const LLT v32s16 = LLT::vector(32, 16);
+ const LLT v16s32 = LLT::vector(16, 32);
+ const LLT v8s64 = LLT::vector(8, 64);
+
for (unsigned BinOp : {G_ADD, G_SUB})
for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
setAction({BinOp, Ty}, Legal);
for (auto Ty : {v16s16, v8s32})
setAction({G_MUL, Ty}, Legal);
+
+ // Merge/Unmerge
+ for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) {
+ setAction({G_MERGE_VALUES, Ty}, Legal);
+ setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
+ }
+ for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) {
+ setAction({G_MERGE_VALUES, 1, Ty}, Legal);
+ setAction({G_UNMERGE_VALUES, Ty}, Legal);
+ }
}
void X86LegalizerInfo::setLegalizerInfoAVX512() {