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.cpp45
1 files changed, 32 insertions, 13 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index fc6c2903471a..98cb7aba562c 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -43,7 +43,7 @@ using namespace llvm;
WebAssemblyTargetLowering::WebAssemblyTargetLowering(
const TargetMachine &TM, const WebAssemblySubtarget &STI)
- : TargetLowering(TM), Subtarget(&STI) {
+ : TargetLowering(TM, STI), Subtarget(&STI) {
auto MVTPtr = Subtarget->hasAddr64() ? MVT::i64 : MVT::i32;
// Set the load count for memcmp expand optimization
@@ -319,6 +319,7 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
// Support vector extending
for (auto T : MVT::integer_fixedlen_vector_valuetypes()) {
+ setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom);
setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Custom);
setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Custom);
}
@@ -1136,7 +1137,27 @@ void WebAssemblyTargetLowering::computeKnownBitsForTargetNode(
}
break;
}
-
+ case WebAssemblyISD::EXTEND_LOW_U:
+ case WebAssemblyISD::EXTEND_HIGH_U: {
+ // We know the high half, of each destination vector element, will be zero.
+ SDValue SrcOp = Op.getOperand(0);
+ EVT VT = SrcOp.getSimpleValueType();
+ unsigned BitWidth = Known.getBitWidth();
+ if (VT == MVT::v8i8 || VT == MVT::v16i8) {
+ assert(BitWidth >= 8 && "Unexpected width!");
+ APInt Mask = APInt::getHighBitsSet(BitWidth, BitWidth - 8);
+ Known.Zero |= Mask;
+ } else if (VT == MVT::v4i16 || VT == MVT::v8i16) {
+ assert(BitWidth >= 16 && "Unexpected width!");
+ APInt Mask = APInt::getHighBitsSet(BitWidth, BitWidth - 16);
+ Known.Zero |= Mask;
+ } else if (VT == MVT::v2i32 || VT == MVT::v4i32) {
+ assert(BitWidth >= 32 && "Unexpected width!");
+ APInt Mask = APInt::getHighBitsSet(BitWidth, BitWidth - 32);
+ Known.Zero |= Mask;
+ }
+ break;
+ }
// For 128-bit addition if the upper bits are all zero then it's known that
// the upper bits of the result will have all bits guaranteed zero except the
// first.
@@ -1705,6 +1726,7 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
return LowerSIGN_EXTEND_INREG(Op, DAG);
case ISD::ZERO_EXTEND_VECTOR_INREG:
case ISD::SIGN_EXTEND_VECTOR_INREG:
+ case ISD::ANY_EXTEND_VECTOR_INREG:
return LowerEXTEND_VECTOR_INREG(Op, DAG);
case ISD::BUILD_VECTOR:
return LowerBUILD_VECTOR(Op, DAG);
@@ -2299,6 +2321,9 @@ WebAssemblyTargetLowering::LowerEXTEND_VECTOR_INREG(SDValue Op,
unsigned Ext;
switch (Op.getOpcode()) {
+ default:
+ llvm_unreachable("unexpected opcode");
+ case ISD::ANY_EXTEND_VECTOR_INREG:
case ISD::ZERO_EXTEND_VECTOR_INREG:
Ext = WebAssemblyISD::EXTEND_LOW_U;
break;
@@ -2603,18 +2628,12 @@ SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
// Values may need to be fixed so that they will sign extend to be
// within the expected range during ISel. Check whether the value is in
// bounds based on the lane bit width and if it is out of bounds, lop
- // off the extra bits and subtract 2^n to reflect giving the high bit
- // value -2^(n-1) rather than +2^(n-1). Skip the i64 case because it
- // cannot possibly be out of range.
- auto *Const = dyn_cast<ConstantSDNode>(Lane.getNode());
- int64_t Val = Const ? Const->getSExtValue() : 0;
+ // off the extra bits.
uint64_t LaneBits = 128 / Lanes;
- assert((LaneBits == 64 || Val >= -(1ll << (LaneBits - 1))) &&
- "Unexpected out of bounds negative value");
- if (Const && LaneBits != 64 && Val > (1ll << (LaneBits - 1)) - 1) {
- uint64_t Mask = (1ll << LaneBits) - 1;
- auto NewVal = (((uint64_t)Val & Mask) - (1ll << LaneBits)) & Mask;
- ConstLanes.push_back(DAG.getConstant(NewVal, SDLoc(Lane), LaneT));
+ if (auto *Const = dyn_cast<ConstantSDNode>(Lane.getNode())) {
+ ConstLanes.push_back(DAG.getConstant(
+ Const->getAPIntValue().trunc(LaneBits).getZExtValue(),
+ SDLoc(Lane), LaneT));
} else {
ConstLanes.push_back(Lane);
}