Skip to content

Commit 1548150

Browse files
asbDisasm
authored andcommitted
[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
1 parent 7509897 commit 1548150

File tree

4 files changed

+61
-42
lines changed

4 files changed

+61
-42
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -585,16 +585,41 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
585585

586586
SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
587587
DAGCombinerInfo &DCI) const {
588+
SelectionDAG &DAG = DCI.DAG;
589+
588590
switch (N->getOpcode()) {
589591
default:
590592
break;
591593
case RISCVISD::SplitF64: {
594+
SDValue Op0 = N->getOperand(0);
592595
// If the input to SplitF64 is just BuildPairF64 then the operation is
593596
// redundant. Instead, use BuildPairF64's operands directly.
594-
SDValue Op0 = N->getOperand(0);
595-
if (Op0->getOpcode() != RISCVISD::BuildPairF64)
597+
if (Op0->getOpcode() == RISCVISD::BuildPairF64)
598+
return DCI.CombineTo(N, Op0.getOperand(0), Op0.getOperand(1));
599+
600+
SDLoc DL(N);
601+
// This is a target-specific version of a DAGCombine performed in
602+
// DAGCombiner::visitBITCAST. It performs the equivalent of:
603+
// fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit)
604+
// fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit))
605+
if (!(Op0.getOpcode() == ISD::FNEG || Op0.getOpcode() == ISD::FABS) ||
606+
!Op0.getNode()->hasOneUse())
596607
break;
597-
return DCI.CombineTo(N, Op0.getOperand(0), Op0.getOperand(1));
608+
SDValue NewSplitF64 =
609+
DAG.getNode(RISCVISD::SplitF64, DL, DAG.getVTList(MVT::i32, MVT::i32),
610+
Op0.getOperand(0));
611+
SDValue Lo = NewSplitF64.getValue(0);
612+
SDValue Hi = NewSplitF64.getValue(1);
613+
APInt SignBit = APInt::getSignMask(32);
614+
if (Op0.getOpcode() == ISD::FNEG) {
615+
SDValue NewHi = DAG.getNode(ISD::XOR, DL, MVT::i32, Hi,
616+
DAG.getConstant(SignBit, DL, MVT::i32));
617+
return DCI.CombineTo(N, Lo, NewHi);
618+
}
619+
assert(Op0.getOpcode() == ISD::FABS);
620+
SDValue NewHi = DAG.getNode(ISD::AND, DL, MVT::i32, Hi,
621+
DAG.getConstant(~SignBit, DL, MVT::i32));
622+
return DCI.CombineTo(N, Lo, NewHi);
598623
}
599624
case RISCVISD::SLLW:
600625
case RISCVISD::SRAW:

llvm/test/CodeGen/RISCV/double-arith.ll

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,25 @@ define double @fsgnj_d(double %a, double %b) nounwind {
127127
ret double %1
128128
}
129129

130-
define double @fneg_d(double %a) nounwind {
130+
; This function performs extra work to ensure that
131+
; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
132+
define i32 @fneg_d(double %a, double %b) nounwind {
131133
; RV32IFD-LABEL: fneg_d:
132134
; RV32IFD: # %bb.0:
133135
; RV32IFD-NEXT: addi sp, sp, -16
134136
; RV32IFD-NEXT: sw a0, 8(sp)
135137
; RV32IFD-NEXT: sw a1, 12(sp)
136138
; RV32IFD-NEXT: fld ft0, 8(sp)
137-
; RV32IFD-NEXT: fneg.d ft0, ft0
138-
; RV32IFD-NEXT: fsd ft0, 8(sp)
139-
; RV32IFD-NEXT: lw a0, 8(sp)
140-
; RV32IFD-NEXT: lw a1, 12(sp)
139+
; RV32IFD-NEXT: fadd.d ft0, ft0, ft0
140+
; RV32IFD-NEXT: fneg.d ft1, ft0
141+
; RV32IFD-NEXT: feq.d a0, ft0, ft1
141142
; RV32IFD-NEXT: addi sp, sp, 16
142143
; RV32IFD-NEXT: ret
143-
%1 = fsub double -0.0, %a
144-
ret double %1
144+
%1 = fadd double %a, %a
145+
%2 = fneg double %1
146+
%3 = fcmp oeq double %1, %2
147+
%4 = zext i1 %3 to i32
148+
ret i32 %4
145149
}
146150

147151
define double @fsgnjn_d(double %a, double %b) nounwind {
@@ -167,21 +171,30 @@ define double @fsgnjn_d(double %a, double %b) nounwind {
167171

168172
declare double @llvm.fabs.f64(double)
169173

170-
define double @fabs_d(double %a) nounwind {
174+
; This function performs extra work to ensure that
175+
; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
176+
define double @fabs_d(double %a, double %b) nounwind {
171177
; RV32IFD-LABEL: fabs_d:
172178
; RV32IFD: # %bb.0:
173179
; RV32IFD-NEXT: addi sp, sp, -16
180+
; RV32IFD-NEXT: sw a2, 8(sp)
181+
; RV32IFD-NEXT: sw a3, 12(sp)
182+
; RV32IFD-NEXT: fld ft0, 8(sp)
174183
; RV32IFD-NEXT: sw a0, 8(sp)
175184
; RV32IFD-NEXT: sw a1, 12(sp)
176-
; RV32IFD-NEXT: fld ft0, 8(sp)
177-
; RV32IFD-NEXT: fabs.d ft0, ft0
185+
; RV32IFD-NEXT: fld ft1, 8(sp)
186+
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
187+
; RV32IFD-NEXT: fabs.d ft1, ft0
188+
; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
178189
; RV32IFD-NEXT: fsd ft0, 8(sp)
179190
; RV32IFD-NEXT: lw a0, 8(sp)
180191
; RV32IFD-NEXT: lw a1, 12(sp)
181192
; RV32IFD-NEXT: addi sp, sp, 16
182193
; RV32IFD-NEXT: ret
183-
%1 = call double @llvm.fabs.f64(double %a)
184-
ret double %1
194+
%1 = fadd double %a, %b
195+
%2 = call double @llvm.fabs.f64(double %1)
196+
%3 = fadd double %2, %1
197+
ret double %3
185198
}
186199

187200
declare double @llvm.minnum.f64(double, double)

llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,8 @@ define double @fneg(double %a) nounwind {
2424
;
2525
; RV32IFD-LABEL: fneg:
2626
; RV32IFD: # %bb.0:
27-
; RV32IFD-NEXT: addi sp, sp, -16
28-
; RV32IFD-NEXT: sw a0, 8(sp)
29-
; RV32IFD-NEXT: sw a1, 12(sp)
30-
; RV32IFD-NEXT: fld ft0, 8(sp)
31-
; RV32IFD-NEXT: fneg.d ft0, ft0
32-
; RV32IFD-NEXT: fsd ft0, 8(sp)
33-
; RV32IFD-NEXT: lw a0, 8(sp)
34-
; RV32IFD-NEXT: lw a1, 12(sp)
35-
; RV32IFD-NEXT: addi sp, sp, 16
27+
; RV32IFD-NEXT: lui a2, 524288
28+
; RV32IFD-NEXT: xor a1, a1, a2
3629
; RV32IFD-NEXT: ret
3730
;
3831
; RV64I-LABEL: fneg:
@@ -57,15 +50,9 @@ define double @fabs(double %a) nounwind {
5750
;
5851
; RV32IFD-LABEL: fabs:
5952
; RV32IFD: # %bb.0:
60-
; RV32IFD-NEXT: addi sp, sp, -16
61-
; RV32IFD-NEXT: sw a0, 8(sp)
62-
; RV32IFD-NEXT: sw a1, 12(sp)
63-
; RV32IFD-NEXT: fld ft0, 8(sp)
64-
; RV32IFD-NEXT: fabs.d ft0, ft0
65-
; RV32IFD-NEXT: fsd ft0, 8(sp)
66-
; RV32IFD-NEXT: lw a0, 8(sp)
67-
; RV32IFD-NEXT: lw a1, 12(sp)
68-
; RV32IFD-NEXT: addi sp, sp, 16
53+
; RV32IFD-NEXT: lui a2, 524288
54+
; RV32IFD-NEXT: addi a2, a2, -1
55+
; RV32IFD-NEXT: and a1, a1, a2
6956
; RV32IFD-NEXT: ret
7057
;
7158
; RV64I-LABEL: fabs:

llvm/test/CodeGen/RISCV/double-intrinsics.ll

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,9 @@ declare double @llvm.fabs.f64(double)
254254
define double @fabs_f64(double %a) nounwind {
255255
; RV32IFD-LABEL: fabs_f64:
256256
; RV32IFD: # %bb.0:
257-
; RV32IFD-NEXT: addi sp, sp, -16
258-
; RV32IFD-NEXT: sw a0, 8(sp)
259-
; RV32IFD-NEXT: sw a1, 12(sp)
260-
; RV32IFD-NEXT: fld ft0, 8(sp)
261-
; RV32IFD-NEXT: fabs.d ft0, ft0
262-
; RV32IFD-NEXT: fsd ft0, 8(sp)
263-
; RV32IFD-NEXT: lw a0, 8(sp)
264-
; RV32IFD-NEXT: lw a1, 12(sp)
265-
; RV32IFD-NEXT: addi sp, sp, 16
257+
; RV32IFD-NEXT: lui a2, 524288
258+
; RV32IFD-NEXT: addi a2, a2, -1
259+
; RV32IFD-NEXT: and a1, a1, a2
266260
; RV32IFD-NEXT: ret
267261
%1 = call double @llvm.fabs.f64(double %a)
268262
ret double %1

0 commit comments

Comments
 (0)