Dr. ERDI Gergo via llvm-dev
2017-Jul-29 08:28 UTC
[llvm-dev] ISelDAGToDAG breaks node ordering
Hi, During instruction selection, I have the following code for certain LOAD instructions: const LoadSDNode *LD = cast<LoadSDNode>(N); SDNode* LDW = CurDAG->getMachineNode(AVR::LDWRdPtr, SDLoc(N), VT, PtrVT, MVT::Other, LD->getBasePtr(), LD->getChain()); // Honestly, I have no idea what this does, but other memory // accessing instructions have something similar... MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); MemOp[0] = cast<MemSDNode>(N)->getMemOperand(); cast<MachineSDNode>(LDW)->setMemRefs(MemOp, MemOp + 1); // Reshuffle LDW's results so that the first two match LOAD's result // type SDValue Unpack[] = { SDValue(LDW, 0), SDValue(LDW, 2), SDValue(LDW, 1) }; SDNode* NN = CurDAG->getMergeValues(Unpack, SDLoc(N)).getNode(); ReplaceUses(N, NN); CurDAG->RemoveDeadNode(N); With this code, I get correct-looking machine instructions, but the node order is all botched up. For example, given this input: SelectionDAG has 8 nodes: t0: ch = EntryToken t2: i16,ch = CopyFromReg t0, Register:i16 %vreg0 t5: i16,ch = load<Volatile LD2[%1](align=1)(dereferenceable)> t0, t2, undef:i16 t7: ch,glue = CopyToReg t5:1, Register:i16 %R25R24, t5 t8: ch = RET_FLAG t7, Register:i16 %R25R24, t7:1 The resulting output is SelectionDAG has 8 nodes: t0: ch = EntryToken t7: ch,glue = CopyToReg t10:1, Register:i16 %R25R24, t10 t2: i16,ch = CopyFromReg t0, Register:i16 %vreg0 t9: i16,i16,ch = LDWRdPtr<Mem:Volatile LD2[%1](align=1)(dereferenceable)> t2, t0 t10: i16,ch,i16 = merge_values t9, t9:2, t9:1 t8: ch = RET Register:i16 %R25R24, t7, t7:1 As you can see, even though the edges are correct, t7 should be after t10. This trips up LLVM further downstream: lib/CodeGen/SelectionDAG/InstrEmitter.cpp:303: unsigned int llvm::InstrEmitter::getVR(llvm::SDValue, llvm::DenseMap<llvm::SDValue, unsigned int>&): Assertion `I != VRBaseMap.end() && "Node emitted out of order - late"' failed. Any idea what might be causing this? Where does the order of nodes come from anyway? Thanks, Gergo
Friedman, Eli via llvm-dev
2017-Jul-31 19:26 UTC
[llvm-dev] ISelDAGToDAG breaks node ordering
On 7/29/2017 1:28 AM, Dr. ERDI Gergo via llvm-dev wrote:> Hi, > > During instruction selection, I have the following code for certain > LOAD instructions: > > const LoadSDNode *LD = cast<LoadSDNode>(N); > SDNode* LDW = CurDAG->getMachineNode(AVR::LDWRdPtr, SDLoc(N), > VT, PtrVT, MVT::Other, > LD->getBasePtr(), LD->getChain()); > > // Honestly, I have no idea what this does, but other memory > // accessing instructions have something similar... > MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); > MemOp[0] = cast<MemSDNode>(N)->getMemOperand(); > cast<MachineSDNode>(LDW)->setMemRefs(MemOp, MemOp + 1); > > // Reshuffle LDW's results so that the first two match LOAD's > result > // type > SDValue Unpack[] = { SDValue(LDW, 0), SDValue(LDW, 2), > SDValue(LDW, 1) }; > SDNode* NN = CurDAG->getMergeValues(Unpack, SDLoc(N)).getNode();Calling getMergeValues in ISelDAGToDAG is a bad idea; there aren't supposed to be any MERGE_VALUES nodes at that point in the pipeline. You can call ReplaceUses with SDValues rather than SDNodes. -Eli -- Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Dr. ERDI Gergo via llvm-dev
2017-Aug-01 11:03 UTC
[llvm-dev] ISelDAGToDAG breaks node ordering
On Mon, 31 Jul 2017, Friedman, Eli wrote:> Calling getMergeValues in ISelDAGToDAG is a bad idea; there aren't supposed > to be any MERGE_VALUES nodes at that point in the pipeline. > > You can call ReplaceUses with SDValues rather than SDNodes.Oh wow, yes! These are exactly the two pieces of information I was missing. This works now: SDNode* LDW = CurDAG->getMachineNode(AVR::LDWRdPtr, SDLoc(N), VT, PtrVT, MVT::Other, LD->getBasePtr(), LD->getChain()); transferMemOperands(N, LDW); ReplaceUses(SDValue(N, 0), SDValue(LDW, 0)); ReplaceUses(SDValue(N, 1), SDValue(LDW, 2)); CurDAG->RemoveDeadNode(N); Thanks a lot! Gergo