[llvm] 532815d - [ARM][AArch64][DebugInfo] Improve call site instruction interpretation

Djordje Todorovic via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 30 05:58:35 PDT 2019


Author: Djordje Todorovic
Date: 2019-10-30T13:58:14+01:00
New Revision: 532815dd5c54b9ee7d16cf4a437e82bab39c99ad

URL: https://github.com/llvm/llvm-project/commit/532815dd5c54b9ee7d16cf4a437e82bab39c99ad
DIFF: https://github.com/llvm/llvm-project/commit/532815dd5c54b9ee7d16cf4a437e82bab39c99ad.diff

LOG: [ARM][AArch64][DebugInfo] Improve call site instruction interpretation

Extend the describeLoadedValue() with support for target specific ARM and
AArch64 instructions interpretation. The patch provides specialization for
ADD and SUB operations that include a register and an immediate/offset
operand. Some of the instructions can operate with global string addresses
or constant pool indexes but such cases are omitted since we currently lack
flexible support for processing such operands at DWARF production stage.

Patch by Nikola Prica

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

Added: 
    llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-interpretation.mir

Modified: 
    llvm/include/llvm/CodeGen/TargetInstrInfo.h
    llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
    llvm/lib/CodeGen/TargetInstrInfo.cpp
    llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
    llvm/lib/Target/AArch64/AArch64InstrInfo.h
    llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
    llvm/lib/Target/ARM/ARMBaseInstrInfo.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 5011cf34c0ee..66420c1c4184 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -944,6 +944,17 @@ class TargetInstrInfo : public MCInstrInfo {
     return isCopyInstrImpl(MI, Source, Destination);
   }
 
+  /// If the specific machine instruction is an instruction that adds an
+  /// immediate value to its \c Source operand and stores it in \c Destination,
+  /// return true along with \c Destination and \c Source machine operand to
+  /// which \c Offset has been added.
+  virtual bool isAddImmediate(const MachineInstr &MI,
+                              const MachineOperand *&Destination,
+                              const MachineOperand *&Source,
+                              int64_t &Offset) const {
+    return false;
+  }
+
   /// Store the specified register of the given register class to the specified
   /// stack frame index. The store instruction is to be added to the given
   /// machine basic block before the specified machine instruction. If isKill

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index c505e77e5acd..2f7025945a15 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -642,15 +642,20 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
     // least partially) defined by the instruction's single explicit define.
     if (I->getNumExplicitDefs() != 1 || ExplicitFwdRegDefs.empty())
       continue;
-    unsigned Reg = ExplicitFwdRegDefs[0];
+    unsigned ParamFwdReg = ExplicitFwdRegDefs[0];
 
     if (auto ParamValue = TII->describeLoadedValue(*I)) {
       if (ParamValue->first.isImm()) {
         int64_t Val = ParamValue->first.getImm();
         DbgValueLoc DbgLocVal(ParamValue->second, Val);
-        finishCallSiteParam(DbgLocVal, Reg);
+        finishCallSiteParam(DbgLocVal, ParamFwdReg);
       } else if (ParamValue->first.isReg()) {
         Register RegLoc = ParamValue->first.getReg();
+       // TODO: For now, there is no use of describing the value loaded into the
+       //       register that is also the source registers (e.g. $r0 = add $r0, x).
+       if (ParamFwdReg == RegLoc)
+         continue;
+
         unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
         Register FP = TRI->getFrameRegister(*MF);
         bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP);
@@ -658,10 +663,12 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
           DbgValueLoc DbgLocVal(ParamValue->second,
                                 MachineLocation(RegLoc,
                                                 /*IsIndirect=*/IsSPorFP));
-          finishCallSiteParam(DbgLocVal, Reg);
-        } else if (ShouldTryEmitEntryVals) {
+          finishCallSiteParam(DbgLocVal, ParamFwdReg);
+        // TODO: Add support for entry value plus an expression.
+        } else if (ShouldTryEmitEntryVals &&
+                   ParamValue->second->getNumElements() == 0) {
           ForwardedRegWorklist.insert(RegLoc);
-          RegsForEntryValues[RegLoc] = Reg;
+          RegsForEntryValues[RegLoc] = ParamFwdReg;
         }
       }
     }

