bool AssumeSingleUse) const {
EVT VT = Op.getValueType();
- // TODO: We can probably do more work on calculating the known bits and
- // simplifying the operations for scalable vectors, but for now we just
- // bail out.
- if (VT.isScalableVector()) {
- // Pretend we don't know anything for now.
- Known = KnownBits(DemandedBits.getBitWidth());
- return false;
- }
-
- APInt DemandedElts = VT.isVector()
+ // Since the number of lanes in a scalable vector is unknown at compile time,
+ // we track one bit which is implicitly broadcast to all lanes. This means
+ // that all lanes in a scalable vector are considered demanded.
+ APInt DemandedElts = VT.isFixedLengthVector()
? APInt::getAllOnes(VT.getVectorNumElements())
: APInt(1, 1);
return SimplifyDemandedBits(Op, DemandedBits, DemandedElts, Known, TLO, Depth,
SelectionDAG &DAG, unsigned Depth) const {
EVT VT = Op.getValueType();
- // Pretend we don't know anything about scalable vectors for now.
- // TODO: We can probably do more work on simplifying the operations for
- // scalable vectors, but for now we just bail out.
- if (VT.isScalableVector())
- return SDValue();
-
// Limit search depth.
if (Depth >= SelectionDAG::MaxRecursionDepth)
return SDValue();
KnownBits LHSKnown, RHSKnown;
switch (Op.getOpcode()) {
case ISD::BITCAST: {
+ if (VT.isScalableVector())
+ return SDValue();
+
SDValue Src = peekThroughBitcasts(Op.getOperand(0));
EVT SrcVT = Src.getValueType();
EVT DstVT = Op.getValueType();
case ISD::ANY_EXTEND_VECTOR_INREG:
case ISD::SIGN_EXTEND_VECTOR_INREG:
case ISD::ZERO_EXTEND_VECTOR_INREG: {
+ if (VT.isScalableVector())
+ return SDValue();
+
// If we only want the lowest element and none of extended bits, then we can
// return the bitcasted source vector.
SDValue Src = Op.getOperand(0);
break;
}
case ISD::INSERT_VECTOR_ELT: {
+ if (VT.isScalableVector())
+ return SDValue();
+
// If we don't demand the inserted element, return the base vector.
SDValue Vec = Op.getOperand(0);
auto *CIdx = dyn_cast<ConstantSDNode>(Op.getOperand(2));
break;
}
case ISD::INSERT_SUBVECTOR: {
+ if (VT.isScalableVector())
+ return SDValue();
+
SDValue Vec = Op.getOperand(0);
SDValue Sub = Op.getOperand(1);
uint64_t Idx = Op.getConstantOperandVal(2);
break;
}
case ISD::VECTOR_SHUFFLE: {
+ assert(!VT.isScalableVector());
ArrayRef<int> ShuffleMask = cast<ShuffleVectorSDNode>(Op)->getMask();
// If all the demanded elts are from one operand and are inline,
break;
}
default:
+ // TODO: Probably okay to remove after audit; here to reduce change size
+ // in initial enablement patch for scalable vectors
+ if (VT.isScalableVector())
+ return SDValue();
+
if (Op.getOpcode() >= ISD::BUILTIN_OP_END)
if (SDValue V = SimplifyMultipleUseDemandedBitsForTargetNode(
Op, DemandedBits, DemandedElts, DAG, Depth))
SDValue Op, const APInt &DemandedBits, SelectionDAG &DAG,
unsigned Depth) const {
EVT VT = Op.getValueType();
-
- // Pretend we don't know anything about scalable vectors for now.
- // TODO: We can probably do more work on simplifying the operations for
- // scalable vectors, but for now we just bail out.
- if (VT.isScalableVector())
- return SDValue();
-
- APInt DemandedElts = VT.isVector()
+ // Since the number of lanes in a scalable vector is unknown at compile time,
+ // we track one bit which is implicitly broadcast to all lanes. This means
+ // that all lanes in a scalable vector are considered demanded.
+ APInt DemandedElts = VT.isFixedLengthVector()
? APInt::getAllOnes(VT.getVectorNumElements())
: APInt(1, 1);
return SimplifyMultipleUseDemandedBits(Op, DemandedBits, DemandedElts, DAG,
// Don't know anything.
Known = KnownBits(BitWidth);
- // TODO: We can probably do more work on calculating the known bits and
- // simplifying the operations for scalable vectors, but for now we just
- // bail out.
EVT VT = Op.getValueType();
- if (VT.isScalableVector())
- return false;
-
bool IsLE = TLO.DAG.getDataLayout().isLittleEndian();
unsigned NumElts = OriginalDemandedElts.getBitWidth();
- assert((!VT.isVector() || NumElts == VT.getVectorNumElements()) &&
+ assert((!VT.isFixedLengthVector() || NumElts == VT.getVectorNumElements()) &&
"Unexpected vector size");
APInt DemandedBits = OriginalDemandedBits;
KnownBits Known2;
switch (Op.getOpcode()) {
case ISD::SCALAR_TO_VECTOR: {
+ if (VT.isScalableVector())
+ return false;
if (!DemandedElts[0])
return TLO.CombineTo(Op, TLO.DAG.getUNDEF(VT));
break;
}
case ISD::INSERT_VECTOR_ELT: {
+ if (VT.isScalableVector())
+ return false;
SDValue Vec = Op.getOperand(0);
SDValue Scl = Op.getOperand(1);
auto *CIdx = dyn_cast<ConstantSDNode>(Op.getOperand(2));
return false;
}
case ISD::INSERT_SUBVECTOR: {
+ if (VT.isScalableVector())
+ return false;
// Demand any elements from the subvector and the remainder from the src its
// inserted into.
SDValue Src = Op.getOperand(0);
break;
}
case ISD::EXTRACT_SUBVECTOR: {
+ if (VT.isScalableVector())
+ return false;
// Offset the demanded elts by the subvector index.
SDValue Src = Op.getOperand(0);
if (Src.getValueType().isScalableVector())
break;
}
case ISD::CONCAT_VECTORS: {
+ if (VT.isScalableVector())
+ return false;
Known.Zero.setAllBits();
Known.One.setAllBits();
EVT SubVT = Op.getOperand(0).getValueType();
break;
}
case ISD::VECTOR_SHUFFLE: {
+ assert(!VT.isScalableVector());
ArrayRef<int> ShuffleMask = cast<ShuffleVectorSDNode>(Op)->getMask();
// Collect demanded elements from shuffle operands..
// AND(INSERT_SUBVECTOR(C,X,I),M) -> INSERT_SUBVECTOR(AND(C,M),X,I)
// iff 'C' is Undef/Constant and AND(X,M) == X (for DemandedBits).
- if (Op0.getOpcode() == ISD::INSERT_SUBVECTOR &&
+ if (Op0.getOpcode() == ISD::INSERT_SUBVECTOR && !VT.isScalableVector() &&
(Op0.getOperand(0).isUndef() ||
ISD::isBuildVectorOfConstantSDNodes(Op0.getOperand(0).getNode())) &&
Op0->hasOneUse()) {
Known = KnownHi.concat(KnownLo);
break;
}
- case ISD::ZERO_EXTEND:
- case ISD::ZERO_EXTEND_VECTOR_INREG: {
+ case ISD::ZERO_EXTEND_VECTOR_INREG:
+ if (VT.isScalableVector())
+ return false;
+ [[fallthrough]];
+ case ISD::ZERO_EXTEND: {
SDValue Src = Op.getOperand(0);
EVT SrcVT = Src.getValueType();
unsigned InBits = SrcVT.getScalarSizeInBits();
- unsigned InElts = SrcVT.isVector() ? SrcVT.getVectorNumElements() : 1;
+ unsigned InElts = SrcVT.isFixedLengthVector() ? SrcVT.getVectorNumElements() : 1;
bool IsVecInReg = Op.getOpcode() == ISD::ZERO_EXTEND_VECTOR_INREG;
// If none of the top bits are demanded, convert this into an any_extend.
return TLO.CombineTo(Op, TLO.DAG.getNode(Op.getOpcode(), dl, VT, NewSrc));
break;
}
- case ISD::SIGN_EXTEND:
- case ISD::SIGN_EXTEND_VECTOR_INREG: {
+ case ISD::SIGN_EXTEND_VECTOR_INREG:
+ if (VT.isScalableVector())
+ return false;
+ [[fallthrough]];
+ case ISD::SIGN_EXTEND: {
SDValue Src = Op.getOperand(0);
EVT SrcVT = Src.getValueType();
unsigned InBits = SrcVT.getScalarSizeInBits();
- unsigned InElts = SrcVT.isVector() ? SrcVT.getVectorNumElements() : 1;
+ unsigned InElts = SrcVT.isFixedLengthVector() ? SrcVT.getVectorNumElements() : 1;
bool IsVecInReg = Op.getOpcode() == ISD::SIGN_EXTEND_VECTOR_INREG;
// If none of the top bits are demanded, convert this into an any_extend.
return TLO.CombineTo(Op, TLO.DAG.getNode(Op.getOpcode(), dl, VT, NewSrc));
break;
}
- case ISD::ANY_EXTEND:
- case ISD::ANY_EXTEND_VECTOR_INREG: {
+ case ISD::ANY_EXTEND_VECTOR_INREG:
+ if (VT.isScalableVector())
+ return false;
+ [[fallthrough]];
+ case ISD::ANY_EXTEND: {
SDValue Src = Op.getOperand(0);
EVT SrcVT = Src.getValueType();
unsigned InBits = SrcVT.getScalarSizeInBits();
- unsigned InElts = SrcVT.isVector() ? SrcVT.getVectorNumElements() : 1;
+ unsigned InElts = SrcVT.isFixedLengthVector() ? SrcVT.getVectorNumElements() : 1;
bool IsVecInReg = Op.getOpcode() == ISD::ANY_EXTEND_VECTOR_INREG;
// If we only need the bottom element then we can just bitcast.
break;
}
case ISD::BITCAST: {
+ if (VT.isScalableVector())
+ return false;
SDValue Src = Op.getOperand(0);
EVT SrcVT = Src.getValueType();
unsigned NumSrcEltBits = SrcVT.getScalarSizeInBits();
// We also ask the target about intrinsics (which could be specific to it).
if (Op.getOpcode() >= ISD::BUILTIN_OP_END ||
Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN) {
+ // TODO: Probably okay to remove after audit; here to reduce change size
+ // in initial enablement patch for scalable vectors
+ if (Op.getValueType().isScalableVector())
+ break;
if (SimplifyDemandedBitsForTargetNode(Op, DemandedBits, DemandedElts,
Known, TLO, Depth))
return true;
"Vector binop only");
EVT EltVT = VT.getVectorElementType();
- unsigned NumElts = VT.getVectorNumElements();
+ unsigned NumElts = VT.isFixedLengthVector() ? VT.getVectorNumElements() : 1;
assert(UndefOp0.getBitWidth() == NumElts &&
UndefOp1.getBitWidth() == NumElts && "Bad type for undef analysis");
; CHECK: // %bb.0:
; CHECK-NEXT: and w8, w0, #0xff
; CHECK-NEXT: index z0.s, #0, #1
+; CHECK-NEXT: and w9, w1, #0xff
; CHECK-NEXT: and z0.s, z0.s, #0xff
; CHECK-NEXT: ptrue p0.s
; CHECK-NEXT: mov z1.s, w8
-; CHECK-NEXT: and w8, w1, #0xff
; CHECK-NEXT: add z0.s, z0.s, z1.s
+; CHECK-NEXT: mov z1.s, w9
; CHECK-NEXT: umin z0.s, z0.s, #255
-; CHECK-NEXT: and z0.s, z0.s, #0xff
-; CHECK-NEXT: mov z1.s, w8
; CHECK-NEXT: cmphi p0.s, p0/z, z1.s, z0.s
; CHECK-NEXT: ret
%active.lane.mask = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i8(i8 %index, i8 %TC)
; CHECK: // %bb.0:
; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-NEXT: and x8, x0, #0xff
-; CHECK-NEXT: index z0.d, #0, #1
; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1
; CHECK-NEXT: and x9, x1, #0xff
-; CHECK-NEXT: and z0.d, z0.d, #0xff
+; CHECK-NEXT: index z0.d, #0, #1
; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: and z0.d, z0.d, #0xff
; CHECK-NEXT: mov z1.d, x8
+; CHECK-NEXT: mov z2.d, x9
; CHECK-NEXT: add z0.d, z0.d, z1.d
-; CHECK-NEXT: mov z1.d, x9
; CHECK-NEXT: umin z0.d, z0.d, #255
-; CHECK-NEXT: and z0.d, z0.d, #0xff
-; CHECK-NEXT: cmphi p0.d, p0/z, z1.d, z0.d
+; CHECK-NEXT: cmphi p0.d, p0/z, z2.d, z0.d
; CHECK-NEXT: ret
%active.lane.mask = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i8(i8 %index, i8 %TC)
ret <vscale x 2 x i1> %active.lane.mask