Skip to content

Rust generating LLVM IR for dependencies of inline functions #40392

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
retep998 opened this issue Mar 9, 2017 · 5 comments
Closed

Rust generating LLVM IR for dependencies of inline functions #40392

retep998 opened this issue Mar 9, 2017 · 5 comments
Assignees
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. I-compiletime Issue: Problems and improvements with respect to compile times. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@retep998
Copy link
Member

retep998 commented Mar 9, 2017

Example code:

#![crate_type = "rlib"]
#[inline]
pub fn foo() -> bool {
    [1, 2] == [3, 4]
}

This is an inline function and as such it shouldn't generate any LLVM IR. If you check what the LLVM IR is with stable you see that it is pretty much empty.

; ModuleID = 'rust_out.cgu-0.rs'
source_filename = "rust_out.cgu-0.rs"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@__rustc_debug_gdb_scripts_section__ = internal unnamed_addr constant [34 x i8] c"\01gdb_load_rust_pretty_printers.py\00", section ".debug_gdb_scripts", align 1

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3}

!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "rustc version 1.15.1 (021bd294c 2017-02-08)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "rust_out", directory: "/tmp")
!2 = !{}
!3 = !{i32 2, !"Debug Info Version", i32 3}

If you switch to beta or nightly however, then the LLVM IR is filled with a bunch of junk that the function depends on, yet not the function itself.

; ModuleID = 'rust_out.cgu-0.rs'
source_filename = "rust_out.cgu-0.rs"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%"core::slice::Repr<i32>" = type { i32*, i64 }

@__rustc_debug_gdb_scripts_section__ = internal unnamed_addr constant [34 x i8] c"\01gdb_load_rust_pretty_printers.py\00", section ".debug_gdb_scripts", align 1

; Function Attrs: inlinehint uwtable
define internal i64 @_ZN4core3mem11size_of_val17h360e37c198a29e05E(i32* noalias nonnull readonly, i64) unnamed_addr #0 !dbg !4 {
entry-block:
  %tmp_ret = alloca i64
  %val = alloca { i32*, i64 }
  %arg0 = alloca { i32*, i64 }
  %2 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0
  store i32* %0, i32** %2
  %3 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1
  store i64 %1, i64* %3
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %arg0, metadata !24, metadata !26), !dbg !27
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %val, metadata !28, metadata !26), !dbg !30
  br label %start, !dbg !30

start:                                            ; preds = %entry-block
  %4 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0, !dbg !31
  %5 = load i32*, i32** %4, !dbg !31, !nonnull !2
  %6 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1, !dbg !31
  %7 = load i64, i64* %6, !dbg !31
  %8 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %val, i32 0, i32 0, !dbg !31
  store i32* %5, i32** %8, !dbg !31
  %9 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %val, i32 0, i32 1, !dbg !31
  store i64 %7, i64* %9, !dbg !31
  %10 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %val, i32 0, i32 0, !dbg !32
  %11 = load i32*, i32** %10, !dbg !32, !nonnull !2
  %12 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %val, i32 0, i32 1, !dbg !32
  %13 = load i64, i64* %12, !dbg !32
  %14 = mul i64 %13, 4, !dbg !32
  store i64 %14, i64* %tmp_ret, !dbg !32
  %15 = load i64, i64* %tmp_ret, !dbg !32
  br label %bb1, !dbg !32

bb1:                                              ; preds = %start
  ret i64 %15, !dbg !33
}

; Function Attrs: uwtable
define internal zeroext i1 @"_ZN4core5slice81_$LT$impl$u20$core..cmp..PartialEq$LT$$u5b$B$u5d$$GT$$u20$for$u20$$u5b$A$u5d$$GT$2eq17h6dec557eb728ce87E"(i32* noalias nonnull readonly, i64, i32* noalias nonnull readonly, i64) unnamed_addr #1 !dbg !34 {
entry-block:
  %other = alloca { i32*, i64 }
  %self = alloca { i32*, i64 }
  %arg1 = alloca { i32*, i64 }
  %arg0 = alloca { i32*, i64 }
  %4 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0
  store i32* %0, i32** %4
  %5 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1
  store i64 %1, i64* %5
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %arg0, metadata !44, metadata !26), !dbg !45
  %6 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg1, i32 0, i32 0
  store i32* %2, i32** %6
  %7 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg1, i32 0, i32 1
  store i64 %3, i64* %7
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %arg1, metadata !46, metadata !26), !dbg !45
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %self, metadata !47, metadata !26), !dbg !49
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %other, metadata !50, metadata !26), !dbg !49
  br label %start, !dbg !49

