Index: lib/Target/MSP430/MSP430CallingConv.td =================================================================== --- lib/Target/MSP430/MSP430CallingConv.td +++ lib/Target/MSP430/MSP430CallingConv.td @@ -13,11 +13,11 @@ // MSP430 Return Value Calling Convention //===----------------------------------------------------------------------===// def RetCC_MSP430 : CallingConv<[ - // i8 are returned in registers R15B, R14B, R13B, R12B - CCIfType<[i8], CCAssignToReg<[R15B, R14B, R13B, R12B]>>, + // i8 are returned in registers R12B, R13B, R14B, R15B + CCIfType<[i8], CCAssignToReg<[R12B, R13B, R14B, R15B]>>, - // i16 are returned in registers R15, R14, R13, R12 - CCIfType<[i16], CCAssignToReg<[R15, R14, R13, R12]>> + // i16 are returned in registers R12, R13, R14, R15 + CCIfType<[i16], CCAssignToReg<[R12, R13, R14, R15]>> ]>; //===----------------------------------------------------------------------===// Index: lib/Target/MSP430/MSP430ISelLowering.h =================================================================== --- lib/Target/MSP430/MSP430ISelLowering.h +++ lib/Target/MSP430/MSP430ISelLowering.h @@ -158,6 +158,12 @@ LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl &InVals) const override; + bool CanLowerReturn(CallingConv::ID CallConv, + MachineFunction &MF, + bool IsVarArg, + const SmallVectorImpl &Outs, + LLVMContext &Context) const; + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, Index: lib/Target/MSP430/MSP430ISelLowering.cpp =================================================================== --- lib/Target/MSP430/MSP430ISelLowering.cpp +++ lib/Target/MSP430/MSP430ISelLowering.cpp @@ -247,7 +247,8 @@ SmallVectorImpl &Out) { unsigned CurrentArgIndex = ~0U; for (unsigned i = 0, e = Args.size(); i != e; i++) { - if (CurrentArgIndex == Args[i].OrigArgIndex) { + if (CurrentArgIndex != ISD::InputArg::NoArgIndex && + CurrentArgIndex == Args[i].OrigArgIndex) { Out.back()++; } else { Out.push_back(1); @@ -275,7 +276,7 @@ SmallVectorImpl &ArgLocs, const SmallVectorImpl &Args) { static const MCPhysReg RegList[] = { - MSP430::R15, MSP430::R14, MSP430::R13, MSP430::R12 + MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15 }; static const unsigned NbRegs = array_lengthof(RegList); @@ -288,7 +289,7 @@ ParseFunctionArgs(Args, ArgsParts); unsigned RegsLeft = NbRegs; - bool UseStack = false; + bool UsedStack = false; unsigned ValNo = 0; for (unsigned i = 0, e = ArgsParts.size(); i != e; i++) { @@ -316,20 +317,23 @@ unsigned Parts = ArgsParts[i]; - if (!UseStack && Parts <= RegsLeft) { - unsigned FirstVal = ValNo; + if (!UsedStack && Parts == 2 && RegsLeft == 1) { + // Special case for 32-bit register split, see EABI section 3.3.3 + unsigned Reg = State.AllocateReg(RegList); + State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo)); + RegsLeft--; + + UsedStack = true; + CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, State); + } + else if (Parts <= RegsLeft) { for (unsigned j = 0; j < Parts; j++) { unsigned Reg = State.AllocateReg(RegList); State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo)); RegsLeft--; } - - // Reverse the order of the pieces to agree with the "big endian" format - // required in the calling convention ABI. - SmallVectorImpl::iterator B = ArgLocs.begin() + FirstVal; - std::reverse(B, B + Parts); } else { - UseStack = true; + UsedStack = true; for (unsigned j = 0; j < Parts; j++) CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, State); } @@ -351,10 +355,6 @@ SmallVectorImpl &RVLocs, const SmallVectorImpl &Args) { AnalyzeRetResult(State, Args); - - // Reverse splitted return values to get the "big endian" format required - // to agree with the calling convention ABI. - std::reverse(RVLocs.begin(), RVLocs.end()); } SDValue MSP430TargetLowering::LowerFormalArguments( @@ -495,10 +495,34 @@ InVals.push_back(InVal); } } - + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + if (Ins[i].Flags.isSRet()) { + unsigned Reg = FuncInfo->getSRetReturnReg(); + if (!Reg) { + Reg = MF.getRegInfo().createVirtualRegister( + getRegClassFor(MVT::i16)); + FuncInfo->setSRetReturnReg(Reg); + } + SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[i]); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain); + } + } + return Chain; } +bool +MSP430TargetLowering::CanLowerReturn(CallingConv::ID CallConv, + MachineFunction &MF, + bool IsVarArg, + const SmallVectorImpl &Outs, + LLVMContext &Context) const { + SmallVector RVLocs; + CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); + return CCInfo.CheckReturn(Outs, RetCC_MSP430); +} + SDValue MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, @@ -506,6 +530,8 @@ const SmallVectorImpl &OutVals, const SDLoc &dl, SelectionDAG &DAG) const { + MachineFunction &MF = DAG.getMachineFunction(); + // CCValAssign - represent the assignment of the return value to a location SmallVector RVLocs; @@ -537,6 +563,22 @@ RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } + if (MF.getFunction()->hasStructRetAttr()) { + MSP430MachineFunctionInfo *FuncInfo = MF.getInfo(); + unsigned Reg = FuncInfo->getSRetReturnReg(); + + if (!Reg) { + llvm_unreachable("sret virtual register not created in entry block"); + } + SDValue Val = + DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy(DAG.getDataLayout())); + unsigned R12 = MSP430::R12; + + Chain = DAG.getCopyToReg(Chain, dl, R12, Val, Flag); + Flag = Chain.getValue(1); + RetOps.push_back(DAG.getRegister(R12, getPointerTy(DAG.getDataLayout()))); + } + unsigned Opc = (CallConv == CallingConv::MSP430_INTR ? MSP430ISD::RETI_FLAG : MSP430ISD::RET_FLAG); Index: lib/Target/MSP430/MSP430MachineFunctionInfo.h =================================================================== --- lib/Target/MSP430/MSP430MachineFunctionInfo.h +++ lib/Target/MSP430/MSP430MachineFunctionInfo.h @@ -32,15 +32,23 @@ /// VarArgsFrameIndex - FrameIndex for start of varargs area. int VarArgsFrameIndex; + + /// SRetReturnReg - Some subtargets require that sret lowering includes + /// returning the value of the returned struct in a register. This field + /// holds the virtual register into which the sret argument is passed. + unsigned SRetReturnReg; public: MSP430MachineFunctionInfo() : CalleeSavedFrameSize(0) {} explicit MSP430MachineFunctionInfo(MachineFunction &MF) - : CalleeSavedFrameSize(0), ReturnAddrIndex(0) {} + : CalleeSavedFrameSize(0), ReturnAddrIndex(0), SRetReturnReg(0) {} unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; } void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; } + + unsigned getSRetReturnReg() const { return SRetReturnReg; } + void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } int getRAIndex() const { return ReturnAddrIndex; } void setRAIndex(int Index) { ReturnAddrIndex = Index; } Index: test/CodeGen/MSP430/AddrMode-bis-rx.ll =================================================================== --- test/CodeGen/MSP430/AddrMode-bis-rx.ll +++ test/CodeGen/MSP430/AddrMode-bis-rx.ll @@ -8,7 +8,7 @@ ret i16 %2 } ; CHECK-LABEL: am1: -; CHECK: bis.w 0(r14), r15 +; CHECK: bis.w 0(r13), r12 @foo = external global i16 @@ -18,7 +18,7 @@ ret i16 %2 } ; CHECK-LABEL: am2: -; CHECK: bis.w &foo, r15 +; CHECK: bis.w &foo, r12 @bar = internal constant [2 x i8] [ i8 32, i8 64 ] @@ -29,7 +29,7 @@ ret i8 %3 } ; CHECK-LABEL: am3: -; CHECK: bis.b bar(r14), r15 +; CHECK: bis.b bar(r13), r12 define i16 @am4(i16 %x) nounwind { %1 = load volatile i16, i16* inttoptr(i16 32 to i16*) @@ -37,7 +37,7 @@ ret i16 %2 } ; CHECK-LABEL: am4: -; CHECK: bis.w &32, r15 +; CHECK: bis.w &32, r12 define i16 @am5(i16 %x, i16* %a) nounwind { %1 = getelementptr i16, i16* %a, i16 2 @@ -46,7 +46,7 @@ ret i16 %3 } ; CHECK-LABEL: am5: -; CHECK: bis.w 4(r14), r15 +; CHECK: bis.w 4(r13), r12 %S = type { i16, i16 } @baz = common global %S zeroinitializer, align 1 @@ -57,7 +57,7 @@ ret i16 %2 } ; CHECK-LABEL: am6: -; CHECK: bis.w &baz+2, r15 +; CHECK: bis.w &baz+2, r12 %T = type { i16, [2 x i8] } @duh = internal constant %T { i16 16, [2 x i8][i8 32, i8 64 ] } @@ -70,5 +70,5 @@ ret i8 %4 } ; CHECK-LABEL: am7: -; CHECK: bis.b duh+2(r14), r15 +; CHECK: bis.b duh+2(r13), r12 Index: test/CodeGen/MSP430/AddrMode-bis-xr.ll =================================================================== --- test/CodeGen/MSP430/AddrMode-bis-xr.ll +++ test/CodeGen/MSP430/AddrMode-bis-xr.ll @@ -9,7 +9,7 @@ ret void } ; CHECK-LABEL: am1: -; CHECK: bis.w r14, 0(r15) +; CHECK: bis.w r13, 0(r12) @foo = external global i16 @@ -20,7 +20,7 @@ ret void } ; CHECK-LABEL: am2: -; CHECK: bis.w r15, &foo +; CHECK: bis.w r12, &foo @bar = external global [2 x i8] @@ -32,7 +32,7 @@ ret void } ; CHECK-LABEL: am3: -; CHECK: bis.b r14, bar(r15) +; CHECK: bis.b r13, bar(r12) define void @am4(i16 %x) nounwind { %1 = load volatile i16, i16* inttoptr(i16 32 to i16*) @@ -41,7 +41,7 @@ ret void } ; CHECK-LABEL: am4: -; CHECK: bis.w r15, &32 +; CHECK: bis.w r12, &32 define void @am5(i16* %a, i16 %x) readonly { %1 = getelementptr inbounds i16, i16* %a, i16 2 @@ -51,7 +51,7 @@ ret void } ; CHECK-LABEL: am5: -; CHECK: bis.w r14, 4(r15) +; CHECK: bis.w r13, 4(r12) %S = type { i16, i16 } @baz = common global %S zeroinitializer @@ -63,7 +63,7 @@ ret void } ; CHECK-LABEL: am6: -; CHECK: bis.w r15, &baz+2 +; CHECK: bis.w r12, &baz+2 %T = type { i16, [2 x i8] } @duh = external global %T @@ -77,5 +77,5 @@ ret void } ; CHECK-LABEL: am7: -; CHECK: bis.b r14, duh+2(r15) +; CHECK: bis.b r13, duh+2(r12) Index: test/CodeGen/MSP430/AddrMode-mov-rx.ll =================================================================== --- test/CodeGen/MSP430/AddrMode-mov-rx.ll +++ test/CodeGen/MSP430/AddrMode-mov-rx.ll @@ -7,7 +7,7 @@ ret i16 %1 } ; CHECK-LABEL: am1: -; CHECK: mov.w 0(r15), r15 +; CHECK: mov.w 0(r12), r12 @foo = external global i16 @@ -16,7 +16,7 @@ ret i16 %1 } ; CHECK-LABEL: am2: -; CHECK: mov.w &foo, r15 +; CHECK: mov.w &foo, r12 @bar = internal constant [2 x i8] [ i8 32, i8 64 ] @@ -26,14 +26,14 @@ ret i8 %2 } ; CHECK-LABEL: am3: -; CHECK: mov.b bar(r15), r15 +; CHECK: mov.b bar(r12), r12 define i16 @am4() nounwind { %1 = load volatile i16, i16* inttoptr(i16 32 to i16*) ret i16 %1 } ; CHECK-LABEL: am4: -; CHECK: mov.w &32, r15 +; CHECK: mov.w &32, r12 define i16 @am5(i16* %a) nounwind { %1 = getelementptr i16, i16* %a, i16 2 @@ -41,7 +41,7 @@ ret i16 %2 } ; CHECK-LABEL: am5: -; CHECK: mov.w 4(r15), r15 +; CHECK: mov.w 4(r12), r12 %S = type { i16, i16 } @baz = common global %S zeroinitializer, align 1 @@ -51,7 +51,7 @@ ret i16 %1 } ; CHECK-LABEL: am6: -; CHECK: mov.w &baz+2, r15 +; CHECK: mov.w &baz+2, r12 %T = type { i16, [2 x i8] } @duh = internal constant %T { i16 16, [2 x i8][i8 32, i8 64 ] } @@ -63,5 +63,5 @@ ret i8 %3 } ; CHECK-LABEL: am7: -; CHECK: mov.b duh+2(r15), r15 +; CHECK: mov.b duh+2(r12), r12 Index: test/CodeGen/MSP430/AddrMode-mov-xr.ll =================================================================== --- test/CodeGen/MSP430/AddrMode-mov-xr.ll +++ test/CodeGen/MSP430/AddrMode-mov-xr.ll @@ -7,7 +7,7 @@ ret void } ; CHECK-LABEL: am1: -; CHECK: mov.w r14, 0(r15) +; CHECK: mov.w r13, 0(r12) @foo = external global i16 @@ -16,7 +16,7 @@ ret void } ; CHECK-LABEL: am2: -; CHECK: mov.w r15, &foo +; CHECK: mov.w r12, &foo @bar = external global [2 x i8] @@ -26,14 +26,14 @@ ret void } ; CHECK-LABEL: am3: -; CHECK: mov.b r14, bar(r15) +; CHECK: mov.b r13, bar(r12) define void @am4(i16 %a) nounwind { store volatile i16 %a, i16* inttoptr(i16 32 to i16*) ret void } ; CHECK-LABEL: am4: -; CHECK: mov.w r15, &32 +; CHECK: mov.w r12, &32 define void @am5(i16* nocapture %p, i16 %a) nounwind readonly { %1 = getelementptr inbounds i16, i16* %p, i16 2 @@ -41,7 +41,7 @@ ret void } ; CHECK-LABEL: am5: -; CHECK: mov.w r14, 4(r15) +; CHECK: mov.w r13, 4(r12) %S = type { i16, i16 } @baz = common global %S zeroinitializer, align 1 @@ -51,7 +51,7 @@ ret void } ; CHECK-LABEL: am6: -; CHECK: mov.w r15, &baz+2 +; CHECK: mov.w r12, &baz+2 %T = type { i16, [2 x i8] } @duh = external global %T @@ -63,5 +63,5 @@ ret void } ; CHECK-LABEL: am7: -; CHECK: mov.b r14, duh+2(r15) +; CHECK: mov.b r13, duh+2(r12) Index: test/CodeGen/MSP430/Inst16mr.ll =================================================================== --- test/CodeGen/MSP430/Inst16mr.ll +++ test/CodeGen/MSP430/Inst16mr.ll @@ -5,14 +5,14 @@ define void @mov(i16 %a) nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.w r15, &foo +; CHECK: mov.w r12, &foo store i16 %a, i16* @foo ret void } define void @add(i16 %a) nounwind { ; CHECK-LABEL: add: -; CHECK: add.w r15, &foo +; CHECK: add.w r12, &foo %1 = load i16, i16* @foo %2 = add i16 %a, %1 store i16 %2, i16* @foo @@ -21,7 +21,7 @@ define void @and(i16 %a) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w r15, &foo +; CHECK: and.w r12, &foo %1 = load i16, i16* @foo %2 = and i16 %a, %1 store i16 %2, i16* @foo @@ -30,7 +30,7 @@ define void @bis(i16 %a) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w r15, &foo +; CHECK: bis.w r12, &foo %1 = load i16, i16* @foo %2 = or i16 %a, %1 store i16 %2, i16* @foo @@ -39,7 +39,7 @@ define void @bic(i16 zeroext %m) nounwind { ; CHECK-LABEL: bic: -; CHECK: bic.w r15, &foo +; CHECK: bic.w r12, &foo %1 = xor i16 %m, -1 %2 = load i16, i16* @foo %3 = and i16 %2, %1 @@ -49,7 +49,7 @@ define void @xor(i16 %a) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w r15, &foo +; CHECK: xor.w r12, &foo %1 = load i16, i16* @foo %2 = xor i16 %a, %1 store i16 %2, i16* @foo Index: test/CodeGen/MSP430/Inst16ri.ll =================================================================== --- test/CodeGen/MSP430/Inst16ri.ll +++ test/CodeGen/MSP430/Inst16ri.ll @@ -4,34 +4,34 @@ define i16 @mov() nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.w #1, r15 +; CHECK: mov.w #1, r12 ret i16 1 } define i16 @add(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: add: -; CHECK: add.w #1, r15 +; CHECK: add.w #1, r12 %1 = add i16 %a, 1 ret i16 %1 } define i16 @and(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w #1, r15 +; CHECK: and.w #1, r12 %1 = and i16 %a, 1 ret i16 %1 } define i16 @bis(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w #1, r15 +; CHECK: bis.w #1, r12 %1 = or i16 %a, 1 ret i16 %1 } define i16 @xor(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w #1, r15 +; CHECK: xor.w #1, r12 %1 = xor i16 %a, 1 ret i16 %1 } Index: test/CodeGen/MSP430/Inst16rm.ll =================================================================== --- test/CodeGen/MSP430/Inst16rm.ll +++ test/CodeGen/MSP430/Inst16rm.ll @@ -5,7 +5,7 @@ define i16 @add(i16 %a) nounwind { ; CHECK-LABEL: add: -; CHECK: add.w &foo, r15 +; CHECK: add.w &foo, r12 %1 = load i16, i16* @foo %2 = add i16 %a, %1 ret i16 %2 @@ -13,7 +13,7 @@ define i16 @and(i16 %a) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w &foo, r15 +; CHECK: and.w &foo, r12 %1 = load i16, i16* @foo %2 = and i16 %a, %1 ret i16 %2 @@ -21,7 +21,7 @@ define i16 @bis(i16 %a) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w &foo, r15 +; CHECK: bis.w &foo, r12 %1 = load i16, i16* @foo %2 = or i16 %a, %1 ret i16 %2 @@ -29,7 +29,7 @@ define i16 @bic(i16 %a) nounwind { ; CHECK-LABEL: bic: -; CHECK: bic.w &foo, r15 +; CHECK: bic.w &foo, r12 %1 = load i16, i16* @foo %2 = xor i16 %1, -1 %3 = and i16 %a, %2 @@ -38,7 +38,7 @@ define i16 @xor(i16 %a) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w &foo, r15 +; CHECK: xor.w &foo, r12 %1 = load i16, i16* @foo %2 = xor i16 %a, %1 ret i16 %2 Index: test/CodeGen/MSP430/Inst16rr.ll =================================================================== --- test/CodeGen/MSP430/Inst16rr.ll +++ test/CodeGen/MSP430/Inst16rr.ll @@ -4,34 +4,34 @@ define i16 @mov(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.w r14, r15 +; CHECK: mov.w r13, r12 ret i16 %b } define i16 @add(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: add: -; CHECK: add.w r14, r15 +; CHECK: add.w r13, r12 %1 = add i16 %a, %b ret i16 %1 } define i16 @and(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w r14, r15 +; CHECK: and.w r13, r12 %1 = and i16 %a, %b ret i16 %1 } define i16 @bis(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w r14, r15 +; CHECK: bis.w r13, r12 %1 = or i16 %a, %b ret i16 %1 } define i16 @bic(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: bic: -; CHECK: bic.w r14, r15 +; CHECK: bic.w r13, r12 %1 = xor i16 %b, -1 %2 = and i16 %a, %1 ret i16 %2 @@ -39,7 +39,7 @@ define i16 @xor(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w r14, r15 +; CHECK: xor.w r13, r12 %1 = xor i16 %a, %b ret i16 %1 } Index: test/CodeGen/MSP430/Inst8mr.ll =================================================================== --- test/CodeGen/MSP430/Inst8mr.ll +++ test/CodeGen/MSP430/Inst8mr.ll @@ -5,14 +5,14 @@ define void @mov(i8 %a) nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.b r15, &foo +; CHECK: mov.b r12, &foo store i8 %a, i8* @foo ret void } define void @and(i8 %a) nounwind { ; CHECK-LABEL: and: -; CHECK: and.b r15, &foo +; CHECK: and.b r12, &foo %1 = load i8, i8* @foo %2 = and i8 %a, %1 store i8 %2, i8* @foo @@ -21,7 +21,7 @@ define void @add(i8 %a) nounwind { ; CHECK-LABEL: add: -; CHECK: add.b r15, &foo +; CHECK: add.b r12, &foo %1 = load i8, i8* @foo %2 = add i8 %a, %1 store i8 %2, i8* @foo @@ -30,7 +30,7 @@ define void @bis(i8 %a) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.b r15, &foo +; CHECK: bis.b r12, &foo %1 = load i8, i8* @foo %2 = or i8 %a, %1 store i8 %2, i8* @foo @@ -39,7 +39,7 @@ define void @bic(i8 zeroext %m) nounwind { ; CHECK-LABEL: bic: -; CHECK: bic.b r15, &foo +; CHECK: bic.b r12, &foo %1 = xor i8 %m, -1 %2 = load i8, i8* @foo %3 = and i8 %2, %1 @@ -49,7 +49,7 @@ define void @xor(i8 %a) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.b r15, &foo +; CHECK: xor.b r12, &foo %1 = load i8, i8* @foo %2 = xor i8 %a, %1 store i8 %2, i8* @foo Index: test/CodeGen/MSP430/Inst8ri.ll =================================================================== --- test/CodeGen/MSP430/Inst8ri.ll +++ test/CodeGen/MSP430/Inst8ri.ll @@ -4,34 +4,34 @@ define i8 @mov() nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.b #1, r15 +; CHECK: mov.b #1, r12 ret i8 1 } define i8 @add(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: add: -; CHECK: add.b #1, r15 +; CHECK: add.b #1, r12 %1 = add i8 %a, 1 ret i8 %1 } define i8 @and(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: and: -; CHECK: and.b #1, r15 +; CHECK: and.b #1, r12 %1 = and i8 %a, 1 ret i8 %1 } define i8 @bis(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.b #1, r15 +; CHECK: bis.b #1, r12 %1 = or i8 %a, 1 ret i8 %1 } define i8 @xor(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.b #1, r15 +; CHECK: xor.b #1, r12 %1 = xor i8 %a, 1 ret i8 %1 } Index: test/CodeGen/MSP430/Inst8rm.ll =================================================================== --- test/CodeGen/MSP430/Inst8rm.ll +++ test/CodeGen/MSP430/Inst8rm.ll @@ -5,7 +5,7 @@ define i8 @add(i8 %a) nounwind { ; CHECK-LABEL: add: -; CHECK: add.b &foo, r15 +; CHECK: add.b &foo, r12 %1 = load i8, i8* @foo %2 = add i8 %a, %1 ret i8 %2 @@ -13,7 +13,7 @@ define i8 @and(i8 %a) nounwind { ; CHECK-LABEL: and: -; CHECK: and.b &foo, r15 +; CHECK: and.b &foo, r12 %1 = load i8, i8* @foo %2 = and i8 %a, %1 ret i8 %2 @@ -21,7 +21,7 @@ define i8 @bis(i8 %a) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.b &foo, r15 +; CHECK: bis.b &foo, r12 %1 = load i8, i8* @foo %2 = or i8 %a, %1 ret i8 %2 @@ -29,7 +29,7 @@ define i8 @bic(i8 %a) nounwind { ; CHECK-LABEL: bic: -; CHECK: bic.b &foo, r15 +; CHECK: bic.b &foo, r12 %1 = load i8, i8* @foo %2 = xor i8 %1, -1 %3 = and i8 %a, %2 @@ -38,7 +38,7 @@ define i8 @xor(i8 %a) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.b &foo, r15 +; CHECK: xor.b &foo, r12 %1 = load i8, i8* @foo %2 = xor i8 %a, %1 ret i8 %2 Index: test/CodeGen/MSP430/Inst8rr.ll =================================================================== --- test/CodeGen/MSP430/Inst8rr.ll +++ test/CodeGen/MSP430/Inst8rr.ll @@ -4,7 +4,7 @@ define i8 @mov(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.{{[bw]}} r14, r15 +; CHECK: mov.{{[bw]}} r13, r12 ret i8 %b } @@ -17,21 +17,21 @@ define i8 @and(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w r14, r15 +; CHECK: and.w r13, r12 %1 = and i8 %a, %b ret i8 %1 } define i8 @bis(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w r14, r15 +; CHECK: bis.w r13, r12 %1 = or i8 %a, %b ret i8 %1 } define i8 @bic(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: bic: -; CHECK: bic.b r14, r15 +; CHECK: bic.b r13, r12 %1 = xor i8 %b, -1 %2 = and i8 %a, %1 ret i8 %2 @@ -39,7 +39,7 @@ define i8 @xor(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w r14, r15 +; CHECK: xor.w r13, r12 %1 = xor i8 %a, %b ret i8 %1 } Index: test/CodeGen/MSP430/bit.ll =================================================================== --- test/CodeGen/MSP430/bit.ll +++ test/CodeGen/MSP430/bit.ll @@ -12,7 +12,7 @@ ret i8 %t3 } ; CHECK-LABEL: bitbrr: -; CHECK: bit.b r14, r15 +; CHECK: bit.b r13, r12 define i8 @bitbri(i8 %a) nounwind { %t1 = and i8 %a, 15 @@ -21,7 +21,7 @@ ret i8 %t3 } ; CHECK-LABEL: bitbri: -; CHECK: bit.b #15, r15 +; CHECK: bit.b #15, r12 define i8 @bitbir(i8 %a) nounwind { %t1 = and i8 15, %a @@ -30,7 +30,7 @@ ret i8 %t3 } ; CHECK-LABEL: bitbir: -; CHECK: bit.b #15, r15 +; CHECK: bit.b #15, r12 define i8 @bitbmi() nounwind { %t1 = load i8, i8* @foo8 @@ -60,7 +60,7 @@ ret i8 %t4 } ; CHECK-LABEL: bitbrm: -; CHECK: bit.b &foo8, r15 +; CHECK: bit.b &foo8, r12 define i8 @bitbmr(i8 %a) nounwind { %t1 = load i8, i8* @foo8 @@ -70,7 +70,7 @@ ret i8 %t4 } ; CHECK-LABEL: bitbmr: -; CHECK: bit.b r15, &foo8 +; CHECK: bit.b r12, &foo8 define i8 @bitbmm() nounwind { %t1 = load i8, i8* @foo8 @@ -93,7 +93,7 @@ ret i16 %t3 } ; CHECK-LABEL: bitwrr: -; CHECK: bit.w r14, r15 +; CHECK: bit.w r13, r12 define i16 @bitwri(i16 %a) nounwind { %t1 = and i16 %a, 4080 @@ -102,7 +102,7 @@ ret i16 %t3 } ; CHECK-LABEL: bitwri: -; CHECK: bit.w #4080, r15 +; CHECK: bit.w #4080, r12 define i16 @bitwir(i16 %a) nounwind { %t1 = and i16 4080, %a @@ -111,7 +111,7 @@ ret i16 %t3 } ; CHECK-LABEL: bitwir: -; CHECK: bit.w #4080, r15 +; CHECK: bit.w #4080, r12 define i16 @bitwmi() nounwind { %t1 = load i16, i16* @foo16 @@ -141,7 +141,7 @@ ret i16 %t4 } ; CHECK-LABEL: bitwrm: -; CHECK: bit.w &foo16, r15 +; CHECK: bit.w &foo16, r12 define i16 @bitwmr(i16 %a) nounwind { %t1 = load i16, i16* @foo16 @@ -151,7 +151,7 @@ ret i16 %t4 } ; CHECK-LABEL: bitwmr: -; CHECK: bit.w r15, &foo16 +; CHECK: bit.w r12, &foo16 define i16 @bitwmm() nounwind { %t1 = load i16, i16* @foo16 Index: test/CodeGen/MSP430/byval.ll =================================================================== --- test/CodeGen/MSP430/byval.ll +++ test/CodeGen/MSP430/byval.ll @@ -9,7 +9,7 @@ define i16 @callee(%struct.Foo* byval %f) nounwind { entry: ; CHECK-LABEL: callee: -; CHECK: mov.w 2(r1), r15 +; CHECK: mov.w 2(r1), r12 %0 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 0 %1 = load i16, i16* %0, align 2 ret i16 %1 Index: test/CodeGen/MSP430/cc_args.ll =================================================================== --- test/CodeGen/MSP430/cc_args.ll +++ test/CodeGen/MSP430/cc_args.ll @@ -7,12 +7,12 @@ entry: ; CHECK: test: -; CHECK: mov.w #1, r15 +; CHECK: mov.w #1, r12 ; CHECK: call #f_i16 call void @f_i16(i16 1) -; CHECK: mov.w #772, r14 -; CHECK: mov.w #258, r15 +; CHECK: mov.w #772, r12 +; CHECK: mov.w #258, r13 ; CHECK: call #f_i32 call void @f_i32(i32 16909060) @@ -23,26 +23,34 @@ ; CHECK: call #f_i64 call void @f_i64(i64 72623859790382856) -; CHECK: mov.w #772, r14 -; CHECK: mov.w #258, r15 -; CHECK: mov.w #1800, r12 -; CHECK: mov.w #1286, r13 +; CHECK: mov.w #772, r12 +; CHECK: mov.w #258, r13 +; CHECK: mov.w #1800, r14 +; CHECK: mov.w #1286, r15 ; CHECK: call #f_i32_i32 call void @f_i32_i32(i32 16909060, i32 84281096) -; CHECK: mov.w #1, r15 +; CHECK: mov.w #1, r12 ; CHECK: mov.w #772, r13 ; CHECK: mov.w #258, r14 -; CHECK: mov.w #2, r12 +; CHECK: mov.w #2, r15 ; CHECK: call #f_i16_i32_i16 call void @f_i16_i32_i16(i16 1, i32 16909060, i16 2) -; CHECK: mov.w #2, 8(r1) +; CHECK: mov.w #1286, 0(r1) +; CHECK: mov.w #1, r12 +; CHECK: mov.w #772, r13 +; CHECK: mov.w #258, r14 +; CHECK: mov.w #1800, r15 +; CHECK: call #f_i16_i32_i32 + call void @f_i16_i32_i32(i16 1, i32 16909060, i32 84281096) + ; CHECK: mov.w #258, 6(r1) ; CHECK: mov.w #772, 4(r1) ; CHECK: mov.w #1286, 2(r1) ; CHECK: mov.w #1800, 0(r1) -; CHECK: mov.w #1, r15 +; CHECK: mov.w #1, r12 +; CHECK: mov.w #2, r13 ; CHECK: call #f_i16_i64_i16 call void @f_i16_i64_i16(i16 1, i64 72623859790382856, i16 2) @@ -55,15 +63,15 @@ define void @f_i16(i16 %a) #0 { ; CHECK: f_i16: -; CHECK: mov.w r15, &g_i16 +; CHECK: mov.w r12, &g_i16 store volatile i16 %a, i16* @g_i16, align 2 ret void } define void @f_i32(i32 %a) #0 { ; CHECK: f_i32: -; CHECK: mov.w r15, &g_i32+2 -; CHECK: mov.w r14, &g_i32 +; CHECK: mov.w r13, &g_i32+2 +; CHECK: mov.w r12, &g_i32 store volatile i32 %a, i32* @g_i32, align 2 ret void } @@ -80,37 +88,50 @@ define void @f_i32_i32(i32 %a, i32 %b) #0 { ; CHECK: f_i32_i32: -; CHECK: mov.w r15, &g_i32+2 -; CHECK: mov.w r14, &g_i32 - store volatile i32 %a, i32* @g_i32, align 2 ; CHECK: mov.w r13, &g_i32+2 ; CHECK: mov.w r12, &g_i32 + store volatile i32 %a, i32* @g_i32, align 2 +; CHECK: mov.w r15, &g_i32+2 +; CHECK: mov.w r14, &g_i32 store volatile i32 %b, i32* @g_i32, align 2 ret void } +define void @f_i16_i32_i32(i16 %a, i32 %b, i32 %c) #0 { +; CHECK: f_i16_i32_i32: +; CHECK: mov.w r12, &g_i16 + store volatile i16 %a, i16* @g_i16, align 2 +; CHECK: mov.w r14, &g_i32+2 +; CHECK: mov.w r13, &g_i32 + store volatile i32 %b, i32* @g_i32, align 2 +; CHECK: mov.w r15, &g_i32 +; CHECK: mov.w 4(r4), &g_i32+2 + store volatile i32 %c, i32* @g_i32, align 2 + ret void +} + define void @f_i16_i32_i16(i16 %a, i32 %b, i16 %c) #0 { ; CHECK: f_i16_i32_i16: -; CHECK: mov.w r15, &g_i16 +; CHECK: mov.w r12, &g_i16 store volatile i16 %a, i16* @g_i16, align 2 ; CHECK: mov.w r14, &g_i32+2 ; CHECK: mov.w r13, &g_i32 store volatile i32 %b, i32* @g_i32, align 2 -; CHECK: mov.w r12, &g_i16 +; CHECK: mov.w r15, &g_i16 store volatile i16 %c, i16* @g_i16, align 2 ret void } define void @f_i16_i64_i16(i16 %a, i64 %b, i16 %c) #0 { ; CHECK: f_i16_i64_i16: -; CHECK: mov.w r15, &g_i16 +; CHECK: mov.w r12, &g_i16 store volatile i16 %a, i16* @g_i16, align 2 ;CHECK: mov.w 10(r4), &g_i64+6 ;CHECK: mov.w 8(r4), &g_i64+4 ;CHECK: mov.w 6(r4), &g_i64+2 ;CHECK: mov.w 4(r4), &g_i64 store volatile i64 %b, i64* @g_i64, align 2 -;CHECK: mov.w 12(r4), &g_i16 +;CHECK: mov.w r13, &g_i16 store volatile i16 %c, i16* @g_i16, align 2 ret void } Index: test/CodeGen/MSP430/cc_ret.ll =================================================================== --- test/CodeGen/MSP430/cc_ret.ll +++ test/CodeGen/MSP430/cc_ret.ll @@ -8,13 +8,13 @@ ; CHECK: test: ; CHECK: call #f_i16 -; CHECK: mov.w r15, &g_i16 +; CHECK: mov.w r12, &g_i16 %0 = call i16 @f_i16() store volatile i16 %0, i16* @g_i16 ; CHECK: call #f_i32 -; CHECK: mov.w r15, &g_i32+2 -; CHECK: mov.w r14, &g_i32 +; CHECK: mov.w r13, &g_i32+2 +; CHECK: mov.w r12, &g_i32 %1 = call i32 @f_i32() store volatile i32 %1, i32* @g_i32 @@ -35,15 +35,15 @@ define i16 @f_i16() #0 { ; CHECK: f_i16: -; CHECK: mov.w #1, r15 +; CHECK: mov.w #1, r12 ; CHECK: ret ret i16 1 } define i32 @f_i32() #0 { ; CHECK: f_i32: -; CHECK: mov.w #772, r14 -; CHECK: mov.w #258, r15 +; CHECK: mov.w #772, r12 +; CHECK: mov.w #258, r13 ; CHECK: ret ret i32 16909060 } Index: test/CodeGen/MSP430/indirectbr2.ll =================================================================== --- test/CodeGen/MSP430/indirectbr2.ll +++ test/CodeGen/MSP430/indirectbr2.ll @@ -5,7 +5,7 @@ entry: %tmp1 = getelementptr inbounds [5 x i8*], [5 x i8*]* @C.0.2070, i16 0, i16 %i ; [#uses=1] %gotovar.4.0 = load i8*, i8** %tmp1, align 4 ; [#uses=1] -; CHECK: br .LC.0.2070(r12) +; CHECK: br .LC.0.2070(r13) indirectbr i8* %gotovar.4.0, [label %L5, label %L4, label %L3, label %L2, label %L1] L5: ; preds = %bb2 Index: test/CodeGen/MSP430/jumptable.ll =================================================================== --- test/CodeGen/MSP430/jumptable.ll +++ test/CodeGen/MSP430/jumptable.ll @@ -11,9 +11,9 @@ %i.addr = alloca i16, align 2 store i16 %i, i16* %i.addr, align 2 %0 = load i16, i16* %i.addr, align 2 -; CHECK: mov.w #2, r14 +; CHECK: mov.w #2, r13 ; CHECK: call #__mulhi3hw_noint -; CHECK: br .LJTI0_0(r15) +; CHECK: br .LJTI0_0(r12) switch i16 %0, label %sw.default [ i16 0, label %sw.bb i16 1, label %sw.bb1 Index: test/CodeGen/MSP430/memset.ll =================================================================== --- test/CodeGen/MSP430/memset.ll +++ test/CodeGen/MSP430/memset.ll @@ -9,9 +9,9 @@ entry: ; CHECK-LABEL: test: %0 = load i8*, i8** @buf, align 2 -; CHECK: mov.w &buf, r15 -; CHECK-NEXT: mov.w #5, r14 -; CHECK-NEXT: mov.w #128, r13 +; CHECK: mov.w &buf, r12 +; CHECK-NEXT: mov.w #5, r13 +; CHECK-NEXT: mov.w #128, r14 ; CHECK-NEXT: call #memset call void @llvm.memset.p0i8.i16(i8* %0, i8 5, i16 128, i32 1, i1 false) ret void Index: test/CodeGen/MSP430/setcc.ll =================================================================== --- test/CodeGen/MSP430/setcc.ll +++ test/CodeGen/MSP430/setcc.ll @@ -9,10 +9,10 @@ ret i16 %t3 } ; CHECK-LABEL: sccweqand: -; CHECK: bit.w r14, r15 -; CHECK: mov.w r2, r15 -; CHECK: rra.w r15 -; CHECK: and.w #1, r15 +; CHECK: bit.w r13, r12 +; CHECK: mov.w r2, r12 +; CHECK: rra.w r12 +; CHECK: and.w #1, r12 define i16 @sccwneand(i16 %a, i16 %b) nounwind { %t1 = and i16 %a, %b @@ -21,9 +21,9 @@ ret i16 %t3 } ; CHECK-LABEL: sccwneand: -; CHECK: bit.w r14, r15 -; CHECK: mov.w r2, r15 -; CHECK: and.w #1, r15 +; CHECK: bit.w r13, r12 +; CHECK: mov.w r2, r12 +; CHECK: and.w #1, r12 define i16 @sccwne(i16 %a, i16 %b) nounwind { %t1 = icmp ne i16 %a, %b @@ -31,11 +31,11 @@ ret i16 %t2 } ; CHECK-LABEL:sccwne: -; CHECK: cmp.w r14, r15 -; CHECK: mov.w r2, r12 -; CHECK: rra.w r12 -; CHECK: mov.w #1, r15 -; CHECK: bic.w r12, r15 +; CHECK: cmp.w r13, r12 +; CHECK: mov.w r2, r13 +; CHECK: rra.w r13 +; CHECK: mov.w #1, r12 +; CHECK: bic.w r13, r12 define i16 @sccweq(i16 %a, i16 %b) nounwind { %t1 = icmp eq i16 %a, %b @@ -43,10 +43,10 @@ ret i16 %t2 } ; CHECK-LABEL:sccweq: -; CHECK: cmp.w r14, r15 -; CHECK: mov.w r2, r15 -; CHECK: rra.w r15 -; CHECK: and.w #1, r15 +; CHECK: cmp.w r13, r12 +; CHECK: mov.w r2, r12 +; CHECK: rra.w r12 +; CHECK: and.w #1, r12 define i16 @sccwugt(i16 %a, i16 %b) nounwind { %t1 = icmp ugt i16 %a, %b @@ -54,9 +54,9 @@ ret i16 %t2 } ; CHECK-LABEL:sccwugt: -; CHECK: cmp.w r15, r14 -; CHECK: mov.w #1, r15 -; CHECK: bic.w r2, r15 +; CHECK: cmp.w r12, r13 +; CHECK: mov.w #1, r12 +; CHECK: bic.w r2, r12 define i16 @sccwuge(i16 %a, i16 %b) nounwind { %t1 = icmp uge i16 %a, %b @@ -64,9 +64,9 @@ ret i16 %t2 } ; CHECK-LABEL:sccwuge: -; CHECK: cmp.w r14, r15 -; CHECK: mov.w r2, r15 -; CHECK: and.w #1, r15 +; CHECK: cmp.w r13, r12 +; CHECK: mov.w r2, r12 +; CHECK: and.w #1, r12 define i16 @sccwult(i16 %a, i16 %b) nounwind { %t1 = icmp ult i16 %a, %b @@ -74,9 +74,9 @@ ret i16 %t2 } ; CHECK-LABEL:sccwult: -; CHECK: cmp.w r14, r15 -; CHECK: mov.w #1, r15 -; CHECK: bic.w r2, r15 +; CHECK: cmp.w r13, r12 +; CHECK: mov.w #1, r12 +; CHECK: bic.w r2, r12 define i16 @sccwule(i16 %a, i16 %b) nounwind { %t1 = icmp ule i16 %a, %b @@ -84,9 +84,9 @@ ret i16 %t2 } ; CHECK-LABEL:sccwule: -; CHECK: cmp.w r15, r14 -; CHECK: mov.w r2, r15 -; CHECK: and.w #1, r15 +; CHECK: cmp.w r12, r13 +; CHECK: mov.w r2, r12 +; CHECK: and.w #1, r12 define i16 @sccwsgt(i16 %a, i16 %b) nounwind { %t1 = icmp sgt i16 %a, %b Index: test/CodeGen/MSP430/struct-return.ll =================================================================== --- test/CodeGen/MSP430/struct-return.ll +++ test/CodeGen/MSP430/struct-return.ll @@ -0,0 +1,24 @@ +; RUN: llc < %s | FileCheck %s + +target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16" +target triple = "msp430---elf" + +; Allow simple structures to be returned by value. + +%s = type { i64, i64 } + + +define %s @fred() #0 { +; CHECK-LABEL: fred: +; CHECK: mov.w #2314, 14(r12) +; CHECK: mov.w #2828, 12(r12) +; CHECK: mov.w #3342, 10(r12) +; CHECK: mov.w #3840, 8(r12) +; CHECK: mov.w #258, 6(r12) +; CHECK: mov.w #772, 4(r12) +; CHECK: mov.w #1286, 2(r12) +; CHECK: mov.w #1800, 0(r12) + ret %s {i64 72623859790382856, i64 651345242494996224} +} + +attributes #0 = { nounwind } Index: test/CodeGen/MSP430/vararg.ll =================================================================== --- test/CodeGen/MSP430/vararg.ll +++ test/CodeGen/MSP430/vararg.ll @@ -25,13 +25,13 @@ entry: ; CHECK-LABEL: va_arg: %vl.addr = alloca i8*, align 2 -; CHECK: mov.w r15, 0(r1) +; CHECK: mov.w r12, 0(r1) store i8* %vl, i8** %vl.addr, align 2 -; CHECK: mov.w r15, [[REG:r[0-9]+]] +; CHECK: mov.w r12, [[REG:r[0-9]+]] ; CHECK-NEXT: add.w #2, [[REG]] ; CHECK-NEXT: mov.w [[REG]], 0(r1) %0 = va_arg i8** %vl.addr, i16 -; CHECK-NEXT: mov.w 0(r15), r15 +; CHECK-NEXT: mov.w 0(r12), r12 ret i16 %0 } @@ -40,11 +40,11 @@ ; CHECK-LABEL: va_copy: %vl.addr = alloca i8*, align 2 %vl2 = alloca i8*, align 2 -; CHECK: mov.w r15, 2(r1) +; CHECK: mov.w r12, 2(r1) store i8* %vl, i8** %vl.addr, align 2 %0 = bitcast i8** %vl2 to i8* %1 = bitcast i8** %vl.addr to i8* -; CHECK-NEXT: mov.w r15, 0(r1) +; CHECK-NEXT: mov.w r12, 0(r1) call void @llvm.va_copy(i8* %0, i8* %1) ret void }