| ; RUN: split-file %s %t | |
| ; RUN: opt -S -passes=mergefunc %t/coff.ll | FileCheck %s --check-prefix=COFF | |
| ; RUN: opt -S -passes=mergefunc %t/coff-noalias.ll | \ | |
| ; RUN: FileCheck %s --check-prefix=NOALIAS | |
| ; RUN: opt -S -passes=mergefunc -mergefunc-use-aliases %t/coff-odr.ll | \ | |
| ; RUN: FileCheck %s --check-prefix=ODR | |
| ; RUN: opt -S -passes=mergefunc %t/elf.ll | FileCheck %s --check-prefix=ELF | |
| ; A COFF weak external names the symbol it resolves to, and a local symbol | |
| ; cannot be named, so an alias must keep pointing at an external definition. | |
| ;--- coff.ll | |
| target triple = "x86_64-pc-windows-msvc" | |
| ; @f is local, so @g is kept as a thunk rather than replaced, and the alias | |
| ; goes on naming @g. | |
| ; COFF: @alias_g = weak alias i32 (i32), ptr @g | |
| ; COFF: define internal i32 @f | |
| ; COFF: define linkonce_odr i32 @g | |
| @alias_g = weak alias i32 (i32), ptr @g | |
| define internal i32 @f(i32 %x) { | |
| %a = mul i32 %x, 3 | |
| %b = add i32 %a, 7 | |
| ret i32 %b | |
| } | |
| define linkonce_odr i32 @g(i32 %x) unnamed_addr { | |
| %a = mul i32 %x, 3 | |
| %b = add i32 %a, 7 | |
| ret i32 %b | |
| } | |
| ;--- coff-noalias.ll | |
| target triple = "x86_64-pc-windows-msvc" | |
| ; Without an alias naming it, @g is replaced as usual. | |
| ; NOALIAS: define internal i32 @f | |
| ; NOALIAS: call i32 @f | |
| define internal i32 @f(i32 %x) { | |
| %a = mul i32 %x, 3 | |
| %b = add i32 %a, 7 | |
| ret i32 %b | |
| } | |
| define linkonce_odr i32 @g(i32 %x) unnamed_addr { | |
| %a = mul i32 %x, 3 | |
| %b = add i32 %a, 7 | |
| ret i32 %b | |
| } | |
| define i32 @use() { | |
| %r = call i32 @g(i32 1) | |
| ret i32 %r | |
| } | |
| ;--- coff-odr.ll | |
| target triple = "x86_64-pc-windows-msvc" | |
| ; The shared body is private, so both halves get a thunk instead of an alias | |
| ; even though aliases are enabled. | |
| ; ODR-NOT: alias i32 | |
| ; ODR-DAG: define weak_odr i32 @f | |
| ; ODR-DAG: define weak_odr i32 @g | |
| define weak_odr i32 @f(i32 %x) unnamed_addr { | |
| %a = mul i32 %x, 3 | |
| %b = add i32 %a, 7 | |
| %c = add i32 %b, 1 | |
| ret i32 %c | |
| } | |
| define weak_odr i32 @g(i32 %x) unnamed_addr { | |
| %a = mul i32 %x, 3 | |
| %b = add i32 %a, 7 | |
| %c = add i32 %b, 1 | |
| ret i32 %c | |
| } | |
| ;--- elf.ll | |
| target triple = "x86_64-unknown-linux-gnu" | |
| ; Other formats can alias a local symbol, so @g is replaced there. | |
| ; ELF: @alias_g = weak alias i32 (i32), ptr @f | |
| ; ELF: define internal i32 @f | |
| ; ELF-NOT: define {{.*}} @g | |
| @alias_g = weak alias i32 (i32), ptr @g | |
| define internal i32 @f(i32 %x) { | |
| %a = mul i32 %x, 3 | |
| %b = add i32 %a, 7 | |
| ret i32 %b | |
| } | |
| define linkonce_odr i32 @g(i32 %x) unnamed_addr { | |
| %a = mul i32 %x, 3 | |
| %b = add i32 %a, 7 | |
| ret i32 %b | |
| } |