start:                                            ; preds = %entry-block
  %8 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0, !dbg !51
  %9 = load i32*, i32** %8, !dbg !51, !nonnull !2
  %10 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1, !dbg !51
  %11 = load i64, i64* %10, !dbg !51
  %12 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !51
  store i32* %9, i32** %12, !dbg !51
  %13 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !51
  store i64 %11, i64* %13, !dbg !51
  %14 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg1, i32 0, i32 0, !dbg !51
  %15 = load i32*, i32** %14, !dbg !51, !nonnull !2
  %16 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg1, i32 0, i32 1, !dbg !51
  %17 = load i64, i64* %16, !dbg !51
  %18 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 0, !dbg !51
  store i32* %15, i32** %18, !dbg !51
  %19 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 1, !dbg !51
  store i64 %17, i64* %19, !dbg !51
  %20 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !52
  %21 = load i32*, i32** %20, !dbg !52, !nonnull !2
  %22 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !52
  %23 = load i64, i64* %22, !dbg !52
  %24 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 0, !dbg !52
  %25 = load i32*, i32** %24, !dbg !52, !nonnull !2
  %26 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 1, !dbg !52
  %27 = load i64, i64* %26, !dbg !52
  %28 = call zeroext i1 @"_ZN68_$LT$$u5b$A$u5d$$u20$as$u20$core..slice..SlicePartialEq$LT$A$GT$$GT$5equal17h29b0745304278f2eE"(i32* noalias nonnull readonly %21, i64 %23, i32* noalias nonnull readonly %25, i64 %27), !dbg !52
  br label %bb1, !dbg !52

bb1:                                              ; preds = %start
  ret i1 %28, !dbg !53
}

; Function Attrs: inlinehint uwtable
define internal i64 @"_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$3len17h6e1c3544d59ef48dE"(i32* noalias nonnull readonly, i64) unnamed_addr #0 !dbg !54 {
entry-block:
  %transmute_temp = alloca %"core::slice::Repr<i32>"
  %self = alloca { i32*, i64 }
  %arg0 = alloca { i32*, i64 }
  %2 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0
  store i32* %0, i32** %2
  %3 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1
  store i64 %1, i64* %3
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %arg0, metadata !58, metadata !26), !dbg !59
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %self, metadata !60, metadata !26), !dbg !62
  br label %start, !dbg !62

start:                                            ; preds = %entry-block
  %4 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0, !dbg !63
  %5 = load i32*, i32** %4, !dbg !63, !nonnull !2
  %6 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1, !dbg !63
  %7 = load i64, i64* %6, !dbg !63
  %8 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !63
  store i32* %5, i32** %8, !dbg !63
  %9 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !63
  store i64 %7, i64* %9, !dbg !63
  %10 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !64
  %11 = load i32*, i32** %10, !dbg !64, !nonnull !2
  %12 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !64
  %13 = load i64, i64* %12, !dbg !64
  %14 = bitcast %"core::slice::Repr<i32>"* %transmute_temp to { i32*, i64 }*, !dbg !64
  %15 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %14, i32 0, i32 0, !dbg !64
  store i32* %11, i32** %15, align 8, !dbg !64
  %16 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %14, i32 0, i32 1, !dbg !64
  store i64 %13, i64* %16, align 8, !dbg !64
  %17 = getelementptr inbounds %"core::slice::Repr<i32>", %"core::slice::Repr<i32>"* %transmute_temp, i32 0, i32 0, !dbg !64
  %18 = getelementptr inbounds %"core::slice::Repr<i32>", %"core::slice::Repr<i32>"* %transmute_temp, i32 0, i32 1, !dbg !64
  %19 = load i32*, i32** %17, !dbg !64
  %20 = load i64, i64* %18, !dbg !64
  br label %bb1, !dbg !64

