@@ -14742,6 +14742,106 @@ static SDValue tryLowerToSLI(SDNode *N, SelectionDAG &DAG) {
1474214742 return ResultSLI;
1474314743}
1474414744
14745+ static SDValue tryCombineToBSL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
14746+ const AArch64TargetLowering &TLI) {
14747+ EVT VT = N->getValueType(0);
14748+ SelectionDAG &DAG = DCI.DAG;
14749+ SDLoc DL(N);
14750+ const auto &Subtarget = DAG.getSubtarget<AArch64Subtarget>();
14751+
14752+ if (!VT.isVector())
14753+ return SDValue();
14754+
14755+ if (VT.isScalableVector() && !Subtarget.hasSVE2())
14756+ return SDValue();
14757+
14758+ if (VT.isFixedLengthVector() &&
14759+ (!Subtarget.isNeonAvailable() || TLI.useSVEForFixedLengthVectorVT(VT)))
14760+ return SDValue();
14761+
14762+ SDValue N0 = N->getOperand(0);
14763+ if (N0.getOpcode() != ISD::AND)
14764+ return SDValue();
14765+
14766+ SDValue N1 = N->getOperand(1);
14767+ if (N1.getOpcode() != ISD::AND)
14768+ return SDValue();
14769+
14770+ // InstCombine does (not (neg a)) => (add a -1).
14771+ // Try: (or (and (neg a) b) (and (add a -1) c)) => (bsl (neg a) b c)
14772+ // Loop over all combinations of AND operands.
14773+ for (int i = 1; i >= 0; --i) {
14774+ for (int j = 1; j >= 0; --j) {
14775+ SDValue O0 = N0->getOperand(i);
14776+ SDValue O1 = N1->getOperand(j);
14777+ SDValue Sub, Add, SubSibling, AddSibling;
14778+
14779+ // Find a SUB and an ADD operand, one from each AND.
14780+ if (O0.getOpcode() == ISD::SUB && O1.getOpcode() == ISD::ADD) {
14781+ Sub = O0;
14782+ Add = O1;
14783+ SubSibling = N0->getOperand(1 - i);
14784+ AddSibling = N1->getOperand(1 - j);
14785+ } else if (O0.getOpcode() == ISD::ADD && O1.getOpcode() == ISD::SUB) {
14786+ Add = O0;
14787+ Sub = O1;
14788+ AddSibling = N0->getOperand(1 - i);
14789+ SubSibling = N1->getOperand(1 - j);
14790+ } else
14791+ continue;
14792+
14793+ if (!ISD::isConstantSplatVectorAllZeros(Sub.getOperand(0).getNode()))
14794+ continue;
14795+
14796+ // Constant ones is always righthand operand of the Add.
14797+ if (!ISD::isConstantSplatVectorAllOnes(Add.getOperand(1).getNode()))
14798+ continue;
14799+
14800+ if (Sub.getOperand(1) != Add.getOperand(0))
14801+ continue;
14802+
14803+ return DAG.getNode(AArch64ISD::BSP, DL, VT, Sub, SubSibling, AddSibling);
14804+ }
14805+ }
14806+
14807+ // (or (and a b) (and (not a) c)) => (bsl a b c)
14808+ // We only have to look for constant vectors here since the general, variable
14809+ // case can be handled in TableGen.
14810+ unsigned Bits = VT.getScalarSizeInBits();
14811+ uint64_t BitMask = Bits == 64 ? -1ULL : ((1ULL << Bits) - 1);
14812+ for (int i = 1; i >= 0; --i)
14813+ for (int j = 1; j >= 0; --j) {
14814+ APInt Val1, Val2;
14815+
14816+ if (ISD::isConstantSplatVector(N0->getOperand(i).getNode(), Val1) &&
14817+ ISD::isConstantSplatVector(N1->getOperand(j).getNode(), Val2) &&
14818+ (BitMask & ~Val1.getZExtValue()) == Val2.getZExtValue()) {
14819+ return DAG.getNode(AArch64ISD::BSP, DL, VT, N0->getOperand(i),
14820+ N0->getOperand(1 - i), N1->getOperand(1 - j));
14821+ }
14822+ BuildVectorSDNode *BVN0 = dyn_cast<BuildVectorSDNode>(N0->getOperand(i));
14823+ BuildVectorSDNode *BVN1 = dyn_cast<BuildVectorSDNode>(N1->getOperand(j));
14824+ if (!BVN0 || !BVN1)
14825+ continue;
14826+
14827+ bool FoundMatch = true;
14828+ for (unsigned k = 0; k < VT.getVectorNumElements(); ++k) {
14829+ ConstantSDNode *CN0 = dyn_cast<ConstantSDNode>(BVN0->getOperand(k));
14830+ ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(BVN1->getOperand(k));
14831+ if (!CN0 || !CN1 ||
14832+ CN0->getZExtValue() != (BitMask & ~CN1->getZExtValue())) {
14833+ FoundMatch = false;
14834+ break;
14835+ }
14836+ }
14837+ if (FoundMatch)
14838+ return DAG.getNode(AArch64ISD::BSP, DL, VT, N0->getOperand(i),
14839+ N0->getOperand(1 - i), N1->getOperand(1 - j));
14840+ }
14841+
14842+ return SDValue();
14843+ }
14844+
1474514845SDValue AArch64TargetLowering::LowerVectorOR(SDValue Op,
1474614846 SelectionDAG &DAG) const {
1474714847 if (useSVEForFixedLengthVectorVT(Op.getValueType(),
@@ -19419,106 +19519,6 @@ static SDValue performFpToIntCombine(SDNode *N, SelectionDAG &DAG,
1941919519 return FixConv;
1942019520}
1942119521
19422- static SDValue tryCombineToBSL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
19423- const AArch64TargetLowering &TLI) {
19424- EVT VT = N->getValueType(0);
19425- SelectionDAG &DAG = DCI.DAG;
19426- SDLoc DL(N);
19427- const auto &Subtarget = DAG.getSubtarget<AArch64Subtarget>();
19428-
19429- if (!VT.isVector())
19430- return SDValue();
19431-
19432- if (VT.isScalableVector() && !Subtarget.hasSVE2())
19433- return SDValue();
19434-
19435- if (VT.isFixedLengthVector() &&
19436- (!Subtarget.isNeonAvailable() || TLI.useSVEForFixedLengthVectorVT(VT)))
19437- return SDValue();
19438-
19439- SDValue N0 = N->getOperand(0);
19440- if (N0.getOpcode() != ISD::AND)
19441- return SDValue();
19442-
19443- SDValue N1 = N->getOperand(1);
19444- if (N1.getOpcode() != ISD::AND)
19445- return SDValue();
19446-
19447- // InstCombine does (not (neg a)) => (add a -1).
19448- // Try: (or (and (neg a) b) (and (add a -1) c)) => (bsl (neg a) b c)
19449- // Loop over all combinations of AND operands.
19450- for (int i = 1; i >= 0; --i) {
19451- for (int j = 1; j >= 0; --j) {
19452- SDValue O0 = N0->getOperand(i);
19453- SDValue O1 = N1->getOperand(j);
19454- SDValue Sub, Add, SubSibling, AddSibling;
19455-
19456- // Find a SUB and an ADD operand, one from each AND.
19457- if (O0.getOpcode() == ISD::SUB && O1.getOpcode() == ISD::ADD) {
19458- Sub = O0;
19459- Add = O1;
19460- SubSibling = N0->getOperand(1 - i);
19461- AddSibling = N1->getOperand(1 - j);
19462- } else if (O0.getOpcode() == ISD::ADD && O1.getOpcode() == ISD::SUB) {
19463- Add = O0;
19464- Sub = O1;
19465- AddSibling = N0->getOperand(1 - i);
19466- SubSibling = N1->getOperand(1 - j);
19467- } else
19468- continue;
19469-
19470- if (!ISD::isConstantSplatVectorAllZeros(Sub.getOperand(0).getNode()))
19471- continue;
19472-
19473- // Constant ones is always righthand operand of the Add.
19474- if (!ISD::isConstantSplatVectorAllOnes(Add.getOperand(1).getNode()))
19475- continue;
19476-
19477- if (Sub.getOperand(1) != Add.getOperand(0))
19478- continue;
19479-
19480- return DAG.getNode(AArch64ISD::BSP, DL, VT, Sub, SubSibling, AddSibling);
19481- }
19482- }
19483-
19484- // (or (and a b) (and (not a) c)) => (bsl a b c)
19485- // We only have to look for constant vectors here since the general, variable
19486- // case can be handled in TableGen.
19487- unsigned Bits = VT.getScalarSizeInBits();
19488- uint64_t BitMask = Bits == 64 ? -1ULL : ((1ULL << Bits) - 1);
19489- for (int i = 1; i >= 0; --i)
19490- for (int j = 1; j >= 0; --j) {
19491- APInt Val1, Val2;
19492-
19493- if (ISD::isConstantSplatVector(N0->getOperand(i).getNode(), Val1) &&
19494- ISD::isConstantSplatVector(N1->getOperand(j).getNode(), Val2) &&
19495- (BitMask & ~Val1.getZExtValue()) == Val2.getZExtValue()) {
19496- return DAG.getNode(AArch64ISD::BSP, DL, VT, N0->getOperand(i),
19497- N0->getOperand(1 - i), N1->getOperand(1 - j));
19498- }
19499- BuildVectorSDNode *BVN0 = dyn_cast<BuildVectorSDNode>(N0->getOperand(i));
19500- BuildVectorSDNode *BVN1 = dyn_cast<BuildVectorSDNode>(N1->getOperand(j));
19501- if (!BVN0 || !BVN1)
19502- continue;
19503-
19504- bool FoundMatch = true;
19505- for (unsigned k = 0; k < VT.getVectorNumElements(); ++k) {
19506- ConstantSDNode *CN0 = dyn_cast<ConstantSDNode>(BVN0->getOperand(k));
19507- ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(BVN1->getOperand(k));
19508- if (!CN0 || !CN1 ||
19509- CN0->getZExtValue() != (BitMask & ~CN1->getZExtValue())) {
19510- FoundMatch = false;
19511- break;
19512- }
19513- }
19514- if (FoundMatch)
19515- return DAG.getNode(AArch64ISD::BSP, DL, VT, N0->getOperand(i),
19516- N0->getOperand(1 - i), N1->getOperand(1 - j));
19517- }
19518-
19519- return SDValue();
19520- }
19521-
1952219522// Given a tree of and/or(csel(0, 1, cc0), csel(0, 1, cc1)), we may be able to
1952319523// convert to csel(ccmp(.., cc0)), depending on cc1:
1952419524
0 commit comments