@@ -4532,7 +4532,9 @@ bool AArch64DAGToDAGISel::trySelectXAR(SDNode *N) {
45324532
45334533 SDValue N0 = N->getOperand (0 );
45344534 SDValue N1 = N->getOperand (1 );
4535+
45354536 EVT VT = N->getValueType (0 );
4537+ SDLoc DL (N);
45364538
45374539 // Essentially: rotr (xor(x, y), imm) -> xar (x, y, imm)
45384540 // Rotate by a constant is a funnel shift in IR which is exanded to
@@ -4558,10 +4560,18 @@ bool AArch64DAGToDAGISel::trySelectXAR(SDNode *N) {
45584560 !TLI->isAllActivePredicate (*CurDAG, N1.getOperand (0 )))
45594561 return false ;
45604562
4561- SDValue XOR = N0.getOperand (1 );
4562- if (XOR.getOpcode () != ISD::XOR || XOR != N1.getOperand (1 ))
4563+ if (N0.getOperand (1 ) != N1.getOperand (1 ))
45634564 return false ;
45644565
4566+ SDValue R1, R2;
4567+ bool IsXOROperand = true ;
4568+ if (N0.getOperand (1 ).getOpcode () != ISD::XOR) {
4569+ IsXOROperand = false ;
4570+ } else {
4571+ R1 = N0.getOperand (1 ).getOperand (0 );
4572+ R2 = N1.getOperand (1 ).getOperand (1 );
4573+ }
4574+
45654575 APInt ShlAmt, ShrAmt;
45664576 if (!ISD::isConstantSplatVector (N0.getOperand (2 ).getNode (), ShlAmt) ||
45674577 !ISD::isConstantSplatVector (N1.getOperand (2 ).getNode (), ShrAmt))
@@ -4570,11 +4580,23 @@ bool AArch64DAGToDAGISel::trySelectXAR(SDNode *N) {
45704580 if (ShlAmt + ShrAmt != VT.getScalarSizeInBits ())
45714581 return false ;
45724582
4573- SDLoc DL (N);
4583+ if (!IsXOROperand) {
4584+ SDValue Zero = CurDAG->getTargetConstant (0 , DL, MVT::i64 );
4585+ SDNode *MOV = CurDAG->getMachineNode (AArch64::MOVIv2d_ns, DL, VT, Zero);
4586+ SDValue MOVIV = SDValue (MOV, 0 );
4587+
4588+ SDValue ZSub = CurDAG->getTargetConstant (AArch64::zsub, DL, MVT::i32 );
4589+ SDNode *SubRegToReg = CurDAG->getMachineNode (AArch64::SUBREG_TO_REG, DL,
4590+ VT, Zero, MOVIV, ZSub);
4591+
4592+ R1 = N1->getOperand (1 );
4593+ R2 = SDValue (SubRegToReg, 0 );
4594+ }
4595+
45744596 SDValue Imm =
45754597 CurDAG->getTargetConstant (ShrAmt.getZExtValue (), DL, MVT::i32 );
45764598
4577- SDValue Ops[] = {XOR. getOperand ( 0 ), XOR. getOperand ( 1 ) , Imm};
4599+ SDValue Ops[] = {R1, R2 , Imm};
45784600 if (auto Opc = SelectOpcodeFromVT<SelectTypeKind::Int>(
45794601 VT, {AArch64::XAR_ZZZI_B, AArch64::XAR_ZZZI_H, AArch64::XAR_ZZZI_S,
45804602 AArch64::XAR_ZZZI_D})) {
@@ -4591,24 +4613,36 @@ bool AArch64DAGToDAGISel::trySelectXAR(SDNode *N) {
45914613 N1->getOpcode () != AArch64ISD::VLSHR)
45924614 return false ;
45934615
4594- if (N0->getOperand (0 ) != N1->getOperand (0 ) ||
4595- N1->getOperand (0 )->getOpcode () != ISD::XOR)
4616+ if (N0->getOperand (0 ) != N1->getOperand (0 ))
45964617 return false ;
45974618
4598- SDValue XOR = N0.getOperand (0 );
4599- SDValue R1 = XOR.getOperand (0 );
4600- SDValue R2 = XOR.getOperand (1 );
4619+ SDValue R1, R2;
4620+ bool IsXOROperand = true ;
4621+ if (N1->getOperand (0 )->getOpcode () != ISD::XOR) {
4622+ IsXOROperand = false ;
4623+ } else {
4624+ SDValue XOR = N0.getOperand (0 );
4625+ R1 = XOR.getOperand (0 );
4626+ R2 = XOR.getOperand (1 );
4627+ }
46014628
46024629 unsigned HsAmt = N0.getConstantOperandVal (1 );
46034630 unsigned ShAmt = N1.getConstantOperandVal (1 );
46044631
4605- SDLoc DL = SDLoc (N0.getOperand (1 ));
46064632 SDValue Imm = CurDAG->getTargetConstant (
46074633 ShAmt, DL, N0.getOperand (1 ).getValueType (), false );
46084634
46094635 if (ShAmt + HsAmt != 64 )
46104636 return false ;
46114637
4638+ if (!IsXOROperand) {
4639+ SDValue Zero = CurDAG->getTargetConstant (0 , DL, MVT::i64 );
4640+ SDNode *MOV = CurDAG->getMachineNode (AArch64::MOVIv2d_ns, DL, VT, Zero);
4641+ SDValue MOVIV = SDValue (MOV, 0 );
4642+ R1 = N1->getOperand (0 );
4643+ R2 = MOVIV;
4644+ }
4645+
46124646 SDValue Ops[] = {R1, R2, Imm};
46134647 CurDAG->SelectNodeTo (N, AArch64::XAR, N0.getValueType (), Ops);
46144648
0 commit comments