bb1:                                              ; preds = %start
  ret i64 %20, !dbg !65
}

; Function Attrs: inlinehint uwtable
define internal i32* @"_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$6as_ptr17h3d03e9129c948913E"(i32* noalias nonnull readonly, i64) unnamed_addr #0 !dbg !66 {
entry-block:
  %self = alloca { i32*, i64 }
  %arg0 = alloca { i32*, i64 }
  %2 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0
  store i32* %0, i32** %2
  %3 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1
  store i64 %1, i64* %3
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %arg0, metadata !69, metadata !26), !dbg !70
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %self, metadata !71, metadata !26), !dbg !73
  br label %start, !dbg !73

start:                                            ; preds = %entry-block
  %4 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0, !dbg !74
  %5 = load i32*, i32** %4, !dbg !74, !nonnull !2
  %6 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1, !dbg !74
  %7 = load i64, i64* %6, !dbg !74
  %8 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !74
  store i32* %5, i32** %8, !dbg !74
  %9 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !74
  store i64 %7, i64* %9, !dbg !74
  %10 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !75
  %11 = load i32*, i32** %10, !dbg !75, !nonnull !2
  %12 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !75
  %13 = load i64, i64* %12, !dbg !75
  ret i32* %11, !dbg !76
}

; Function Attrs: uwtable
define internal zeroext i1 @"_ZN68_$LT$$u5b$A$u5d$$u20$as$u20$core..slice..SlicePartialEq$LT$A$GT$$GT$5equal17h29b0745304278f2eE"(i32* noalias nonnull readonly, i64, i32* noalias nonnull readonly, i64) unnamed_addr #1 !dbg !77 {
entry-block:
  %size = alloca i64
  %_11 = alloca {}
  %_5 = alloca {}
  %other = alloca { i32*, i64 }
  %self = alloca { i32*, i64 }
  %_0 = alloca i8
  %arg1 = alloca { i32*, i64 }
  %arg0 = alloca { i32*, i64 }
  %4 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0
  store i32* %0, i32** %4
  %5 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1
  store i64 %1, i64* %5
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %arg0, metadata !80, metadata !26), !dbg !81
  %6 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg1, i32 0, i32 0
  store i32* %2, i32** %6
  %7 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg1, i32 0, i32 1
  store i64 %3, i64* %7
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %arg1, metadata !82, metadata !26), !dbg !81
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %self, metadata !83, metadata !26), !dbg !85
  call void @llvm.dbg.declare(metadata { i32*, i64 }* %other, metadata !86, metadata !26), !dbg !85
  call void @llvm.dbg.declare(metadata i64* %size, metadata !87, metadata !26), !dbg !89
  br label %start, !dbg !89

start:                                            ; preds = %entry-block
  %8 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 0, !dbg !90
  %9 = load i32*, i32** %8, !dbg !90, !nonnull !2
  %10 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg0, i32 0, i32 1, !dbg !90
  %11 = load i64, i64* %10, !dbg !90
  %12 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !90
  store i32* %9, i32** %12, !dbg !90
  %13 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !90
  store i64 %11, i64* %13, !dbg !90
  %14 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg1, i32 0, i32 0, !dbg !90
  %15 = load i32*, i32** %14, !dbg !90, !nonnull !2
  %16 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %arg1, i32 0, i32 1, !dbg !90
  %17 = load i64, i64* %16, !dbg !90
  %18 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 0, !dbg !90
  store i32* %15, i32** %18, !dbg !90
  %19 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 1, !dbg !90
  store i64 %17, i64* %19, !dbg !90
  %20 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !91
  %21 = load i32*, i32** %20, !dbg !91, !nonnull !2
  %22 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !91
  %23 = load i64, i64* %22, !dbg !91
  %24 = call i64 @"_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$3len17h6e1c3544d59ef48dE"(i32* noalias nonnull readonly %21, i64 %23), !dbg !91
  br label %bb1, !dbg !91

