llvm.org GIT mirror llvm / df9220f
[RISCV][NFCI] Handle redundant splitf64+buildpairf64 pairs during instruction selection Although we can't write a tablegen pattern to remove redundant splitf64+buildf64 pairs due to the multiple return values, we can handle it with some C++ selection code. This is simpler than removing them after instruction selection through RISCVDAGToDAGISel::PostprocessISelDAG, as was done previously. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@343712 91177308-0d34-0410-b5e6-96231b3b80d8 Alex Bradbury 1 year, 9 months ago
1 changed file(s) with 12 addition(s) and 39 deletion(s). Raw diff Collapse all Expand all
5555
5656 private:
5757 void doPeepholeLoadStoreADDI();
58 void doPeepholeBuildPairF64SplitF64();
5958 };
6059 }
6160
6261 void RISCVDAGToDAGISel::PostprocessISelDAG() {
6362 doPeepholeLoadStoreADDI();
64 doPeepholeBuildPairF64SplitF64();
6563 }
6664
6765 void RISCVDAGToDAGISel::Select(SDNode *Node) {
9593 int FI = cast(Node)->getIndex();
9694 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
9795 ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm));
96 return;
97 }
98 case RISCVISD::SplitF64: {
99 // If the input to SplitF64 is just BuildPairF64 then the operation is
100 // redundant. Instead, use BuildPairF64's operands directly. This pattern
101 // can't be written in tablegen due to the multiple outputs.
102 SDValue Op0 = Node->getOperand(0);
103 if (Op0->getOpcode() != RISCVISD::BuildPairF64)
104 break;
105 ReplaceUses(SDValue(Node, 0), Op0.getOperand(0));
106 ReplaceUses(SDValue(Node, 1), Op0.getOperand(1));
107 CurDAG->RemoveDeadNode(Node);
98108 return;
99109 }
100110 }
215225 }
216226 }
217227
218 // Remove redundant BuildPairF64+SplitF64 pairs. i.e. cases where an f64 is
219 // built of two i32 values, only to be split apart again. This must be done
220 // here as a peephole optimisation as the DAG has not been fully legalized at
221 // the point BuildPairF64/SplitF64 nodes are created in RISCVISelLowering, so
222 // some nodes would not yet have been replaced with libcalls.
223 void RISCVDAGToDAGISel::doPeepholeBuildPairF64SplitF64() {
224 SelectionDAG::allnodes_iterator Position(CurDAG->getRoot().getNode());
225 ++Position;
226
227 while (Position != CurDAG->allnodes_begin()) {
228 SDNode *N = &*--Position;
229 // Skip dead nodes and any nodes other than SplitF64Pseudo.
230 if (N->use_empty() || !N->isMachineOpcode() ||
231 !(N->getMachineOpcode() == RISCV::SplitF64Pseudo))
232 continue;
233
234 // If the operand to SplitF64 is a BuildPairF64, the split operation is
235 // redundant. Just use the operands to BuildPairF64 as the result.
236 SDValue F64Val = N->getOperand(0);
237 if (F64Val.isMachineOpcode() &&
238 F64Val.getMachineOpcode() == RISCV::BuildPairF64Pseudo) {
239 LLVM_DEBUG(
240 dbgs() << "Removing redundant SplitF64Pseudo and replacing uses "
241 "with BuildPairF64Pseudo operands:\n");
242 LLVM_DEBUG(dbgs() << "N: ");
243 LLVM_DEBUG(N->dump(CurDAG));
244 LLVM_DEBUG(dbgs() << "F64Val: ");
245 LLVM_DEBUG(F64Val->dump(CurDAG));
246 LLVM_DEBUG(dbgs() << "\n");
247 SDValue From[] = {SDValue(N, 0), SDValue(N, 1)};
248 SDValue To[] = {F64Val.getOperand(0), F64Val.getOperand(1)};
249 CurDAG->ReplaceAllUsesOfValuesWith(From, To, 2);
250 }
251 }
252 CurDAG->RemoveDeadNodes();
253 }
254
255228 // This pass converts a legalized DAG into a RISCV-specific DAG, ready
256229 // for instruction scheduling.
257230 FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) {