@@ -81,10 +81,10 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
81
81
setOperationAction (ISD::SIGN_EXTEND_INREG, VT, Expand);
82
82
83
83
if (Subtarget.is64Bit ()) {
84
- setTargetDAGCombine (ISD::SHL);
85
- setTargetDAGCombine (ISD::SRL);
86
- setTargetDAGCombine (ISD::SRA);
87
84
setTargetDAGCombine (ISD::ANY_EXTEND);
85
+ setOperationAction (ISD::SHL, MVT::i32 , Custom);
86
+ setOperationAction (ISD::SRA, MVT::i32 , Custom);
87
+ setOperationAction (ISD::SRL, MVT::i32 , Custom);
88
88
}
89
89
90
90
if (!Subtarget.hasStdExtM ()) {
@@ -513,15 +513,52 @@ SDValue RISCVTargetLowering::lowerRETURNADDR(SDValue Op,
513
513
return DAG.getCopyFromReg (DAG.getEntryNode (), DL, Reg, XLenVT);
514
514
}
515
515
516
- // Return true if the given node is a shift with a non-constant shift amount.
517
- static bool isVariableShift (SDValue Val) {
518
- switch (Val.getOpcode ()) {
516
+ // Returns the opcode of the target-specific SDNode that implements the 32-bit
517
+ // form of the given Opcode.
518
+ static RISCVISD::NodeType getRISCVWOpcode (unsigned Opcode) {
519
+ switch (Opcode) {
519
520
default :
520
- return false ;
521
+ llvm_unreachable ( " Unexpected opcode " ) ;
521
522
case ISD::SHL:
523
+ return RISCVISD::SLLW;
522
524
case ISD::SRA:
525
+ return RISCVISD::SRAW;
523
526
case ISD::SRL:
524
- return Val.getOperand (1 ).getOpcode () != ISD::Constant;
527
+ return RISCVISD::SRLW;
528
+ }
529
+ }
530
+
531
+ // Converts the given 32-bit operation to a target-specific SelectionDAG node.
532
+ // Because i32 isn't a legal type for RV64, these operations would otherwise
533
+ // be promoted to i64, making it difficult to select the SLLW/DIVUW/.../*W
534
+ // later one because the fact the operation was originally of type i32 is
535
+ // lost.
536
+ static SDValue customLegalizeToWOp (SDNode *N, SelectionDAG &DAG) {
537
+ SDLoc DL (N);
538
+ RISCVISD::NodeType WOpcode = getRISCVWOpcode (N->getOpcode ());
539
+ SDValue NewOp0 = DAG.getNode (ISD::ANY_EXTEND, DL, MVT::i64 , N->getOperand (0 ));
540
+ SDValue NewOp1 = DAG.getNode (ISD::ANY_EXTEND, DL, MVT::i64 , N->getOperand (1 ));
541
+ SDValue NewRes = DAG.getNode (WOpcode, DL, MVT::i64 , NewOp0, NewOp1);
542
+ // ReplaceNodeResults requires we maintain the same type for the return value.
543
+ return DAG.getNode (ISD::TRUNCATE, DL, MVT::i32 , NewRes);
544
+ }
545
+
546
+ void RISCVTargetLowering::ReplaceNodeResults (SDNode *N,
547
+ SmallVectorImpl<SDValue> &Results,
548
+ SelectionDAG &DAG) const {
549
+ SDLoc DL (N);
550
+ switch (N->getOpcode ()) {
551
+ default :
552
+ llvm_unreachable (" Don't know how to custom type legalize this operation!" );
553
+ case ISD::SHL:
554
+ case ISD::SRA:
555
+ case ISD::SRL:
556
+ assert (N->getValueType (0 ) == MVT::i32 && Subtarget.is64Bit () &&
557
+ " Unexpected custom legalisation" );
558
+ if (N->getOperand (1 ).getOpcode () == ISD::Constant)
559
+ return ;
560
+ Results.push_back (customLegalizeToWOp (N, DAG));
561
+ break ;
525
562
}
526
563
}
527
564
@@ -546,34 +583,14 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
546
583
switch (N->getOpcode ()) {
547
584
default :
548
585
break ;
549
- case ISD::SHL:
550
- case ISD::SRL:
551
- case ISD::SRA: {
552
- assert (Subtarget.getXLen () == 64 && " Combine should be 64-bit only" );
553
- if (!DCI.isBeforeLegalize ())
554
- break ;
555
- SDValue RHS = N->getOperand (1 );
556
- if (N->getValueType (0 ) != MVT::i32 || RHS->getOpcode () == ISD::Constant ||
557
- (RHS->getOpcode () == ISD::AssertZext &&
558
- cast<VTSDNode>(RHS->getOperand (1 ))->getVT ().getSizeInBits () <= 5 ))
559
- break ;
560
- SDValue LHS = N->getOperand (0 );
561
- SDLoc DL (N);
562
- SDValue NewRHS =
563
- DAG.getNode (ISD::AssertZext, DL, RHS.getValueType (), RHS,
564
- DAG.getValueType (EVT::getIntegerVT (*DAG.getContext (), 5 )));
565
- return DCI.CombineTo (
566
- N, DAG.getNode (N->getOpcode (), DL, LHS.getValueType (), LHS, NewRHS));
567
- }
568
586
case ISD::ANY_EXTEND: {
569
- // If any-extending an i32 variable-length shift or sdiv/udiv/urem to i64,
570
- // then instead sign-extend in order to increase the chance of being able
571
- // to select the sllw/srlw/sraw/ divw/divuw/remuw instructions.
587
+ // If any-extending an i32 sdiv/udiv/urem to i64, then instead sign-extend
588
+ // in order to increase the chance of being able to select the
589
+ // divw/divuw/remuw instructions.
572
590
SDValue Src = N->getOperand (0 );
573
591
if (N->getValueType (0 ) != MVT::i64 || Src.getValueType () != MVT::i32 )
574
592
break ;
575
- if (!isVariableShift (Src) &&
576
- !(Subtarget.hasStdExtM () && isVariableSDivUDivURem (Src)))
593
+ if (!(Subtarget.hasStdExtM () && isVariableSDivUDivURem (Src)))
577
594
break ;
578
595
SDLoc DL (N);
579
596
// Don't add the new node to the DAGCombiner worklist, in order to avoid
@@ -590,11 +607,42 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
590
607
break ;
591
608
return DCI.CombineTo (N, Op0.getOperand (0 ), Op0.getOperand (1 ));
592
609
}
610
+ case RISCVISD::SLLW:
611
+ case RISCVISD::SRAW:
612
+ case RISCVISD::SRLW: {
613
+ // Only the lower 32 bits of LHS and lower 5 bits of RHS are read.
614
+ SDValue LHS = N->getOperand (0 );
615
+ SDValue RHS = N->getOperand (1 );
616
+ APInt LHSMask = APInt::getLowBitsSet (LHS.getValueSizeInBits (), 32 );
617
+ APInt RHSMask = APInt::getLowBitsSet (RHS.getValueSizeInBits (), 5 );
618
+ if ((SimplifyDemandedBits (N->getOperand (0 ), LHSMask, DCI)) ||
619
+ (SimplifyDemandedBits (N->getOperand (1 ), RHSMask, DCI)))
620
+ return SDValue ();
621
+ break ;
622
+ }
593
623
}
594
624
595
625
return SDValue ();
596
626
}
597
627
628
+ unsigned RISCVTargetLowering::ComputeNumSignBitsForTargetNode (
629
+ SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
630
+ unsigned Depth) const {
631
+ switch (Op.getOpcode ()) {
632
+ default :
633
+ break ;
634
+ case RISCVISD::SLLW:
635
+ case RISCVISD::SRAW:
636
+ case RISCVISD::SRLW:
637
+ // TODO: As the result is sign-extended, this is conservatively correct. A
638
+ // more precise answer could be calculated for SRAW depending on known
639
+ // bits in the shift amount.
640
+ return 33 ;
641
+ }
642
+
643
+ return 1 ;
644
+ }
645
+
598
646
static MachineBasicBlock *emitSplitF64Pseudo (MachineInstr &MI,
599
647
MachineBasicBlock *BB) {
600
648
assert (MI.getOpcode () == RISCV::SplitF64Pseudo && " Unexpected instruction" );
@@ -1683,6 +1731,12 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
1683
1731
return " RISCVISD::SplitF64" ;
1684
1732
case RISCVISD::TAIL:
1685
1733
return " RISCVISD::TAIL" ;
1734
+ case RISCVISD::SLLW:
1735
+ return " RISCVISD::SLLW" ;
1736
+ case RISCVISD::SRAW:
1737
+ return " RISCVISD::SRAW" ;
1738
+ case RISCVISD::SRLW:
1739
+ return " RISCVISD::SRLW" ;
1686
1740
}
1687
1741
return nullptr ;
1688
1742
}
0 commit comments