diff  --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index d99b2b0e9977..88fbfcb7784b 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -1123,13 +1123,15 @@ bool TargetInstrInfo::hasLowDefLatency(const TargetSchedModel &SchedModel,
 Optional<ParamLoadedValue>
 TargetInstrInfo::describeLoadedValue(const MachineInstr &MI) const {
   const MachineFunction *MF = MI.getMF();
-  const MachineOperand *Op = nullptr;
-  DIExpression *Expr = DIExpression::get(MF->getFunction().getContext(), {});;
+  DIExpression *Expr = DIExpression::get(MF->getFunction().getContext(), {});
   const MachineOperand *SrcRegOp, *DestRegOp;
+  int64_t Offset;
 
   if (isCopyInstr(MI, SrcRegOp, DestRegOp)) {
-    Op = SrcRegOp;
-    return ParamLoadedValue(*Op, Expr);
+    return ParamLoadedValue(*SrcRegOp, Expr);
+  } else if (isAddImmediate(MI, DestRegOp, SrcRegOp, Offset)) {
+    Expr = DIExpression::prepend(Expr, DIExpression::ApplyOffset, Offset);
+    return ParamLoadedValue(*SrcRegOp, Expr);
   }
 
   return None;

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 5c35e5bcdd30..96a58cea77c3 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -5727,5 +5727,53 @@ bool AArch64InstrInfo::isCopyInstrImpl(
   return false;
 }
 
+bool AArch64InstrInfo::isAddImmediate(const MachineInstr &MI,
+                                      const MachineOperand *&Destination,
+                                      const MachineOperand *&Source,
+                                      int64_t &Offset) const {
+  int Sign = 1;
+  switch (MI.getOpcode()) {
+  default:
+    return false;
+  case AArch64::SUBWri:
+  case AArch64::SUBXri:
+  case AArch64::SUBSWri:
+  case AArch64::SUBSXri:
+    Sign *= -1;
+    LLVM_FALLTHROUGH;
+  case AArch64::ADDSWri:
+  case AArch64::ADDSXri:
+  case AArch64::ADDWri:
+  case AArch64::ADDXri: {
+    // TODO: Third operand can be global address (usually some string).
+    if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg() ||
+        !MI.getOperand(2).isImm())
+      return false;
+    Source = &MI.getOperand(1);
+    Offset = MI.getOperand(2).getImm() * Sign;
+    int Shift = MI.getOperand(3).getImm();
+    assert((Shift == 0 || Shift == 12) && "Shift can be either 0 or 12");
+    Offset = Offset << Shift;
+  }
+  }
+  Destination = &MI.getOperand(0);
+  return true;
+}
+
+Optional<ParamLoadedValue>
+AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI) const {
+  switch (MI.getOpcode()) {
+  case AArch64::MOVZWi:
+  case AArch64::MOVZXi:
+    if (!MI.getOperand(1).isImm())
+      return None;
+    int Immediate = MI.getOperand(1).getImm();
+    int Shift = MI.getOperand(2).getImm();
+    return ParamLoadedValue(MachineOperand::CreateImm(Immediate << Shift),
+                            nullptr);
+  }
+  return TargetInstrInfo::describeLoadedValue(MI);
+}
+
 #define GET_INSTRINFO_HELPERS
 #include "AArch64GenInstrInfo.inc"

diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 1688045e4fb8..ece791674689 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -265,6 +265,14 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
   /// on Windows.
   static bool isSEHInstruction(const MachineInstr &MI);
 
+  bool isAddImmediate(const MachineInstr &MI,
+                      const MachineOperand *&Destination,
+                      const MachineOperand *&Source,
+                      int64_t &Offset) const override;
+
+  Optional<ParamLoadedValue>
+  describeLoadedValue(const MachineInstr &MI) const override;
+
 #define GET_INSTRINFO_HELPER_DECLS
 #include "AArch64GenInstrInfo.inc"
 

diff  --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 684cd1def977..ffc967769fea 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -5350,6 +5350,32 @@ ARMBaseInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
   return makeArrayRef(TargetFlags);
 }
 
