I’m lowering the ‘callseq_start’ and ‘callseq_end’ using nodes/patterns and the SelectCodeCommon().
‘callseq_end’ is well morphed into an architecture specific ADJCALLSTACKUP PseudoInstruction.
ISEL: Starting pattern match on root node: t9: ch,glue = callseq_end t8, TargetConstant:i16<0>, TargetConstant:i16<0>, t8:1
Morphed node: t9: ch,glue = ADJCALLSTACKUP TargetConstant:i16<0>, TargetConstant:i16<0>, t8, t8:1
‘callseq_start’ failed to be morphed into ADJCALLSTACKDOWN :-/
LLVM ERROR: Cannot select: t6: ch,glue = callseq_start t0, TargetConstant:i16<0>
t5: i16 = TargetConstant<0>
Here is the debug trace of the matching. It should match at 280, but failed at 279 on OPC_EmitMergeInputChains1_0.
ISEL: Starting pattern match on root node: t6: ch,glue = callseq_start t0, TargetConstant:i16<0>
Skipped scope entry (due to false predicate) at index 2, continuing at 30
Skipped scope entry (due to false predicate) at index 31, continuing at 104
Skipped scope entry (due to false predicate) at index 105, continuing at 183
Skipped scope entry (due to false predicate) at index 184, continuing at 225
Skipped scope entry (due to false predicate) at index 226, continuing at 267
Match failed at index 279
Continuing at 287
Match failed at index 288
Continuing at 311
/267/ /Scope/ 19, /->287/
/268/ OPC_CheckOpcode, TARGET_VAL(ISD::CALLSEQ_START),
/271/ OPC_RecordNode, // #0 = ‘callseq_start’ chained node
/272/ OPC_RecordChild1, // #1 = $amt
/273/ OPC_MoveChild, 1,
/275/ OPC_CheckOpcode, TARGET_VAL(ISD::TargetConstant),
/278/ OPC_MoveParent,
/279/ OPC_EmitMergeInputChains1_0,
/280/ OPC_MorphNodeTo, TARGET_VAL(CLP::ADJCALLSTACKDOWN), 0|OPFL_Chain|OPFL_GlueOutput,
0/#VTs/, 1/#Ops/, 1,
// Src: (callseq_start (timm:i16):$amt) - Complexity = 6
// Dst: (ADJCALLSTACKDOWN (timm:i16):$amt)
/287/ /Scope/ 23, /->311/
Using GDB, I’ve traced the reason of the failure:
SelectCodeCommon() failed because Case OPC_EmitMergeInputChains1_0 ‘Failed to merge’ because HandleMergeInputChains() returns CR_InducesCycle because WalkChainUsers() returns CR_InducesCycle;
// Because we structurally match the load/store as a read/modify/write,
// but the call is chained between them. We cannot fold in this case
// because it would induce a cycle in the graph.
What’s the meaning of such status? How to fix the following pattern or the Instruction Selection Graph?
Here are the pattern/nodes definitions:
def SDT_CLPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i16> ]>;
def callseq_start : SDNode<“ISD::CALLSEQ_START”, SDT_CLPCallSeqStart,
[SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>;
def ADJCALLSTACKDOWN : CLPPseudoInst<(ins i16imm:$amt), (outs), ,
“# ADJCALLSTACKDOWN $amt”,
[(callseq_start timm:$amt)],NoItinerary>;