Kevin Choi via llvm-dev
2018-Mar-09 20:04 UTC
[llvm-dev] [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, Kevin
Simon Dardis via llvm-dev
2018-Mar-09 21:47 UTC
[llvm-dev] [SelectionDAG] [TargetOp] How to get sub-half of immediate?
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 ________________________________________ From: llvm-dev [llvm-dev-bounces at lists.llvm.org] on behalf of Kevin Choi via llvm-dev [llvm-dev at lists.llvm.org] Sent: Friday, March 9, 2018 8:04 PM To: llvm-dev Subject: [llvm-dev] [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, Kevin _______________________________________________ LLVM Developers mailing list llvm-dev at lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Kevin Choi via llvm-dev
2018-Mar-09 22:13 UTC
[llvm-dev] [SelectionDAG] [TargetOp] How to get sub-half of immediate?
SDNodeXForm worked like a charm. Thank you very much, Kevin On 3/9/2018 4:47 PM, Simon Dardis wrote:> 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 > ________________________________________ > From: llvm-dev [llvm-dev-bounces at lists.llvm.org] on behalf of Kevin Choi via llvm-dev [llvm-dev at lists.llvm.org] > Sent: Friday, March 9, 2018 8:04 PM > To: llvm-dev > Subject: [llvm-dev] [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, > > Kevin > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev