OPC_EmitMergeInputChains1_0 failed while lowering callseq_start

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>;