[llvm] r310014 - Teach GlobalSRA to update the debug info for split-up globals.

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 7 14:32:48 PDT 2017


On Thu, Aug 3, 2017 at 6:20 PM Adrian Prantl via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: adrian
> Date: Thu Aug  3 18:19:54 2017
> New Revision: 310014
>
> URL: http://llvm.org/viewvc/llvm-project?rev=310014&view=rev
> Log:
> Teach GlobalSRA to update the debug info for split-up globals.
>
> This is similar to what we are doing in "regular" SROA and creates
> DW_OP_LLVM_fragment operations to describe the resulting variables.
>
> rdar://problem/33654891
>
> Added:
>     llvm/trunk/test/DebugInfo/Generic/global-sra-array.ll
>     llvm/trunk/test/DebugInfo/Generic/global-sra-struct.ll
> Modified:
>     llvm/trunk/include/llvm/IR/DIBuilder.h
>     llvm/trunk/lib/IR/DIBuilder.cpp
>     llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
>
> Modified: llvm/trunk/include/llvm/IR/DIBuilder.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DIBuilder.h?rev=310014&r1=310013&r2=310014&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/DIBuilder.h (original)
> +++ llvm/trunk/include/llvm/IR/DIBuilder.h Thu Aug  3 18:19:54 2017
> @@ -551,13 +551,17 @@ namespace llvm {
>      DIExpression *createExpression(ArrayRef<uint64_t> Addr = None);
>      DIExpression *createExpression(ArrayRef<int64_t> Addr);
>
> -    /// Create a descriptor to describe one part
> -    /// of aggregate variable that is fragmented across multiple Values.
> +    /// Create a descriptor to describe one part of an aggregate variable
> that
> +    /// is fragmented across multiple Values. The DW_OP_LLVM_fragment
> operation
> +    /// will be appended to the elements of \c Expr. If \c Expr already
> contains
> +    /// a \c DW_OP_LLVM_fragment \c OffsetInBits is interpreted as an
> offset
> +    /// into the existing fragment.
>      ///
>      /// \param OffsetInBits Offset of the piece in bits.
>      /// \param SizeInBits   Size of the piece in bits.
>      DIExpression *createFragmentExpression(unsigned OffsetInBits,
> -                                           unsigned SizeInBits);
> +                                           unsigned SizeInBits,
> +                                           const DIExpression *Expr =
> nullptr);
>
>      /// Create an expression for a variable that does not have an
> address, but
>      /// does have a constant value.
>
> Modified: llvm/trunk/lib/IR/DIBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DIBuilder.cpp?rev=310014&r1=310013&r2=310014&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/DIBuilder.cpp (original)
> +++ llvm/trunk/lib/IR/DIBuilder.cpp Thu Aug  3 18:19:54 2017
> @@ -668,10 +668,31 @@ DIExpression *DIBuilder::createExpressio
>    return createExpression(Addr);
>  }
>
> -DIExpression *DIBuilder::createFragmentExpression(unsigned OffsetInBytes,
> -                                                  unsigned SizeInBytes) {
> -  uint64_t Addr[] = {dwarf::DW_OP_LLVM_fragment, OffsetInBytes,
> SizeInBytes};
> -  return DIExpression::get(VMContext, Addr);
> +DIExpression *DIBuilder::createFragmentExpression(unsigned OffsetInBits,
> +                                                  unsigned SizeInBits,
> +                                                  const DIExpression
> *Expr) {
> +  SmallVector<uint64_t, 8> Ops;
> +  // Copy over the expression, but leave off any trailing
> DW_OP_LLVM_fragment.
> +  if (Expr) {
> +    for (auto Op : Expr->expr_ops()) {
> +      if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
> +        // Make the new offset point into the existing fragment.
> +        uint64_t FragmentOffsetInBits = Op.getArg(0);
> +        uint64_t FragmentSizeInBits = Op.getArg(1);
> +        assert((OffsetInBits + SizeInBits <= FragmentSizeInBits) &&
> +               "new fragment outside of original fragment");
> +        OffsetInBits += FragmentOffsetInBits;
> +        break;
> +      }
> +      Ops.push_back(Op.getOp());
> +      for (unsigned I = 0; I < Op.getNumArgs(); ++I)
> +        Ops.push_back(Op.getArg(I));
> +    }
> +  }
> +  Ops.push_back(dwarf::DW_OP_LLVM_fragment);
> +  Ops.push_back(OffsetInBits);
> +  Ops.push_back(SizeInBits);
> +  return DIExpression::get(VMContext, Ops);
>  }
>
>  template <class... Ts>
>
> Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=310014&r1=310013&r2=310014&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Thu Aug  3 18:19:54 2017
> @@ -27,7 +27,9 @@
>  #include "llvm/IR/CallingConv.h"
>  #include "llvm/IR/Constants.h"
>  #include "llvm/IR/DataLayout.h"
> +#include "llvm/IR/DebugInfoMetadata.h"
>  #include "llvm/IR/DerivedTypes.h"
> +#include "llvm/IR/DIBuilder.h"
>  #include "llvm/IR/Dominators.h"
>  #include "llvm/IR/GetElementPtrTypeIterator.h"
>  #include "llvm/IR/Instructions.h"
> @@ -419,6 +421,23 @@ static bool GlobalUsersSafeToSRA(GlobalV
>    return true;
>  }
>
> +/// Copy over the debug info for a variable to its SRA replacements.
> +static void transferSRADebugInfo(GlobalVariable *GV, GlobalVariable *NGV,
> +                                 uint64_t FragmentOffsetInBits,
> +                                 uint64_t FragmentSizeInBits) {
> +  DIBuilder DIB(*GV->getParent(), /*AllowUnresolved*/ false);
> +  SmallVector<DIGlobalVariableExpression *, 1> GVs;
> +  GV->getDebugInfo(GVs);
> +  for (auto *GVE : GVs) {
> +    DIVariable *Var = GVE->getVariable();
> +    DIExpression *Expr = GVE->getExpression();
> +    DIExpression *NExpr = DIB.createFragmentExpression(
> +        FragmentOffsetInBits, FragmentSizeInBits, Expr);
> +    auto *NGVE = DIGlobalVariableExpression::get(GVE->getContext(), Var,
> NExpr);
> +    NGV->addDebugInfo(NGVE);
> +  }
> +}
> +
>
>  /// Perform scalar replacement of aggregates on the specified global
> variable.
>  /// This opens the door for other optimizations by exposing the behavior
> of the
> @@ -443,6 +462,7 @@ static GlobalVariable *SRAGlobal(GlobalV
>      StartAlignment = DL.getABITypeAlignment(GV->getType());
>
>    if (StructType *STy = dyn_cast<StructType>(Ty)) {
> +    uint64_t FragmentOffset = 0;
>      NewGlobals.reserve(STy->getNumElements());
>      const StructLayout &Layout = *DL.getStructLayout(STy);
>      for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
> @@ -465,15 +485,22 @@ static GlobalVariable *SRAGlobal(GlobalV
>        unsigned NewAlign = (unsigned)MinAlign(StartAlignment, FieldOffset);
>        if (NewAlign > DL.getABITypeAlignment(STy->getElementType(i)))
>          NGV->setAlignment(NewAlign);
> +
> +      // Copy over the debug info for the variable.
> +      FragmentOffset = alignTo(FragmentOffset, NewAlign);
> +      uint64_t Size = DL.getTypeSizeInBits(NGV->getValueType());
> +      transferSRADebugInfo(GV, NGV, FragmentOffset, Size);
> +      FragmentOffset += Size;
>      }
>    } else if (SequentialType *STy = dyn_cast<SequentialType>(Ty)) {
>      unsigned NumElements = STy->getNumElements();
>      if (NumElements > 16 && GV->hasNUsesOrMore(16))
>        return nullptr; // It's not worth it.
>      NewGlobals.reserve(NumElements);
> -
> -    uint64_t EltSize = DL.getTypeAllocSize(STy->getElementType());
> -    unsigned EltAlign = DL.getABITypeAlignment(STy->getElementType());
> +    auto ElTy = STy->getElementType();
> +    uint64_t EltSize = DL.getTypeAllocSize(ElTy);
> +    unsigned EltAlign = DL.getABITypeAlignment(ElTy);
> +    uint64_t FragmentSizeInBits = DL.getTypeSizeInBits(ElTy);
>      for (unsigned i = 0, e = NumElements; i != e; ++i) {
>        Constant *In = Init->getAggregateElement(i);
>        assert(In && "Couldn't get element of initializer?");
> @@ -494,6 +521,8 @@ static GlobalVariable *SRAGlobal(GlobalV
>        unsigned NewAlign = (unsigned)MinAlign(StartAlignment, EltSize*i);
>        if (NewAlign > EltAlign)
>          NGV->setAlignment(NewAlign);
> +
> +      transferSRADebugInfo(GV, NGV, FragmentSizeInBits * i,
> FragmentSizeInBits);
>      }
>    }
>
>
> Added: llvm/trunk/test/DebugInfo/Generic/global-sra-array.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Generic/global-sra-array.ll?rev=310014&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/Generic/global-sra-array.ll (added)
> +++ llvm/trunk/test/DebugInfo/Generic/global-sra-array.ll Thu Aug  3
> 18:19:54 2017
> @@ -0,0 +1,129 @@
> +; RUN: opt -S -globalopt < %s | FileCheck %s
> +source_filename = "test.c"
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.12.0"
> +
> +%struct.mystruct = type { i32, i64 }
> +; Generated at -Os from:
> +;
> +; static struct { int a; char b; } array[2];
> +; void __attribute__((nodebug)) foo(int in) { array[0].a = in; }
> +; void __attribute__((nodebug)) bar(int in) { array[1].a = in; }
> +; int main(int argc, char **argv)
> +; {
> +;   foo(argv[0][1]);
> +;   bar(argv[0][1]);
> +;   return array[0].a + array[1].a;
> +; }
>

Just some ideas, maybe for future reference/out of curiosity in terms of
how to make test cases most legible:

Might be easier if this wasn't 'main', but an arbitrary function with an
integer parameter & return? (so there's no argv/argc)

Do foo and bar need to be called to make this work? Why? Presumably foo and
bar could be called from other translation units and have the same affect?

Does the struct need to be a struct? I guess it probably does because this
is SRA? (do the members need to be of different types (int/char)? why?)


> +
> +%struct.anon = type { i32, i8 }
> +
> +; This array is first split into two struct, which are then split into
> their
> +; elements, of which only .a survives.
> + at array = internal global [2 x %struct.anon] zeroinitializer, align 16,
> !dbg !0
> +; CHECK: @array.0.0 = internal unnamed_addr global i32 0, align 16, !dbg
> ![[EL0:.*]]
> +; CHECK: @array.1.0 = internal unnamed_addr global i32 0, align 8, !dbg
> ![[EL1:.*]]
> +;
> +; CHECK: ![[EL0]] = !DIGlobalVariableExpression(var: ![[VAR:.*]], expr:
> ![[EX1:.*]])
> +; CHECK: ![[VAR]] = distinct !DIGlobalVariable(name: "array"
> +; CHECK: ![[EX1]] = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
> +; CHECK: ![[EL1]] = !DIGlobalVariableExpression(var: ![[VAR]], expr:
> ![[EX2:.*]])
> +; CHECK: ![[EX2]] = !DIExpression(DW_OP_LLVM_fragment, 64, 32)
> +
> +
> +; Function Attrs: nounwind optsize ssp uwtable
> +define void @foo(i32 %in) #0 {
> +entry:
> +  store i32 %in, i32* getelementptr inbounds ([2 x %struct.anon], [2 x
> %struct.anon]* @array, i64 0, i64 0, i32 0), align 16, !tbaa !20
> +  ret void
> +}
> +
> +; Function Attrs: nounwind optsize ssp uwtable
> +define void @bar(i32 %in) #0 {
> +entry:
> +  store i32 %in, i32* getelementptr inbounds ([2 x %struct.anon], [2 x
> %struct.anon]* @array, i64 0, i64 1, i32 0), align 8, !tbaa !20
> +  ret void
> +}
> +
> +; Function Attrs: nounwind optsize ssp uwtable
> +define i32 @main(i32 %argc, i8** %argv) #0 !dbg !25 {
> +entry:
> +  call void @llvm.dbg.value(metadata i32 %argc, metadata !31, metadata
> !33), !dbg !34
> +  call void @llvm.dbg.value(metadata i8** %argv, metadata !32, metadata
> !33), !dbg !35
> +  %0 = load i8*, i8** %argv, align 8, !dbg !36, !tbaa !37
> +  %arrayidx1 = getelementptr inbounds i8, i8* %0, i64 1, !dbg !36
> +  %1 = load i8, i8* %arrayidx1, align 1, !dbg !36, !tbaa !39
> +  %conv = sext i8 %1 to i32, !dbg !36
> +  call void @foo(i32 %conv) #2, !dbg !40
> +  %2 = load i8*, i8** %argv, align 8, !dbg !41, !tbaa !37
> +  %arrayidx3 = getelementptr inbounds i8, i8* %2, i64 1, !dbg !41
> +  %3 = load i8, i8* %arrayidx3, align 1, !dbg !41, !tbaa !39
> +  %conv4 = sext i8 %3 to i32, !dbg !41
> +  call void @bar(i32 %conv4) #2, !dbg !42
> +  %4 = load i32, i32* getelementptr inbounds ([2 x %struct.anon], [2 x
> %struct.anon]* @array, i64 0, i64 0, i32 0), align 16, !dbg !43, !tbaa !20
> +  %5 = load i32, i32* getelementptr inbounds ([2 x %struct.anon], [2 x
> %struct.anon]* @array, i64 0, i64 1, i32 0), align 8, !dbg !44, !tbaa !20
> +  %add = add nsw i32 %4, %5, !dbg !45
> +  ret i32 %add, !dbg !46
> +}
> +
> +; Function Attrs: nounwind readnone speculatable
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> +
> +; Function Attrs: nounwind readnone speculatable
> +declare void @llvm.dbg.value(metadata, metadata, metadata) #1
> +
> +attributes #0 = { nounwind optsize ssp uwtable
> "correctly-rounded-divide-sqrt-fp-math"="false"
> "disable-tail-calls"="false" "less-precise-fpmad"="false"
> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"
> "no-infs-fp-math"="false" "no-jump-tables"="false"
> "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false"
> "no-trapping-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="penryn"
> "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { nounwind readnone speculatable }
> +attributes #2 = { optsize }
> +
> +!llvm.dbg.cu = !{!2}
> +!llvm.module.flags = !{!15, !16, !17, !18}
> +!llvm.ident = !{!19}
> +
> +!0 = !DIGlobalVariableExpression(var: !1)
> +!1 = distinct !DIGlobalVariable(name: "array", scope: !2, file: !3, line:
> 1, type: !6, isLocal: true, isDefinition: true)
> +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer:
> "clang version 6.0.0 (trunk 309960) (llvm/trunk 309961)", isOptimized:
> true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
> +!3 = !DIFile(filename: "test.c", directory: "/")
> +!4 = !{}
> +!5 = !{!0}
> +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 128,
> elements: !13)
> +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3,
> line: 1, size: 64, elements: !8)
> +!8 = !{!9, !11}
> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !7, file: !3,
> line: 1, baseType: !10, size: 32)
> +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> +!11 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !7, file: !3,
> line: 1, baseType: !12, size: 8, offset: 32)
> +!12 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
> +!13 = !{!14}
> +!14 = !DISubrange(count: 2)
> +!15 = !{i32 2, !"Dwarf Version", i32 4}
> +!16 = !{i32 2, !"Debug Info Version", i32 3}
> +!17 = !{i32 1, !"wchar_size", i32 4}
> +!18 = !{i32 7, !"PIC Level", i32 2}
> +!19 = !{!"clang version 6.0.0 (trunk 309960) (llvm/trunk 309961)"}
> +!20 = !{!21, !22, i64 0}
> +!21 = !{!"", !22, i64 0, !23, i64 4}
> +!22 = !{!"int", !23, i64 0}
> +!23 = !{!"omnipotent char", !24, i64 0}
> +!24 = !{!"Simple C/C++ TBAA"}
> +!25 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 4,
> type: !26, isLocal: false, isDefinition: true, scopeLine: 5, flags:
> DIFlagPrototyped, isOptimized: true, unit: !2, variables: !30)
> +!26 = !DISubroutineType(types: !27)
> +!27 = !{!10, !10, !28}
> +!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !29, size: 64)
> +!29 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
> +!30 = !{!31, !32}
> +!31 = !DILocalVariable(name: "argc", arg: 1, scope: !25, file: !3, line:
> 4, type: !10)
> +!32 = !DILocalVariable(name: "argv", arg: 2, scope: !25, file: !3, line:
> 4, type: !28)
> +!33 = !DIExpression()
> +!34 = !DILocation(line: 4, column: 14, scope: !25)
> +!35 = !DILocation(line: 4, column: 27, scope: !25)
> +!36 = !DILocation(line: 6, column: 7, scope: !25)
> +!37 = !{!38, !38, i64 0}
> +!38 = !{!"any pointer", !23, i64 0}
> +!39 = !{!23, !23, i64 0}
> +!40 = !DILocation(line: 6, column: 3, scope: !25)
> +!41 = !DILocation(line: 7, column: 7, scope: !25)
> +!42 = !DILocation(line: 7, column: 3, scope: !25)
> +!43 = !DILocation(line: 8, column: 19, scope: !25)
> +!44 = !DILocation(line: 8, column: 32, scope: !25)
> +!45 = !DILocation(line: 8, column: 21, scope: !25)
> +!46 = !DILocation(line: 8, column: 3, scope: !25)
>
> Added: llvm/trunk/test/DebugInfo/Generic/global-sra-struct.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/Generic/global-sra-struct.ll?rev=310014&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/Generic/global-sra-struct.ll (added)
> +++ llvm/trunk/test/DebugInfo/Generic/global-sra-struct.ll Thu Aug  3
> 18:19:54 2017
> @@ -0,0 +1,132 @@
> +; RUN: opt -S -globalopt < %s | FileCheck %s
> +source_filename = "test.c"
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.12.0"
> +
> +%struct.mystruct = type { i32, i64 }
> +; Generated at -Os from:
> +;
> +; static struct mystruct {
> +;     int a;
> +;     long long int b;
> +; } static_struct;
> +; void __attribute__((nodebug)) foo(int in) { static_struct.a = in; }
> +; void __attribute__((nodebug)) bar(int in) { static_struct.b = in; }
> +; int main(int argc, char **argv)
> +; {
> +;     foo(argv[0][1]);
> +;     bar(argv[0][1]);
> +;     return static_struct.a + static_struct.b;
> +; }
> +
> +; CHECK: @static_struct.0 = internal unnamed_addr global i32 0, align 8,
> !dbg ![[EL0:.*]]
> +; CHECK: @static_struct.1 = internal unnamed_addr global i64 0, align 8,
> !dbg ![[EL1:.*]]
> +
> +; CHECK: ![[EL0]] = !DIGlobalVariableExpression(var: ![[VAR:.*]], expr:
> ![[EX1:.*]])
> +; CHECK: ![[VAR]] = distinct !DIGlobalVariable(name: "static_struct"
> +; CHECK: ![[EX1]] = !DIExpression(DW_OP_LLVM_fragment, 0, 32)
> +; CHECK: ![[EL1]] = !DIGlobalVariableExpression(var: ![[VAR]], expr:
> ![[EX2:.*]])
> +; CHECK: ![[EX2]] = !DIExpression(DW_OP_LLVM_fragment, 32, 64)
> +
> + at static_struct = internal global %struct.mystruct zeroinitializer, align
> 8, !dbg !0
> +
> +; Function Attrs: nounwind optsize ssp uwtable
> +define void @foo(i32 %in) #0 {
> +entry:
> +  store i32 %in, i32* getelementptr inbounds (%struct.mystruct,
> %struct.mystruct* @static_struct, i32 0, i32 0), align 8, !tbaa !17
> +  ret void
> +}
> +
> +; Function Attrs: nounwind optsize ssp uwtable
> +define void @bar(i32 %in) #0 {
> +entry:
> +  %conv = sext i32 %in to i64
> +  store i64 %conv, i64* getelementptr inbounds (%struct.mystruct,
> %struct.mystruct* @static_struct, i32 0, i32 1), align 8, !tbaa !23
> +  ret void
> +}
> +
> +; Function Attrs: nounwind optsize ssp uwtable
> +define i32 @main(i32 %argc, i8** %argv) #0 !dbg !24 {
> +entry:
> +  call void @llvm.dbg.value(metadata i32 %argc, metadata !31, metadata
> !33), !dbg !34
> +  call void @llvm.dbg.value(metadata i8** %argv, metadata !32, metadata
> !33), !dbg !35
> +  %0 = load i8*, i8** %argv, align 8, !dbg !36, !tbaa !37
> +  %arrayidx1 = getelementptr inbounds i8, i8* %0, i64 1, !dbg !36
> +  %1 = load i8, i8* %arrayidx1, align 1, !dbg !36, !tbaa !39
> +  %conv = sext i8 %1 to i32, !dbg !36
> +  call void @foo(i32 %conv) #2, !dbg !40
> +  %2 = load i8*, i8** %argv, align 8, !dbg !41, !tbaa !37
> +  %arrayidx3 = getelementptr inbounds i8, i8* %2, i64 1, !dbg !41
> +  %3 = load i8, i8* %arrayidx3, align 1, !dbg !41, !tbaa !39
> +  %conv4 = sext i8 %3 to i32, !dbg !41
> +  call void @bar(i32 %conv4) #2, !dbg !42
> +  %4 = load i32, i32* getelementptr inbounds (%struct.mystruct,
> %struct.mystruct* @static_struct, i32 0, i32 0), align 8, !dbg !43, !tbaa
> !17
> +  %conv5 = sext i32 %4 to i64, !dbg !44
> +  %5 = load i64, i64* getelementptr inbounds (%struct.mystruct,
> %struct.mystruct* @static_struct, i32 0, i32 1), align 8, !dbg !45, !tbaa
> !23
> +  %add = add nsw i64 %conv5, %5, !dbg !46
> +  %conv6 = trunc i64 %add to i32, !dbg !44
> +  ret i32 %conv6, !dbg !47
> +}
> +
> +; Function Attrs: nounwind readnone speculatable
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> +
> +; Function Attrs: nounwind readnone speculatable
> +declare void @llvm.dbg.value(metadata, metadata, metadata) #1
> +
> +attributes #0 = { nounwind optsize ssp uwtable }
> +attributes #1 = { nounwind readnone speculatable }
> +attributes #2 = { optsize }
> +
> +!llvm.dbg.cu = !{!2}
> +!llvm.module.flags = !{!12, !13, !14, !15}
> +!llvm.ident = !{!16}
> +
> +!0 = !DIGlobalVariableExpression(var: !1)
> +!1 = distinct !DIGlobalVariable(name: "static_struct", scope: !2, file:
> !3, line: 4, type: !6, isLocal: true, isDefinition: true)
> +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer:
> "clang version 6.0.0 (trunk 309852) (llvm/trunk 309850)", isOptimized:
> true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
> +!3 = !DIFile(filename: "test.c", directory: "/")
> +!4 = !{}
> +!5 = !{!0}
> +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name:
> "mystruct", file: !3, line: 1, size: 128, elements: !7)
> +!7 = !{!8, !10}
> +!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !3,
> line: 2, baseType: !9, size: 32)
> +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> +!10 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !6, file: !3,
> line: 3, baseType: !11, size: 64, offset: 64)
> +!11 = !DIBasicType(name: "long long int", size: 64, encoding:
> DW_ATE_signed)
> +!12 = !{i32 2, !"Dwarf Version", i32 4}
> +!13 = !{i32 2, !"Debug Info Version", i32 3}
> +!14 = !{i32 1, !"wchar_size", i32 4}
> +!15 = !{i32 7, !"PIC Level", i32 2}
> +!16 = !{!"clang version 6.0.0 (trunk 309852) (llvm/trunk 309850)"}
> +!17 = !{!18, !19, i64 0}
> +!18 = !{!"mystruct", !19, i64 0, !22, i64 8}
> +!19 = !{!"int", !20, i64 0}
> +!20 = !{!"omnipotent char", !21, i64 0}
> +!21 = !{!"Simple C/C++ TBAA"}
> +!22 = !{!"long long", !20, i64 0}
> +!23 = !{!18, !22, i64 8}
> +!24 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 7,
> type: !25, isLocal: false, isDefinition: true, scopeLine: 8, flags:
> DIFlagPrototyped, isOptimized: true, unit: !2, variables: !30)
> +!25 = !DISubroutineType(types: !26)
> +!26 = !{!9, !9, !27}
> +!27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !28, size: 64)
> +!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !29, size: 64)
> +!29 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
> +!30 = !{!31, !32}
> +!31 = !DILocalVariable(name: "argc", arg: 1, scope: !24, file: !3, line:
> 7, type: !9)
> +!32 = !DILocalVariable(name: "argv", arg: 2, scope: !24, file: !3, line:
> 7, type: !27)
> +!33 = !DIExpression()
> +!34 = !DILocation(line: 7, column: 14, scope: !24)
> +!35 = !DILocation(line: 7, column: 27, scope: !24)
> +!36 = !DILocation(line: 9, column: 9, scope: !24)
> +!37 = !{!38, !38, i64 0}
> +!38 = !{!"any pointer", !20, i64 0}
> +!39 = !{!20, !20, i64 0}
> +!40 = !DILocation(line: 9, column: 5, scope: !24)
> +!41 = !DILocation(line: 10, column: 9, scope: !24)
> +!42 = !DILocation(line: 10, column: 5, scope: !24)
> +!43 = !DILocation(line: 11, column: 26, scope: !24)
> +!44 = !DILocation(line: 11, column: 12, scope: !24)
> +!45 = !DILocation(line: 11, column: 44, scope: !24)
> +!46 = !DILocation(line: 11, column: 28, scope: !24)
> +!47 = !DILocation(line: 11, column: 5, scope: !24)
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170807/d2d2246d/attachment.html>


More information about the llvm-commits mailing list