[LLVMdev] Problem using a label to a MachineBasicBlock
Jeroen Dobbelaere
Jeroen.Dobbelaere at synopsys.com
Wed Nov 30 08:23:57 PST 2011
Hi all,
I think that I came somewhat closer to a solution for splitting a
MachineBasicBlock for a PSEUDO_CALL_R instruction and having a label to the new MBB:
For following piece of code:
---
typedef int callme_t(int a, int b);
callme_t* c01;
int foo(int a, int b)
{
return c01(a,b); // MachineBasicBlock will be split at call instruction
}
---
I have initially following correspondence:
BB1 -> MBB10 (aka, BasicBlock 1 corresponds to MachineBasicBlock 10)
After splitting MBB10 at the call instruction, we get :
BB1 -> MBB10, MBB11
Because I need the address of MBB11, I found that I need to ensure
that 'MBB11->hasAddressTaken()' returns true. Otherwise it can be optimized
away.
This can be done by:
MBB11->setHasAddressTaken();
But this is not sufficient: an assertion failure in
llvm::MMIAddrLabelMap::getAddrLabelSymbolToEmit(..)
is triggered:
'BB->hasAddressTaken()' should also be set.
The only way I found to do this (although it does not look clean to me)
is the following:
(void)llvm::BlockAddress::get(const_cast<BasicBlock*>(MBB11->getBasicBlock()))
In this way, BB1 will have its reference count incremented and the assertion will
not trigger.
So, after splitting the MachineBasicBlock and migrating the successors etc., I have to do:
---
NEW_MBB->setHasAddressTaken();
(void)llvm::BlockAddress::get(const_cast<BasicBlock*>(NEW_MBB->getBasicBlock()))
---
With this, my basic example works as expected.
Now, I want to try this on a more complex example:
---
typedef int callme_t(int a, int b);
callme_t* c01;
callme_t* c02;
int foo(int a, int b)
{
int result = c01(a,b); // MachineBasicBlock will be split at call instruction
result += c02(a,b); // MachineBasicBlock will also be split at this call instruction
return result;
}
---
This corresponds with:
BB1 -> MBB10, MBB11, MBB12
where MBB11 and MBB12 have both their address taken, and the reference count for BB1
is increased twice. With this, I am triggering a new assertion failure:
In lib/MC/MCAsmStreamer.cpp:328 of MCAsmStreamer::EmitLabel(llvm::MCSymbol*)
----
void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
MCStreamer::EmitLabel(Symbol);
OS << *Symbol << MAI.getLabelSuffix();
EmitEOL();
}
---
When I disable the assertion, I observe the following:
The different labels for the machine basic blocks are emitted, but the two new
basic blocks that were created, also have a common extra label '_tmp0'
---
.text
.globl _foo
_foo:
....
load_immediate R15, __BB0_1
branch_to_reg R1
_tmp0:
_BB0_1:
...
load_immediate R15, __BB0_2:
branch_to_reg R2
_tmp0: // *** duplicate unnecessary label, _tmp0 is not used
_BB0_2
...
---
Any idea how this can be resolved in a clean way ?
Thanks,
Jeroen Dobbelaere
More information about the llvm-dev
mailing list