Thumb unconditional branches are allowed in IT blocks, and therefore should have a predicate operand, unlike conditional branches.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139415 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2011-09-09 21:48:23 +00:00
parent 13d8baa3fc
commit 51f6a7abf2
10 changed files with 71 additions and 24 deletions

View File

@ -963,6 +963,8 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
MCInst BrInst;
BrInst.setOpcode(ARM::t2B);
BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr));
BrInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
BrInst.addOperand(MCOperand::CreateReg(0));
OutStreamer.EmitInstruction(BrInst);
continue;
}
@ -1677,6 +1679,8 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MCInst TmpInst;
TmpInst.setOpcode(ARM::tB);
TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr));
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
TmpInst.addOperand(MCOperand::CreateReg(0));
OutStreamer.EmitInstruction(TmpInst);
}
{

View File

@ -404,7 +404,8 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB);
int BccOpc = !AFI->isThumbFunction()
? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc);
bool isThumb = AFI->isThumbFunction() || AFI->isThumb2Function();
// Shouldn't be a fall through.
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
assert((Cond.size() == 2 || Cond.size() == 0) &&
@ -412,7 +413,10 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
if (FBB == 0) {
if (Cond.empty()) // Unconditional branch?
BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB);
if (isThumb)
BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB).addImm(ARMCC::AL).addReg(0);
else
BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB);
else
BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB)
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
@ -422,7 +426,10 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
// Two-way conditional branch.
BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB)
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB);
if (isThumb)
BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB).addImm(ARMCC::AL).addReg(0);
else
BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB);
return 2;
}

View File

@ -739,7 +739,11 @@ MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
// There doesn't seem to be meaningful DebugInfo available; this doesn't
// correspond to anything in the source.
unsigned Opc = isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B;
BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB);
if (!isThumb)
BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB);
else
BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB)
.addImm(ARMCC::AL).addReg(0);
++NumSplit;
// Update the CFG. All succs of OrigBB are now succs of NewBB.
@ -1151,7 +1155,11 @@ void ARMConstantIslands::CreateNewWater(unsigned CPUserIndex,
// targets will be exchanged, and the altered branch may be out of
// range, so the machinery has to know about it.
int UncondBr = isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) : ARM::B;
BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB);
if (!isThumb)
BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB);
else
BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB)
.addImm(ARMCC::AL).addReg(0);
unsigned MaxDisp = getUnconditionalBrDisp(UncondBr);
ImmBranches.push_back(ImmBranch(&UserMBB->back(),
MaxDisp, false, UncondBr));
@ -1893,7 +1901,8 @@ AdjustJTTargetBlockForward(MachineBasicBlock *BB, MachineBasicBlock *JTBB)
// There doesn't seem to be meaningful DebugInfo available; this doesn't
// correspond directly to anything in the source.
assert (isThumb2 && "Adjusting for TB[BH] but not in Thumb2?");
BuildMI(NewBB, DebugLoc(), TII->get(ARM::t2B)).addMBB(BB);
BuildMI(NewBB, DebugLoc(), TII->get(ARM::t2B)).addMBB(BB)
.addImm(ARMCC::AL).addReg(0);
// Update internal data structures to account for the newly inserted MBB.
MF.RenumberBlocks(NewBB);

View File

@ -414,6 +414,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
MIB.addExternalSymbol(JumpTarget.getSymbolName(),
JumpTarget.getTargetFlags());
}
// Add the default predicate in Thumb mode.
if (STI.isThumb()) MIB.addImm(ARMCC::AL).addReg(0);
} else if (RetOpcode == ARM::TCRETURNri) {
BuildMI(MBB, MBBI, dl,
TII.get(STI.isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr)).

View File

@ -5713,8 +5713,10 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
.addMBB(destMBB).addImm(ARMCC::EQ).addReg(ARM::CPSR);
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2B : ARM::B))
.addMBB(exitMBB);
if (isThumb2)
AddDefaultPred(BuildMI(BB, dl, TII->get(ARM::t2B)).addMBB(exitMBB));
else
BuildMI(BB, dl, TII->get(ARM::B)) .addMBB(exitMBB);
MI->eraseFromParent(); // The pseudo instruction is gone now.
return BB;

View File

@ -487,8 +487,8 @@ let isCall = 1,
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
let isPredicable = 1 in
def tB : T1I<(outs), (ins t_brtarget:$target), IIC_Br,
"b\t$target", [(br bb:$target)]>,
def tB : T1pI<(outs), (ins t_brtarget:$target), IIC_Br,
"b", "\t$target", [(br bb:$target)]>,
T1Encoding<{1,1,1,0,0,?}> {
bits<11> target;
let Inst{10-0} = target;
@ -537,9 +537,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
// Non-Darwin versions (the difference is R9).
let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC],
Uses = [SP] in {
def tTAILJMPdND : tPseudoExpand<(outs), (ins t_brtarget:$dst, variable_ops),
def tTAILJMPdND : tPseudoExpand<(outs),
(ins t_brtarget:$dst, pred:$p, variable_ops),
4, IIC_Br, [],
(tB t_brtarget:$dst)>,
(tB t_brtarget:$dst, pred:$p)>,
Requires<[IsThumb, IsNotDarwin]>;
def tTAILJMPrND : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops),
4, IIC_Br, [],

