LLVM pass question

I'm implementing this ability to switch between mips16 and mips32 on a per function basis.

One issue that I've run into is regarding the DAGToDAGIsel pass.

We have a different subclass for mips16 and non mips16 ( conceivably later there could be a separate one for micromips).

I need to run a different pass depending on whether it's mips16 or mips32.

My initial plan was to create a dummy ModuleDAGToDAGIsel whose sole purpose in it's run machine function was to decide which one of these
to run and then call an appropriate DAGToDAGIIsel but I'm running into some issue where that class wants to be started up by the pass manager
and not another pass.

So now I'm think that maybe I should have either:
1) The ModuleDAGToDAGIsel pass add another pass.
2) Maybe create two passes, one for Mips16 and one for Mips32 and have them be dependent on the ModuleDAGToDAGISel pass and then turn them on or off depending on which one needs to be run for this function.

I'm reading the pass code now to understand this better but thought that someone might know the answer.



I guess another way to do this is to just register both passes for mips16 and mips32 and have them return immediately if it is not their turn to run.

What I am thinking of now is to just register the MIPS116 and MIPS32 DAGToDAGISel passes and then within run on machine function, I can just
return if the current mode indicates that mips16 is needed for example, so the run on machine function for Mips32 would return immediately.

This seems to work okay.

I register both the Mips16 and non Mips16 passes of the instruction selector and then those return false if they are not supposed to be running.

Make-check at least passes in this case.

So in principle turn on the dual mode now and debug whatever misc is left.

For this I insert another pass before the mips16 and non mips16 passes.

So the switching between mips16 and mips32 on a per function basis seems to basically be working except that asm printer has some kind of
issue here.

I'm debugging that now.

I get this:
lc: /home/rkotler/workspace/llvmpb6/include/llvm/MC/MCStreamer.h:224: void llvm::MCStreamer::SwitchSection(const llvm::MCSection*): Assertion `Section && "Cannot switch to a null section!"' failed.
0 llc 0x00000000015a98b1 llvm::sys::PrintStackTrace(_IO_FILE*) + 38
1 llc 0x00000000015a9b2e
2 llc 0x00000000015a9586
3 libpthread.so.0 0x00007f0f517568f0
4 libc.so.6 0x00007f0f5083da75 gsignal + 53
5 libc.so.6 0x00007f0f508415c0 abort + 384
6 libc.so.6 0x00007f0f50836941 __assert_fail + 241
7 llc 0x000000000096d740
8 llc 0x0000000000f7d1ec llvm::AsmPrinter::EmitFunctionHeader() + 160

Maybe someone knows how this dependency can exist from switching subtarget information.

If so, TIA.

My additional work is to turn BasicTransformInfoPass into a function pass from an immutable pass but I don't need that right now for this functionality in mips16/32 dual mode. It will just generate worse code until I solve that.


Turns out to be a really easy fix.

The problem is that AsmPrinter initializes some things in the base class of target lowering, so when I substitute a new target lowering, this initializiation was not taking place.

Fortunately, AsmPrinter is already a subclass of MipsAsmPrinter so I just need to add the following line to runOnMachineFunction ins MipsAsmPrinter.

     .Initialize(OutContext, TM);

I need to add the optimization to not call this if the subtarget kind has not changed.