bb1:                                              ; preds = %start
  %25 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 0, !dbg !91
  %26 = load i32*, i32** %25, !dbg !91, !nonnull !2
  %27 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 1, !dbg !91
  %28 = load i64, i64* %27, !dbg !91
  %29 = call i64 @"_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$3len17h6e1c3544d59ef48dE"(i32* noalias nonnull readonly %26, i64 %28), !dbg !91
  br label %bb2, !dbg !91

bb2:                                              ; preds = %bb1
  %30 = icmp ne i64 %24, %29, !dbg !91
  br i1 %30, label %bb3, label %bb4, !dbg !91

bb3:                                              ; preds = %bb2
  store i8 0, i8* %_0, !dbg !92
  br label %bb6, !dbg !92

bb4:                                              ; preds = %bb2
  %31 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !93
  %32 = load i32*, i32** %31, !dbg !93, !nonnull !2
  %33 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !93
  %34 = load i64, i64* %33, !dbg !93
  %35 = call i32* @"_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$6as_ptr17h3d03e9129c948913E"(i32* noalias nonnull readonly %32, i64 %34), !dbg !93
  br label %bb7, !dbg !93

bb5:                                              ; preds = %bb6, %bb14
  %36 = load i8, i8* %_0, !dbg !94, !range !95
  %37 = trunc i8 %36 to i1, !dbg !94
  ret i1 %37, !dbg !94

bb6:                                              ; preds = %bb3, %bb9
  br label %bb5, !dbg !96

bb7:                                              ; preds = %bb4
  %38 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 0, !dbg !93
  %39 = load i32*, i32** %38, !dbg !93, !nonnull !2
  %40 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 1, !dbg !93
  %41 = load i64, i64* %40, !dbg !93
  %42 = call i32* @"_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$6as_ptr17h3d03e9129c948913E"(i32* noalias nonnull readonly %39, i64 %41), !dbg !93
  br label %bb8, !dbg !93

bb8:                                              ; preds = %bb7
  %43 = icmp eq i32* %35, %42, !dbg !93
  br i1 %43, label %bb9, label %bb10, !dbg !93

bb9:                                              ; preds = %bb8
  store i8 1, i8* %_0, !dbg !97
  br label %bb6, !dbg !97

bb10:                                             ; preds = %bb8
  %44 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !98
  %45 = load i32*, i32** %44, !dbg !98, !nonnull !2
  %46 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !98
  %47 = load i64, i64* %46, !dbg !98
  %48 = call i64 @_ZN4core3mem11size_of_val17h360e37c198a29e05E(i32* noalias nonnull readonly %45, i64 %47), !dbg !98
  store i64 %48, i64* %size, !dbg !98
  br label %bb11, !dbg !98

bb11:                                             ; preds = %bb10
  %49 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 0, !dbg !99
  %50 = load i32*, i32** %49, !dbg !99, !nonnull !2
  %51 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %self, i32 0, i32 1, !dbg !99
  %52 = load i64, i64* %51, !dbg !99
  %53 = call i32* @"_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$6as_ptr17h3d03e9129c948913E"(i32* noalias nonnull readonly %50, i64 %52), !dbg !99
  br label %bb12, !dbg !99

bb12:                                             ; preds = %bb11
  %54 = bitcast i32* %53 to i8*, !dbg !99
  %55 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 0, !dbg !100
  %56 = load i32*, i32** %55, !dbg !100, !nonnull !2
  %57 = getelementptr inbounds { i32*, i64 }, { i32*, i64 }* %other, i32 0, i32 1, !dbg !100
  %58 = load i64, i64* %57, !dbg !100
  %59 = call i32* @"_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$6as_ptr17h3d03e9129c948913E"(i32* noalias nonnull readonly %56, i64 %58), !dbg !100
  br label %bb13, !dbg !100

