[llvm] 9a9c6b8 - [MSP430] Add CFI instructions for MSP430.

Anton Korobeynikov via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 5 15:53:10 PDT 2023


Author: Ilia Kuklin
Date: 2023-04-05T15:53:01-07:00
New Revision: 9a9c6b8e7587d0459393024e793e299c96bde0d2

URL: https://github.com/llvm/llvm-project/commit/9a9c6b8e7587d0459393024e793e299c96bde0d2
DIFF: https://github.com/llvm/llvm-project/commit/9a9c6b8e7587d0459393024e793e299c96bde0d2.diff

LOG: [MSP430] Add CFI instructions for MSP430.

Implement emission of DWARF CFI instructions for MSP430. This includes descriptions of stack frame layout and location of callee-saved registers that could be used for backtracing.

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

Added: 
    llvm/test/DebugInfo/MSP430/fp-vla-callee-saved.ll

Modified: 
    llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp
    llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.h
    llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
    llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h
    llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
    llvm/lib/Target/MSP430/MSP430FrameLowering.cpp
    llvm/lib/Target/MSP430/MSP430FrameLowering.h
    llvm/lib/Target/MSP430/MSP430InstrInfo.h
    llvm/lib/Target/MSP430/MSP430RegisterInfo.h
    llvm/lib/Target/MSP430/MSP430RegisterInfo.td
    llvm/lib/Target/MSP430/MSP430Subtarget.cpp
    llvm/lib/Target/MSP430/MSP430Subtarget.h
    llvm/test/CodeGen/MSP430/asm-clobbers.ll
    llvm/test/CodeGen/MSP430/callee-saved.ll
    llvm/test/CodeGen/MSP430/interrupt.ll
    llvm/test/CodeGen/MSP430/jumptable.ll
    llvm/test/DebugInfo/MSP430/dwarf-basics-v5.ll
    llvm/test/DebugInfo/MSP430/dwarf-basics.ll
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_function_name.ll.expected
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.generated.expected
    llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.nogenerated.expected

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp
index 420893f65d5b9..3726c600f4a7b 100644
--- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp
+++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp
@@ -26,6 +26,10 @@ using namespace llvm;
 #define PRINT_ALIAS_INSTR
 #include "MSP430GenAsmWriter.inc"
 
+void MSP430InstPrinter::printRegName(raw_ostream &O, MCRegister Reg) const {
+  O << getRegisterName(Reg);
+}
+
 void MSP430InstPrinter::printInst(const MCInst *MI, uint64_t Address,
                                   StringRef Annot, const MCSubtargetInfo &STI,
                                   raw_ostream &O) {

diff  --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.h b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.h
index 60849d69e04e5..40605b92bcb01 100644
--- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.h
+++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.h
@@ -22,6 +22,8 @@ namespace llvm {
                       const MCRegisterInfo &MRI)
       : MCInstPrinter(MAI, MII, MRI) {}
 
+    void printRegName(raw_ostream &O, MCRegister Reg) const override;
+
     void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
                    const MCSubtargetInfo &STI, raw_ostream &O) override;
 

diff  --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
index de07b47096d34..d04bb406b9bb8 100644
--- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
+++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
@@ -15,9 +15,9 @@ using namespace llvm;
 
 void MSP430MCAsmInfo::anchor() { }
 
