3

In an LLVM backend, during instruction selection, my input looks something like this:

t17: i16,ch = load t16:1, t2, undef:i16

I'd like to select an opcode that has some extra result as well, i.e. replace the above with something like

t17: i16, _: i16, ch = LDW t2, undef:i16

Of course, if I just try to replace the load with this LDW, it fails because the return types are not the same:

llc: lib/CodeGen/SelectionDAG/SelectionDAG.cpp:6525: 
void llvm::SelectionDAG::ReplaceAllUsesWith(llvm::SDNode*, llvm::SDNode*): 
Assertion `(!From->hasAnyUseOfValue(i) || From->getValueType(i) == To->getValueType(i)) && 
"Cannot use this version of ReplaceAllUsesWith!"' failed.

That's because for i == 1, From->getValueType(i) is ch, and To->getValueType(i) is i16.

My question is, how do I re-shuffle the tuple (x: i16, y: i16, ch) into (x : i16, ch) during instruction selection? I.e. how would I do something like

t17 : i16, ch = project [0, 2] (LDW t2, undef:i16)

where project [0, 2] would be some magic tuple-reshuffling pseudo-instruction that just takes care of dropping coordinate 1?

EDIT: Found what seemed like a possible solution, but still doesn't work

I found that there's a MERGE_VALUES node type which should make what I'm trying to do possible, since it allows taking some inputs and packing them into a multi-value output. So I tried

SDNode* LDW = CurDAG->getMachineNode(
  AVR::LDWRdPtr, SDLoc(N), VT, PtrVT, MVT::Other,
  LD->getBasePtr(), LD->getChain());
SDValue Unpack[] = { SDValue(LDW, 0), SDValue(LDW, 2) };
SDNode* NN = CurDAG->getMergeValues(Unpack, SDLoc(N)).getNode();

ReplaceNode(N, NN);

If I run instruction selection with --debug, this looks very promising, since it turns this:

SelectionDAG has 16 nodes:
  t0: ch = EntryToken
    t2: i16,ch = CopyFromReg t0, Register:i16 %vreg0
  t5: i16,ch = load<LD2[%v25](align=1)(dereferenceable)> t0, t2, undef:i16
    t9: ch,glue = callseq_start t5:1, TargetConstant:i16<0>
  t11: ch,glue = CopyToReg t9, Register:i16 %R25R24, t5
  t13: ch,glue = CALL t11, TargetGlobalAddress:i16<i8 (i16)* @read_ram> 0, Register:i16 %R25R24, RegisterMask:Untyped, t11:1
  t14: ch,glue = callseq_end t13, TargetConstant:i16<0>, TargetConstant:i16<0>, t13:1
    t16: i8,ch,glue = CopyFromReg t14, Register:i8 %R24, t14:1
  t17: ch = RET_FLAG t16:1

into this:

SelectionDAG has 16 nodes:
  t0: ch = EntryToken
    t9: i16,ch,glue = ADJCALLSTACKDOWN TargetConstant:i16<0>, t19:1
  t11: ch,glue = CopyToReg t9:1, Register:i16 %R25R24, t19
  t13: ch,glue = CALLk TargetGlobalAddress:i16<i8 (i16)* @read_ram> 0, Register:i16 %R25R24, RegisterMask:Untyped, t11, t11:1
  t14: i16,ch,glue = ADJCALLSTACKUP TargetConstant:i16<0>, TargetConstant:i16<0>, t13, t13:1
    t2: i16,ch = CopyFromReg t0, Register:i16 %vreg0
  t18: i16,i16,ch = LDWRdPtr t2, t0
  t19: i16,ch = merge_values t18, t18:2
    t16: i8,ch,glue = CopyFromReg t14:1, Register:i8 %R24, t14:2
  t17: ch = RET t16:1

which looks fine to me: t18,_,ch is where we store the result of LDW, then t19,ch unpacks it.

However, this later trips up instruction scheduling:

llc: CodeGen/SelectionDAG/InstrEmitter.cpp:305: 
unsigned int llvm::InstrEmitter::getVR(llvm::SDValue, llvm::DenseMap<llvm::SDValue, unsigned int>&): 
Assertion `I != VRBaseMap.end() && "Node emitted out of order - late"' failed.

#9 0x0000000001a7eae8 llvm::InstrEmitter::getVR(llvm::SDValue, llvm::DenseMap<llvm::SDValue, unsigned int, llvm::DenseMapInfo<llvm::SDValue>, llvm::detail::DenseMapPair<llvm::SDValue, unsigned int> >&) CodeGen/SelectionDAG/InstrEmitter.cpp:305:0
#10 0x0000000001a819c2 llvm::InstrEmitter::EmitSpecialNode(llvm::SDNode*, bool, bool, llvm::DenseMap<llvm::SDValue, unsigned int, llvm::DenseMapInfo<llvm::SDValue>, llvm::detail::DenseMapPair<llvm::SDValue, unsigned int> >&) CodeGen/SelectionDAG/InstrEmitter.cpp:928:0
#11 0x0000000001971c9c llvm::InstrEmitter::EmitNode(llvm::SDNode*, bool, bool, llvm::DenseMap<llvm::SDValue, unsigned int, llvm::DenseMapInfo<llvm::SDValue>, llvm::detail::DenseMapPair<llvm::SDValue, unsigned int> >&) CodeGen/SelectionDAG/InstrEmitter.h:124:0
#12 0x0000000001988bdb llvm::ScheduleDAGSDNodes::EmitSchedule(llvm::MachineInstrBundleIterator<llvm::MachineInstr, false>&) CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp:841:0
#13 0x0000000001a33cdc llvm::SelectionDAGISel::CodeGenAndEmitDAG() CodeGen/SelectionDAG/SelectionDAGISel.cpp:890:0
Cactus
  • 27,075
  • 9
  • 69
  • 149
  • Actually, in the line `t19: i16,ch = merge_values t18, t18:2`, shouldn't that be `t19: i16,ch = merge_values t18, ch`? What does that `t18:2` mean? – Cactus Jun 06 '17 at 15:46

0 Answers0