Same basic block label being emitted multiple times for different blocks

Hello,

I am a newbie working on a backend for a custom target, and I am getting a crash when I try to compile the code generated for an LLVM switch instruction. My backend doesn’t currently support jump tables, so this happens for code generated to implement a switch as a binary tree (by SelectionDAGBuilder).

I am working with LLVM 3.5.

The following assert is failing in the AsmStreamer’s EmitLabel method for my target:
assert(Symbol->isUndefined() && “Cannot define a symbol twice!”);

Without this check, the emitted code containes several different basic blocks with the same label. Several labels are emitted for each block: The MachineBasicBlock symbol, and any symbols used to refer to that block. While the MachineBasicBlock symbols are unique in the emitted code, the symbols used to reference blocks are not.

An example:

Ltmp0: // Block address taken
BB0_1: // %entry

Ltmp0: // Block address taken
BB0_2: // %entry

This seems to happen because of the difference between MachineModuleInfo::getAddrLabelSymbolToEmit (the labels used to refer to the block) and MachineBasicBlock::getSymbol(), both of which are called in AsmPrinter::EmitBasicBlockStart when the block is being emitted, to print the different labels.

My target only supports indirect branches (through a register) so I custom lower branches to an indirect branch - this is why both (all) labels are marked as “Block address taken”.

The reason the the same label is emitted for different basic blocks is that SelectionDAGBuilder uses the same BasicBlock insance to create several MachineBasicBlock instances. This can be seen in the following snippet from SelectionDAGBuilder::handleBTSplitSwitchCase:

} else {
FalseBB = CurMF->CreateMachineBasicBlock(LLVMBB);
CurMF->insert(BBI, FalseBB);
WorkList.push_back(CaseRec(FalseBB,CR.LT,C,RHSR));

Some of the calls to CreateMachineBasicBlock get the same LLVMBB instance. I am not sure this is what is supposed to happen.

Below is the code I use to custom lower BR_CC nodes, in context. Perhaps I’m missing something I did wrong there:
SDValue CustomTargetLowering::LowerOperation(SDValue Op,
SelectionDAG &DAG) const {
SDValue Chain = Op->getOperand(0);
SDValue Target = Op->getOperand(1);
SDLoc dl(Op.getNode());
BasicBlockSDNode *BBNode = cast(Target);
MachineBasicBlock MBB = BBNode->getBasicBlock();
const BasicBlock * BB = MBB->getBasicBlock();
MBB->setHasAddressTaken();
SDValue BlockAddressNode = DAG.getBlockAddress(BlockAddress::get(const_cast<BasicBlock
>(BB)), EVT(MVT::i64));
return DAG.getNode(ISD::BRIND, dl, EVT(MVT::Other), Chain, BlockAddressNode);
}

Another issue is that the emitted branches target the same label when they should be targetting different blocks, so a patch to make the streamer stop emitting the same label twice would not be sufficient to solve this issue.

Note: There is a post to the list entitled “Problem using a label to a MachineBasicBlock” (can be found here: http://lists.cs.uiuc.edu/pipermail/llvmdev/2011-November/045748.html) from someone who encountered the same symptom, it seems that the underlying cause is different.

Please help

Simon.