[LLVMdev] Same basic block label being emitted multiple times for different blocks
פ מSimon Glumcher
simongl at gmail.com
Tue Jun 2 12:11:04 PDT 2015
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<BasicBlockSDNode>(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.
--
Regards,
Simon.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150602/e8c5140d/attachment.html>
More information about the llvm-dev
mailing list