[SelectionDAG] [TargetOp] How to get sub-half of immediate?

Hi all,

This seems like a dumb question but while setting up a pattern in TD file, I got stuck on trying to get each half of an immediate as the half-sized type (ie. i64 imm -> pair of i32 imm's). Is there an existing way to do it? I've tried the 'EXTRACT_SUBREG' but that seems to error at the end of scheduling. Looking at Target.td, I'm not sure which opcode is meant for my need. Copying imm to reg would be another solution but I'm also not sure which opcode forces it.

Many Thanks,


Hi Kevin,

To get some portion of a constant immediate you can use SDNodeXForms to
transform constant SDNodes into other values. For a worked example, in the
MIPS backend we use this for constant synthesis by materializing the value into a

(From lib/Target/MipsInstrInfo.td):

// Transformation Function - get the lower 16 bits.
def LO16 : SDNodeXForm<imm, [{
  return getImm(N, N->getZExtValue() & 0xFFFF);

The above fragment will take an immediate node and get the lower 16 bits.

// Transformation Function - get the higher 16 bits.
def HI16 : SDNodeXForm<imm, [{
  return getImm(N, (N->getZExtValue() >> 16) & 0xFFFF);

Similarly, get the high 16 bits.

def LUiORiPred : PatLeaf<(imm), [{
  int64_t SVal = N->getSExtValue();
  return isInt<32>(SVal) && (SVal & 0xffff);

For completeness sake I've included this, but it's return true there are bits in both
16 bit fragments.

Then we use (here VT = i32, ORiOp is our logical or which takes an immediate,
LUiOp loads the upper bits of a register with an immediate, zeroing the lower 16 bits):

// Arbitrary immediates
def : MipsPat<(VT LUiORiPred:$imm), (ORiOp (LUiOp (HI16 imm:$imm)), (LO16 imm:$imm))>;

This anonymous pattern matches any sign-extended 32 bit immediate due to
LUiORiPred, and the expression (HI16 imm:$imm) takes an immediate and
extracts the upper bits of the immediate into a constant which LUiOp accepts.
The outer (LO16 imm:$imm) expression gets the lower 16 bits which ORiOp accepts.

As the SDNodeXForm takes arbitrary C++ code, you can go a bit farther with
transforming values.

Depending on your target, the usage of SDNodeXForm example alone may be
enough for your needs, otherwise hopefully the synthesize into a register example
is sufficient.


SDNodeXForm worked like a charm.

Thank you very much,