ThinLTO Bug ?

Hi

I have encountered a module verification failure when running 2 files
with thin-lto (I hit this bug in the link step in LTO on a really
large program and I reduced to this test case).

~/llvmfb/build-debug/bin/llvm-lto2 run -o c a.o b.o -r a.o,c,px -r
b.o,a,px -r b.o,b,px -r a.o,gv -r b.o,gv
Called function is not the same type as the call!
%2 = call i1 bitcast (i1 (%struct.TA*)* @b to i1 (%0*)*)(%struct.TA* %0)
in function a
LLVM ERROR: Broken function found, compilation aborted!

My understanding why this is happening is roughly as follow. I would
like to check with people whether this is a real bug. And also would
like to help fixing it with other people’s help if it’s a real bug. I
am quite new to this part of LLVM.

1. DICompositeType “SHARED” in a.ll is ODRed with the one in b.ll at load time.
2. %struct.TA.0 (renamed from %struct.TA at load time) = type opaque
and i1 (%struct.TA.0*)* @b in b.ll gets pulled into the destination
module when we are merging in a.ll.
3. We only found out that %struct.TA.0 maps to %struct.TA when we link
in b.ll because of the @gv global variable.
4. Then we have a problem, because declare i1 @b(%struct.TA.0*) in
a.ll should have been remapped due to what we found in #3, but was
not. This eventually leads to the IR verifier failure.

Thanks
-Xin

Commands to reproduce with ToT LLVM:

From: llvm-dev [mailto:llvm-dev-bounces@lists.llvm.org] On Behalf Of Xin
Tong via llvm-dev
Sent: Friday, July 27, 2018 9:33 PM
To: llvm-dev
Subject: [llvm-dev] ThinLTO Bug ?

Hi

I have encountered a module verification failure when running 2 files
with thin-lto (I hit this bug in the link step in LTO on a really
large program and I reduced to this test case).

~/llvmfb/build-debug/bin/llvm-lto2 run -o c a.o b.o -r a.o,c,px -r
b.o,a,px -r b.o,b,px -r a.o,gv -r b.o,gv
Called function is not the same type as the call!
%2 = call i1 bitcast (i1 (%struct.TA*)* @b to i1 (%0*)*)(%struct.TA* %0)
in function a
LLVM ERROR: Broken function found, compilation aborted!

My understanding why this is happening is roughly as follow. I would
like to check with people whether this is a real bug. And also would
like to help fixing it with other people’s help if it’s a real bug. I
am quite new to this part of LLVM.

1. DICompositeType “SHARED” in a.ll is ODRed with the one in b.ll at load
time.

I know relatively little about LTO but I see that in a.ll, "SHARED" is
described as a DW_TAG_class_type while in b.ll it is DW_TAG_array_type.
This suggests that you have an ODR violation in your source code.

ODR violations in LTO tend to exhibit as a "broken module" or "broken
function" at link time. It would be nice to diagnose these better,
admittedly.
--paulr

> From: llvm-dev [mailto:llvm-dev-bounces@lists.llvm.org] On Behalf Of Xin
> Tong via llvm-dev
> Sent: Friday, July 27, 2018 9:33 PM
> To: llvm-dev
> Subject: [llvm-dev] ThinLTO Bug ?
>
> Hi
>
> I have encountered a module verification failure when running 2 files
> with thin-lto (I hit this bug in the link step in LTO on a really
> large program and I reduced to this test case).
>
>
> ~/llvmfb/build-debug/bin/llvm-lto2 run -o c a.o b.o -r a.o,c,px -r
> b.o,a,px -r b.o,b,px -r a.o,gv -r b.o,gv
> Called function is not the same type as the call!
> %2 = call i1 bitcast (i1 (%struct.TA*)* @b to i1 (%0*)*)(%struct.TA* %0)
> in function a
> LLVM ERROR: Broken function found, compilation aborted!
>
>
> My understanding why this is happening is roughly as follow. I would
> like to check with people whether this is a real bug. And also would
> like to help fixing it with other people’s help if it’s a real bug. I
> am quite new to this part of LLVM.
>
> 1. DICompositeType “SHARED” in a.ll is ODRed with the one in b.ll at load
> time.

I know relatively little about LTO but I see that in a.ll, "SHARED" is
described as a DW_TAG_class_type while in b.ll it is DW_TAG_array_type.
This suggests that you have an ODR violation in your source code.

Hi Paul

Thanks for pointing it out.
I fixed this by making in b.ll and the same failure persists.
!9 = !DICompositeType(tag: DW_TAG_class_type, file: !3, identifier:
"SHARED", scope: !8)

-Xin

I took a quick look and it looks like the declare of @b is fine, but the call in @a is using a different type (the “type opaque”). I dumped the module at the point of the failure, shown below. This was with the change of !9 in a.ll to be a class type.

Xin - can you file a bug and cc me on it and also reply here with the bug number? I am traveling all this week and next and likely won’t have a chance to look more until afterwards. Hopefully someone else can take a look in the meantime.

Teresa

; ModuleID = ‘ld-temp.o’
source_filename = “ld-temp.o”
target datalayout = “e-m:e-i64:64-f80:128-n8:16:32:64-S128”
target triple = “x86_64-unknown-linux-gnu”

%0 = type opaque
%struct.TA = type {}

@gv = external dso_local global %struct.TA*

define i32 @c() !dbg !13 {
%1 = bitcast %struct.TA** @gv to i8*
unreachable
}

declare i1 @b(%struct.TA*)

define i1 @a(%struct.TA*) {
%2 = call i1 bitcast (i1 (%struct.TA*)* @b to i1 (%0*))(%struct.TA %0)
unreachable
}

llvm.dbg.cu = !{!0, !6}
!llvm.module.flags = !{!11, !12}

!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, retainedTypes: !2)
!1 = !DIFile(filename: “f2”, directory: “”)
!2 = !{!3}
!3 = distinct !DICompositeType(tag: DW_TAG_class_type, scope: !5, file: !4, identifier: “SHARED”)
!4 = !DIFile(filename: “f1”, directory: “”)
!5 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false, unit: !6)
!6 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !4, isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, retainedTypes: !7)
!7 = !{!8, !3}
!8 = !DICompositeType(tag: DW_TAG_class_type, scope: !5, file: !4, templateParams: !9)
!9 = !{!10}
!10 = !DITemplateValueParameter(value: i1 (%0*)* bitcast (i1 (%struct.TA*)* @b to i1 (%0*)*))
!11 = !{i32 2, !“Debug Info Version”, i32 3}
!12 = !{i32 1, !“ThinLTO”, i32 0}
!13 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false, unit: !0)

Hi Teresa

I file a bug here. https://bugs.llvm.org/show_bug.cgi?id=38372

Thanks
-Xin