llvm.org GIT mirror llvm / f21e608
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@352247 91177308-0d34-0410-b5e6-96231b3b80d8 Alex Bradbury 1 year, 4 months ago
4 changed file(s) with 70 addition(s) and 51 deletion(s). Raw diff Collapse all Expand all
583583
584584 SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
585585 DAGCombinerInfo &DCI) const {
586 SelectionDAG &DAG = DCI.DAG;
587
586588 switch (N->getOpcode()) {
587589 default:
588590 break;
589591 case RISCVISD::SplitF64: {
592 SDValue Op0 = N->getOperand(0);
590593 // If the input to SplitF64 is just BuildPairF64 then the operation is
591594 // redundant. Instead, use BuildPairF64's operands directly.
592 SDValue Op0 = N->getOperand(0);
593 if (Op0->getOpcode() != RISCVISD::BuildPairF64)
595 if (Op0->getOpcode() == RISCVISD::BuildPairF64)
596 return DCI.CombineTo(N, Op0.getOperand(0), Op0.getOperand(1));
597
598 SDLoc DL(N);
599 // This is a target-specific version of a DAGCombine performed in
600 // DAGCombiner::visitBITCAST. It performs the equivalent of:
601 // fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit)
602 // fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit))
603 if (!(Op0.getOpcode() == ISD::FNEG || Op0.getOpcode() == ISD::FABS) ||
604 !Op0.getNode()->hasOneUse())
594605 break;
595 return DCI.CombineTo(N, Op0.getOperand(0), Op0.getOperand(1));
606 SDValue NewSplitF64 =
607 DAG.getNode(RISCVISD::SplitF64, DL, DAG.getVTList(MVT::i32, MVT::i32),
608 Op0.getOperand(0));
609 SDValue Lo = NewSplitF64.getValue(0);
610 SDValue Hi = NewSplitF64.getValue(1);
611 APInt SignBit = APInt::getSignMask(32);
612 if (Op0.getOpcode() == ISD::FNEG) {
613 SDValue NewHi = DAG.getNode(ISD::XOR, DL, MVT::i32, Hi,
614 DAG.getConstant(SignBit, DL, MVT::i32));
615 return DCI.CombineTo(N, Lo, NewHi);
616 }
617 assert(Op0.getOpcode() == ISD::FABS);
618 SDValue NewHi = DAG.getNode(ISD::AND, DL, MVT::i32, Hi,
619 DAG.getConstant(~SignBit, DL, MVT::i32));
620 return DCI.CombineTo(N, Lo, NewHi);
596621 }
597622 case RISCVISD::SLLW:
598623 case RISCVISD::SRAW:
126126 ret double %1
127127 }
128128
129 define double @fneg_d(double %a) nounwind {
129 ; This function performs extra work to ensure that
130 ; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor.
131 define i32 @fneg_d(double %a, double %b) nounwind {
130132 ; RV32IFD-LABEL: fneg_d:
131133 ; RV32IFD: # %bb.0:
132134 ; RV32IFD-NEXT: addi sp, sp, -16
133135 ; RV32IFD-NEXT: sw a0, 8(sp)
134136 ; RV32IFD-NEXT: sw a1, 12(sp)
135137 ; RV32IFD-NEXT: fld ft0, 8(sp)
136 ; RV32IFD-NEXT: fneg.d ft0, ft0
137 ; RV32IFD-NEXT: fsd ft0, 8(sp)
138 ; RV32IFD-NEXT: lw a0, 8(sp)
139 ; RV32IFD-NEXT: lw a1, 12(sp)
140 ; RV32IFD-NEXT: addi sp, sp, 16
141 ; RV32IFD-NEXT: ret
142 %1 = fsub double -0.0, %a
143 ret double %1
138 ; RV32IFD-NEXT: fadd.d ft0, ft0, ft0
139 ; RV32IFD-NEXT: fneg.d ft1, ft0
140 ; RV32IFD-NEXT: feq.d a0, ft0, ft1
141 ; RV32IFD-NEXT: addi sp, sp, 16
142 ; RV32IFD-NEXT: ret
143 %1 = fadd double %a, %a
144 %2 = fneg double %1
145 %3 = fcmp oeq double %1, %2
146 %4 = zext i1 %3 to i32
147 ret i32 %4
144148 }
145149
146150 define double @fsgnjn_d(double %a, double %b) nounwind {
166170
167171 declare double @llvm.fabs.f64(double)
168172
169 define double @fabs_d(double %a) nounwind {
173 ; This function performs extra work to ensure that
174 ; DAGCombiner::visitBITCAST doesn't replace the fabs with an and.
175 define double @fabs_d(double %a, double %b) nounwind {
170176 ; RV32IFD-LABEL: fabs_d:
171177 ; RV32IFD: # %bb.0:
172178 ; RV32IFD-NEXT: addi sp, sp, -16
173 ; RV32IFD-NEXT: sw a0, 8(sp)
174 ; RV32IFD-NEXT: sw a1, 12(sp)
175 ; RV32IFD-NEXT: fld ft0, 8(sp)
176 ; RV32IFD-NEXT: fabs.d ft0, ft0
177 ; RV32IFD-NEXT: fsd ft0, 8(sp)
178 ; RV32IFD-NEXT: lw a0, 8(sp)
179 ; RV32IFD-NEXT: lw a1, 12(sp)
180 ; RV32IFD-NEXT: addi sp, sp, 16
181 ; RV32IFD-NEXT: ret
182 %1 = call double @llvm.fabs.f64(double %a)
183 ret double %1
179 ; RV32IFD-NEXT: sw a2, 8(sp)
180 ; RV32IFD-NEXT: sw a3, 12(sp)
181 ; RV32IFD-NEXT: fld ft0, 8(sp)
182 ; RV32IFD-NEXT: sw a0, 8(sp)
183 ; RV32IFD-NEXT: sw a1, 12(sp)
184 ; RV32IFD-NEXT: fld ft1, 8(sp)
185 ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
186 ; RV32IFD-NEXT: fabs.d ft1, ft0
187 ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
188 ; RV32IFD-NEXT: fsd ft0, 8(sp)
189 ; RV32IFD-NEXT: lw a0, 8(sp)
190 ; RV32IFD-NEXT: lw a1, 12(sp)
191 ; RV32IFD-NEXT: addi sp, sp, 16
192 ; RV32IFD-NEXT: ret
193 %1 = fadd double %a, %b
194 %2 = call double @llvm.fabs.f64(double %1)
195 %3 = fadd double %2, %1
196 ret double %3
184197 }
185198
186199 declare double @llvm.minnum.f64(double, double)
2323 ;
2424 ; RV32IFD-LABEL: fneg:
2525 ; RV32IFD: # %bb.0:
26 ; RV32IFD-NEXT: addi sp, sp, -16
27 ; RV32IFD-NEXT: sw a0, 8(sp)
28 ; RV32IFD-NEXT: sw a1, 12(sp)
29 ; RV32IFD-NEXT: fld ft0, 8(sp)
30 ; RV32IFD-NEXT: fneg.d ft0, ft0
31 ; RV32IFD-NEXT: fsd ft0, 8(sp)
32 ; RV32IFD-NEXT: lw a0, 8(sp)
33 ; RV32IFD-NEXT: lw a1, 12(sp)
34 ; RV32IFD-NEXT: addi sp, sp, 16
26 ; RV32IFD-NEXT: lui a2, 524288
27 ; RV32IFD-NEXT: xor a1, a1, a2
3528 ; RV32IFD-NEXT: ret
3629 ;
3730 ; RV64I-LABEL: fneg:
5649 ;
5750 ; RV32IFD-LABEL: fabs:
5851 ; RV32IFD: # %bb.0:
59 ; RV32IFD-NEXT: addi sp, sp, -16
60 ; RV32IFD-NEXT: sw a0, 8(sp)
61 ; RV32IFD-NEXT: sw a1, 12(sp)
62 ; RV32IFD-NEXT: fld ft0, 8(sp)
63 ; RV32IFD-NEXT: fabs.d ft0, ft0
64 ; RV32IFD-NEXT: fsd ft0, 8(sp)
65 ; RV32IFD-NEXT: lw a0, 8(sp)
66 ; RV32IFD-NEXT: lw a1, 12(sp)
67 ; RV32IFD-NEXT: addi sp, sp, 16
52 ; RV32IFD-NEXT: lui a2, 524288
53 ; RV32IFD-NEXT: addi a2, a2, -1
54 ; RV32IFD-NEXT: and a1, a1, a2
6855 ; RV32IFD-NEXT: ret
6956 ;
7057 ; RV64I-LABEL: fabs:
253253 define double @fabs_f64(double %a) nounwind {
254254 ; RV32IFD-LABEL: fabs_f64:
255255 ; RV32IFD: # %bb.0:
256 ; RV32IFD-NEXT: addi sp, sp, -16
257 ; RV32IFD-NEXT: sw a0, 8(sp)
258 ; RV32IFD-NEXT: sw a1, 12(sp)
259 ; RV32IFD-NEXT: fld ft0, 8(sp)
260 ; RV32IFD-NEXT: fabs.d ft0, ft0
261 ; RV32IFD-NEXT: fsd ft0, 8(sp)
262 ; RV32IFD-NEXT: lw a0, 8(sp)
263 ; RV32IFD-NEXT: lw a1, 12(sp)
264 ; RV32IFD-NEXT: addi sp, sp, 16
256 ; RV32IFD-NEXT: lui a2, 524288
257 ; RV32IFD-NEXT: addi a2, a2, -1
258 ; RV32IFD-NEXT: and a1, a1, a2
265259 ; RV32IFD-NEXT: ret
266260 %1 = call double @llvm.fabs.f64(double %a)
267261 ret double %1