diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index c5227eeb66da..e9ae4e685b29 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -6103,14 +6103,19 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, break; } + case RISCVISD::FMV_X_ANYEXTH: case RISCVISD::FMV_X_ANYEXTW_RV64: { SDLoc DL(N); SDValue Op0 = N->getOperand(0); + MVT VT = N->getSimpleValueType(0); // If the input to FMV_X_ANYEXTW_RV64 is just FMV_W_X_RV64 then the - // conversion is unnecessary and can be replaced with an ANY_EXTEND - // of the FMV_W_X_RV64 operand. - if (Op0->getOpcode() == RISCVISD::FMV_W_X_RV64) { - assert(Op0.getOperand(0).getValueType() == MVT::i64 && + // conversion is unnecessary and can be replaced with the FMV_W_X_RV64 + // operand. Similar for FMV_X_ANYEXTH and FMV_H_X. + if ((N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 && + Op0->getOpcode() == RISCVISD::FMV_W_X_RV64) || + (N->getOpcode() == RISCVISD::FMV_X_ANYEXTH && + Op0->getOpcode() == RISCVISD::FMV_H_X)) { + assert(Op0.getOperand(0).getValueType() == VT && "Unexpected value type!"); return Op0.getOperand(0); } @@ -6122,16 +6127,16 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, if (!(Op0.getOpcode() == ISD::FNEG || Op0.getOpcode() == ISD::FABS) || !Op0.getNode()->hasOneUse()) break; - SDValue NewFMV = DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, MVT::i64, - Op0.getOperand(0)); - APInt SignBit = APInt::getSignMask(32).sext(64); + SDValue NewFMV = DAG.getNode(N->getOpcode(), DL, VT, Op0.getOperand(0)); + unsigned FPBits = N->getOpcode() == RISCVISD::FMV_X_ANYEXTW_RV64 ? 32 : 16; + APInt SignBit = APInt::getSignMask(FPBits).sextOrSelf(VT.getSizeInBits()); if (Op0.getOpcode() == ISD::FNEG) - return DAG.getNode(ISD::XOR, DL, MVT::i64, NewFMV, - DAG.getConstant(SignBit, DL, MVT::i64)); + return DAG.getNode(ISD::XOR, DL, VT, NewFMV, + DAG.getConstant(SignBit, DL, VT)); assert(Op0.getOpcode() == ISD::FABS); - return DAG.getNode(ISD::AND, DL, MVT::i64, NewFMV, - DAG.getConstant(~SignBit, DL, MVT::i64)); + return DAG.getNode(ISD::AND, DL, VT, NewFMV, + DAG.getConstant(~SignBit, DL, VT)); } case ISD::AND: return performANDCombine(N, DCI, Subtarget); diff --git a/llvm/test/CodeGen/RISCV/half-bitmanip-dagcombines.ll b/llvm/test/CodeGen/RISCV/half-bitmanip-dagcombines.ll index 7a3465516b35..d37f1ad5abb8 100644 --- a/llvm/test/CodeGen/RISCV/half-bitmanip-dagcombines.ll +++ b/llvm/test/CodeGen/RISCV/half-bitmanip-dagcombines.ll @@ -23,9 +23,8 @@ define half @fneg(half %a) nounwind { ; ; RV32IZFH-LABEL: fneg: ; RV32IZFH: # %bb.0: -; RV32IZFH-NEXT: fmv.h.x ft0, a0 -; RV32IZFH-NEXT: fneg.h ft0, ft0 -; RV32IZFH-NEXT: fmv.x.h a0, ft0 +; RV32IZFH-NEXT: lui a1, 1048568 +; RV32IZFH-NEXT: xor a0, a0, a1 ; RV32IZFH-NEXT: ret ; ; RV64I-LABEL: fneg: @@ -36,9 +35,8 @@ define half @fneg(half %a) nounwind { ; ; RV64IZFH-LABEL: fneg: ; RV64IZFH: # %bb.0: -; RV64IZFH-NEXT: fmv.h.x ft0, a0 -; RV64IZFH-NEXT: fneg.h ft0, ft0 -; RV64IZFH-NEXT: fmv.x.h a0, ft0 +; RV64IZFH-NEXT: lui a1, 1048568 +; RV64IZFH-NEXT: xor a0, a0, a1 ; RV64IZFH-NEXT: ret %1 = fneg half %a ret half %1 @@ -56,9 +54,9 @@ define half @fabs(half %a) nounwind { ; ; RV32IZFH-LABEL: fabs: ; RV32IZFH: # %bb.0: -; RV32IZFH-NEXT: fmv.h.x ft0, a0 -; RV32IZFH-NEXT: fabs.h ft0, ft0 -; RV32IZFH-NEXT: fmv.x.h a0, ft0 +; RV32IZFH-NEXT: lui a1, 8 +; RV32IZFH-NEXT: addi a1, a1, -1 +; RV32IZFH-NEXT: and a0, a0, a1 ; RV32IZFH-NEXT: ret ; ; RV64I-LABEL: fabs: @@ -70,9 +68,9 @@ define half @fabs(half %a) nounwind { ; ; RV64IZFH-LABEL: fabs: ; RV64IZFH: # %bb.0: -; RV64IZFH-NEXT: fmv.h.x ft0, a0 -; RV64IZFH-NEXT: fabs.h ft0, ft0 -; RV64IZFH-NEXT: fmv.x.h a0, ft0 +; RV64IZFH-NEXT: lui a1, 8 +; RV64IZFH-NEXT: addiw a1, a1, -1 +; RV64IZFH-NEXT: and a0, a0, a1 ; RV64IZFH-NEXT: ret %1 = call half @llvm.fabs.f16(half %a) ret half %1