forked from OSchip/llvm-project
[RISCV] Add target DAG combine for bitcast fabs/fneg on RV32FD
DAGCombiner::visitBITCAST will perform: fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit) fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit)) As shown in double-bitmanip-dagcombines.ll, this can be advantageous. But RV32FD doesn't use bitcast directly (as i64 isn't a legal type), and instead uses RISCVISD::SplitF64. This patch adds an equivalent DAG combine for SplitF64. llvm-svn: 352247
This commit is contained in:
parent
519f42d914
commit
0092df0669
|
@ -584,16 +584,41 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
|
|||
|
||||
SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
|
||||
DAGCombinerInfo &DCI) const {
|
||||
SelectionDAG &DAG = DCI.DAG;
|
||||
|
||||
switch (N->getOpcode()) {
|
||||
default:
|
||||
break;
|
||||
case RISCVISD::SplitF64: {
|
||||
SDValue Op0 = N->getOperand(0);
|
||||
// If the input to SplitF64 is just BuildPairF64 then the operation is
|
||||
// redundant. Instead, use BuildPairF64's operands directly.
|
||||
SDValue Op0 = N->getOperand(0);
|
||||
if (Op0->getOpcode() != RISCVISD::BuildPairF64)
|
||||
if (Op0->getOpcode() == RISCVISD::BuildPairF64)
|
||||
return DCI.CombineTo(N, Op0.getOperand(0), Op0.getOperand(1));
|
||||
|
||||
SDLoc DL(N);
|
||||
// This is a target-specific version of a DAGCombine performed in
|
||||
// DAGCombiner::visitBITCAST. It performs the equivalent of:
|
||||
// fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit)
|
||||
// fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit))
|
||||
if (!(Op0.getOpcode() == ISD::FNEG || Op0.getOpcode() == ISD::FABS) ||
|
||||
!Op0.getNode()->hasOneUse())
|
||||
break;
|
||||
return DCI.CombineTo(N, Op0.getOperand(0), Op0.getOperand(1));
|
||||
SDValue NewSplitF64 =
|
||||
DAG.getNode(RISCVISD::SplitF64, DL, DAG.getVTList(MVT::i32, MVT::i32),
|
||||
Op0.getOperand(0));
|
||||
SDValue Lo = NewSplitF64.getValue(0);
|
||||
SDValue Hi = NewSplitF64.getValue(1);
|
||||
APInt SignBit = APInt::getSignMask(32);
|
||||
if (Op0.getOpcode() == ISD::FNEG) {
|
||||
SDValue NewHi = DAG.getNode(ISD::XOR, DL, MVT::i32, Hi,
|
||||
DAG.getConstant(SignBit, DL, MVT::i32));
|
||||
return DCI.CombineTo(N, Lo, NewHi);
|
||||
}
|
||||
assert(Op0.getOpcode() == ISD::FABS);
|
||||
SDValue NewHi = DAG.getNode(ISD::AND, DL, MVT::i32, Hi,
|
||||
DAG.getConstant(~SignBit, DL, MVT::i32));
|
||||
return DCI.CombineTo(N, Lo, NewHi);
|
||||
}
|
||||
case RISCVISD::SLLW:
|
||||
case RISCVISD::SRAW:
|
||||
|
|
|
@ -127,21 +127,25 @@ define double @fsgnj_d(double %a, double %b) nounwind {
|
|||
ret double %1
|
||||
}
|
||||
|
||||
define double @fneg_d(double %a) nounwind {
|
||||
; This function performs extra work to ensure that
|
||||
; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
|
||||
define i32 @fneg_d(double %a, double %b) nounwind {
|
||||
; RV32IFD-LABEL: fneg_d:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: fneg.d ft0, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft0, ft0
|
||||
; RV32IFD-NEXT: fneg.d ft1, ft0
|
||||
; RV32IFD-NEXT: feq.d a0, ft0, ft1
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = fsub double -0.0, %a
|
||||
ret double %1
|
||||
%1 = fadd double %a, %a
|
||||
%2 = fneg double %1
|
||||
%3 = fcmp oeq double %1, %2
|
||||
%4 = zext i1 %3 to i32
|
||||
ret i32 %4
|
||||
}
|
||||
|
||||
define double @fsgnjn_d(double %a, double %b) nounwind {
|
||||
|
@ -167,21 +171,30 @@ define double @fsgnjn_d(double %a, double %b) nounwind {
|
|||
|
||||
declare double @llvm.fabs.f64(double)
|
||||
|
||||
define double @fabs_d(double %a) nounwind {
|
||||
; This function performs extra work to ensure that
|
||||
; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
|
||||
define double @fabs_d(double %a, double %b) nounwind {
|
||||
; RV32IFD-LABEL: fabs_d:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a2, 8(sp)
|
||||
; RV32IFD-NEXT: sw a3, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: fabs.d ft0, ft0
|
||||
; RV32IFD-NEXT: fld ft1, 8(sp)
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fabs.d ft1, ft0
|
||||
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = call double @llvm.fabs.f64(double %a)
|
||||
ret double %1
|
||||
%1 = fadd double %a, %b
|
||||
%2 = call double @llvm.fabs.f64(double %1)
|
||||
%3 = fadd double %2, %1
|
||||
ret double %3
|
||||
}
|
||||
|
||||
declare double @llvm.minnum.f64(double, double)
|
||||
|
|
|
@ -24,15 +24,8 @@ define double @fneg(double %a) nounwind {
|
|||
;
|
||||
; RV32IFD-LABEL: fneg:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: fneg.d ft0, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: lui a2, 524288
|
||||
; RV32IFD-NEXT: xor a1, a1, a2
|
||||
; RV32IFD-NEXT: ret
|
||||
;
|
||||
; RV64I-LABEL: fneg:
|
||||
|
@ -57,15 +50,9 @@ define double @fabs(double %a) nounwind {
|
|||
;
|
||||
; RV32IFD-LABEL: fabs:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: fabs.d ft0, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: lui a2, 524288
|
||||
; RV32IFD-NEXT: addi a2, a2, -1
|
||||
; RV32IFD-NEXT: and a1, a1, a2
|
||||
; RV32IFD-NEXT: ret
|
||||
;
|
||||
; RV64I-LABEL: fabs:
|
||||
|
|
|
@ -254,15 +254,9 @@ declare double @llvm.fabs.f64(double)
|
|||
define double @fabs_f64(double %a) nounwind {
|
||||
; RV32IFD-LABEL: fabs_f64:
|
||||
; RV32IFD: # %bb.0:
|
||||
; RV32IFD-NEXT: addi sp, sp, -16
|
||||
; RV32IFD-NEXT: sw a0, 8(sp)
|
||||
; RV32IFD-NEXT: sw a1, 12(sp)
|
||||
; RV32IFD-NEXT: fld ft0, 8(sp)
|
||||
; RV32IFD-NEXT: fabs.d ft0, ft0
|
||||
; RV32IFD-NEXT: fsd ft0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a0, 8(sp)
|
||||
; RV32IFD-NEXT: lw a1, 12(sp)
|
||||
; RV32IFD-NEXT: addi sp, sp, 16
|
||||
; RV32IFD-NEXT: lui a2, 524288
|
||||
; RV32IFD-NEXT: addi a2, a2, -1
|
||||
; RV32IFD-NEXT: and a1, a1, a2
|
||||
; RV32IFD-NEXT: ret
|
||||
%1 = call double @llvm.fabs.f64(double %a)
|
||||
ret double %1
|
||||
|
|
Loading…
Reference in New Issue