Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -277,8 +277,7 @@ auto GUID = Ref.getGUID(); auto *RefSummary = FindGlobalSummaryInModule(GUID); if (RefSummary) - // Found a ref in the current module, mark it as exported - ExportList.insert(GUID); + exportGlobalInModule(Index, ExportModulePath, GUID, ExportList); } } Index: test/ThinLTO/X86/Inputs/global_const.ll =================================================================== --- /dev/null +++ test/ThinLTO/X86/Inputs/global_const.ll @@ -0,0 +1,23 @@ +; ModuleID = 'global_const_input.o' +source_filename = "global_const_input.cc" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 + +; Function Attrs: norecurse uwtable +define i32 @main() local_unnamed_addr #0 { +entry: + %call = tail call i32 ()* @_Z8GetCallNii(i32 1, i32 1) + %call1 = tail call i32 %call() + %call2 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %call1) + %call3 = tail call i32 ()* @_Z8GetCallNii(i32 2, i32 1) + %call4 = tail call i32 %call3() + %call5 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %call4) + ret i32 0 +} + +; Function Attrs: nounwind +declare i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr #1 + +declare i32 ()* @_Z8GetCallNii(i32, i32) local_unnamed_addr #2 Index: test/ThinLTO/X86/global_const.ll =================================================================== --- /dev/null +++ test/ThinLTO/X86/global_const.ll @@ -0,0 +1,61 @@ +; Ensure we promote global variables referenced indirectly due to exported +; unnamed_addr constant switch.table + +; Do setup work for all below tests: generate bitcode and combined index +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %p/Inputs/global_const.ll -o %t2.bc +; RUN: llvm-lto -thinlto-action=thinlink -o %t3.bc %t1.bc %t2.bc + +; RUN: llvm-lto -thinlto-action=promote %t1.bc -thinlto-index=%t3.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=EXPORT + +; RUN: llvm-lto2 %t1.bc %t2.bc -o %t.o -save-temps \ +; RUN: -r=%t1.bc,_Z8GetCallNii,pxl \ +; RUN: -r=%t2.bc,main,pxl \ +; RUN: -r=%t2.bc,printf,pxl \ +; RUN: -r=%t2.bc,_Z8GetCallNii, +; RUN: llvm-dis < %t.o.0.1.promote.bc | FileCheck %s --check-prefix=EXPORT + +; EXPORT-DAG: define hidden i32 @_ZL5CallXv.llvm.0 +; EXPORT-DAG: define hidden i32 @_ZL5CallYv.llvm.0 + +; ModuleID = 'global_const.o' +source_filename = "global_const.cc" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@_ZL6Funcs0 = internal unnamed_addr constant [4 x i32 ()*] [i32 ()* @_ZL5CallXv, i32 ()* @_ZL5CallYv, i32 ()* @_ZL5CallYv, i32 ()* @_ZL5CallYv], align 16 +@_ZL6Funcs1 = internal unnamed_addr constant [4 x i32 ()*] [i32 ()* @_ZL5CallYv, i32 ()* @_ZL5CallXv, i32 ()* @_ZL5CallYv, i32 ()* @_ZL5CallYv], align 16 +@_ZL6Funcs2 = internal unnamed_addr constant [4 x i32 ()*] [i32 ()* @_ZL5CallYv, i32 ()* @_ZL5CallYv, i32 ()* @_ZL5CallXv, i32 ()* @_ZL5CallYv], align 16 +@switch.table = private unnamed_addr constant [3 x [4 x i32 ()*]*] [[4 x i32 ()*]* @_ZL6Funcs0, [4 x i32 ()*]* @_ZL6Funcs1, [4 x i32 ()*]* @_ZL6Funcs2] + +; Function Attrs: norecurse nounwind readonly uwtable +define i32 ()* @_Z8GetCallNii(i32 %i, i32 %j) local_unnamed_addr #0 { +entry: + %0 = icmp ult i32 %i, 3 + br i1 %0, label %switch.lookup, label %return + +switch.lookup: ; preds = %entry + %1 = sext i32 %i to i64 + %switch.gep = getelementptr inbounds [3 x [4 x i32 ()*]*], [3 x [4 x i32 ()*]*]* @switch.table, i64 0, i64 %1 + %switch.load = load [4 x i32 ()*]*, [4 x i32 ()*]** %switch.gep, align 8 + %idxprom5 = sext i32 %j to i64 + %arrayidx6 = getelementptr inbounds [4 x i32 ()*], [4 x i32 ()*]* %switch.load, i64 0, i64 %idxprom5 + %2 = load i32 ()*, i32 ()** %arrayidx6, align 8 + br label %return + +return: ; preds = %switch.lookup, %entry + %retval.0 = phi i32 ()* [ null, %entry ], [ %2, %switch.lookup ] + ret i32 ()* %retval.0 +} + +; Function Attrs: norecurse nounwind readnone uwtable +define internal i32 @_ZL5CallXv() #1 { +entry: + ret i32 0 +} + +; Function Attrs: norecurse nounwind readnone uwtable +define internal i32 @_ZL5CallYv() #1 { +entry: + ret i32 1 +}