I think I understand the motivation for these node types, but I’m not positive:
/// SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded
/// integer shift operations, just like ADD/SUB_PARTS. The operation
/// ordering is:
/// [Lo,Hi] = op [LoLHS,HiLHS], Amt
SHL_PARTS, SRA_PARTS, SRL_PARTS
Okay, for one thing, I can’t find a reference to ADD_PARTS or SUB_PARTS other than in diffs from about 8 years ago, so the doc comment appears to be highly out of step with current llvm facilities. It seems to me, after looking around a bit, that these nodes are intended to allow one to extend bit shifts to higher widths than the target would normally support. For example, a 64-bit shift on a system with only 32-bit shift instructions. If that is exactly the case, then I am a bit confused as to how one is expected to implement even bit shifts on larger types that might appear in IR, such as for i96, i128, or i256.
You could indeed handle i128 by doing Custom lowering on that operation via setOperationAction with MVT::i64, but for sizes beyond that I don’t see how it could be accomplished without modifying CodeGen. Now, I’m not saying that those types of large shifts are at likely to be seen out in the wild, but I’m curious to know if it’s expected that a target handle extreme cases like that.
The add and subtraction node families have add, addc, adde, sub, subc, sube at their disposal to express these types of extended operations that facilitate working with arbitrarily large operands at the IR level. I don’t believe there are any such node types for shl, lshr, and ashr that track shifted out bit(s), as well as bit(s) to be shifted in. Would it be worth considering looking into creating some support for that? For now, the best I can tell is that one would have to implement that directly in the target specific code.
~MoN / Dave