bb13:                                             ; preds = %bb12
  %60 = bitcast i32* %59 to i8*, !dbg !100
  %61 = load i64, i64* %size, !dbg !100
  %62 = call i32 @memcmp(i8* %54, i8* %60, i64 %61), !dbg !99
  br label %bb14, !dbg !99

bb14:                                             ; preds = %bb13
  %63 = icmp eq i32 %62, 0, !dbg !99
  %64 = zext i1 %63 to i8, !dbg !99
  store i8 %64, i8* %_0, !dbg !99
  br label %bb5, !dbg !94
}

; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata, metadata) #2

; Function Attrs: nounwind
declare i32 @memcmp(i8*, i8*, i64) unnamed_addr #3

attributes #0 = { inlinehint uwtable "no-frame-pointer-elim"="true" }
attributes #1 = { uwtable "no-frame-pointer-elim"="true" }
attributes #2 = { nounwind readnone }
attributes #3 = { nounwind "no-frame-pointer-elim"="true" }

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3}

!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "rustc version 1.16.0-beta.3 (ecbf0b59e 2017-03-02)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "rust_out", directory: "/tmp")
!2 = !{}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = distinct !DISubprogram(name: "size_of_val<[i32]>", linkageName: "_ZN4core3mem18size_of_val<[i32]>E", scope: !6, file: !5, line: 217, type: !9, isLocal: false, isDefinition: true, scopeLine: 217, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !19, variables: !2)
!5 = !DIFile(filename: "/buildslave/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/mem.rs", directory: "/tmp")
!6 = !DINamespace(name: "mem", scope: !7, file: !5, line: 11)
!7 = !DINamespace(name: "core", scope: null, file: !8, line: 11)
!8 = !DIFile(filename: "/buildslave/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/lib.rs", directory: "/tmp")
!9 = !DISubroutineType(types: !10)
!10 = !{!11, !12}
!11 = !DIBasicType(name: "usize", size: 64, align: 64, encoding: DW_ATE_unsigned)
!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "&[i32]", file: !13, size: 128, align: 64, elements: !14, identifier: "a5cff9aaa9457687cc2319407c8037a34d60d3c2")
!13 = !DIFile(filename: "<unknown>", directory: "")
!14 = !{!15, !18}
!15 = !DIDerivedType(tag: DW_TAG_member, name: "data_ptr", scope: !12, file: !13, baseType: !16, size: 64, align: 64)
!16 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const i32", baseType: !17, size: 64, align: 64)
!17 = !DIBasicType(name: "i32", size: 32, align: 32, encoding: DW_ATE_signed)
!18 = !DIDerivedType(tag: DW_TAG_member, name: "length", scope: !12, file: !13, baseType: !11, size: 64, align: 64, offset: 64)
!19 = !{!20}
!20 = !DITemplateTypeParameter(name: "T", type: !21)
!21 = !DICompositeType(tag: DW_TAG_array_type, baseType: !17, align: 32, elements: !22)
!22 = !{!23}
!23 = !DISubrange(count: -1)
!24 = !DILocalVariable(name: "val", arg: 1, scope: !4, file: !25, line: 1, type: !12)
!25 = !DIFile(filename: "<anon>", directory: "/tmp")
!26 = !DIExpression()
!27 = !DILocation(line: 1, scope: !4)
!28 = !DILocalVariable(name: "val", scope: !29, file: !5, line: 217, type: !12)
!29 = distinct !DILexicalBlock(scope: !4, file: !5, line: 217, column: 48)
!30 = !DILocation(line: 217, scope: !29)
!31 = !DILocation(line: 217, scope: !4)
!32 = !DILocation(line: 218, scope: !29)
!33 = !DILocation(line: 219, scope: !29)
!34 = distinct !DISubprogram(name: "eq<i32,i32>", linkageName: "_ZN4core5slice8{{impl}}11eq<i32,i32>E", scope: !36, file: !35, line: 2193, type: !38, isLocal: false, isDefinition: true, scopeLine: 2193, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !41, variables: !2)
!35 = !DIFile(filename: "/buildslave/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/slice.rs", directory: "/tmp")
!36 = !DINamespace(name: "{{impl}}", scope: !37, file: !35, line: 2192)
!37 = !DINamespace(name: "slice", scope: !7, file: !35, line: 11)
!38 = !DISubroutineType(types: !39)
!39 = !{!40, !12, !12}
!40 = !DIBasicType(name: "bool", size: 8, align: 8, encoding: DW_ATE_boolean)
!41 = !{!42, !43}
!42 = !DITemplateTypeParameter(name: "A", type: !17)
!43 = !DITemplateTypeParameter(name: "B", type: !17)
!44 = !DILocalVariable(name: "self", arg: 1, scope: !34, file: !25, line: 1, type: !12)
!45 = !DILocation(line: 1, scope: !34)
!46 = !DILocalVariable(name: "other", arg: 2, scope: !34, file: !25, line: 1, type: !12)
!47 = !DILocalVariable(name: "self", scope: !48, file: !35, line: 2193, type: !12)
!48 = distinct !DILexicalBlock(scope: !34, file: !35, line: 2193, column: 38)
!49 = !DILocation(line: 2193, scope: !48)
!50 = !DILocalVariable(name: "other", scope: !48, file: !35, line: 2193, type: !12)
!51 = !DILocation(line: 2193, scope: !34)
!52 = !DILocation(line: 2194, scope: !48)
!53 = !DILocation(line: 2195, scope: !48)
!54 = distinct !DISubprogram(name: "len<i32>", linkageName: "_ZN4core5slice8{{impl}}8len<i32>E", scope: !55, file: !35, line: 348, type: !9, isLocal: false, isDefinition: true, scopeLine: 348, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !56, variables: !2)
!55 = !DINamespace(name: "{{impl}}", scope: !37, file: !35, line: 211)
!56 = !{!57}
!57 = !DITemplateTypeParameter(name: "T", type: !17)
!58 = !DILocalVariable(name: "self", arg: 1, scope: !54, file: !25, line: 1, type: !12)
!59 = !DILocation(line: 1, scope: !54)
!60 = !DILocalVariable(name: "self", scope: !61, file: !35, line: 348, type: !12)
!61 = distinct !DILexicalBlock(scope: !54, file: !35, line: 348, column: 27)
!62 = !DILocation(line: 348, scope: !61)
!63 = !DILocation(line: 348, scope: !54)
!64 = !DILocation(line: 350, scope: !61)
!65 = !DILocation(line: 352, scope: !61)
!66 = distinct !DISubprogram(name: "as_ptr<i32>", linkageName: "_ZN4core5slice8{{impl}}11as_ptr<i32>E", scope: !55, file: !35, line: 321, type: !67, isLocal: false, isDefinition: true, scopeLine: 321, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !56, variables: !2)
!67 = !DISubroutineType(types: !68)
!68 = !{!16, !12}
!69 = !DILocalVariable(name: "self", arg: 1, scope: !66, file: !25, line: 1, type: !12)
!70 = !DILocation(line: 1, scope: !66)
!71 = !DILocalVariable(name: "self", scope: !72, file: !35, line: 321, type: !12)
!72 = distinct !DILexicalBlock(scope: !66, file: !35, line: 321, column: 33)
!73 = !DILocation(line: 321, scope: !72)
!74 = !DILocation(line: 321, scope: !66)
!75 = !DILocation(line: 322, scope: !72)
!76 = !DILocation(line: 323, scope: !72)
!77 = distinct !DISubprogram(name: "equal<i32>", linkageName: "_ZN4core5slice8{{impl}}10equal<i32>E", scope: !78, file: !35, line: 2250, type: !38, isLocal: false, isDefinition: true, scopeLine: 2250, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !79, variables: !2)
!78 = !DINamespace(name: "{{impl}}", scope: !37, file: !35, line: 2247)
!79 = !{!42}
!80 = !DILocalVariable(name: "self", arg: 1, scope: !77, file: !25, line: 1, type: !12)
!81 = !DILocation(line: 1, scope: !77)
!82 = !DILocalVariable(name: "other", arg: 2, scope: !77, file: !25, line: 1, type: !12)
!83 = !DILocalVariable(name: "self", scope: !84, file: !35, line: 2250, type: !12)
!84 = distinct !DILexicalBlock(scope: !77, file: !35, line: 2250, column: 41)
!85 = !DILocation(line: 2250, scope: !84)
!86 = !DILocalVariable(name: "other", scope: !84, file: !35, line: 2250, type: !12)
!87 = !DILocalVariable(name: "size", scope: !88, file: !35, line: 2258, type: !11)
!88 = distinct !DILexicalBlock(scope: !84, file: !35, line: 2258, column: 46)
!89 = !DILocation(line: 2258, scope: !88)
!90 = !DILocation(line: 2250, scope: !77)
!91 = !DILocation(line: 2251, scope: !84)
!92 = !DILocation(line: 2252, scope: !84)
!93 = !DILocation(line: 2254, scope: !84)
!94 = !DILocation(line: 2262, scope: !84)
!95 = !{i8 0, i8 2}
!96 = !DILocation(line: 2252, scope: !77)
!97 = !DILocation(line: 2255, scope: !84)
!98 = !DILocation(line: 2258, scope: !84)
!99 = !DILocation(line: 2259, scope: !88)
!100 = !DILocation(line: 2260, scope: !88)
@michaelwoerister
Copy link
Member