+bool ARMBaseInstrInfo::isAddImmediate(const MachineInstr &MI,
+                                      const MachineOperand *&Destination,
+                                      const MachineOperand *&Source,
+                                      int64_t &Offset) const {
+  int Sign = 1;
+  unsigned Opcode = MI.getOpcode();
+
+  // We describe SUBri or ADDri instructions.
+  if (Opcode == ARM::SUBri)
+    Sign = -1;
+  else if (Opcode != ARM::ADDri)
+    return false;
+
+  // TODO: Third operand can be global address (usually some string). Since
+  //       strings can be relocated we cannot calculate their offsets for
+  //       now.
+  if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg() ||
+      !MI.getOperand(2).isImm())
+    return false;
+
+  Destination = &MI.getOperand(0);
+  Source = &MI.getOperand(1);
+  Offset = MI.getOperand(2).getImm() * Sign;
+  return true;
+}
+
 bool llvm::registerDefinedBetween(unsigned Reg,
                                   MachineBasicBlock::iterator From,
                                   MachineBasicBlock::iterator To,

diff  --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
index c232b6f0b45d..0f4f2d4b687d 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -455,6 +455,11 @@ class ARMBaseInstrInfo : public ARMGenInstrInfo {
     // 3 - predicate reg
     return MI.getOperand(3).getReg();
   }
+
+  bool isAddImmediate(const MachineInstr &MI,
+                      const MachineOperand *&Destination,
+                      const MachineOperand *&Source,
+                      int64_t &Offset) const override;
 };
 
 /// Get the operands corresponding to the given \p Pred value. By default, the