-MSP430MCAsmInfo::MSP430MCAsmInfo(const Triple &TT,
-                                 const MCTargetOptions &Options) {
-  CodePointerSize = CalleeSaveStackSlotSize = 2;
+MSP430MCAsmInfo::MSP430MCAsmInfo(const Triple &TT) {
+  CodePointerSize = 2;
+  CalleeSaveStackSlotSize = 2;
 
   CommentString = ";";
   SeparatorString = "{";
@@ -26,4 +26,6 @@ MSP430MCAsmInfo::MSP430MCAsmInfo(const Triple &TT,
   UsesELFSectionDirectiveForBSS = true;
 
   SupportsDebugInformation = true;
+
+  ExceptionsType = ExceptionHandling::DwarfCFI;
 }

diff  --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h
index c4ff4a9eefb1a..93979df037e64 100644
--- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h
+++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h
@@ -22,7 +22,7 @@ class MSP430MCAsmInfo : public MCAsmInfoELF {
   void anchor() override;
 
 public:
-  explicit MSP430MCAsmInfo(const Triple &TT, const MCTargetOptions &Options);
+  explicit MSP430MCAsmInfo(const Triple &TT);
 };
 
 } // namespace llvm

diff  --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
index 13a880de68b56..df182a5459ead 100644
--- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
+++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
@@ -14,6 +14,7 @@
 #include "MSP430InstPrinter.h"
 #include "MSP430MCAsmInfo.h"
 #include "TargetInfo/MSP430TargetInfo.h"
+#include "llvm/MC/MCDwarf.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
@@ -43,6 +44,27 @@ static MCRegisterInfo *createMSP430MCRegisterInfo(const Triple &TT) {
   return X;
 }
 
+static MCAsmInfo *createMSP430MCAsmInfo(const MCRegisterInfo &MRI,
+                                        const Triple &TT,
+                                        const MCTargetOptions &Options) {
+  MCAsmInfo *MAI = new MSP430MCAsmInfo(TT);
+
+  // Initialize initial frame state.
+  int stackGrowth = -2;
+
+  // Initial state of the frame pointer is sp+ptr_size.
+  MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(
+      nullptr, MRI.getDwarfRegNum(MSP430::SP, true), -stackGrowth);
+  MAI->addInitialFrameState(Inst);
+
+  // Add return address to move list
+  MCCFIInstruction Inst2 = MCCFIInstruction::createOffset(
+      nullptr, MRI.getDwarfRegNum(MSP430::PC, true), stackGrowth);
+  MAI->addInitialFrameState(Inst2);
+
+  return MAI;
+}
+
 static MCSubtargetInfo *
 createMSP430MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
   return createMSP430MCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
@@ -61,7 +83,7 @@ static MCInstPrinter *createMSP430MCInstPrinter(const Triple &T,
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430TargetMC() {
   Target &T = getTheMSP430Target();
 
-  RegisterMCAsmInfo<MSP430MCAsmInfo> X(T);
+  TargetRegistry::RegisterMCAsmInfo(T, createMSP430MCAsmInfo);
   TargetRegistry::RegisterMCInstrInfo(T, createMSP430MCInstrInfo);
   TargetRegistry::RegisterMCRegInfo(T, createMSP430MCRegisterInfo);
   TargetRegistry::RegisterMCSubtargetInfo(T, createMSP430MCSubtargetInfo);

diff  --git a/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp b/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp
index 6a8dc3502496f..176387d71fcb6 100644
--- a/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp
+++ b/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp
@@ -25,6 +25,11 @@
 
 using namespace llvm;
 
+MSP430FrameLowering::MSP430FrameLowering(const MSP430Subtarget &STI)
+    : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
+                          Align(2)),
+      STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
+
 bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
 
@@ -37,6 +42,45 @@ bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const
   return !MF.getFrameInfo().hasVarSizedObjects();
 }
 
+void MSP430FrameLowering::BuildCFI(MachineBasicBlock &MBB,
+                                   MachineBasicBlock::iterator MBBI,
+                                   const DebugLoc &DL,
+                                   const MCCFIInstruction &CFIInst,
+                                   MachineInstr::MIFlag Flag) const {
+  MachineFunction &MF = *MBB.getParent();
+  unsigned CFIIndex = MF.addFrameInst(CFIInst);
+  BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
+      .addCFIIndex(CFIIndex)
+      .setMIFlag(Flag);
+}
+
+void MSP430FrameLowering::emitCalleeSavedFrameMoves(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    const DebugLoc &DL, bool IsPrologue) const {
+  MachineFunction &MF = *MBB.getParent();
+  MachineFrameInfo &MFI = MF.getFrameInfo();
+  MachineModuleInfo &MMI = MF.getMMI();
+  const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
+
+  // Add callee saved registers to move list.
+  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
+
+  // Calculate offsets.
+  for (const CalleeSavedInfo &I : CSI) {
+    int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
+    Register Reg = I.getReg();
+    unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
+
+    if (IsPrologue) {
+      BuildCFI(MBB, MBBI, DL,
+               MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
+    } else {
+      BuildCFI(MBB, MBBI, DL,
+               MCCFIInstruction::createRestore(nullptr, DwarfReg));
+    }
+  }
+}
+
 void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
                                        MachineBasicBlock &MBB) const {
   assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
@@ -50,6 +94,7 @@ void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
 
   // Get the number of bytes to allocate from the FrameInfo.
   uint64_t StackSize = MFI.getStackSize();
+  int stackGrowth = -2;
 
   uint64_t NumBytes = 0;
   if (hasFP(MF)) {
@@ -64,23 +109,56 @@ void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
 
     // Save FP into the appropriate stack slot...
     BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
-      .addReg(MSP430::R4, RegState::Kill);
+        .addReg(MSP430::R4, RegState::Kill)
+        .setMIFlag(MachineInstr::FrameSetup);
+
+    // Mark the place where FP was saved.
+    // Define the current CFA rule to use the provided offset.
+    BuildCFI(MBB, MBBI, DL,
+             MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
+             MachineInstr::FrameSetup);
+
+    // Change the rule for the FramePtr to be an "offset" rule.
+    unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
+    BuildCFI(
+        MBB, MBBI, DL,
+        MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
+        MachineInstr::FrameSetup);
 
     // Update FP with the new base value...
     BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
-      .addReg(MSP430::SP);
+        .addReg(MSP430::SP)
+        .setMIFlag(MachineInstr::FrameSetup);
+
+    // Mark effective beginning of when frame pointer becomes valid.
+    // Define the current CFA to use the FP register.
+    BuildCFI(MBB, MBBI, DL,
+             MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
+             MachineInstr::FrameSetup);
 
     // Mark the FramePtr as live-in in every block except the entry.
     for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
       MBBJ.addLiveIn(MSP430::R4);
-
   } else
     NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
 
   // Skip the callee-saved push instructions.
-  while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
+  int StackOffset = 2 * stackGrowth;
+  while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
+         (MBBI->getOpcode() == MSP430::PUSH16r)) {
     ++MBBI;
 
+    if (!hasFP(MF)) {
+      // Mark callee-saved push instruction.
+      // Define the current CFA rule to use the provided offset.
+      assert(StackSize && "Expected stack frame");
+      BuildCFI(MBB, MBBI, DL,
+               MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackOffset),
+               MachineInstr::FrameSetup);
+      StackOffset += stackGrowth;
+    }
+  }
+
   if (MBBI != MBB.end())
     DL = MBBI->getDebugLoc();
 
@@ -94,12 +172,23 @@ void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
 
     if (NumBytes) {
       MachineInstr *MI =
-        BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
-        .addReg(MSP430::SP).addImm(NumBytes);
+          BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
+              .addReg(MSP430::SP)
+              .addImm(NumBytes)
+              .setMIFlag(MachineInstr::FrameSetup);
       // The SRW implicit def is dead.
       MI->getOperand(3).setIsDead();
     }
+    if (!hasFP(MF)) {
+      // Adjust the previous CFA value if CFA was not redefined by FP
+      BuildCFI(
+          MBB, MBBI, DL,
+          MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
+          MachineInstr::FrameSetup);
+    }
   }
+
+  emitCalleeSavedFrameMoves(MBB, MBBI, DL, true);
 }
 
 void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
@@ -125,24 +214,43 @@ void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
   unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
   uint64_t NumBytes = 0;
 
+  MachineBasicBlock::iterator AfterPop = MBBI;
   if (hasFP(MF)) {
     // Calculate required stack adjustment
     uint64_t FrameSize = StackSize - 2;
     NumBytes = FrameSize - CSSize;
 
     // pop FP.
-    BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4);
+    BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)
+        .setMIFlag(MachineInstr::FrameDestroy);
+    unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);
+    BuildCFI(MBB, MBBI, DL,
+             MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
+             MachineInstr::FrameDestroy);
+    --MBBI;
+    if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
+      unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
+      BuildCFI(MBB, AfterPop, DL,
+               MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
+               MachineInstr::FrameDestroy);
+      --MBBI;
+      --AfterPop;
+    }
   } else
     NumBytes = StackSize - CSSize;
 
   // Skip the callee-saved pop instructions.
