is a function pass allowed to transform code in other functions too?
We are currently facing a problem with codegenprepare, an IR function pass in the backend pipeline. It eliminates a basic block in the function it is executed on, main, and also updates another function foo0, which takes the address of the basic block with blockaddress.
For some unknown reason, the change of blockaddress in foo0 is not working correctly. So, I’m wondering if a function pass is only allowed to change the function it is executed on.
That’s generally true, but I’m not sure it holds in the specific case here. A function pass can drop a block in function F which is referenced by a blockaddress, which is referenced by a function F2. Dropping the block in F will thus result in the blockaddress in F2 being replaced. I don’t think we consider that a violation of FunctionPass rules (or if we do, that’s a general problem with how blockaddress works).
I think, there is an issue with function passes changing other functions. The update to the other function can get lost if the other function is defined earlier in the IR module.
The example has two code variations. They only differ in the order of the functions. foo0 and foo1 contain blockaddress expressions, main contains the referenced basic blocks.
If the function order is main, foo0 and foo1, everything is fine. But if we reorder to foo0, foo1 and main, then we get an undefined symbol used in foo0.
As far as I understand, the function pass pipeline is executed in definition order of the functions. First all function passes are run on foo0, then on foo1 and at the end on main. When codegenprepare is run on main, it eliminates a block in main and updates the blockaddress in foo0. This last update is lost, probably because foo0 is already done.