diff  --git a/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-interpretation.mir b/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-interpretation.mir
new file mode 100644
index 000000000000..22e85387b6b4
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/AArch64/dbgcall-site-interpretation.mir
@@ -0,0 +1,180 @@
+# RUN: llc -mtriple aarch64-linux-gnu -debug-entry-values -start-after=machineverifier -filetype=obj %s -o -| llvm-dwarfdump -| FileCheck %s
+# Following code is used for producing this test case. Note that
+# some of argument loading instruction are modified in order to
+# cover certain cases.
+#
+# extern int func2(int,int,int*);
+# int func1(int arg1, int arg2, int arg3) {
+#   int a = func2(arg1 + 2, arg2 - 4, &arg3);
+#   a += func2(arg3 - 16, arg1 + 8, &a);
+#   return a++;
+# }
+#
+# CHECK: DW_TAG_GNU_call_site
+# CHECK-NEXT: DW_AT_abstract_origin {{.*}} "func2"
+# CHECK: DW_TAG_GNU_call_site_parameter
+# CHECK-NOT:   DW_AT_location      (DW_OP_reg2 W0)
+# CHECK-NEXT:   DW_AT_location      (DW_OP_reg2 W2)
+# CHECK-NEXT:   DW_AT_GNU_call_site_value   (DW_OP_fbreg +28)
+# CHECK-EMPTY: 
+# CHECK-NEXT: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:   DW_AT_location      (DW_OP_reg1 W1)
+# CHECK-NEXT:   DW_AT_GNU_call_site_value   (DW_OP_breg19 W19-4)
+# CHECK: DW_TAG_GNU_call_site
+# CHECK-NEXT: DW_AT_abstract_origin {{.*}} "func2")
+# CHECK-NEXT: DW_AT_low_pc
+# CHECK-EMPTY: 
+# CHECK-NEXT: DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:   DW_AT_location      (DW_OP_reg0 W0)
+# CHECK-NEXT:   DW_AT_GNU_call_site_value   (DW_OP_lit13)
+# CHECK-EMPTY: 
+# CHECK-NEXT: DW_TAG_GNU_call_site_parameter
+# W2 loads memory location. We can't rely that memory location won't be changed.
+# CHECK-NOT:   DW_AT_location      (DW_OP_reg2 W2)
+# CHECK-NEXT:   DW_AT_location      (DW_OP_reg1 W1)
+# CHECK-NEXT:   DW_AT_GNU_call_site_value   (DW_OP_constu 0xc0)
+--- |
+  ; ModuleID = 'describe-call-pram-load-instruction.c'
+  source_filename = "describe-call-pram-load-instruction.c"
+  target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+  target triple = "aarch64-unknown-linux-gnu"
+  
+  ; Function Attrs: nounwind
+  define dso_local i32 @func1(i32 %arg1, i32 %arg2, i32 %arg3) local_unnamed_addr #0 !dbg !13 {
+  entry:
+    %arg3.addr = alloca i32, align 4
+    %a = alloca i32, align 4
+    call void @llvm.dbg.value(metadata i32 %arg1, metadata !17, metadata !DIExpression()), !dbg !21
+    call void @llvm.dbg.value(metadata i32 %arg2, metadata !18, metadata !DIExpression()), !dbg !21
+    call void @llvm.dbg.value(metadata i32 %arg3, metadata !19, metadata !DIExpression()), !dbg !21
+    store i32 %arg3, i32* %arg3.addr, align 4
+    %0 = bitcast i32* %a to i8*, !dbg !21
+    call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0), !dbg !21
+    %add = add nsw i32 %arg1, 2, !dbg !21
+    %sub = add nsw i32 %arg2, -4, !dbg !21
+    call void @llvm.dbg.value(metadata i32* %arg3.addr, metadata !19, metadata !DIExpression(DW_OP_deref)), !dbg !21
+    %call = call i32 @func2(i32 %add, i32 %sub, i32* nonnull %arg3.addr), !dbg !21
+    call void @llvm.dbg.value(metadata i32 %call, metadata !20, metadata !DIExpression()), !dbg !21
+    store i32 %call, i32* %a, align 4, !dbg !21
+    %1 = load i32, i32* %arg3.addr, align 4, !dbg !21
+    call void @llvm.dbg.value(metadata i32 %1, metadata !19, metadata !DIExpression()), !dbg !21
+    %sub1 = add nsw i32 %1, -16, !dbg !21
+    %add2 = add nsw i32 %arg1, 8, !dbg !21
+    call void @llvm.dbg.value(metadata i32* %a, metadata !20, metadata !DIExpression(DW_OP_deref)), !dbg !21
+    %call3 = call i32 @func2(i32 %sub1, i32 %add2, i32* nonnull %a), !dbg !21
+    %2 = load i32, i32* %a, align 4, !dbg !21
+    call void @llvm.dbg.value(metadata i32 %2, metadata !20, metadata !DIExpression()), !dbg !21
+    %add4 = add nsw i32 %2, %call3, !dbg !21
+    call void @llvm.dbg.value(metadata i32 %add4, metadata !20, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !21
+    call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0), !dbg !21
+    ret i32 %add4, !dbg !21
+  }
+  
+  ; Function Attrs: argmemonly nounwind willreturn
+  declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
+  
+  declare !dbg !4 dso_local i32 @func2(i32, i32, i32*) local_unnamed_addr
+  
+  ; Function Attrs: argmemonly nounwind willreturn
+  declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
+  
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+  
+  ; Function Attrs: nounwind
+  declare void @llvm.stackprotector(i8*, i8**)
+  
+  attributes #0 = { "frame-pointer"="all" }
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!9, !10, !11}
+  !llvm.ident = !{!12}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
+  !1 = !DIFile(filename: "describe-call-pram-load-instruction.c", directory: "/")
+  !2 = !{}
+  !3 = !{!4}
+  !4 = !DISubprogram(name: "func2", scope: !1, file: !1, line: 8, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !DISubroutineType(types: !6)
+  !6 = !{!7, !7, !7, !8}
+  !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+  !9 = !{i32 2, !"Dwarf Version", i32 4}
+  !10 = !{i32 2, !"Debug Info Version", i32 3}
+  !11 = !{i32 1, !"wchar_size", i32 4}
+  !12 = !{!"clang version 10.0.0 "}
+  !13 = distinct !DISubprogram(name: "func1", scope: !1, file: !1, line: 9, type: !14, scopeLine: 9, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16)
+  !14 = !DISubroutineType(types: !15)
+  !15 = !{!7, !7, !7, !7}
+  !16 = !{!17, !18, !19, !20}
+  !17 = !DILocalVariable(name: "arg1", arg: 1, scope: !13, file: !1, line: 9, type: !7, flags: DIFlagArgumentNotModified)
+  !18 = !DILocalVariable(name: "arg2", arg: 2, scope: !13, file: !1, line: 9, type: !7, flags: DIFlagArgumentNotModified)
+  !19 = !DILocalVariable(name: "arg3", arg: 3, scope: !13, file: !1, line: 9, type: !7)
+  !20 = !DILocalVariable(name: "a", scope: !13, file: !1, line: 10, type: !7)
+  !21 = !DILocation(line: 0, scope: !13)
+
+...
+---
+name:            func1
+frameInfo:
+  adjustsStack:    true
+  hasCalls:        true
+stack:
+  - { id: 0, name: arg3.addr, offset: -4, size: 4, alignment: 4, local-offset: -4 }
+  - { id: 1, name: a, offset: -8, size: 4, alignment: 4, local-offset: -8 }
+  - { id: 2, type: spill-slot, offset: -16, size: 8, alignment: 16, callee-saved-register: '$x19' }
+  - { id: 3, type: spill-slot, offset: -24, size: 8, alignment: 8, callee-saved-register: '$lr' }
+  - { id: 4, type: spill-slot, offset: -32, size: 8, alignment: 8, callee-saved-register: '$fp' }
+callSites:
+  - { bb: 0, offset: 20, fwdArgRegs: 
+      - { arg: 0, reg: '$w0' }
+      - { arg: 1, reg: '$w1' }
+      - { arg: 2, reg: '$x2' } }
+  - { bb: 0, offset: 29, fwdArgRegs: 
+      - { arg: 0, reg: '$w0' }
+      - { arg: 1, reg: '$w1' }
+      - { arg: 2, reg: '$x2' } }
+body:             |
+  bb.0.entry:
+    liveins: $w0, $w1, $w2, $lr, $x19
+  
+    DBG_VALUE $w0, $noreg, !17, !DIExpression(), debug-location !21
+    DBG_VALUE $w1, $noreg, !18, !DIExpression(), debug-location !21
+    DBG_VALUE $w1, $noreg, !18, !DIExpression(), debug-location !21
+    DBG_VALUE $w2, $noreg, !19, !DIExpression(), debug-location !21
+    DBG_VALUE $w2, $noreg, !19, !DIExpression(), debug-location !21
+    early-clobber $sp = frame-setup STPXpre $fp, killed $lr, $sp, -4 :: (store 8 into %stack.4), (store 8 into %stack.3)
+    frame-setup STRXui killed $x19, $sp, 2 :: (store 8 into %stack.2)
+    $fp = frame-setup ADDXri $sp, 0, 0
+    frame-setup CFI_INSTRUCTION def_cfa $w29, 32
+    frame-setup CFI_INSTRUCTION offset $w19, -16
+    frame-setup CFI_INSTRUCTION offset $w30, -24
+    frame-setup CFI_INSTRUCTION offset $w29, -32
+    $w19 = ORRWrs $wzr, $w0, 0
+    DBG_VALUE $w19, $noreg, !17, !DIExpression(), debug-location !21
+    STRWui killed renamable $w2, $fp, 7 :: (store 4 into %ir.arg3.addr)
+    renamable $w0 = nsw ADDWri $w0, 2, 0, debug-location !21
+    renamable $w1 = nsw SUBWri renamable $w19, 4, 0, debug-location !21
+    DBG_VALUE $w1, $noreg, !18, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !21
+    DBG_VALUE $fp, $noreg, !19, !DIExpression(DW_OP_plus_uconst, 28, DW_OP_deref), debug-location !21
+    $x2 = ADDXri $fp, 28, 0, debug-location !21
+    BL @func2, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit killed $x2, implicit-def $sp, implicit-def $w0, debug-location !21
+    DBG_VALUE $w0, $noreg, !20, !DIExpression(), debug-location !21
+    renamable $w8 = LDRWui $fp, 7, debug-location !21 :: (dereferenceable load 4 from %ir.arg3.addr)
+    DBG_VALUE $w8, $noreg, !19, !DIExpression(), debug-location !21
+    STRWui killed renamable $w0, $fp, 6, debug-location !21 :: (store 4 into %ir.a)
+    renamable $w1 = nsw MOVZWi 12, 4
+    DBG_VALUE $fp, $noreg, !20, !DIExpression(DW_OP_plus_uconst, 24, DW_OP_deref), debug-location !21
+    $x2 = LDRXui $fp, 24, debug-location !21
+    renamable $w0 = nsw MOVZWi 13, 0
+    BL @func2, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit killed $x2, implicit-def $sp, implicit-def $w0, debug-location !21
+    renamable $w8 = LDRWui $fp, 6, debug-location !21 :: (dereferenceable load 4 from %ir.a)
+    DBG_VALUE $w8, $noreg, !20, !DIExpression(), debug-location !21
+    $x19 = frame-destroy LDRXui $sp, 2, debug-location !21 :: (load 8 from %stack.2)
+    DBG_VALUE $w0, $noreg, !17, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !21
+    $w0 = ADDWrs killed renamable $w8, killed renamable $w0, 0, debug-location !21
+    DBG_VALUE $w0, $noreg, !20, !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value), debug-location !21
+    early-clobber $sp, $fp, $lr = frame-destroy LDPXpost $sp, 4, debug-location !21 :: (load 8 from %stack.4), (load 8 from %stack.3)
+    RET undef $lr, implicit killed $w0, debug-location !21
+
+...


        


More information about the llvm-commits mailing list