summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp47
1 files changed, 46 insertions, 1 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index f06afdbcea9eb..5b177c0c5d9d5 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -28,6 +28,7 @@
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -180,6 +181,13 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
setOperationAction(Op, MVT::v2i64, Expand);
}
+ // But we do have integer min and max operations
+ if (Subtarget->hasUnimplementedSIMD128()) {
+ for (auto Op : {ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX})
+ for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
+ setOperationAction(Op, T, Legal);
+ }
+
// Expand float operations supported for scalars but not SIMD
for (auto Op : {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT,
ISD::FCOPYSIGN, ISD::FLOG, ISD::FLOG2, ISD::FLOG10,
@@ -189,6 +197,11 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
setOperationAction(Op, MVT::v2f64, Expand);
}
+ // Expand operations not supported for i64x2 vectors
+ if (Subtarget->hasUnimplementedSIMD128())
+ for (unsigned CC = 0; CC < ISD::SETCC_INVALID; ++CC)
+ setCondCodeAction(static_cast<ISD::CondCode>(CC), MVT::v2i64, Custom);
+
// Expand additional SIMD ops that V8 hasn't implemented yet
if (!Subtarget->hasUnimplementedSIMD128()) {
setOperationAction(ISD::FSQRT, MVT::v4f32, Expand);
@@ -461,11 +474,14 @@ const char *
WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
case WebAssemblyISD::FIRST_NUMBER:
+ case WebAssemblyISD::FIRST_MEM_OPCODE:
break;
#define HANDLE_NODETYPE(NODE) \
case WebAssemblyISD::NODE: \
return "WebAssemblyISD::" #NODE;
+#define HANDLE_MEM_NODETYPE(NODE) HANDLE_NODETYPE(NODE)
#include "WebAssemblyISD.def"
+#undef HANDLE_MEM_NODETYPE
#undef HANDLE_NODETYPE
}
return nullptr;
@@ -1011,6 +1027,8 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
return LowerBUILD_VECTOR(Op, DAG);
case ISD::VECTOR_SHUFFLE:
return LowerVECTOR_SHUFFLE(Op, DAG);
+ case ISD::SETCC:
+ return LowerSETCC(Op, DAG);
case ISD::SHL:
case ISD::SRA:
case ISD::SRL:
@@ -1425,7 +1443,11 @@ SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
if (Subtarget->hasUnimplementedSIMD128() &&
(SplattedLoad = dyn_cast<LoadSDNode>(SplatValue)) &&
SplattedLoad->getMemoryVT() == VecT.getVectorElementType()) {
- Result = DAG.getNode(WebAssemblyISD::LOAD_SPLAT, DL, VecT, SplatValue);
+ Result = DAG.getMemIntrinsicNode(
+ WebAssemblyISD::LOAD_SPLAT, DL, DAG.getVTList(VecT),
+ {SplattedLoad->getChain(), SplattedLoad->getBasePtr(),
+ SplattedLoad->getOffset()},
+ SplattedLoad->getMemoryVT(), SplattedLoad->getMemOperand());
} else {
Result = DAG.getSplatBuildVector(VecT, DL, SplatValue);
}
@@ -1472,6 +1494,29 @@ WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
}
+SDValue WebAssemblyTargetLowering::LowerSETCC(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ // The legalizer does not know how to expand the comparison modes of i64x2
+ // vectors because no comparison modes are supported. We could solve this by
+ // expanding all i64x2 SETCC nodes, but that seems to expand f64x2 SETCC nodes
+ // (which return i64x2 results) as well. So instead we manually unroll i64x2
+ // comparisons here.
+ assert(Subtarget->hasUnimplementedSIMD128());
+ assert(Op->getOperand(0)->getSimpleValueType(0) == MVT::v2i64);
+ SmallVector<SDValue, 2> LHS, RHS;
+ DAG.ExtractVectorElements(Op->getOperand(0), LHS);
+ DAG.ExtractVectorElements(Op->getOperand(1), RHS);
+ const SDValue &CC = Op->getOperand(2);
+ auto MakeLane = [&](unsigned I) {
+ return DAG.getNode(ISD::SELECT_CC, DL, MVT::i64, LHS[I], RHS[I],
+ DAG.getConstant(uint64_t(-1), DL, MVT::i64),
+ DAG.getConstant(uint64_t(0), DL, MVT::i64), CC);
+ };
+ return DAG.getBuildVector(Op->getValueType(0), DL,
+ {MakeLane(0), MakeLane(1)});
+}
+
SDValue
WebAssemblyTargetLowering::LowerAccessVectorElement(SDValue Op,
SelectionDAG &DAG) const {