[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