在 LLVM 后端,在指令选择期间,我的输入如下所示:
t17: i16,ch = load t16:1, t2, undef:i16
我想选择一个也有一些额外结果的操作码,即用类似的东西替换上面的操作码
t17: i16, _: i16, ch = LDW t2, undef:i16
当然,如果我只是尝试load
用 this替换LDW
,它会失败,因为返回类型不一样:
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.
那是因为 for i == 1
, From->getValueType(i)
isch
和To->getValueType(i)
is i16
。
我的问题是,如何在指令选择期间将元组重新(x: i16, y: i16, ch)
洗牌(x : i16, ch)
?即我将如何做类似的事情
t17 : i16, ch = project [0, 2] (LDW t2, undef:i16)
哪里project [0, 2]
会有一些神奇的元组改组伪指令,它只负责删除坐标 1?
编辑:找到似乎可能的解决方案,但仍然不起作用
我发现有一个MERGE_VALUES
节点类型应该使我正在尝试做的事情成为可能,因为它允许获取一些输入并将它们打包成一个多值输出。所以我尝试了
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);
如果我用 运行指令选择--debug
,这看起来很有希望,因为它变成了这样:
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
进入这个:
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
这对我来说看起来不错:t18,_,ch
是我们存储结果的地方LDW
,然后将其t19,ch
解包。
但是,这稍后会破坏指令调度:
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