[MC] Questions about relaxation in MC

Hi all,

In RISC-V ISA, the range of conditional branches is within 4KiB. In current implementation, if the branch target is out of range, LLVM MC will issue an error message to tell users it could not resolve the fixup record. I have compared the result with the GNU assembler. GNU assembler will convert the branch to inverted one plus jump to make the branch possible. The range of unconditional jump is 1MiB. It looks like

Correct the title.

This sounds very similar to what PowerPC does, see:

However, PowerPC is doing this in the compiler backend, not in the assembler. One issue is that the process must be iterative, because branches can go both forward and backward, and replacing some branch instructions with the branch pairs can then cause other branches to go out of range.


And... MSP430 has the similar code :slight_smile:

Hi Hal,

Thanks for your information. If the input source is assembly code, is there any chance to do the similar thing? MC assembler seems to scan the assembly code one by one and convert them to MCInsts. Then do the assembler work, i.e., put MCInsts into fragments, generate fixups if needed, relaxation, code emission, etc.


Hi Anton,

Thanks for your information. I will look into MSP430.


If done in the assembler, this is branch relaxation. You need to implement the calls backs mayNeedRelaxation, and relaxInstruction on your target MCAsmBackend. The iteration relaxation logic already exists, see the generic MC code.


Hi Kai,

did you make any progress on this topic?
We have a similar case in our backend, where conditional branches have only a limited range.
So for hand-written assembly, we would like to relax using the scheme you describe: invert the branch condition and add an unconditional jump.

As you’ve already discovered, the relaxInstruction callback doesn’t allow to insert additional instructions, but requires the relaxed instruction to be returned.
We could work around that by relaxing to a pseudo instruction whose size is the combined size of the conditional branch + jump and expand it later to the actual instructions, but that seems unnecessarily complex.

Did you come up with a better solution?


We had a similar issue with a hardware bug where we changed the 32 bit branch instruction encoding into a 64 encoding, the other 32 bit being a NOP: https://reviews.llvm.org/rG9ab812d4752b2a1442426db2ccc17dc95d12eb04

We also looked at using a bundle instead of this encoding method as we thought that might have been cleaner but that’s a bit more complex, not sure if either of these help you.

Thanks for highlighting that patch!

Using instruction bundles indeed sounds interesting, as it seems more flexible. We’ll see how far we get with this.


Hi Konstantin,

No, I have no progress in this issue. After discussing in the RISC-V sync-up meeting, I filed a bug in the LLVM bugzilla. https://bugs.llvm.org/show_bug.cgi?id=47910

You should check Hexagon, it appears that they use bundles with relaxation.

Hi Ryan,

Thanks for your information. I will check it out.

We could make this work using bundles in our backend, but needed to pass the MCContext to relaxInstruction to be able to allocate new instructions without leaking memory.

Could someone have a look at the patch ()?