Interesting. @eddyb, might this be related to some reachability changes because of impl Trait?

@eddyb
Copy link
Member

eddyb commented Mar 9, 2017

Doubt it, the function itself isn't translated, just its dependencies.

@Mark-Simulacrum Mark-Simulacrum added the I-compiletime Issue: Problems and improvements with respect to compile times. label May 28, 2017
@Mark-Simulacrum Mark-Simulacrum added C-enhancement Category: An issue proposing an enhancement or a PR with one. regression-from-stable-to-stable Performance or correctness regression from one stable version to another. labels Jul 27, 2017
@andjo403
Copy link
Contributor

@michaelwoerister the commit 5f90947 is the first commit where this regression is triggered.
This is still a regression https://godbolt.org/g/yAAJaJ.
Have tried to find why this is happening but I'm not that familiar with the compiler code so can not find it.

@michaelwoerister
Copy link
Member

I completely forgot about that. Nominating for priority assignment.

@michaelwoerister michaelwoerister added I-nominated T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 11, 2017
@nikomatsakis
Copy link
Contributor

triage: P-medium

@rust-highfive rust-highfive added P-medium Medium priority and removed I-nominated labels Oct 19, 2017
bors added a commit that referenced this issue Nov 8, 2017
…ikomatsakis

Only instantiate inline- and const-fns if they are referenced (again).

