case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break;
case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break;
case ISD::STORE: Res = SoftenFloatOp_STORE(N, OpNo); break;
+ case ISD::FCOPYSIGN: Res = SoftenFloatOp_FCOPYSIGN(N); break;
}
// If the result is null, the sub-method took care of registering results etc.
ST->getMemOperand());
}
+SDValue DAGTypeLegalizer::SoftenFloatOp_FCOPYSIGN(SDNode *N) {
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = BitConvertToInteger(N->getOperand(1));
+ SDLoc dl(N);
+
+ EVT LVT = LHS.getValueType();
+ EVT ILVT = EVT::getIntegerVT(*DAG.getContext(), LVT.getSizeInBits());
+ EVT RVT = RHS.getValueType();
+
+ unsigned LSize = LVT.getSizeInBits();
+ unsigned RSize = RVT.getSizeInBits();
+
+ // Shift right or sign-extend it if the two operands have different types.
+ int SizeDiff = RSize - LSize;
+ if (SizeDiff > 0) {
+ RHS =
+ DAG.getNode(ISD::SRL, dl, RVT, RHS,
+ DAG.getConstant(SizeDiff, dl,
+ TLI.getShiftAmountTy(RHS.getValueType(),
+ DAG.getDataLayout())));
+ RHS = DAG.getNode(ISD::TRUNCATE, dl, ILVT, RHS);
+ } else if (SizeDiff < 0) {
+ RHS = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, RHS);
+ RHS =
+ DAG.getNode(ISD::SHL, dl, ILVT, RHS,
+ DAG.getConstant(-SizeDiff, dl,
+ TLI.getShiftAmountTy(RHS.getValueType(),
+ DAG.getDataLayout())));
+ }
+
+ RHS = DAG.getBitcast(LVT, RHS);
+ return DAG.getNode(ISD::FCOPYSIGN, dl, LVT, LHS, RHS);
+}
+
SDValue DAGTypeLegalizer::SoftenFloatOp_LROUND(SDNode *N) {
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
; RUN: | FileCheck %s -check-prefix=RV32I
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64I
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f \
+; RUN: -target-abi ilp32f < %s | FileCheck %s -check-prefix=RV32IF
; RUN: llc -mtriple=riscv32 -verify-machineinstrs -mattr=+f -mattr=+d \
; RUN: -target-abi ilp32d < %s | FileCheck %s -check-prefix=RV32IFD
; RUN: llc -mtriple=riscv64 -verify-machineinstrs -mattr=+f -mattr=+d \
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
+; RV32IF-LABEL: fold_promote:
+; RV32IF: # %bb.0:
+; RV32IF-NEXT: fmv.x.w a2, fa0
+; RV32IF-NEXT: lui a3, 524288
+; RV32IF-NEXT: and a2, a2, a3
+; RV32IF-NEXT: addi a3, a3, -1
+; RV32IF-NEXT: and a1, a1, a3
+; RV32IF-NEXT: or a1, a1, a2
+; RV32IF-NEXT: ret
+;
; RV32IFD-LABEL: fold_promote:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: fcvt.d.s ft0, fa1
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
+; RV32IF-LABEL: fold_demote:
+; RV32IF: # %bb.0:
+; RV32IF-NEXT: fmv.w.x ft0, a1
+; RV32IF-NEXT: fsgnj.s fa0, fa0, ft0
+; RV32IF-NEXT: ret
+;
; RV32IFD-LABEL: fold_demote:
; RV32IFD: # %bb.0:
; RV32IFD-NEXT: fcvt.s.d ft0, fa1