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
register:
(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.
Thanks,
Simon