+  MachineBasicBlock::iterator FirstCSPop = MBBI;
   while (MBBI != MBB.begin()) {
     MachineBasicBlock::iterator PI = std::prev(MBBI);
     unsigned Opc = PI->getOpcode();
-    if (Opc != MSP430::POP16r && !PI->isTerminator())
+    if ((Opc != MSP430::POP16r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
+        !PI->isTerminator())
       break;
+    FirstCSPop = PI;
     --MBBI;
   }
+  MBBI = FirstCSPop;
 
   DL = MBBI->getDebugLoc();
 
@@ -152,13 +260,15 @@ void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
   //  mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
 
   if (MFI.hasVarSizedObjects()) {
-    BuildMI(MBB, MBBI, DL,
-            TII.get(MSP430::MOV16rr), MSP430::SP).addReg(MSP430::R4);
+    BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)
+        .addReg(MSP430::R4)
+        .setMIFlag(MachineInstr::FrameDestroy);
     if (CSSize) {
       MachineInstr *MI =
-        BuildMI(MBB, MBBI, DL,
-                TII.get(MSP430::SUB16ri), MSP430::SP)
-        .addReg(MSP430::SP).addImm(CSSize);
+          BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
+              .addReg(MSP430::SP)
+              .addImm(CSSize)
+              .setMIFlag(MachineInstr::FrameDestroy);
       // The SRW implicit def is dead.
       MI->getOperand(3).setIsDead();
     }
@@ -166,12 +276,40 @@ void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
     // adjust stack pointer back: SP += numbytes
     if (NumBytes) {
       MachineInstr *MI =
-        BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
-        .addReg(MSP430::SP).addImm(NumBytes);
+          BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
+              .addReg(MSP430::SP)
+              .addImm(NumBytes)
+              .setMIFlag(MachineInstr::FrameDestroy);
       // The SRW implicit def is dead.
       MI->getOperand(3).setIsDead();
+
+      if (!hasFP(MF)) {
+        // Adjust CFA value if it was defined by SP
+        BuildCFI(MBB, MBBI, DL,
+                 MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
+                 MachineInstr::FrameDestroy);
+      }
+    }
+  }
+
+  if (!hasFP(MF)) {
+    MBBI = FirstCSPop;
+    int64_t Offset = -CSSize - 2;
+    // Mark callee-saved pop instruction.
+    // Define the current CFA rule to use the provided offset.
+    while (MBBI != MBB.end()) {
+      MachineBasicBlock::iterator PI = MBBI;
+      unsigned Opc = PI->getOpcode();
+      ++MBBI;
+      if (Opc == MSP430::POP16r) {
+        Offset += 2;
+        BuildCFI(MBB, MBBI, DL,
+                 MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset),
+                 MachineInstr::FrameDestroy);
+      }
     }
   }
+  emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
 }
 
 // FIXME: Can we eleminate these in favour of generic code?
@@ -189,12 +327,13 @@ bool MSP430FrameLowering::spillCalleeSavedRegisters(
   MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
   MFI->setCalleeSavedFrameSize(CSI.size() * 2);
 
-  for (const CalleeSavedInfo &I : llvm::reverse(CSI)) {
+  for (const CalleeSavedInfo &I : CSI) {
     Register Reg = I.getReg();
     // Add the callee-saved register as live-in. It's killed at the spill.
     MBB.addLiveIn(Reg);
     BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
-      .addReg(Reg, RegState::Kill);
+        .addReg(Reg, RegState::Kill)
+        .setMIFlag(MachineInstr::FrameSetup);
   }
   return true;
 }
@@ -211,8 +350,9 @@ bool MSP430FrameLowering::restoreCalleeSavedRegisters(
   MachineFunction &MF = *MBB.getParent();
   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
 
-  for (const CalleeSavedInfo &I : CSI)
-    BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg());
+  for (const CalleeSavedInfo &I : llvm::reverse(CSI))
+    BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())
+        .setMIFlag(MachineInstr::FrameDestroy);
 
   return true;
 }
@@ -269,6 +409,11 @@ MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr(
           BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
               .addReg(MSP430::SP)
               .addImm(CalleeAmt);
+      if (!hasFP(MF)) {
+        DebugLoc DL = I->getDebugLoc();
+        BuildCFI(MBB, I, DL,
+                 MCCFIInstruction::createAdjustCfaOffset(nullptr, CalleeAmt));
+      }
       // The SRW implicit def is dead.
       New->getOperand(3).setIsDead();
 

diff  --git a/llvm/lib/Target/MSP430/MSP430FrameLowering.h b/llvm/lib/Target/MSP430/MSP430FrameLowering.h
index f6995edf4b0ad..5227d3e731edb 100644
--- a/llvm/lib/Target/MSP430/MSP430FrameLowering.h
+++ b/llvm/lib/Target/MSP430/MSP430FrameLowering.h
@@ -17,13 +17,20 @@
 #include "llvm/CodeGen/TargetFrameLowering.h"
 
 namespace llvm {
+
+class MSP430Subtarget;
+class MSP430InstrInfo;
+class MSP430RegisterInfo;
+
 class MSP430FrameLowering : public TargetFrameLowering {
 protected:
 
 public:
-  explicit MSP430FrameLowering()
-      : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
-                            Align(2)) {}
+  MSP430FrameLowering(const MSP430Subtarget &STI);
+
+  const MSP430Subtarget &STI;
+  const MSP430InstrInfo &TII;
+  const MSP430RegisterInfo *TRI;
 
   /// emitProlog/emitEpilog - These methods insert prolog and epilog code into
   /// the function.
@@ -48,6 +55,15 @@ class MSP430FrameLowering : public TargetFrameLowering {
   bool hasReservedCallFrame(const MachineFunction &MF) const override;
   void processFunctionBeforeFrameFinalized(MachineFunction &MF,
                                      RegScavenger *RS = nullptr) const override;
+
+  /// Wraps up getting a CFI index and building a MachineInstr for it.
+  void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+                const DebugLoc &DL, const MCCFIInstruction &CFIInst,
+                MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const;
+
+  void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB,
+                                 MachineBasicBlock::iterator MBBI,
+                                 const DebugLoc &DL, bool IsPrologue) const;
 };
 
 } // End llvm namespace

