@@ -137,6 +137,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
137137 setOperationAction (Op, MVT::f32 , Expand);
138138 }
139139
140+ if (Subtarget.hasStdExtF () && Subtarget.is64Bit ())
141+ setOperationAction (ISD::BITCAST, MVT::i32 , Custom);
142+
140143 if (Subtarget.hasStdExtD ()) {
141144 setOperationAction (ISD::FMINNUM, MVT::f64 , Legal);
142145 setOperationAction (ISD::FMAXNUM, MVT::f64 , Legal);
@@ -338,6 +341,17 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
338341 return lowerFRAMEADDR (Op, DAG);
339342 case ISD::RETURNADDR:
340343 return lowerRETURNADDR (Op, DAG);
344+ case ISD::BITCAST: {
345+ assert (Subtarget.is64Bit () && Subtarget.hasStdExtF () &&
346+ " Unexpected custom legalisation" );
347+ SDLoc DL (Op);
348+ SDValue Op0 = Op.getOperand (0 );
349+ if (Op.getValueType () != MVT::f32 || Op0.getValueType () != MVT::i32 )
350+ return SDValue ();
351+ SDValue NewOp0 = DAG.getNode (ISD::ANY_EXTEND, DL, MVT::i64 , Op0);
352+ SDValue FPConv = DAG.getNode (RISCVISD::FMV_W_X_RV64, DL, MVT::f32 , NewOp0);
353+ return FPConv;
354+ }
341355 }
342356}
343357
@@ -579,6 +593,18 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
579593 return ;
580594 Results.push_back (customLegalizeToWOp (N, DAG));
581595 break ;
596+ case ISD::BITCAST: {
597+ assert (N->getValueType (0 ) == MVT::i32 && Subtarget.is64Bit () &&
598+ Subtarget.hasStdExtF () && " Unexpected custom legalisation" );
599+ SDLoc DL (N);
600+ SDValue Op0 = N->getOperand (0 );
601+ if (Op0.getValueType () != MVT::f32 )
602+ return ;
603+ SDValue FPConv =
604+ DAG.getNode (RISCVISD::FMV_X_ANYEXTW_RV64, DL, MVT::i64 , Op0);
605+ Results.push_back (DAG.getNode (ISD::TRUNCATE, DL, MVT::i32 , FPConv));
606+ break ;
607+ }
582608 }
583609}
584610
@@ -633,6 +659,38 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
633659 return SDValue ();
634660 break ;
635661 }
662+ case RISCVISD::FMV_X_ANYEXTW_RV64: {
663+ SDLoc DL (N);
664+ SDValue Op0 = N->getOperand (0 );
665+ // If the input to FMV_X_ANYEXTW_RV64 is just FMV_W_X_RV64 then the
666+ // conversion is unnecessary and can be replaced with an ANY_EXTEND
667+ // of the FMV_W_X_RV64 operand.
668+ if (Op0->getOpcode () == RISCVISD::FMV_W_X_RV64) {
669+ SDValue AExtOp =
670+ DAG.getNode (ISD::ANY_EXTEND, DL, MVT::i64 , Op0.getOperand (0 ));
671+ return DCI.CombineTo (N, AExtOp);
672+ }
673+
674+ // This is a target-specific version of a DAGCombine performed in
675+ // DAGCombiner::visitBITCAST. It performs the equivalent of:
676+ // fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit)
677+ // fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit))
678+ if (!(Op0.getOpcode () == ISD::FNEG || Op0.getOpcode () == ISD::FABS) ||
679+ !Op0.getNode ()->hasOneUse ())
680+ break ;
681+ SDValue NewFMV = DAG.getNode (RISCVISD::FMV_X_ANYEXTW_RV64, DL, MVT::i64 ,
682+ Op0.getOperand (0 ));
683+ APInt SignBit = APInt::getSignMask (32 ).sext (64 );
684+ if (Op0.getOpcode () == ISD::FNEG) {
685+ return DCI.CombineTo (N,
686+ DAG.getNode (ISD::XOR, DL, MVT::i64 , NewFMV,
687+ DAG.getConstant (SignBit, DL, MVT::i64 )));
688+ }
689+ assert (Op0.getOpcode () == ISD::FABS);
690+ return DCI.CombineTo (N,
691+ DAG.getNode (ISD::AND, DL, MVT::i64 , NewFMV,
692+ DAG.getConstant (~SignBit, DL, MVT::i64 )));
693+ }
636694 }
637695
638696 return SDValue ();
@@ -874,7 +932,7 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
874932 assert (XLen == 32 || XLen == 64 );
875933 MVT XLenVT = XLen == 32 ? MVT::i32 : MVT::i64 ;
876934 if (ValVT == MVT::f32 ) {
877- LocVT = MVT:: i32 ;
935+ LocVT = XLenVT ;
878936 LocInfo = CCValAssign::BCvt;
879937 }
880938
@@ -1047,6 +1105,10 @@ static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val,
10471105 case CCValAssign::Full:
10481106 break ;
10491107 case CCValAssign::BCvt:
1108+ if (VA.getLocVT () == MVT::i64 && VA.getValVT () == MVT::f32 ) {
1109+ Val = DAG.getNode (RISCVISD::FMV_W_X_RV64, DL, MVT::f32 , Val);
1110+ break ;
1111+ }
10501112 Val = DAG.getNode (ISD::BITCAST, DL, VA.getValVT (), Val);
10511113 break ;
10521114 }
@@ -1082,6 +1144,10 @@ static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDValue Val,
10821144 case CCValAssign::Full:
10831145 break ;
10841146 case CCValAssign::BCvt:
1147+ if (VA.getLocVT () == MVT::i64 && VA.getValVT () == MVT::f32 ) {
1148+ Val = DAG.getNode (RISCVISD::FMV_X_ANYEXTW_RV64, DL, MVT::i64 , Val);
1149+ break ;
1150+ }
10851151 Val = DAG.getNode (ISD::BITCAST, DL, LocVT, Val);
10861152 break ;
10871153 }
@@ -1108,9 +1174,12 @@ static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,
11081174 llvm_unreachable (" Unexpected CCValAssign::LocInfo" );
11091175 case CCValAssign::Full:
11101176 case CCValAssign::Indirect:
1177+ case CCValAssign::BCvt:
11111178 ExtType = ISD::NON_EXTLOAD;
11121179 break ;
11131180 }
1181+ if (ValVT == MVT::f32 )
1182+ LocVT = MVT::f32 ;
11141183 Val = DAG.getExtLoad (
11151184 ExtType, DL, LocVT, Chain, FIN,
11161185 MachinePointerInfo::getFixedStack (DAG.getMachineFunction (), FI), ValVT);
@@ -1759,6 +1828,10 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
17591828 return " RISCVISD::DIVUW" ;
17601829 case RISCVISD::REMUW:
17611830 return " RISCVISD::REMUW" ;
1831+ case RISCVISD::FMV_W_X_RV64:
1832+ return " RISCVISD::FMV_W_X_RV64" ;
1833+ case RISCVISD::FMV_X_ANYEXTW_RV64:
1834+ return " RISCVISD::FMV_X_ANYEXTW_RV64" ;
17621835 }
17631836 return nullptr ;
17641837}
0 commit comments