Hi All,
I am working on a target which requires to generated two
instructions for a single branch instruction.
ex:
imm 1
br r4,0xabcd
branch address is 0x1abcd, imm has the upper 16 bits and br has
lower 16 bits.
Can anyone let me know how to write these kind of patterns in the
InstrInfo.td file.
Thanks in Advance,
Nagaraju
Do the two instructions need to be together? Is one providing an operand via an implicit register?
If the two are simply a sequence that must be emitted together, then the easiest thing to do is make it a pseudo and then expand it into two instructions later. If one is really providing part of the operand via an implicit register, then it’s best to describe that directly and let the scheduler decide where to put the first instruction.
David
I am working on a target which requires to generated two
instructions for a single branch instruction.
ex:
imm 1
br r4,0xabcd
branch address is 0x1abcd, imm has the upper 16 bits and br has
lower 16 bits.
Can anyone let me know how to write these kind of patterns in the
InstrInfo.td file.
Do the two instructions need to be together? Is one providing an operand via an implicit register?
If the two are simply a sequence that must be emitted together, then the easiest thing to do is make it a pseudo and then expand it into two instructions later. If one is really providing part of the operand via an implicit register, then it’s best to describe that directly and let the scheduler decide where to put the first instruction.
Thanks for the reply.
yes they are dependent if the branch immediate value is > 0xffff then
the imm instruction should generate other wise only "br" instruction
is enough.
Thanks,
Nagaraju
This sounds as if you have two br instructions, one that takes an immediate and one that takes a register and requires that another instruction materialise the address in a register. This is common to most targets - you will find lots of examples in the code - but the high-level picture is to describe both variants in TableGen with appropriate constraints on the range of the immediate. SelectionDAG will pick the immediate version of the constraints match, otherwise it will pick the register version.
David
RISC-V does this kind of thing, and the (new) LLVM back end has been written to (hopefully!) be an example of best practice, so it should be a good one to copy. The first (AUIPC) instruction adds the top 20 bits of a 32 bit offset to the current PC and puts the result into a temporary register. The branch instruction then adds a 12 bit offset to the temporary register.
The compiler always generates code this way. It’s the linker’s job to detect when the AUIPC isn’t necessary and delete it and convert the branch to 12 bit PC-relative instead of register relative. You can turn this off (in gnu ld) if you want faster links and don’t care about the occasional extra instruction.
Hi Nagaraju,
Few suggestions split this into following steps.
1/ DAG Legalization : Custom lower the instruction (branch in your case) appropriately in legalization to target specific DAG nodes and glue the nodes together which you want scheduler should schedule together.
2/ Instruction Selection : Define patterns to match the custom DAG nodes.
Other suggestions
1/ Write a separate MI pass to split the macro MI which was generated earlier as a result of ISel to multiple MIs.
2/ Take the decision of splitting later in the pipeling during MC lowering.
Decision about when you need to split should be driven by your intent to do any further processing over constituent instruction.
~ Jatin
Hi Jatin, Bruce, David
Thanks for your valuable suggestions.
I have defined the patterns to match the custom DAG nodes and it
worked for me.
Thanks,
Nagaraju