View File

@ -3004,8 +3004,8 @@ def t2LDMIA_RET: t2PseudoExpand<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
let isPredicable = 1 in
def t2B : T2XI<(outs), (ins uncondbrtarget:$target), IIC_Br,
"b.w\t$target",
def t2B : T2I<(outs), (ins uncondbrtarget:$target), IIC_Br,
"b", ".w\t$target",
[(br bb:$target)]> {
let Inst{31-27} = 0b11110;
let Inst{15-14} = 0b10;
@ -3060,7 +3060,7 @@ def t2TBH : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
} // isBranch, isTerminator, isBarrier
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
// a two-value operand where a dag node expects two operands. :(
// a two-value operand where a dag node expects ", "two operands. :(
let isBranch = 1, isTerminator = 1 in
def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
"b", ".w\t$target",
@ -3088,9 +3088,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
// Darwin version.
let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC],
Uses = [SP] in
def tTAILJMPd: tPseudoExpand<(outs), (ins uncondbrtarget:$dst, variable_ops),
def tTAILJMPd: tPseudoExpand<(outs),
(ins uncondbrtarget:$dst, pred:$p, variable_ops),
4, IIC_Br, [],
(t2B uncondbrtarget:$dst)>,
(t2B uncondbrtarget:$dst, pred:$p)>,
Requires<[IsThumb2, IsDarwin]>;
}

View File

@ -3567,8 +3567,8 @@ validateInstruction(MCInst &Inst,
// Check for non-'al' condition codes outside of the IT block.
} else if (isThumbTwo() && MCID.isPredicable() &&
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
ARMCC::AL && Inst.getOpcode() != ARM::tBcc &&
Inst.getOpcode() != ARM::t2Bcc)
ARMCC::AL && Inst.getOpcode() != ARM::tB &&
Inst.getOpcode() != ARM::t2B)
return Error(Loc, "predicated instructions must be in IT block");
switch (Inst.getOpcode()) {
@ -3721,6 +3721,16 @@ processInstruction(MCInst &Inst,
if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Inst.setOpcode(ARM::tADDi3);
break;
case ARM::tB:
// A Thumb conditional branch outside of an IT block is a tBcc.
if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
Inst.setOpcode(ARM::tBcc);
break;
case ARM::t2B:
// A Thumb2 conditional branch outside of an IT block is a t2Bcc.
if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
Inst.setOpcode(ARM::t2Bcc);
break;
case ARM::t2Bcc:
// If the conditional is AL or we're in an IT block, we really want t2B.
if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())

View File

@ -426,6 +426,8 @@ static void AddThumb1SBit(MCInst &MI, bool InITBlock) {
// post-pass.
MCDisassembler::DecodeStatus
ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
MCDisassembler::DecodeStatus S = Success;
// A few instructions actually have predicates encoded in them. Don't
// try to overwrite it if we're seeing one of those.
switch (MI.getOpcode()) {
@ -436,8 +438,16 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
// Some instructions (mostly conditional branches) are not
// allowed in IT blocks.
if (!ITBlock.empty())
return SoftFail;
return Success;
S = SoftFail;
else
return Success;
break;
case ARM::tB:
case ARM::t2B:
// Some instructions (mostly unconditional branches) can
// only appears at the end of, or outside of, an IT.
if (ITBlock.size() > 1)
S = SoftFail;
break;
default:
break;
@ -466,7 +476,7 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
MI.insert(I, MCOperand::CreateReg(0));
else
MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
return Success;
return S;
}
}
@ -477,7 +487,7 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
else
MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
return Success;
return S;
}
// Thumb VFP instructions are a special case. Because we share their

View File

@ -188,7 +188,7 @@ _func:
@ CHECK: beq.w _bar @ encoding: [A,0xf0'A',A,0x80'A']
@ fixup A - offset: 0, value: _bar, kind: fixup_t2_condbranch
@ CHECK: it eq @ encoding: [0x08,0xbf]
@ CHECK: b.w _bar @ encoding: [A,0xf0'A',A,0x90'A']
@ CHECK: beq.w _bar @ encoding: [A,0xf0'A',A,0x90'A']
@ fixup A - offset: 0, value: _bar, kind: fixup_t2_uncondbranch
@ CHECK: bmi.w #-183396 @ encoding: [0x13,0xf5,0xce,0xa9]