diff  --git a/llvm/lib/Target/MSP430/MSP430InstrInfo.h b/llvm/lib/Target/MSP430/MSP430InstrInfo.h
index 94cf9f8e1f164..b8d015a21cd15 100644
--- a/llvm/lib/Target/MSP430/MSP430InstrInfo.h
+++ b/llvm/lib/Target/MSP430/MSP430InstrInfo.h
@@ -33,7 +33,7 @@ class MSP430InstrInfo : public MSP430GenInstrInfo {
   /// such, whenever a client has an instance of instruction info, it should
   /// always be able to get register info as well (through this method).
   ///
-  const TargetRegisterInfo &getRegisterInfo() const { return RI; }
+  const MSP430RegisterInfo &getRegisterInfo() const { return RI; }
 
   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
                    const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,

diff  --git a/llvm/lib/Target/MSP430/MSP430RegisterInfo.h b/llvm/lib/Target/MSP430/MSP430RegisterInfo.h
index 78b02cf8ecc0d..51e07f4e8e9ea 100644
--- a/llvm/lib/Target/MSP430/MSP430RegisterInfo.h
+++ b/llvm/lib/Target/MSP430/MSP430RegisterInfo.h
@@ -20,7 +20,7 @@
 
 namespace llvm {
 
-struct MSP430RegisterInfo : public MSP430GenRegisterInfo {
+class MSP430RegisterInfo : public MSP430GenRegisterInfo {
 public:
   MSP430RegisterInfo();
 

diff  --git a/llvm/lib/Target/MSP430/MSP430RegisterInfo.td b/llvm/lib/Target/MSP430/MSP430RegisterInfo.td
index 61cc72d494b5b..153df285aebd5 100644
--- a/llvm/lib/Target/MSP430/MSP430RegisterInfo.td
+++ b/llvm/lib/Target/MSP430/MSP430RegisterInfo.td
@@ -32,42 +32,42 @@ class MSP430RegWithSubregs<bits<4> num, string n, list<Register> subregs,
 //  Registers
 //===----------------------------------------------------------------------===//
 
-def PCB  : MSP430Reg<0,  "r0", ["pc"]>;
-def SPB  : MSP430Reg<1,  "r1", ["sp"]>;
-def SRB  : MSP430Reg<2,  "r2", ["sr"]>;
-def CGB  : MSP430Reg<3,  "r3", ["cg"]>;
-def R4B  : MSP430Reg<4,  "r4", ["fp"]>;
-def R5B  : MSP430Reg<5,  "r5">;
-def R6B  : MSP430Reg<6,  "r6">;
-def R7B  : MSP430Reg<7,  "r7">;
-def R8B  : MSP430Reg<8,  "r8">;
-def R9B  : MSP430Reg<9,  "r9">;
-def R10B : MSP430Reg<10, "r10">;
-def R11B : MSP430Reg<11, "r11">;
-def R12B : MSP430Reg<12, "r12">;
-def R13B : MSP430Reg<13, "r13">;
-def R14B : MSP430Reg<14, "r14">;
-def R15B : MSP430Reg<15, "r15">;
+def PCB  : MSP430Reg<0,  "r0", ["pc"]>, DwarfRegNum<[16]>;
+def SPB  : MSP430Reg<1,  "r1", ["sp"]>, DwarfRegNum<[17]>;
+def SRB  : MSP430Reg<2,  "r2", ["sr"]>, DwarfRegNum<[18]>;
+def CGB  : MSP430Reg<3,  "r3", ["cg"]>, DwarfRegNum<[19]>;
+def R4B  : MSP430Reg<4,  "r4", ["fp"]>, DwarfRegNum<[20]>;
+def R5B  : MSP430Reg<5,  "r5">,  DwarfRegNum<[21]>;
+def R6B  : MSP430Reg<6,  "r6">,  DwarfRegNum<[22]>;
+def R7B  : MSP430Reg<7,  "r7">,  DwarfRegNum<[23]>;
+def R8B  : MSP430Reg<8,  "r8">,  DwarfRegNum<[24]>;
+def R9B  : MSP430Reg<9,  "r9">,  DwarfRegNum<[25]>;
+def R10B : MSP430Reg<10, "r10">, DwarfRegNum<[26]>;
+def R11B : MSP430Reg<11, "r11">, DwarfRegNum<[27]>;
+def R12B : MSP430Reg<12, "r12">, DwarfRegNum<[28]>;
+def R13B : MSP430Reg<13, "r13">, DwarfRegNum<[29]>;
+def R14B : MSP430Reg<14, "r14">, DwarfRegNum<[30]>;
+def R15B : MSP430Reg<15, "r15">, DwarfRegNum<[31]>;
 
 def subreg_8bit : SubRegIndex<8> { let Namespace = "MSP430"; }
 
 let SubRegIndices = [subreg_8bit] in {
-def PC  : MSP430RegWithSubregs<0,  "r0",  [PCB], ["pc"]>;
-def SP  : MSP430RegWithSubregs<1,  "r1",  [SPB], ["sp"]>;
-def SR  : MSP430RegWithSubregs<2,  "r2",  [SRB], ["sr"]>;
-def CG  : MSP430RegWithSubregs<3,  "r3",  [CGB], ["cg"]>;
-def R4  : MSP430RegWithSubregs<4,  "r4",  [R4B], ["fp"]>;
-def R5  : MSP430RegWithSubregs<5,  "r5",  [R5B]>;
-def R6  : MSP430RegWithSubregs<6,  "r6",  [R6B]>;
-def R7  : MSP430RegWithSubregs<7,  "r7",  [R7B]>;
-def R8  : MSP430RegWithSubregs<8,  "r8",  [R8B]>;
-def R9  : MSP430RegWithSubregs<9,  "r9",  [R9B]>;
-def R10 : MSP430RegWithSubregs<10, "r10", [R10B]>;
-def R11 : MSP430RegWithSubregs<11, "r11", [R11B]>;
-def R12 : MSP430RegWithSubregs<12, "r12", [R12B]>;
-def R13 : MSP430RegWithSubregs<13, "r13", [R13B]>;
-def R14 : MSP430RegWithSubregs<14, "r14", [R14B]>;
-def R15 : MSP430RegWithSubregs<15, "r15", [R15B]>;
+def PC  : MSP430RegWithSubregs<0,  "r0",  [PCB], ["pc"]>, DwarfRegNum<[0]>;
+def SP  : MSP430RegWithSubregs<1,  "r1",  [SPB], ["sp"]>, DwarfRegNum<[1]>;
+def SR  : MSP430RegWithSubregs<2,  "r2",  [SRB], ["sr"]>, DwarfRegNum<[2]>;
+def CG  : MSP430RegWithSubregs<3,  "r3",  [CGB], ["cg"]>, DwarfRegNum<[3]>;
+def R4  : MSP430RegWithSubregs<4,  "r4",  [R4B], ["fp"]>, DwarfRegNum<[4]>;
+def R5  : MSP430RegWithSubregs<5,  "r5",  [R5B]>,  DwarfRegNum<[5]>;
+def R6  : MSP430RegWithSubregs<6,  "r6",  [R6B]>,  DwarfRegNum<[6]>;
+def R7  : MSP430RegWithSubregs<7,  "r7",  [R7B]>,  DwarfRegNum<[7]>;
+def R8  : MSP430RegWithSubregs<8,  "r8",  [R8B]>,  DwarfRegNum<[8]>;
+def R9  : MSP430RegWithSubregs<9,  "r9",  [R9B]>,  DwarfRegNum<[9]>;
+def R10 : MSP430RegWithSubregs<10, "r10", [R10B]>, DwarfRegNum<[10]>;
+def R11 : MSP430RegWithSubregs<11, "r11", [R11B]>, DwarfRegNum<[11]>;
+def R12 : MSP430RegWithSubregs<12, "r12", [R12B]>, DwarfRegNum<[12]>;
+def R13 : MSP430RegWithSubregs<13, "r13", [R13B]>, DwarfRegNum<[13]>;
+def R14 : MSP430RegWithSubregs<14, "r14", [R14B]>, DwarfRegNum<[14]>;
+def R15 : MSP430RegWithSubregs<15, "r15", [R15B]>, DwarfRegNum<[15]>;
 }
 
 def GR8 : RegisterClass<"MSP430", [i8], 8,

diff  --git a/llvm/lib/Target/MSP430/MSP430Subtarget.cpp b/llvm/lib/Target/MSP430/MSP430Subtarget.cpp
index 0604d47597e25..2d208cdf3f05c 100644
--- a/llvm/lib/Target/MSP430/MSP430Subtarget.cpp
+++ b/llvm/lib/Target/MSP430/MSP430Subtarget.cpp
@@ -58,4 +58,5 @@ MSP430Subtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS) {
 MSP430Subtarget::MSP430Subtarget(const Triple &TT, const std::string &CPU,
                                  const std::string &FS, const TargetMachine &TM)
     : MSP430GenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
-      InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this) {}
+      InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
+      FrameLowering(*this) {}

diff  --git a/llvm/lib/Target/MSP430/MSP430Subtarget.h b/llvm/lib/Target/MSP430/MSP430Subtarget.h
index 079af2c75ec13..d99545a2224d4 100644
--- a/llvm/lib/Target/MSP430/MSP430Subtarget.h
+++ b/llvm/lib/Target/MSP430/MSP430Subtarget.h
@@ -38,10 +38,10 @@ class MSP430Subtarget : public MSP430GenSubtargetInfo {
   virtual void anchor();
   bool ExtendedInsts = false;
   HWMultEnum HWMultMode = NoHWMult;
-  MSP430FrameLowering FrameLowering;
   MSP430InstrInfo InstrInfo;
   MSP430TargetLowering TLInfo;
   SelectionDAGTargetInfo TSInfo;
+  MSP430FrameLowering FrameLowering;
 
 public:
   /// This constructor initializes the data members to match that
@@ -64,9 +64,10 @@ class MSP430Subtarget : public MSP430GenSubtargetInfo {
     return &FrameLowering;
   }
   const MSP430InstrInfo *getInstrInfo() const override { return &InstrInfo; }
-  const TargetRegisterInfo *getRegisterInfo() const override {
-    return &InstrInfo.getRegisterInfo();
+  const MSP430RegisterInfo *getRegisterInfo() const override {
+    return &getInstrInfo()->getRegisterInfo();
   }
+
   const MSP430TargetLowering *getTargetLowering() const override {
     return &TLInfo;
   }

diff  --git a/llvm/test/CodeGen/MSP430/asm-clobbers.ll b/llvm/test/CodeGen/MSP430/asm-clobbers.ll
index bd6f88cc2436c..3e411192fd6a8 100644
--- a/llvm/test/CodeGen/MSP430/asm-clobbers.ll
+++ b/llvm/test/CodeGen/MSP430/asm-clobbers.ll
@@ -16,26 +16,50 @@ entry:
 define void @test_1() {
 entry:
 ; CHECK-LABEL: test_1:
-; CHECK: push r8
-; CHECK: push r6
 ; CHECK: push r4
+; CHECK: .cfi_def_cfa_offset 4
+; CHECK: push r6
+; CHECK: .cfi_def_cfa_offset 6
+; CHECK: push r8
+; CHECK: .cfi_def_cfa_offset 8
+; CHECK: .cfi_offset r4, -4
+; CHECK: .cfi_offset r6, -6
+; CHECK: .cfi_offset r8, -8
   call void asm sideeffect "", "~{r4},~{r6},~{r8}"()
-; CHECK: pop r4
-; CHECK: pop r6
 ; CHECK: pop r8
+; CHECK: .cfi_def_cfa_offset 6
+; CHECK: pop r6
+; CHECK: .cfi_def_cfa_offset 4
+; CHECK: pop r4
+; CHECK: .cfi_def_cfa_offset 2
+; CHECK: .cfi_restore r4
+; CHECK: .cfi_restore r6
+; CHECK: .cfi_restore r8
   ret void
 }
 
 define void @test_2() {
 entry:
 ; CHECK-LABEL: test_2:
-; CHECK: push r9
-; CHECK: push r7
-; CHECK: push r5
+; CHECK: push  r5
+; CHECK: .cfi_def_cfa_offset 4
+; CHECK: push  r7
+; CHECK: .cfi_def_cfa_offset 6
+; CHECK: push  r9
+; CHECK: .cfi_def_cfa_offset 8
+; CHECK: .cfi_offset r5, -4
+; CHECK: .cfi_offset r7, -6
+; CHECK: .cfi_offset r9, -8
   call void asm sideeffect "", "~{r5},~{r7},~{r9}"()
-; CHECK: pop r5
-; CHECK: pop r7
 ; CHECK: pop r9
+; CHECK: .cfi_def_cfa_offset 6
+; CHECK: pop r7
+; CHECK: .cfi_def_cfa_offset 4
+; CHECK: pop r5
+; CHECK: .cfi_def_cfa_offset 2
+; CHECK: .cfi_restore r5
+; CHECK: .cfi_restore r7
+; CHECK: .cfi_restore r9
   ret void
 }
 
@@ -50,7 +74,11 @@ define void @test_r10() {
 entry:
 ; CHECK-LABEL: test_r10:
 ; CHECK: push r10
+; CHECK: .cfi_def_cfa_offset 4
+; CHECK: .cfi_offset r10, -4
   call void asm sideeffect "", "~{r10}"()
 ; CHECK: pop r10
+; CHECK: .cfi_def_cfa_offset 2
+; CHECK: .cfi_restore r10
   ret void
 }

diff  --git a/llvm/test/CodeGen/MSP430/callee-saved.ll b/llvm/test/CodeGen/MSP430/callee-saved.ll
index 76db4dcdfe886..4f323298dd42e 100644
--- a/llvm/test/CodeGen/MSP430/callee-saved.ll
+++ b/llvm/test/CodeGen/MSP430/callee-saved.ll
@@ -9,18 +9,34 @@ target triple = "msp430-generic-generic"
 
 define void @foo() {
 ; CHECK-LABEL: foo:
-; CHECK-NOT: push	r15
-; CHECK-NOT: push	r14
-; CHECK-NOT: push	r13
-; CHECK-NOT: push	r12
 ; CHECK-NOT: push	r11
-; CHECK: push	r10
-; CHECK: push	r9
-; CHECK: push	r8
-; CHECK: push	r7
-; CHECK: push	r6
-; CHECK: push	r5
-; CHECK: push	r4
+; CHECK-NOT: push	r12
+; CHECK-NOT: push	r13
+; CHECK-NOT: push	r14
+; CHECK-NOT: push	r15
+; CHECK: push  r4
+; CHECK: .cfi_def_cfa_offset 4
+; CHECK: push  r5
+; CHECK: .cfi_def_cfa_offset 6
+; CHECK: push  r6
+; CHECK: .cfi_def_cfa_offset 8
+; CHECK: push  r7
+; CHECK: .cfi_def_cfa_offset 10
+; CHECK: push  r8
+; CHECK: .cfi_def_cfa_offset 12
+; CHECK: push  r9
+; CHECK: .cfi_def_cfa_offset 14
+; CHECK: push  r10
+; CHECK: .cfi_def_cfa_offset 16
+
+; CHECK: .cfi_offset r4, -4
+; CHECK: .cfi_offset r5, -6
+; CHECK: .cfi_offset r6, -8
+; CHECK: .cfi_offset r7, -10
+; CHECK: .cfi_offset r8, -12
+; CHECK: .cfi_offset r9, -14
+; CHECK: .cfi_offset r10, -16
+
   %t1 = load volatile float, float* @g
   %t2 = load volatile float, float* @g
   %t3 = load volatile float, float* @g

diff  --git a/llvm/test/CodeGen/MSP430/interrupt.ll b/llvm/test/CodeGen/MSP430/interrupt.ll
index dac3e14321d70..47e72dd1cefc8 100644
--- a/llvm/test/CodeGen/MSP430/interrupt.ll
+++ b/llvm/test/CodeGen/MSP430/interrupt.ll
@@ -21,18 +21,18 @@ target triple = "msp430-generic-generic"
 define msp430_intrcc void @ISR() #0 {
 entry:
 ; CHECK-LABEL: ISR:
-; CHECK: push	r15
-; CHECK: push	r14
-; CHECK: push	r13
-; CHECK: push	r12
-; CHECK: push	r11
-; CHECK: push	r10
-; CHECK: push	r9
-; CHECK: push	r8
-; CHECK: push	r7
-; CHECK: push	r6
-; CHECK: push	r5
-; CHECK: push	r4
+; CHECK: push r4
+; CHECK: push r5
+; CHECK: push r6
+; CHECK: push r7
+; CHECK: push r8
+; CHECK: push r9
+; CHECK: push r10
+; CHECK: push r11
+; CHECK: push r12
+; CHECK: push r13
+; CHECK: push r14
+; CHECK: push r15
   %t1 = load volatile float, float* @g
   %t2 = load volatile float, float* @g
   %t3 = load volatile float, float* @g

diff  --git a/llvm/test/CodeGen/MSP430/jumptable.ll b/llvm/test/CodeGen/MSP430/jumptable.ll
index 6121f7ebed67c..3e50123957726 100644
--- a/llvm/test/CodeGen/MSP430/jumptable.ll
+++ b/llvm/test/CodeGen/MSP430/jumptable.ll
@@ -8,7 +8,7 @@ define i16 @test(i16 %i) #0 {
 entry:
 ; CHECK-LABEL: test:
 ; CHECK:      sub   #4, r1
-; CHECK-NEXT: mov   r12, 0(r1)
+; CHECK:      mov   r12, 0(r1)
 ; CHECK-NEXT: cmp   #4, r12
 ; CHECK-NEXT: jhs     .LBB0_3
   %retval = alloca i16, align 2

diff  --git a/llvm/test/DebugInfo/MSP430/dwarf-basics-v5.ll b/llvm/test/DebugInfo/MSP430/dwarf-basics-v5.ll
index 98922f1b7d088..2e61566c7993b 100644
--- a/llvm/test/DebugInfo/MSP430/dwarf-basics-v5.ll
+++ b/llvm/test/DebugInfo/MSP430/dwarf-basics-v5.ll
@@ -38,7 +38,7 @@
 ; CHECK:   DW_TAG_subprogram
 ; CHECK:     DW_AT_low_pc    (0x{{.*}})
 ; CHECK:     DW_AT_high_pc   (0x{{.*}})
-; CHECK:     DW_AT_frame_base        (DW_OP_reg1 SPB)
+; CHECK:     DW_AT_frame_base        (DW_OP_reg1 SP)
 ; CHECK:     DW_AT_call_all_calls    (true)
 ; CHECK:     DW_AT_name      ("f")
 ; CHECK:     DW_AT_decl_file ("/tmp{{[/\\]}}dwarf-basics-v5.c")
@@ -49,14 +49,14 @@
 
 ; CHECK:       DW_TAG_formal_parameter
 ; CHECK:         DW_AT_location        (indexed (0x0) loclist = 0x{{.*}}:
-; CHECK:            [0x0000, 0x0004): DW_OP_reg12 R12B)
+; CHECK:            [0x0000, 0x0004): DW_OP_reg12 R12)
 ; CHECK:         DW_AT_name    ("y")
 ; CHECK:         DW_AT_decl_file       ("/tmp{{[/\\]}}dwarf-basics-v5.c")
 ; CHECK:         DW_AT_decl_line       (5)
 ; CHECK:         DW_AT_type    (0x{{.*}} "long")
 
 ; CHECK:       DW_TAG_formal_parameter
-; CHECK:         DW_AT_location        (DW_OP_reg14 R14B)
+; CHECK:         DW_AT_location        (DW_OP_reg14 R14)
 ; CHECK:         DW_AT_name    ("p")
 ; CHECK:         DW_AT_decl_file       ("/tmp{{[/\\]}}dwarf-basics-v5.c")
 ; CHECK:         DW_AT_decl_line       (5)

diff  --git a/llvm/test/DebugInfo/MSP430/dwarf-basics.ll b/llvm/test/DebugInfo/MSP430/dwarf-basics.ll
index 592e3a507b86c..7d81d9c28d6f2 100644
--- a/llvm/test/DebugInfo/MSP430/dwarf-basics.ll
+++ b/llvm/test/DebugInfo/MSP430/dwarf-basics.ll
@@ -35,7 +35,7 @@
 ; CHECK:   DW_TAG_subprogram
 ; CHECK:     DW_AT_low_pc    (0x{{.*}})
 ; CHECK:     DW_AT_high_pc   (0x{{.*}})
-; CHECK:     DW_AT_frame_base        (DW_OP_reg1 SPB)
+; CHECK:     DW_AT_frame_base        (DW_OP_reg1 SP)
 ; CHECK:     DW_AT_name      ("f")
 ; CHECK:     DW_AT_decl_file ("/tmp{{[/\\]}}dwarf-basics.c")
 ; CHECK:     DW_AT_decl_line (5)
@@ -45,14 +45,14 @@
 
 ; CHECK:       DW_TAG_formal_parameter
 ; CHECK:         DW_AT_location        (0x{{.*}}:
-; CHECK:            [0x0000, 0x0004): DW_OP_reg12 R12B)
+; CHECK:            [0x0000, 0x0004): DW_OP_reg12 R12)
 ; CHECK:         DW_AT_name    ("y")
 ; CHECK:         DW_AT_decl_file       ("/tmp{{[/\\]}}dwarf-basics.c")
 ; CHECK:         DW_AT_decl_line       (5)
 ; CHECK:         DW_AT_type    (0x{{.*}} "long int")
 
 ; CHECK:       DW_TAG_formal_parameter
-; CHECK:         DW_AT_location        (DW_OP_reg14 R14B)
+; CHECK:         DW_AT_location        (DW_OP_reg14 R14)
 ; CHECK:         DW_AT_name    ("p")
 ; CHECK:         DW_AT_decl_file       ("/tmp{{[/\\]}}dwarf-basics.c")
 ; CHECK:         DW_AT_decl_line       (5)

diff  --git a/llvm/test/DebugInfo/MSP430/fp-vla-callee-saved.ll b/llvm/test/DebugInfo/MSP430/fp-vla-callee-saved.ll
new file mode 100644
index 0000000000000..fc4d3aa9d7a67
--- /dev/null
+++ b/llvm/test/DebugInfo/MSP430/fp-vla-callee-saved.ll
@@ -0,0 +1,60 @@
+; RUN: llc -O0 -frame-pointer=all < %s | FileCheck %s
+
+; Check that CFI instructions are generated properly when
+; a frame pointer, variable length array and callee-saved
+; registers are all present at the same time
+
+target datalayout = "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16"
+target triple = "msp430-unknown-unknown-elf"
+
+ at g = global float 0.0
+ at N = external global i16, align 2
+
+define void @foo() {
+; CHECK-LABEL: foo:
+; CHECK: push  r4
+; CHECK-NEXT: .cfi_def_cfa_offset 4
+; CHECK-NEXT: .cfi_offset r4, -4
+; CHECK-NEXT: mov r1, r4
+; CHECK-NEXT: .cfi_def_cfa_register r4
+; CHECK: push  r6
+; CHECK-NEXT: push  r7
+; CHECK-NEXT: push  r8
+; CHECK-NEXT: push  r9
+; CHECK-NEXT: push  r10
+; CHECK: .cfi_offset r6, -6
+; CHECK: .cfi_offset r7, -8
+; CHECK: .cfi_offset r8, -10
+; CHECK: .cfi_offset r9, -12
+; CHECK: .cfi_offset r10, -14
+
+  %n = load i16, ptr @N, align 2
+  %vla = alloca i8, i16 %n, align 1
+  %t1 = load volatile float, float* @g
+  %t2 = load volatile float, float* @g
+  %t3 = load volatile float, float* @g
+  %t4 = load volatile float, float* @g
+  %t5 = load volatile float, float* @g
+  store volatile float %t1, float* @g
+  store volatile float %t2, float* @g
+  store volatile float %t3, float* @g
+  store volatile float %t4, float* @g
+  store volatile float %t5, float* @g
+  
+; CHECK: mov r4, r1
+; CHECK-NEXT: sub #10, r1
+; CHECK: pop r10
+; CHECK-NEXT: pop r9
+; CHECK-NEXT: pop r8
+; CHECK-NEXT: pop r7
+; CHECK-NEXT: pop r6
+; CHECK: pop r4
+; CHECK: .cfi_def_cfa r1, 2
+; CHECK: .cfi_restore r6
+; CHECK: .cfi_restore r7
+; CHECK: .cfi_restore r8
+; CHECK: .cfi_restore r9
+; CHECK: .cfi_restore r10
+
+  ret void
+}

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_function_name.ll.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_function_name.ll.expected
index bb066c2ce4137..b8967743b06fd 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_function_name.ll.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_function_name.ll.expected
@@ -5,7 +5,8 @@
 
 define hidden i32 @"_Z54bar$ompvariant$bar"() {
 ; CHECK-LABEL: _Z54bar$ompvariant$bar:
-; CHECK:       ; %bb.0: ; %entry
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ; %bb.0: ; %entry
 ; CHECK-NEXT:    mov #2, r12
 ; CHECK-NEXT:    clr r13
 ; CHECK-NEXT:    ret

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.generated.expected
index 4625b0c73b3b3..36519299c1ffb 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.generated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.generated.expected
@@ -65,9 +65,13 @@ define dso_local i32 @main() #0 {
 
 attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" }
 ; CHECK-LABEL: check_boundaries:
-; CHECK:       ; %bb.0:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ; %bb.0:
 ; CHECK-NEXT:    push r4
+; CHECK-NEXT:    .cfi_def_cfa_offset 4
+; CHECK-NEXT:    .cfi_offset r4, -4
 ; CHECK-NEXT:    mov r1, r4
+; CHECK-NEXT:    .cfi_def_cfa_register r4
 ; CHECK-NEXT:    sub #20, r1
 ; CHECK-NEXT:    clr -6(r4)
 ; CHECK-NEXT:    clr -8(r4)
@@ -112,12 +116,17 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" }
 ; CHECK-NEXT:    clr r13
 ; CHECK-NEXT:    add #20, r1
 ; CHECK-NEXT:    pop r4
+; CHECK-NEXT:    .cfi_def_cfa r1, 2
 ; CHECK-NEXT:    ret
 ;
 ; CHECK-LABEL: main:
-; CHECK:       ; %bb.0:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ; %bb.0:
 ; CHECK-NEXT:    push r4
+; CHECK-NEXT:    .cfi_def_cfa_offset 4
+; CHECK-NEXT:    .cfi_offset r4, -4
 ; CHECK-NEXT:    mov r1, r4
+; CHECK-NEXT:    .cfi_def_cfa_register r4
 ; CHECK-NEXT:    sub #20, r1
 ; CHECK-NEXT:    clr &x+2
 ; CHECK-NEXT:    mov #1, &x
@@ -145,4 +154,5 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" }
 ; CHECK-NEXT:    clr r13
 ; CHECK-NEXT:    add #20, r1
 ; CHECK-NEXT:    pop r4
+; CHECK-NEXT:    .cfi_def_cfa r1, 2
 ; CHECK-NEXT:    ret

diff  --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.nogenerated.expected
index 2b511b1a09022..ffe417b9d618b 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.nogenerated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/msp430_generated_funcs.ll.nogenerated.expected
@@ -6,9 +6,13 @@
 
 define dso_local i32 @check_boundaries() #0 {
 ; CHECK-LABEL: check_boundaries:
-; CHECK:       ; %bb.0:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ; %bb.0:
 ; CHECK-NEXT:    push r4
+; CHECK-NEXT:    .cfi_def_cfa_offset 4
+; CHECK-NEXT:    .cfi_offset r4, -4
 ; CHECK-NEXT:    mov r1, r4
+; CHECK-NEXT:    .cfi_def_cfa_register r4
 ; CHECK-NEXT:    sub #20, r1
 ; CHECK-NEXT:    clr -6(r4)
 ; CHECK-NEXT:    clr -8(r4)
@@ -53,6 +57,7 @@ define dso_local i32 @check_boundaries() #0 {
 ; CHECK-NEXT:    clr r13
 ; CHECK-NEXT:    add #20, r1
 ; CHECK-NEXT:    pop r4
+; CHECK-NEXT:    .cfi_def_cfa r1, 2
 ; CHECK-NEXT:    ret
   %1 = alloca i32, align 4
   %2 = alloca i32, align 4
@@ -92,9 +97,13 @@ define dso_local i32 @check_boundaries() #0 {
 
 define dso_local i32 @main() #0 {
 ; CHECK-LABEL: main:
-; CHECK:       ; %bb.0:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ; %bb.0:
 ; CHECK-NEXT:    push r4
+; CHECK-NEXT:    .cfi_def_cfa_offset 4
+; CHECK-NEXT:    .cfi_offset r4, -4
 ; CHECK-NEXT:    mov r1, r4
+; CHECK-NEXT:    .cfi_def_cfa_register r4
 ; CHECK-NEXT:    sub #20, r1
 ; CHECK-NEXT:    clr &x+2
 ; CHECK-NEXT:    mov #1, &x
@@ -122,6 +131,7 @@ define dso_local i32 @main() #0 {
 ; CHECK-NEXT:    clr r13
 ; CHECK-NEXT:    add #20, r1
 ; CHECK-NEXT:    pop r4
+; CHECK-NEXT:    .cfi_def_cfa r1, 2
 ; CHECK-NEXT:    ret
   %1 = alloca i32, align 4
   %2 = alloca i32, align 4


        


More information about the llvm-commits mailing list