diff --git a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp index f4d7d8a5288..d1d9a115863 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp @@ -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); diff --git a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.h b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.h index a2b99ae83c0..f9620e8ccfd 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.h +++ b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.h @@ -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; }; } diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index 2695f8c2908..c3e2bdf7b46 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -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(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); diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h index 6047a49248f..01c5071622a 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.h +++ b/lib/Target/MSP430/MSP430ISelLowering.h @@ -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; diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp index 24ce403ddc7..2b09b3d5268 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.cpp +++ b/lib/Target/MSP430/MSP430InstrInfo.cpp @@ -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) { diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td index 37129e37ef8..999364872b3 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.td +++ b/lib/Target/MSP430/MSP430InstrInfo.td @@ -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)), diff --git a/test/CodeGen/MSP430/indirectbr.ll b/test/CodeGen/MSP430/indirectbr.ll new file mode 100644 index 00000000000..2a62c9135c6 --- /dev/null +++ b/test/CodeGen/MSP430/indirectbr.ll @@ -0,0 +1,41 @@ +; RUN: llc -march=msp430 < %s + +@nextaddr = global i8* null ; [#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 ; [#uses=2] + %1 = icmp eq i8* %0, null ; [#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 ] ; [#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 ; [#uses=1] + %gotovar.4.0.pre = load i8** %2, align 4 ; [#uses=1] + br label %bb2 + +L5: ; preds = %bb2 + br label %L4 + +L4: ; preds = %L5, %bb2 + %res.0 = phi i16 [ 385, %L5 ], [ 35, %bb2 ] ; [#uses=1] + br label %L3 + +L3: ; preds = %L4, %bb2 + %res.1 = phi i16 [ %res.0, %L4 ], [ 5, %bb2 ] ; [#uses=1] + br label %L2 + +L2: ; preds = %L3, %bb2 + %res.2 = phi i16 [ %res.1, %L3 ], [ 1, %bb2 ] ; [#uses=1] + %phitmp = mul i16 %res.2, 6 ; [#uses=1] + br label %L1 + +L1: ; preds = %L2, %bb2 + %res.3 = phi i16 [ %phitmp, %L2 ], [ 2, %bb2 ] ; [#uses=1] + store i8* blockaddress(@foo, %L5), i8** @nextaddr, align 4 + ret i16 %res.3 +}