1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[MSP430] Add SRet support to MSP430 target

This patch adds support for struct return values to the MSP430
target backend. It also reverses the order of argument and return
registers in the calling convention to bring it into closer
alignment with the published EABI from TI.

Patch by Andrew Wygle (awygle).

Differential Revision: https://reviews.llvm.org/D29069

llvm-svn: 296807
This commit is contained in:
Vadzim Dambrouski 2017-03-02 20:25:10 +00:00
parent b4c9dc6b06
commit bdc6e663e7
26 changed files with 277 additions and 172 deletions

View File

@ -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]>>
]>;
//===----------------------------------------------------------------------===//

View File

@ -245,13 +245,20 @@ MSP430TargetLowering::getRegForInlineAsmConstraint(
template<typename ArgT>
static void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args,
SmallVectorImpl<unsigned> &Out) {
unsigned CurrentArgIndex = ~0U;
for (unsigned i = 0, e = Args.size(); i != e; i++) {
if (CurrentArgIndex == Args[i].OrigArgIndex) {
Out.back()++;
unsigned CurrentArgIndex;
if (Args.empty())
return;
CurrentArgIndex = Args[0].OrigArgIndex;
Out.push_back(0);
for (auto &Arg : Args) {
if (CurrentArgIndex == Arg.OrigArgIndex) {
Out.back() += 1;
} else {
Out.push_back(1);
CurrentArgIndex++;
CurrentArgIndex = Arg.OrigArgIndex;
}
}
}
@ -275,7 +282,7 @@ static void AnalyzeArguments(CCState &State,
SmallVectorImpl<CCValAssign> &ArgLocs,
const SmallVectorImpl<ArgT> &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 +295,7 @@ static void AnalyzeArguments(CCState &State,
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 +323,22 @@ static void AnalyzeArguments(CCState &State,
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 -= 1;
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<CCValAssign>::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 +360,6 @@ static void AnalyzeReturnValues(CCState &State,
SmallVectorImpl<CCValAssign> &RVLocs,
const SmallVectorImpl<ArgT> &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(
@ -496,9 +501,33 @@ SDValue MSP430TargetLowering::LowerCCCArguments(
}
}
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<ISD::OutputArg> &Outs,
LLVMContext &Context) const {
SmallVector<CCValAssign, 16> 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 +535,8 @@ MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
const SmallVectorImpl<SDValue> &OutVals,
const SDLoc &dl, SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
// CCValAssign - represent the assignment of the return value to a location
SmallVector<CCValAssign, 16> RVLocs;
@ -537,6 +568,22 @@ MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
}
if (MF.getFunction()->hasStructRetAttr()) {
MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();
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);

View File

@ -158,6 +158,12 @@ namespace llvm {
LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const override;
bool CanLowerReturn(CallingConv::ID CallConv,
MachineFunction &MF,
bool IsVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
LLVMContext &Context) const override;
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals,

View File

@ -33,15 +33,23 @@ class MSP430MachineFunctionInfo : public MachineFunctionInfo {
/// 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; }

View File

@ -8,7 +8,7 @@ define i16 @am1(i16 %x, i16* %a) nounwind {
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 @@ define i16 @am2(i16 %x) nounwind {
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 @@ define i8 @am3(i8 %x, i16 %n) nounwind {
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 @@ define i16 @am4(i16 %x) nounwind {
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 @@ define i16 @am5(i16 %x, i16* %a) nounwind {
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 @@ define i16 @am6(i16 %x) nounwind {
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 @@ define i8 @am7(i8 %x, i16 %n) nounwind {
ret i8 %4
}
; CHECK-LABEL: am7:
; CHECK: bis.b duh+2(r14), r15
; CHECK: bis.b duh+2(r13), r12

View File

@ -9,7 +9,7 @@ define void @am1(i16* %a, i16 %x) nounwind {
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 @@ define void @am2(i16 %x) nounwind {
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 @@ define void @am3(i16 %i, i8 %x) nounwind {
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 @@ define void @am4(i16 %x) nounwind {
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 @@ define void @am5(i16* %a, i16 %x) readonly {
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 @@ define void @am6(i16 %x) nounwind {
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 @@ define void @am7(i16 %n, i8 %x) nounwind {
ret void
}
; CHECK-LABEL: am7:
; CHECK: bis.b r14, duh+2(r15)
; CHECK: bis.b r13, duh+2(r12)

View File

@ -7,7 +7,7 @@ define i16 @am1(i16* %a) nounwind {
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 @@ define i16 @am2() nounwind {
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 @@ define i8 @am3(i16 %n) nounwind {
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 @@ define i16 @am5(i16* %a) nounwind {
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 @@ define i16 @am6() nounwind {
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 @@ define i8 @am7(i16 %n) nounwind {
ret i8 %3
}
; CHECK-LABEL: am7:
; CHECK: mov.b duh+2(r15), r15
; CHECK: mov.b duh+2(r12), r12

View File

@ -7,7 +7,7 @@ define void @am1(i16* %a, i16 %b) nounwind {
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 @@ define void @am2(i16 %a) nounwind {
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 @@ define void @am3(i16 %i, i8 %a) nounwind {
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 @@ define void @am5(i16* nocapture %p, i16 %a) nounwind readonly {
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 @@ define void @am6(i16 %a) nounwind {
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 @@ define void @am7(i16 %n, i8 %a) nounwind {
ret void
}
; CHECK-LABEL: am7:
; CHECK: mov.b r14, duh+2(r15)
; CHECK: mov.b r13, duh+2(r12)

View File

@ -5,14 +5,14 @@ target triple = "msp430-generic-generic"
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 @add(i16 %a) nounwind {
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 @and(i16 %a) nounwind {
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 @bis(i16 %a) nounwind {
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 @bic(i16 zeroext %m) nounwind {
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

View File

@ -4,34 +4,34 @@ target triple = "msp430-generic-generic"
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
}

View File

@ -5,7 +5,7 @@ target triple = "msp430-generic-generic"
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 @add(i16 %a) nounwind {
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 @and(i16 %a) nounwind {
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 @bis(i16 %a) nounwind {
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 @bic(i16 %a) nounwind {
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

View File

@ -4,34 +4,34 @@ target triple = "msp430-generic-generic"
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 @bic(i16 %a, i16 %b) nounwind {
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
}

View File

@ -5,14 +5,14 @@ target triple = "msp430-generic-generic"
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 @and(i8 %a) nounwind {
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 @add(i8 %a) nounwind {
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 @bis(i8 %a) nounwind {
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 @bic(i8 zeroext %m) nounwind {
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

View File

@ -4,34 +4,34 @@ target triple = "msp430-generic-generic"
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
}

View File

@ -5,7 +5,7 @@ target triple = "msp430-generic-generic"
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 @add(i8 %a) nounwind {
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 @and(i8 %a) nounwind {
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 @bis(i8 %a) nounwind {
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 @bic(i8 %a) nounwind {
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

View File

@ -4,7 +4,7 @@ target triple = "msp430-generic-generic"
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 @add(i8 %a, i8 %b) nounwind {
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 @bic(i8 %a, i8 %b) nounwind {
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
}

View File

@ -12,7 +12,7 @@ define i8 @bitbrr(i8 %a, i8 %b) nounwind {
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 @@ define i8 @bitbri(i8 %a) nounwind {
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 @@ define i8 @bitbir(i8 %a) nounwind {
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 @@ define i8 @bitbrm(i8 %a) nounwind {
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 @@ define i8 @bitbmr(i8 %a) nounwind {
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 @@ define i16 @bitwrr(i16 %a, i16 %b) nounwind {
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 @@ define i16 @bitwri(i16 %a) nounwind {
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 @@ define i16 @bitwir(i16 %a) nounwind {
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 @@ define i16 @bitwrm(i16 %a) nounwind {
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 @@ define i16 @bitwmr(i16 %a) nounwind {
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

View File

@ -9,7 +9,7 @@ target triple = "msp430---elf"
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

View File

@ -7,12 +7,12 @@ define void @test() #0 {
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 @@ entry:
; 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 @@ entry:
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_i64(i64 %a) #0 {
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
}

View File

@ -8,13 +8,13 @@ entry:
; 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 @@ entry:
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
}

View File

@ -5,7 +5,7 @@ define internal i16 @foo(i16 %i) nounwind {
entry:
%tmp1 = getelementptr inbounds [5 x i8*], [5 x i8*]* @C.0.2070, i16 0, i16 %i ; <i8**> [#uses=1]
%gotovar.4.0 = load i8*, i8** %tmp1, align 4 ; <i8*> [#uses=1]
; CHECK: br .LC.0.2070(r15)
; CHECK: br .LC.0.2070(r12)
indirectbr i8* %gotovar.4.0, [label %L5, label %L4, label %L3, label %L2, label %L1]
L5: ; preds = %bb2

View File

@ -11,9 +11,9 @@ entry:
%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

View File

@ -9,9 +9,9 @@ define void @test() nounwind {
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

View File

@ -9,10 +9,10 @@ define i16 @sccweqand(i16 %a, i16 %b) nounwind {
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 @@ define i16 @sccwneand(i16 %a, i16 %b) nounwind {
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 @@ define i16 @sccwne(i16 %a, i16 %b) nounwind {
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 @@ define i16 @sccweq(i16 %a, i16 %b) nounwind {
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 @@ define i16 @sccwugt(i16 %a, i16 %b) nounwind {
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 @@ define i16 @sccwuge(i16 %a, i16 %b) nounwind {
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 @@ define i16 @sccwult(i16 %a, i16 %b) nounwind {
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 @@ define i16 @sccwule(i16 %a, i16 %b) nounwind {
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

View File

@ -0,0 +1,23 @@
; 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 }

View File

@ -25,13 +25,13 @@ define i16 @va_arg(i8* %vl) nounwind {
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 @@ entry:
; 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
}