It seems that we have regressed on not translating `#[inline]` functions unless they are actually used. This should bring back this optimization. I also added a regression test this time so it doesn't happen again accidentally.

Fixes #40392.

r? @alexcrichton

UPDATE & PSA
---------------------
This patch **makes translation very lazy** -- in general this is a good thing (we don't want the compiler to do unnecessary work) but it has two consequences:
1. Some error messages are only generated when an item is actually translated. Consequently, this patch will lead to more cases where the compiler will only start emitting errors when the erroneous function is actually used. This has always been true to some extend (e.g. when passing generic values to an intrinsic) but since this is something user-facing it's worth mentioning.
2. When writing tests, one has to make sure that the functions in question are actually generated. In other words, it must not be dead code. This can usually  be achieved by either
    1. making sure the function is exported from the resulting binary or
    2. by making sure the function is called from something that is exported (or `main()`).

Note that it depends on the crate type what functions are exported:
   1. For rlibs and dylibs everything that is reachable from the outside is exported.
   2. For executables, cdylibs, and staticlibs, items are only exported if they are additionally `#[no_mangle]` or have an `#[export_name]`.

The commits in this PR contain many examples of how tests can be updated to comply to the new requirements.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. I-compiletime Issue: Problems and improvements with respect to compile times. P-medium Medium priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants