Implement indirect branches on MSP430

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@102835 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anton Korobeynikov 2010-05-01 12:04:32 +00:00
parent 650a8e49f9
commit 69d5b48bc3
7 changed files with 91 additions and 8 deletions

View File

@ -78,6 +78,16 @@ GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
return Ctx.GetOrCreateSymbol(Name.str());
}
MCSymbol *MSP430MCInstLower::
GetBlockAddressSymbol(const MachineOperand &MO) const {
switch (MO.getTargetFlags()) {
default: assert(0 && "Unknown target flag on GV operand");
case 0: break;
}
return Printer.GetBlockAddressSymbol(MO.getBlockAddress());
}
MCOperand MSP430MCInstLower::
LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const {
// FIXME: We would like an efficient form for this, so we don't have to do a
@ -131,6 +141,8 @@ void MSP430MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
case MachineOperand::MO_ConstantPoolIndex:
MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
break;
case MachineOperand::MO_BlockAddress:
MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO));
}
OutMI.addOperand(MCOp);

View File

@ -42,6 +42,7 @@ public:
MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const;
MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const;
MCSymbol *GetBlockAddressSymbol(const MachineOperand &MO) const;
};
}

View File

@ -110,8 +110,8 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
setOperationAction(ISD::ROTR, MVT::i16, Expand);
setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom);
setOperationAction(ISD::BlockAddress, MVT::i16, Custom);
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
setOperationAction(ISD::BRIND, MVT::Other, Expand);
setOperationAction(ISD::BR_CC, MVT::i8, Custom);
setOperationAction(ISD::BR_CC, MVT::i16, Custom);
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
@ -183,6 +183,7 @@ SDValue MSP430TargetLowering::LowerOperation(SDValue Op,
case ISD::SRL:
case ISD::SRA: return LowerShifts(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
case ISD::BR_CC: return LowerBR_CC(Op, DAG);
@ -655,6 +656,15 @@ SDValue MSP430TargetLowering::LowerExternalSymbol(SDValue Op,
return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result);;
}
SDValue MSP430TargetLowering::LowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const {
DebugLoc dl = Op.getDebugLoc();
const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), /*isTarget=*/true);
return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result);;
}
static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC,
ISD::CondCode CC,
DebugLoc dl, SelectionDAG &DAG) {
@ -753,7 +763,6 @@ SDValue MSP430TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
Chain, Dest, TargetCC, Flag);
}
SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
SDValue LHS = Op.getOperand(0);
SDValue RHS = Op.getOperand(1);

View File

@ -85,6 +85,7 @@ namespace llvm {
SDValue LowerShifts(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;

View File

@ -176,7 +176,9 @@ unsigned MSP430InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
if (I->isDebugValue())
continue;
if (I->getOpcode() != MSP430::JMP &&
I->getOpcode() != MSP430::JCC)
I->getOpcode() != MSP430::JCC &&
I->getOpcode() != MSP430::Br &&
I->getOpcode() != MSP430::Bm)
break;
// Remove the branch.
I->eraseFromParent();
@ -256,6 +258,11 @@ bool MSP430InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
if (!I->getDesc().isBranch())
return true;
// Cannot handle indirect branches.
if (I->getOpcode() == MSP430::Br ||
I->getOpcode() == MSP430::Bm)
return true;
// Handle unconditional branches.
if (I->getOpcode() == MSP430::JMP) {
if (!AllowModify) {

View File

@ -175,11 +175,18 @@ let isBarrier = 1 in {
def JMP : CJForm<0, 0, (outs), (ins jmptarget:$dst),
"jmp\t$dst",
[(br bb:$dst)]>;
// Long branch
def B : I16ri<0,
(outs), (ins brtarget:$dst),
"br\t$dst",
[]>;
let isIndirectBranch = 1 in {
// Long branches
def B : I16ri<0, (outs), (ins brtarget:$dst),
"br\t$dst",
[]>;
def Br : I16rr<0, (outs), (ins GR16:$brdst),
"mov.w\t{$brdst, pc}",
[(brind GR16:$brdst)]>;
def Bm : I16rm<0, (outs), (ins memsrc:$brdst),
"mov.w\t{$brdst, pc}",
[(brind (load addr:$brdst))]>;
}
}
// Conditional branches
@ -1128,16 +1135,21 @@ def : Pat<(i8 (trunc GR16:$src)),
// GlobalAddress, ExternalSymbol
def : Pat<(i16 (MSP430Wrapper tglobaladdr:$dst)), (MOV16ri tglobaladdr:$dst)>;
def : Pat<(i16 (MSP430Wrapper texternalsym:$dst)), (MOV16ri texternalsym:$dst)>;
def : Pat<(i16 (MSP430Wrapper tblockaddress:$dst)), (MOV16ri tblockaddress:$dst)>;
def : Pat<(add GR16:$src1, (MSP430Wrapper tglobaladdr :$src2)),
(ADD16ri GR16:$src1, tglobaladdr:$src2)>;
def : Pat<(add GR16:$src1, (MSP430Wrapper texternalsym:$src2)),
(ADD16ri GR16:$src1, texternalsym:$src2)>;
def : Pat<(add GR16:$src1, (MSP430Wrapper tblockaddress:$src2)),
(ADD16ri GR16:$src1, tblockaddress:$src2)>;
def : Pat<(store (i16 (MSP430Wrapper tglobaladdr:$src)), addr:$dst),
(MOV16mi addr:$dst, tglobaladdr:$src)>;
def : Pat<(store (i16 (MSP430Wrapper texternalsym:$src)), addr:$dst),
(MOV16mi addr:$dst, texternalsym:$src)>;
def : Pat<(store (i16 (MSP430Wrapper tblockaddress:$src)), addr:$dst),
(MOV16mi addr:$dst, tblockaddress:$src)>;
// calls
def : Pat<(MSP430call (i16 tglobaladdr:$dst)),

View File

@ -0,0 +1,41 @@
; RUN: llc -march=msp430 < %s
@nextaddr = global i8* null ; <i8**> [#uses=2]
@C.0.2070 = private constant [5 x i8*] [i8* blockaddress(@foo, %L1), i8* blockaddress(@foo, %L2), i8* blockaddress(@foo, %L3), i8* blockaddress(@foo, %L4), i8* blockaddress(@foo, %L5)] ; <[5 x i8*]*> [#uses=1]
define internal i16 @foo(i16 %i) nounwind {
entry:
%0 = load i8** @nextaddr, align 4 ; <i8*> [#uses=2]
%1 = icmp eq i8* %0, null ; <i1> [#uses=1]
br i1 %1, label %bb3, label %bb2
bb2: ; preds = %bb3, %entry
%gotovar.4.0 = phi i8* [ %gotovar.4.0.pre, %bb3 ], [ %0, %entry ] ; <i8*> [#uses=1]
indirectbr i8* %gotovar.4.0, [label %L5, label %L4, label %L3, label %L2, label %L1]
bb3: ; preds = %entry
%2 = getelementptr inbounds [5 x i8*]* @C.0.2070, i16 0, i16 %i ; <i8**> [#uses=1]
%gotovar.4.0.pre = load i8** %2, align 4 ; <i8*> [#uses=1]
br label %bb2
L5: ; preds = %bb2
br label %L4
L4: ; preds = %L5, %bb2
%res.0 = phi i16 [ 385, %L5 ], [ 35, %bb2 ] ; <i16> [#uses=1]
br label %L3
L3: ; preds = %L4, %bb2
%res.1 = phi i16 [ %res.0, %L4 ], [ 5, %bb2 ] ; <i16> [#uses=1]
br label %L2
L2: ; preds = %L3, %bb2
%res.2 = phi i16 [ %res.1, %L3 ], [ 1, %bb2 ] ; <i16> [#uses=1]
%phitmp = mul i16 %res.2, 6 ; <i16> [#uses=1]
br label %L1
L1: ; preds = %L2, %bb2
%res.3 = phi i16 [ %phitmp, %L2 ], [ 2, %bb2 ] ; <i16> [#uses=1]
store i8* blockaddress(@foo, %L5), i8** @nextaddr, align 4
ret i16 %res.3
}