<div dir="ltr"><div>In RISC-V we have these nodes and type constraint.</div><div><br></div><div><font face="monospace">def SDT_RISCVGREVGORC  : SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>,<br>                                              SDTCisSameAs<0, 1>,<br>                                              SDTCisSameAs<1, 2>]>;<br>def riscv_grevi    : SDNode<"RISCVISD::GREVI", SDT_RISCVGREVGORC, []>;<br>def riscv_greviw   : SDNode<"RISCVISD::GREVIW", SDT_RISCVGREVGORC, []>;<br>def riscv_gorci    : SDNode<"RISCVISD::GORCI", SDT_RISCVGREVGORC, []>;<br>def riscv_gorciw   : SDNode<"RISCVISD::GORCIW", SDT_RISCVGREVGORC, []>;</font><br></div><div><br></div><div>Where XLenVT is dependent on HW mode. My expectation is that a pattern using one of these nodes would need no type checks in the isel table since the type is fixed for a particular HW mode. Even without the fixed type, I would expect the two SDTCisSameAs to get it down to 1 type check. But this is what I see in the DAG isel table.</div><div><br></div><div>/* 31138*/ /*SwitchOpcode*/ 49, TARGET_VAL(RISCVISD::GREVI),// ->31190<br>/* 31141*/  OPC_RecordChild0, // #0 = $rs1<br>/* 31142*/  OPC_Scope, 22, /*->31166*/ // 2 children in Scope<br>/* 31144*/   OPC_CheckChild0Type, MVT::i64,<br>/* 31146*/   OPC_RecordChild1, // #1 = $shamt<br>/* 31147*/   OPC_MoveChild1,<br>/* 31148*/   OPC_CheckOpcode, TARGET_VAL(ISD::TargetConstant),<br>/* 31151*/   OPC_CheckType, MVT::i64,<br>/* 31153*/   OPC_MoveParent,<br>/* 31154*/   OPC_CheckType, MVT::i64,<br>/* 31156*/   OPC_CheckPatternPredicate, 49, // (Subtarget->hasStdExtZbp()) && (MF->getSubtarget().checkFeatures("+64bit"))<br>/* 31158*/   OPC_MorphNodeTo1, TARGET_VAL(RISCV::GREVI), 0,<br>                 MVT::i64, 2/*#Ops*/, 0, 1, <br>             // Src: (riscv_grevi:{ *:[i64] } GPR:{ *:[i64] }:$rs1, (timm:{ *:[i64] }):$shamt) - Complexity = 6<br>             // Dst: (GREVI:{ *:[i64] } GPR:{ *:[i64] }:$rs1, (timm:{ *:[i64] }):$shamt)<br>/* 31166*/  /*Scope*/ 22, /*->31189*/<br>/* 31167*/   OPC_CheckChild0Type, MVT::i32,<br>/* 31169*/   OPC_RecordChild1, // #1 = $shamt<br>/* 31170*/   OPC_MoveChild1,<br>/* 31171*/   OPC_CheckOpcode, TARGET_VAL(ISD::TargetConstant),<br>/* 31174*/   OPC_CheckType, MVT::i32,<br>/* 31176*/   OPC_MoveParent,<br>/* 31177*/   OPC_CheckType, MVT::i32,<br>/* 31179*/   OPC_CheckPatternPredicate, 50, // (Subtarget->hasStdExtZbp())<br>/* 31181*/   OPC_MorphNodeTo1, TARGET_VAL(RISCV::GREVI), 0,<br>                 MVT::i32, 2/*#Ops*/, 0, 1, <br>             // Src: (riscv_grevi:{ *:[i32] } GPR:{ *:[i32] }:$rs1, (timm:{ *:[i32] }):$shamt) - Complexity = 6<br>             // Dst: (GREVI:{ *:[i32] } GPR:{ *:[i32] }:$rs1, (timm:{ *:[i32] }):$shamt)<br></div><div><br></div><div>There are 3 type checks for i64 in one HW mode and 3 checks for i32 in the other HW mode. One for each operand and one for the result.</div><div><br></div><div>I'm probably going to change this to use SDTIntBinOp and get rid of the custom type constraints. That works correctly and generates one type check. It's probably not worth being more specific than that for this case even if it was working correctly. I wanted to bring up the issue since it might be affecting other patterns.</div><div><br></div><div>Possibly related, while I was briefly trying to investigate this I noticed that ForceMode in the tablegen backend's TypeInfer class is only ever assigned and never read from. And the DefaultPred std::vector in CodeGenDAGPatterns::ExpandHwModeBasedTypes() is also never read from.</div><div><br></div><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">~Craig</div></div></div>