forked from OSchip/llvm-project
Thumb unconditional branches are allowed in IT blocks, and therefore should have a predicate operand, unlike conditional branches.
llvm-svn: 139415
This commit is contained in:
parent
8726d330f1
commit
29cfe6c368
|
@ -963,6 +963,8 @@ void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
|
||||||
MCInst BrInst;
|
MCInst BrInst;
|
||||||
BrInst.setOpcode(ARM::t2B);
|
BrInst.setOpcode(ARM::t2B);
|
||||||
BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr));
|
BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr));
|
||||||
|
BrInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||||
|
BrInst.addOperand(MCOperand::CreateReg(0));
|
||||||
OutStreamer.EmitInstruction(BrInst);
|
OutStreamer.EmitInstruction(BrInst);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1677,6 +1679,8 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||||
MCInst TmpInst;
|
MCInst TmpInst;
|
||||||
TmpInst.setOpcode(ARM::tB);
|
TmpInst.setOpcode(ARM::tB);
|
||||||
TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr));
|
TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr));
|
||||||
|
TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
||||||
|
TmpInst.addOperand(MCOperand::CreateReg(0));
|
||||||
OutStreamer.EmitInstruction(TmpInst);
|
OutStreamer.EmitInstruction(TmpInst);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
|
@ -404,7 +404,8 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||||
? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB);
|
? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB);
|
||||||
int BccOpc = !AFI->isThumbFunction()
|
int BccOpc = !AFI->isThumbFunction()
|
||||||
? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc);
|
? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc);
|
||||||
|
bool isThumb = AFI->isThumbFunction() || AFI->isThumb2Function();
|
||||||
|
|
||||||
// Shouldn't be a fall through.
|
// Shouldn't be a fall through.
|
||||||
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
||||||
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
||||||
|
@ -412,7 +413,10 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||||
|
|
||||||
if (FBB == 0) {
|
if (FBB == 0) {
|
||||||
if (Cond.empty()) // Unconditional branch?
|
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
|
else
|
||||||
BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB)
|
BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB)
|
||||||
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
|
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
|
||||||
|
@ -422,7 +426,10 @@ ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||||
// Two-way conditional branch.
|
// Two-way conditional branch.
|
||||||
BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB)
|
BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB)
|
||||||
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg());
|
.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;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -739,7 +739,11 @@ MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
|
||||||
// There doesn't seem to be meaningful DebugInfo available; this doesn't
|
// There doesn't seem to be meaningful DebugInfo available; this doesn't
|
||||||
// correspond to anything in the source.
|
// correspond to anything in the source.
|
||||||
unsigned Opc = isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B;
|
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;
|
++NumSplit;
|
||||||
|
|
||||||
// Update the CFG. All succs of OrigBB are now succs of NewBB.
|
// 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
|
// targets will be exchanged, and the altered branch may be out of
|
||||||
// range, so the machinery has to know about it.
|
// range, so the machinery has to know about it.
|
||||||
int UncondBr = isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) : ARM::B;
|
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);
|
unsigned MaxDisp = getUnconditionalBrDisp(UncondBr);
|
||||||
ImmBranches.push_back(ImmBranch(&UserMBB->back(),
|
ImmBranches.push_back(ImmBranch(&UserMBB->back(),
|
||||||
MaxDisp, false, UncondBr));
|
MaxDisp, false, UncondBr));
|
||||||
|
@ -1893,7 +1901,8 @@ AdjustJTTargetBlockForward(MachineBasicBlock *BB, MachineBasicBlock *JTBB)
|
||||||
// There doesn't seem to be meaningful DebugInfo available; this doesn't
|
// There doesn't seem to be meaningful DebugInfo available; this doesn't
|
||||||
// correspond directly to anything in the source.
|
// correspond directly to anything in the source.
|
||||||
assert (isThumb2 && "Adjusting for TB[BH] but not in Thumb2?");
|
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.
|
// Update internal data structures to account for the newly inserted MBB.
|
||||||
MF.RenumberBlocks(NewBB);
|
MF.RenumberBlocks(NewBB);
|
||||||
|
|
|
@ -414,6 +414,9 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||||
MIB.addExternalSymbol(JumpTarget.getSymbolName(),
|
MIB.addExternalSymbol(JumpTarget.getSymbolName(),
|
||||||
JumpTarget.getTargetFlags());
|
JumpTarget.getTargetFlags());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the default predicate in Thumb mode.
|
||||||
|
if (STI.isThumb()) MIB.addImm(ARMCC::AL).addReg(0);
|
||||||
} else if (RetOpcode == ARM::TCRETURNri) {
|
} else if (RetOpcode == ARM::TCRETURNri) {
|
||||||
BuildMI(MBB, MBBI, dl,
|
BuildMI(MBB, MBBI, dl,
|
||||||
TII.get(STI.isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr)).
|
TII.get(STI.isThumb() ? ARM::tTAILJMPr : ARM::TAILJMPr)).
|
||||||
|
|
|
@ -5713,8 +5713,10 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||||
|
|
||||||
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
|
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
|
||||||
.addMBB(destMBB).addImm(ARMCC::EQ).addReg(ARM::CPSR);
|
.addMBB(destMBB).addImm(ARMCC::EQ).addReg(ARM::CPSR);
|
||||||
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2B : ARM::B))
|
if (isThumb2)
|
||||||
.addMBB(exitMBB);
|
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.
|
MI->eraseFromParent(); // The pseudo instruction is gone now.
|
||||||
return BB;
|
return BB;
|
||||||
|
|
|
@ -487,8 +487,8 @@ let isCall = 1,
|
||||||
|
|
||||||
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
|
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
|
||||||
let isPredicable = 1 in
|
let isPredicable = 1 in
|
||||||
def tB : T1I<(outs), (ins t_brtarget:$target), IIC_Br,
|
def tB : T1pI<(outs), (ins t_brtarget:$target), IIC_Br,
|
||||||
"b\t$target", [(br bb:$target)]>,
|
"b", "\t$target", [(br bb:$target)]>,
|
||||||
T1Encoding<{1,1,1,0,0,?}> {
|
T1Encoding<{1,1,1,0,0,?}> {
|
||||||
bits<11> target;
|
bits<11> target;
|
||||||
let Inst{10-0} = 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).
|
// Non-Darwin versions (the difference is R9).
|
||||||
let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC],
|
let Defs = [R0, R1, R2, R3, R12, QQQQ0, QQQQ2, QQQQ3, PC],
|
||||||
Uses = [SP] in {
|
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, [],
|
4, IIC_Br, [],
|
||||||
(tB t_brtarget:$dst)>,
|
(tB t_brtarget:$dst, pred:$p)>,
|
||||||
Requires<[IsThumb, IsNotDarwin]>;
|
Requires<[IsThumb, IsNotDarwin]>;
|
||||||
def tTAILJMPrND : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops),
|
def tTAILJMPrND : tPseudoExpand<(outs), (ins tcGPR:$dst, variable_ops),
|
||||||
4, IIC_Br, [],
|
4, IIC_Br, [],
|
||||||
|
|
|
@ -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 isBranch = 1, isTerminator = 1, isBarrier = 1 in {
|
||||||
let isPredicable = 1 in
|
let isPredicable = 1 in
|
||||||
def t2B : T2XI<(outs), (ins uncondbrtarget:$target), IIC_Br,
|
def t2B : T2I<(outs), (ins uncondbrtarget:$target), IIC_Br,
|
||||||
"b.w\t$target",
|
"b", ".w\t$target",
|
||||||
[(br bb:$target)]> {
|
[(br bb:$target)]> {
|
||||||
let Inst{31-27} = 0b11110;
|
let Inst{31-27} = 0b11110;
|
||||||
let Inst{15-14} = 0b10;
|
let Inst{15-14} = 0b10;
|
||||||
|
@ -3060,7 +3060,7 @@ def t2TBH : T2I<(outs), (ins GPR:$Rn, GPR:$Rm), IIC_Br,
|
||||||
} // isBranch, isTerminator, isBarrier
|
} // isBranch, isTerminator, isBarrier
|
||||||
|
|
||||||
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
|
// 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
|
let isBranch = 1, isTerminator = 1 in
|
||||||
def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
|
def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
|
||||||
"b", ".w\t$target",
|
"b", ".w\t$target",
|
||||||
|
@ -3088,9 +3088,10 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
|
||||||
// Darwin version.
|
// Darwin version.
|
||||||
let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC],
|
let Defs = [R0, R1, R2, R3, R9, R12, QQQQ0, QQQQ2, QQQQ3, PC],
|
||||||
Uses = [SP] in
|
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, [],
|
4, IIC_Br, [],
|
||||||
(t2B uncondbrtarget:$dst)>,
|
(t2B uncondbrtarget:$dst, pred:$p)>,
|
||||||
Requires<[IsThumb2, IsDarwin]>;
|
Requires<[IsThumb2, IsDarwin]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3567,8 +3567,8 @@ validateInstruction(MCInst &Inst,
|
||||||
// Check for non-'al' condition codes outside of the IT block.
|
// Check for non-'al' condition codes outside of the IT block.
|
||||||
} else if (isThumbTwo() && MCID.isPredicable() &&
|
} else if (isThumbTwo() && MCID.isPredicable() &&
|
||||||
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
|
Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
|
||||||
ARMCC::AL && Inst.getOpcode() != ARM::tBcc &&
|
ARMCC::AL && Inst.getOpcode() != ARM::tB &&
|
||||||
Inst.getOpcode() != ARM::t2Bcc)
|
Inst.getOpcode() != ARM::t2B)
|
||||||
return Error(Loc, "predicated instructions must be in IT block");
|
return Error(Loc, "predicated instructions must be in IT block");
|
||||||
|
|
||||||
switch (Inst.getOpcode()) {
|
switch (Inst.getOpcode()) {
|
||||||
|
@ -3721,6 +3721,16 @@ processInstruction(MCInst &Inst,
|
||||||
if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
|
if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
|
||||||
Inst.setOpcode(ARM::tADDi3);
|
Inst.setOpcode(ARM::tADDi3);
|
||||||
break;
|
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:
|
case ARM::t2Bcc:
|
||||||
// If the conditional is AL or we're in an IT block, we really want t2B.
|
// If the conditional is AL or we're in an IT block, we really want t2B.
|
||||||
if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
|
if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
|
||||||
|
|
|
@ -426,6 +426,8 @@ static void AddThumb1SBit(MCInst &MI, bool InITBlock) {
|
||||||
// post-pass.
|
// post-pass.
|
||||||
MCDisassembler::DecodeStatus
|
MCDisassembler::DecodeStatus
|
||||||
ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
|
ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
|
||||||
|
MCDisassembler::DecodeStatus S = Success;
|
||||||
|
|
||||||
// A few instructions actually have predicates encoded in them. Don't
|
// A few instructions actually have predicates encoded in them. Don't
|
||||||
// try to overwrite it if we're seeing one of those.
|
// try to overwrite it if we're seeing one of those.
|
||||||
switch (MI.getOpcode()) {
|
switch (MI.getOpcode()) {
|
||||||
|
@ -436,8 +438,16 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
|
||||||
// Some instructions (mostly conditional branches) are not
|
// Some instructions (mostly conditional branches) are not
|
||||||
// allowed in IT blocks.
|
// allowed in IT blocks.
|
||||||
if (!ITBlock.empty())
|
if (!ITBlock.empty())
|
||||||
return SoftFail;
|
S = SoftFail;
|
||||||
return Success;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -466,7 +476,7 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
|
||||||
MI.insert(I, MCOperand::CreateReg(0));
|
MI.insert(I, MCOperand::CreateReg(0));
|
||||||
else
|
else
|
||||||
MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
|
MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
|
||||||
return Success;
|
return S;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,7 +487,7 @@ ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
|
||||||
else
|
else
|
||||||
MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
|
MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
|
||||||
|
|
||||||
return Success;
|
return S;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Thumb VFP instructions are a special case. Because we share their
|
// Thumb VFP instructions are a special case. Because we share their
|
||||||
|
|
|
@ -188,7 +188,7 @@ _func:
|
||||||
@ CHECK: beq.w _bar @ encoding: [A,0xf0'A',A,0x80'A']
|
@ CHECK: beq.w _bar @ encoding: [A,0xf0'A',A,0x80'A']
|
||||||
@ fixup A - offset: 0, value: _bar, kind: fixup_t2_condbranch
|
@ fixup A - offset: 0, value: _bar, kind: fixup_t2_condbranch
|
||||||
@ CHECK: it eq @ encoding: [0x08,0xbf]
|
@ 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
|
@ fixup A - offset: 0, value: _bar, kind: fixup_t2_uncondbranch
|
||||||
@ CHECK: bmi.w #-183396 @ encoding: [0x13,0xf5,0xce,0xa9]
|
@ CHECK: bmi.w #-183396 @ encoding: [0x13,0xf5,0xce,0xa9]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue