]> granicus.if.org Git - llvm/commitdiff
[MSP430] Add SRet support to MSP430 target
authorVadzim Dambrouski <pftbest@gmail.com>
Thu, 2 Mar 2017 20:25:10 +0000 (20:25 +0000)
committerVadzim Dambrouski <pftbest@gmail.com>
Thu, 2 Mar 2017 20:25:10 +0000 (20:25 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296807 91177308-0d34-0410-b5e6-96231b3b80d8

26 files changed:
lib/Target/MSP430/MSP430CallingConv.td
lib/Target/MSP430/MSP430ISelLowering.cpp
lib/Target/MSP430/MSP430ISelLowering.h
lib/Target/MSP430/MSP430MachineFunctionInfo.h
test/CodeGen/MSP430/AddrMode-bis-rx.ll
test/CodeGen/MSP430/AddrMode-bis-xr.ll
test/CodeGen/MSP430/AddrMode-mov-rx.ll
test/CodeGen/MSP430/AddrMode-mov-xr.ll
test/CodeGen/MSP430/Inst16mr.ll
test/CodeGen/MSP430/Inst16ri.ll
test/CodeGen/MSP430/Inst16rm.ll
test/CodeGen/MSP430/Inst16rr.ll
test/CodeGen/MSP430/Inst8mr.ll
test/CodeGen/MSP430/Inst8ri.ll
test/CodeGen/MSP430/Inst8rm.ll
test/CodeGen/MSP430/Inst8rr.ll
test/CodeGen/MSP430/bit.ll
test/CodeGen/MSP430/byval.ll
test/CodeGen/MSP430/cc_args.ll
test/CodeGen/MSP430/cc_ret.ll
test/CodeGen/MSP430/indirectbr2.ll
test/CodeGen/MSP430/jumptable.ll
test/CodeGen/MSP430/memset.ll
test/CodeGen/MSP430/setcc.ll
test/CodeGen/MSP430/struct-return.ll [new file with mode: 0644]
test/CodeGen/MSP430/vararg.ll

index b38f5781c84a1e01ae2f6e65be798479b1a6c281..0434f8abfbf46679cd004bb39cf293ab8165efc8 100644 (file)
 // 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 4305f60b15e4ab0128c1d82fa25ee7c0d7939228..40b1dd3cc2ebfc94396812a67ca270d06a07bc1e 100644 (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);
 
index 8864807e999e88d17797fd713bd41db6d6c00c7e..3a729623c99a89f4ff6fafefad4fbd74852d0f96 100644 (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,
index 2d937318c7e5f2654646a59a41f76210bd926eda..fcaa8a1d6c728ee72076574c27bfae7843720094 100644 (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; }
 
index 941ee2dc2ce924e42076d60b360587640f1a6b12..f4cb30f2d014c38a358524fec3337d79fefeadfb 100644 (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
 
index 4b8f367a8880ed4044c76ccc19ab097e0be01cf5..1e150f382062ccc32ed550377941ba0142e85737 100644 (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)
 
index cdee931bf96de9e4d4b6b869d0e31c82c3111fc1..808aca0ea10b549ce04cec2bac8cfeedbf1308fa 100644 (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
 
index ccb42886e9b424c0c7b7cc75bbdb31981af4dc78..c336289a60d730350318b51019237914eec313ad 100644 (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)
 
index 50dc4c0b673105cf16b11fcd5e3f0f79b2ebd0d9..847c093f4088c2dbcffa890f4920a310d2214a3c 100644 (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
index f89f686ab567c951871bd82de3ab156887f5ea2a..3a4bb6a93d995a8551e3706d97a2a89dba86675b 100644 (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
 }
index 4f6998ee68dfe9d73b8cf09efd8c38d0de25a8be..44b8f39d8fa625b808f5989d8a18effca5788494 100644 (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
index d74bfae9b938b9d00818bf2da07d83966eb9eeb3..75440ca2b403a78b5114a3c6c5412d705899f7eb 100644 (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
 }
index f03c7e1a659b005c4f8c61ac86300888954c6de4..7fbdff257fe7c5eaa26978a286947a3e4ca05eef 100644 (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
index ec0dff9c563e2e27a58226eeaa928cda5b08a73f..0e50f17f2a550b1e312ea8ed9c4f5fd7ba3d1f2e 100644 (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
 }
index e1a9703955787191c85ef7a1a473a5b7127d97ee..826a3c65ec949e31e0b33e7992ff68980631d7f1 100644 (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
index 76e8d19112820cdfaeb2395ca4bb2317fd9d5ed4..f37bc32a28fe1063ecf4b7179414414c459fac32 100644 (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
 }
index 45964f97f1bf86a6a8110ea3cc6d54384a3358a1..172822fbb5fef3fc7ffd40e8853ee0a8cd6bb3b8 100644 (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
index 410a6b047b6e38a4b46ebb99d87fee481dbca2cd..401896b43c20cc96a564711ec59b324281db3d9e 100644 (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
index 39e99e2637449be888ad0f960b20145502d8a83b..70ac901f7e4e291fec47b67c13edf3c92ac6fe7c 100644 (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
 }
index c2a9ae664509d4896200dd94fa2abada824194e0..937db6dbf3bf0a26f534e4281c24ced91eb972f3 100644 (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
 }
index 55598b97d9120f7b94b360afa90a52dea2c30cc3..b0b4f1cbfd24f36099e5f66c37a7273bc9cc4146 100644 (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
index 4ba930b04e39c09be9c559512f0d4d064b62f0e3..5ccdbb701db1fc82de723e195c9372fd08506bd8 100644 (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
index 76cfb29586d784dab7842005e76c0123a10e9d31..a24bfafc20051e783c26c2a88d9fb022f97d2ffd 100644 (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
index d5a8057ddd6c49e981851fcf65994a4dcf33d5a8..6e2ec8ea3ea1dade9979e54b40fb3c78869b47d2 100644 (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
diff --git a/test/CodeGen/MSP430/struct-return.ll b/test/CodeGen/MSP430/struct-return.ll
new file mode 100644 (file)
index 0000000..c28bf06
--- /dev/null
@@ -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 }
index 9e511fce956f11dc9f25401f3b5e97873c20a282..6c8bceff5de94b100882689c345cd8112ead8bdd 100644 (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
 }