[llvm] 10cadee - [ThinLTO] Always import constants

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 15 08:32:04 PST 2020


Author: evgeny
Date: 2020-01-15T19:29:01+03:00
New Revision: 10cadee5ce86e80d7486855199d329951f38af01

URL: https://github.com/llvm/llvm-project/commit/10cadee5ce86e80d7486855199d329951f38af01
DIFF: https://github.com/llvm/llvm-project/commit/10cadee5ce86e80d7486855199d329951f38af01.diff

LOG: [ThinLTO] Always import constants

This patch imports constant variables even when they can't be internalized
(which results in promotion). This offers some extra constant folding
opportunities.

Differential revision: https://reviews.llvm.org/D70404

Added: 
    llvm/test/ThinLTO/X86/Inputs/import-constant.ll
    llvm/test/ThinLTO/X86/Inputs/import-ro-constant-bar.ll
    llvm/test/ThinLTO/X86/Inputs/import-ro-constant-foo.ll
    llvm/test/ThinLTO/X86/import-constant.ll
    llvm/test/ThinLTO/X86/import-ro-constant.ll

Modified: 
    llvm/include/llvm/IR/ModuleSummaryIndex.h
    llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/ModuleSummaryIndex.cpp
    llvm/test/Assembler/thinlto-summary.ll
    llvm/test/Assembler/thinlto-vtable-summary.ll
    llvm/test/Bitcode/thinlto-function-summary-refgraph.ll
    llvm/test/ThinLTO/X86/Inputs/dot-dumper.ll
    llvm/test/ThinLTO/X86/dot-dumper.ll
    llvm/test/ThinLTO/X86/load-store-caching.ll
    llvm/test/ThinLTO/X86/referenced_by_constant.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h
index aa4054c8409e..2c6357421354 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -757,14 +757,29 @@ class GlobalVarSummary : public GlobalValueSummary {
 
 public:
   struct GVarFlags {
-    GVarFlags(bool ReadOnly, bool WriteOnly)
-        : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly) {}
-
-    // In permodule summaries both MaybeReadOnly and MaybeWriteOnly
-    // bits are set, because attribute propagation occurs later on
-    // thin link phase.
+    GVarFlags(bool ReadOnly, bool WriteOnly, bool Constant)
+        : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly),
+          Constant(Constant) {}
+
+    // If true indicates that this global variable might be accessed
+    // purely by non-volatile load instructions. This in turn means
+    // it can be internalized in source and destination modules during
+    // thin LTO import because it neither modified nor its address
+    // is taken.
     unsigned MaybeReadOnly : 1;
+    // If true indicates that variable is possibly only written to, so
+    // its value isn't loaded and its address isn't taken anywhere.
+    // False, when 'Constant' attribute is set.
     unsigned MaybeWriteOnly : 1;
+    // Indicates that value is a compile-time constant. Global variable
+    // can be 'Constant' while not being 'ReadOnly' on several occasions:
+    // - it is volatile, (e.g mapped device address)
+    // - its address is taken, meaning that unlike 'ReadOnly' vars we can't
+    //   internalize it.
+    // Constant variables are always imported thus giving compiler an
+    // opportunity to make some extra optimizations. Readonly constants
+    // are also internalized.
+    unsigned Constant : 1;
   } VarFlags;
 
   GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags,
@@ -782,6 +797,7 @@ class GlobalVarSummary : public GlobalValueSummary {
   void setWriteOnly(bool WO) { VarFlags.MaybeWriteOnly = WO; }
   bool maybeReadOnly() const { return VarFlags.MaybeReadOnly; }
   bool maybeWriteOnly() const { return VarFlags.MaybeWriteOnly; }
+  bool isConstant() const { return VarFlags.Constant; }
 
   void setVTableFuncs(VTableFuncList Funcs) {
     assert(!VTableFuncs);

diff  --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
index 8a1206f49c21..c7a0984ed282 100644
--- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
+++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
@@ -599,7 +599,9 @@ static void computeVariableSummary(ModuleSummaryIndex &Index,
   bool CanBeInternalized =
       !V.hasComdat() && !V.hasAppendingLinkage() && !V.isInterposable() &&
       !V.hasAvailableExternallyLinkage() && !V.hasDLLExportStorageClass();
-  GlobalVarSummary::GVarFlags VarFlags(CanBeInternalized, CanBeInternalized);
+  bool Constant = V.isConstant();
+  GlobalVarSummary::GVarFlags VarFlags(
+      CanBeInternalized, Constant ? false : CanBeInternalized, Constant);
   auto GVarSummary = std::make_unique<GlobalVarSummary>(Flags, VarFlags,
                                                          RefEdges.takeVector());
   if (NonRenamableLocal)
@@ -718,7 +720,9 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
           } else {
             std::unique_ptr<GlobalVarSummary> Summary =
                 std::make_unique<GlobalVarSummary>(
-                    GVFlags, GlobalVarSummary::GVarFlags(false, false),
+                    GVFlags,
+                    GlobalVarSummary::GVarFlags(
+                        false, false, cast<GlobalVariable>(GV)->isConstant()),
                     ArrayRef<ValueInfo>{});
             Index.addGlobalValueSummary(*GV, std::move(Summary));
           }

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 1a17f633ae16..d0d0b948316e 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -8155,7 +8155,8 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,
       /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false,
       /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false);
   GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false,
-                                        /* WriteOnly */ false);
+                                        /* WriteOnly */ false,
+                                        /* Constant */ false);
   std::vector<ValueInfo> Refs;
   VTableFuncList VTableFuncs;
   if (ParseToken(lltok::colon, "expected ':' here") ||
@@ -8827,7 +8828,8 @@ bool LLParser::ParseGVFlags(GlobalValueSummary::GVFlags &GVFlags) {
 
 /// GVarFlags
 ///   ::= 'varFlags' ':' '(' 'readonly' ':' Flag
-///                      ',' 'writeonly' ':' Flag ')'
+///                      ',' 'writeonly' ':' Flag
+///                      ',' 'constant' ':' Flag ')'
 bool LLParser::ParseGVarFlags(GlobalVarSummary::GVarFlags &GVarFlags) {
   assert(Lex.getKind() == lltok::kw_varFlags);
   Lex.Lex();
@@ -8856,6 +8858,11 @@ bool LLParser::ParseGVarFlags(GlobalVarSummary::GVarFlags &GVarFlags) {
         return true;
       GVarFlags.MaybeWriteOnly = Flag;
       break;
+    case lltok::kw_constant:
+      if (ParseRest(Flag))
+        return true;
+      GVarFlags.Constant = Flag;
+      break;
     default:
       return Error(Lex.getLoc(), "expected gvar flag type");
     }

diff  --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 33464412edc5..1eefb1b889ab 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -986,7 +986,8 @@ static GlobalValueSummary::GVFlags getDecodedGVSummaryFlags(uint64_t RawFlags,
 // Decode the flags for GlobalVariable in the summary
 static GlobalVarSummary::GVarFlags getDecodedGVarFlags(uint64_t RawFlags) {
   return GlobalVarSummary::GVarFlags((RawFlags & 0x1) ? true : false,
-                                     (RawFlags & 0x2) ? true : false);
+                                     (RawFlags & 0x2) ? true : false,
+                                     (RawFlags & 0x4) ? true : false);
 }
 
 static GlobalValue::VisibilityTypes getDecodedVisibility(unsigned Val) {
@@ -5965,7 +5966,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
       uint64_t RawFlags = Record[1];
       unsigned RefArrayStart = 2;
       GlobalVarSummary::GVarFlags GVF(/* ReadOnly */ false,
-                                      /* WriteOnly */ false);
+                                      /* WriteOnly */ false,
+                                      /* Constant */ false);
       auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
       if (Version >= 5) {
         GVF = getDecodedGVarFlags(Record[2]);
@@ -6101,7 +6103,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
       uint64_t RawFlags = Record[2];
       unsigned RefArrayStart = 3;
       GlobalVarSummary::GVarFlags GVF(/* ReadOnly */ false,
-                                      /* WriteOnly */ false);
+                                      /* WriteOnly */ false,
+                                      /* Constant */ false);
       auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
       if (Version >= 5) {
         GVF = getDecodedGVarFlags(Record[3]);

diff  --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index dcff7c421fc4..ef92bc2c91c7 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1028,7 +1028,8 @@ static uint64_t getEncodedGVSummaryFlags(GlobalValueSummary::GVFlags Flags) {
 }
 
 static uint64_t getEncodedGVarFlags(GlobalVarSummary::GVarFlags Flags) {
-  uint64_t RawFlags = Flags.MaybeReadOnly | (Flags.MaybeWriteOnly << 1);
+  uint64_t RawFlags =
+      Flags.MaybeReadOnly | (Flags.MaybeWriteOnly << 1) | (Flags.Constant << 2);
   return RawFlags;
 }
 

diff  --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index acf0e4afef27..71d97755d661 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2901,7 +2901,8 @@ void AssemblyWriter::printAliasSummary(const AliasSummary *AS) {
 
 void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
   Out << ", varFlags: (readonly: " << GS->VarFlags.MaybeReadOnly << ", "
-      << "writeonly: " << GS->VarFlags.MaybeWriteOnly << ")";
+      << "writeonly: " << GS->VarFlags.MaybeWriteOnly << ", "
+      << "constant: " << GS->VarFlags.Constant << ")";
 
   auto VTableFuncs = GS->vTableFuncs();
   if (!VTableFuncs.empty()) {

diff  --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp
index 180f96269a13..301df9a9d493 100644
--- a/llvm/lib/IR/ModuleSummaryIndex.cpp
+++ b/llvm/lib/IR/ModuleSummaryIndex.cpp
@@ -221,7 +221,8 @@ bool ModuleSummaryIndex::canImportGlobalVar(GlobalValueSummary *S,
     // c) Link error (external declaration with internal definition).
     // However we do not promote objects referenced by writeonly GV
     // initializer by means of converting it to 'zeroinitializer'
-    return !isReadOnly(GVS) && !isWriteOnly(GVS) && GVS->refs().size();
+    return !GVS->isConstant() && !isReadOnly(GVS) && !isWriteOnly(GVS) &&
+           GVS->refs().size();
   };
   auto *GVS = cast<GlobalVarSummary>(S->getBaseObject());
 
@@ -405,6 +406,12 @@ static bool hasWriteOnlyFlag(const GlobalValueSummary *S) {
   return false;
 }
 
+static bool hasConstantFlag(const GlobalValueSummary *S) {
+  if (auto *GVS = dyn_cast<GlobalVarSummary>(S))
+    return GVS->isConstant();
+  return false;
+}
+
 void ModuleSummaryIndex::exportToDot(
     raw_ostream &OS,
     const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols) const {
@@ -482,6 +489,8 @@ void ModuleSummaryIndex::exportToDot(
           A.addComment("immutable");
         if (Flags.Live && hasWriteOnlyFlag(SummaryIt.second))
           A.addComment("writeOnly");
+        if (Flags.Live && hasConstantFlag(SummaryIt.second))
+          A.addComment("constant");
       }
       if (Flags.DSOLocal)
         A.addComment("dsoLocal");

diff  --git a/llvm/test/Assembler/thinlto-summary.ll b/llvm/test/Assembler/thinlto-summary.ll
index dea535cc47f1..d018363b3b59 100644
--- a/llvm/test/Assembler/thinlto-summary.ll
+++ b/llvm/test/Assembler/thinlto-summary.ll
@@ -76,10 +76,10 @@
 ; CHECK: ^8 = gv: (guid: 7, summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), insts: 1)))
 ; CHECK: ^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 1), insts: 1)))
 ; CHECK: ^10 = gv: (guid: 9, summaries: (function: (module: ^0, flags: (linkage: weak, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), insts: 1)))
-; CHECK: ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0))))
-; CHECK: ^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), refs: (^4))))
-; CHECK: ^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 0))))
-; CHECK: ^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0))))
+; CHECK: ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0))))
+; CHECK: ^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), refs: (^4))))
+; CHECK: ^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 0, constant: 0))))
+; CHECK: ^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0))))
 ; CHECK: ^15 = gv: (guid: 14, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 1, live: 1, dsoLocal: 0, canAutoHide: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 1, alwaysInline: 0))))
 ; CHECK: ^16 = gv: (guid: 15, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), insts: 1, funcFlags: (readNone: 1, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 1))))
 ; CHECK: ^17 = gv: (guid: 16, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 1, noRecurse: 0, returnDoesNotAlias: 1, noInline: 0, alwaysInline: 0), calls: ((callee: ^15)))))

diff  --git a/llvm/test/Assembler/thinlto-vtable-summary.ll b/llvm/test/Assembler/thinlto-vtable-summary.ll
index e4d2a68463c1..014955d8ad9d 100644
--- a/llvm/test/Assembler/thinlto-vtable-summary.ll
+++ b/llvm/test/Assembler/thinlto-vtable-summary.ll
@@ -29,9 +29,9 @@ declare i32 @_ZN1C1fEi(%struct.C*, i32)
 
 ^0 = module: (path: "<stdin>", hash: (0, 0, 0, 0, 0))
 ^1 = gv: (name: "_ZN1A1nEi") ; guid = 1621563287929432257
-^2 = gv: (name: "_ZTV1B", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), vTableFuncs: ((virtFunc: ^3, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^3, ^1)))) ; guid = 5283576821522790367
+^2 = gv: (name: "_ZTV1B", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), vTableFuncs: ((virtFunc: ^3, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^3, ^1)))) ; guid = 5283576821522790367
 ^3 = gv: (name: "_ZN1B1fEi") ; guid = 7162046368816414394
-^4 = gv: (name: "_ZTV1C", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), vTableFuncs: ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1, ^5)))) ; guid = 13624023785555846296
+^4 = gv: (name: "_ZTV1C", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 0), vTableFuncs: ((virtFunc: ^5, offset: 16), (virtFunc: ^1, offset: 24)), refs: (^1, ^5)))) ; guid = 13624023785555846296
 ^5 = gv: (name: "_ZN1C1fEi") ; guid = 14876272565662207556
 ^6 = typeidCompatibleVTable: (name: "_ZTS1A", summary: ((offset: 16, ^2), (offset: 16, ^4))) ; guid = 7004155349499253778
 ^7 = typeidCompatibleVTable: (name: "_ZTS1B", summary: ((offset: 16, ^2))) ; guid = 6203814149063363976

diff  --git a/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll b/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll
index 5a33daa95e34..92a9b7064376 100644
--- a/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll
+++ b/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll
@@ -73,7 +73,7 @@ target triple = "x86_64-unknown-linux-gnu"
 
 @bar = global void (...)* bitcast (void ()* @func to void (...)*), align 8
 
- at globalvar = global i32 0, align 4
+ at globalvar = constant i32 0, align 4
 
 declare void @func() #0
 declare i32 @func2(...) #1
@@ -154,11 +154,12 @@ entry:
 ; DIS-DAG: = gv: (name: "foo") ; guid = 6699318081062747564
 ; DIS-DAG: = gv: (name: "func") ; guid = 7289175272376759421
 ; DIS-DAG: = gv: (name: "func3") ; guid = 11517462787082255043
-; DIS-DAG: = gv: (name: "globalvar", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 1)))) ; guid = 12887606300320728018
+; Check that default value of writeonly attribute is zero for constant variables 
+; DIS-DAG: = gv: (name: "globalvar", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 0, constant: 1)))) ; guid = 12887606300320728018
 ; DIS-DAG: = gv: (name: "func2") ; guid = 14069196320850861797
 ; DIS-DAG: = gv: (name: "llvm.ctpop.i8") ; guid = 15254915475081819833
 ; DIS-DAG: = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), insts: 9, calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 15822663052811949562
-; DIS-DAG: = gv: (name: "bar", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 1),  refs: (^{{.*}})))) ; guid = 16434608426314478903
+; DIS-DAG: = gv: (name: "bar", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 1, constant: 0),  refs: (^{{.*}})))) ; guid = 16434608426314478903
 ; Don't try to match the exact GUID. Since it is private, the file path
 ; will get hashed, and that will be test dependent.
 ; DIS-DAG: = gv: (name: "Y", summaries: (function: (module: ^0, flags: (linkage: private, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0), insts: 14, calls: ((callee: ^{{.*}}))))) ; guid =

diff  --git a/llvm/test/ThinLTO/X86/Inputs/dot-dumper.ll b/llvm/test/ThinLTO/X86/Inputs/dot-dumper.ll
index 4e745a459fac..cc4b21e4ea55 100644
--- a/llvm/test/ThinLTO/X86/Inputs/dot-dumper.ll
+++ b/llvm/test/ThinLTO/X86/Inputs/dot-dumper.ll
@@ -2,7 +2,7 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16
 target triple = "x86_64-unknown-linux-gnu"
 
 @A = local_unnamed_addr global i32 10, align 4
- at B = local_unnamed_addr global i32 20, align 4
+ at B = local_unnamed_addr constant i32 20, align 4
 
 ; Function Attrs: norecurse nounwind readonly uwtable
 define i32 @foo() local_unnamed_addr #0 {

diff  --git a/llvm/test/ThinLTO/X86/Inputs/import-constant.ll b/llvm/test/ThinLTO/X86/Inputs/import-constant.ll
new file mode 100644
index 000000000000..94bba2d02c88
--- /dev/null
+++ b/llvm/test/ThinLTO/X86/Inputs/import-constant.ll
@@ -0,0 +1,15 @@
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.S = type { i32, i32, i32* }
+%struct.Q = type { %struct.S* }
+
+ at val = dso_local global i32 42, align 4
+ at _ZL3Obj = internal constant %struct.S { i32 4, i32 8, i32* @val }, align 8
+ at outer = dso_local local_unnamed_addr global %struct.Q { %struct.S* @_ZL3Obj }, align 8
+
+define dso_local nonnull %struct.S* @_Z6getObjv() local_unnamed_addr {
+entry:
+  store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 0, i32 0), align 8
+  ret %struct.S* @_ZL3Obj
+}

diff  --git a/llvm/test/ThinLTO/X86/Inputs/import-ro-constant-bar.ll b/llvm/test/ThinLTO/X86/Inputs/import-ro-constant-bar.ll
new file mode 100644
index 000000000000..636d4027a03b
--- /dev/null
+++ b/llvm/test/ThinLTO/X86/Inputs/import-ro-constant-bar.ll
@@ -0,0 +1,10 @@
+source_filename = "bar.c"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = external dso_local local_unnamed_addr constant i32, align 4
+define dso_local i32 @_Z3barv() local_unnamed_addr {
+entry:
+  %0 = load i32, i32* @foo, align 4
+  ret i32 %0
+}

diff  --git a/llvm/test/ThinLTO/X86/Inputs/import-ro-constant-foo.ll b/llvm/test/ThinLTO/X86/Inputs/import-ro-constant-foo.ll
new file mode 100644
index 000000000000..896cc2a7bea0
--- /dev/null
+++ b/llvm/test/ThinLTO/X86/Inputs/import-ro-constant-foo.ll
@@ -0,0 +1,5 @@
+source_filename = "foo.c"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = dso_local local_unnamed_addr constant i32 21, align 4

diff  --git a/llvm/test/ThinLTO/X86/dot-dumper.ll b/llvm/test/ThinLTO/X86/dot-dumper.ll
index 22cbdec28f1a..f52254df87be 100644
--- a/llvm/test/ThinLTO/X86/dot-dumper.ll
+++ b/llvm/test/ThinLTO/X86/dot-dumper.ll
@@ -52,7 +52,7 @@
 ; COMBINED-NEXT:    node [style=filled,fillcolor=lightblue];
 ; COMBINED-NEXT:    M1_[[FOO:[0-9]+]] [shape="record",label="foo|extern (inst: 4, ffl: 000010)}"]; // function
 ; COMBINED-NEXT:    M1_[[A:[0-9]+]] [shape="Mrecord",label="A|extern}"]; // variable, immutable
-; COMBINED-NEXT:    M1_[[B:[0-9]+]] [shape="Mrecord",label="B|extern}"]; // variable, immutable
+; COMBINED-NEXT:    M1_[[B:[0-9]+]] [shape="Mrecord",label="B|extern}"]; // variable, immutable, constant
 ; COMBINED-NEXT:    M1_{{[0-9]+}} [shape="record",label="bar|extern (inst: 1, ffl: 000000)}",fillcolor="red"]; // function, dead
 ; COMBINED-NEXT:    // Edges:
 ; COMBINED-NEXT:    M1_[[FOO]] -> M1_[[B]] [style=dashed,color=forestgreen]; // const-ref

diff  --git a/llvm/test/ThinLTO/X86/import-constant.ll b/llvm/test/ThinLTO/X86/import-constant.ll
new file mode 100644
index 000000000000..6902359e4738
--- /dev/null
+++ b/llvm/test/ThinLTO/X86/import-constant.ll
@@ -0,0 +1,47 @@
+; Check that we promote constant object in the source module and import it
+; even when it is referenced in some other GV initializer and/or is used
+; by store instructions.
+; RUN: opt -thinlto-bc %s -o %t1.bc
+; RUN: opt -thinlto-bc %p/Inputs/import-constant.ll -o %t2.bc
+; RUN: llvm-lto2 run -save-temps %t1.bc %t2.bc -o %t-out \
+; RUN:    -r=%t1.bc,main,plx \
+; RUN:    -r=%t1.bc,_Z6getObjv,l \
+; RUN:    -r=%t2.bc,_Z6getObjv,pl \
+; RUN:    -r=%t2.bc,val,pl \
+; RUN:    -r=%t2.bc,outer,pl
+; RUN: llvm-dis %t-out.2.1.promote.bc -o - | FileCheck %s --check-prefix=PROMOTE
+; RUN: llvm-dis %t-out.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT
+; RUN: llvm-dis %t-out.1.4.opt.bc -o - | FileCheck %s --check-prefix=OPT
+
+; Check that variable has been promoted in the source module
+; PROMOTE: @_ZL3Obj.llvm.{{.*}} = hidden constant %struct.S { i32 4, i32 8, i32* @val }
+
+; @outer is a write-only variable, so it's been converted to zeroinitializer.
+; IMPORT:      @outer = internal local_unnamed_addr global %struct.Q zeroinitializer
+; IMPORT-NEXT: @_ZL3Obj.llvm.{{.*}} =  available_externally hidden constant %struct.S { i32 4, i32 8, i32* @val }
+; IMPORT-NEXT: @val = external dso_local global i32
+
+; OPT: @outer = internal unnamed_addr global %struct.Q zeroinitializer
+
+; OPT:      define dso_local i32 @main()
+; OPT-NEXT: entry:
+; OPT-NEXT:   store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 0, i32 0)
+; OPT-NEXT:   ret i32 12
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.S = type { i32, i32, i32* }
+
+define dso_local i32 @main() local_unnamed_addr {
+entry:
+  %call = tail call %struct.S* @_Z6getObjv()
+  %d = getelementptr inbounds %struct.S, %struct.S* %call, i64 0, i32 0
+  %0 = load i32, i32* %d, align 8
+  %v = getelementptr inbounds %struct.S, %struct.S* %call, i64 0, i32 1
+  %1 = load i32, i32* %v, align 4
+  %add = add nsw i32 %1, %0
+  ret i32 %add
+}
+
+declare dso_local %struct.S* @_Z6getObjv() local_unnamed_addr

diff  --git a/llvm/test/ThinLTO/X86/import-ro-constant.ll b/llvm/test/ThinLTO/X86/import-ro-constant.ll
new file mode 100644
index 000000000000..a3af22f1b34f
--- /dev/null
+++ b/llvm/test/ThinLTO/X86/import-ro-constant.ll
@@ -0,0 +1,34 @@
+; Check that we internalize external constant if it is accessed
+; purely by non-volatile loads.
+; RUN: opt -thinlto-bc %s -o %t-main
+; RUN: opt -thinlto-bc %p/Inputs/import-ro-constant-foo.ll -o %t-foo
+; RUN: opt -thinlto-bc %p/Inputs/import-ro-constant-bar.ll -o %t-bar
+; RUN: llvm-lto2 run -save-temps -o %t-out %t-main %t-foo %t-bar \
+; RUN:      -r=%t-foo,foo,pl \
+; RUN:      -r=%t-main,main,plx \
+; RUN:      -r=%t-main,_Z3barv,l \
+; RUN:      -r=%t-main,foo, \
+; RUN:      -r=%t-bar,_Z3barv,pl \
+; RUN:      -r=%t-bar,foo,
+; RUN: llvm-dis %t-out.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT
+; RUN: llvm-dis %t-out.1.4.opt.bc -o - | FileCheck %s --check-prefix=OPT
+
+; IMPORT: @foo = internal local_unnamed_addr constant i32 21, align 4 #0
+; IMPORT: attributes #0 = { "thinlto-internalize" }
+; OPT:      i32 @main()
+; OPT-NEXT: entry:
+; OPT-NEXT:   ret i32 42
+
+source_filename = "main.c"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = external dso_local local_unnamed_addr constant i32, align 4
+define dso_local i32 @main() local_unnamed_addr {
+entry:
+  %0 = load i32, i32* @foo, align 4
+  %call = tail call i32 @_Z3barv()
+  %add = add nsw i32 %call, %0
+  ret i32 %add
+}
+declare dso_local i32 @_Z3barv() local_unnamed_addr

diff  --git a/llvm/test/ThinLTO/X86/load-store-caching.ll b/llvm/test/ThinLTO/X86/load-store-caching.ll
index cb3a5c0d54d5..d460c240b461 100644
--- a/llvm/test/ThinLTO/X86/load-store-caching.ll
+++ b/llvm/test/ThinLTO/X86/load-store-caching.ll
@@ -22,5 +22,5 @@ entry:
 }
 
 ; CHECK:       ^0 = module:
-; CHECK-NEXT:  ^1 = gv: (name: "obj", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 1)))) ; guid =
+; CHECK-NEXT:  ^1 = gv: (name: "obj", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 1, constant: 0)))) ; guid =
 ; CHECK-NEXT:  ^2 = gv: (name: "foo", summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0), insts: 3, refs: (^1)))) ; guid =

diff  --git a/llvm/test/ThinLTO/X86/referenced_by_constant.ll b/llvm/test/ThinLTO/X86/referenced_by_constant.ll
index b352cbb2ea42..4c5e757907f4 100644
--- a/llvm/test/ThinLTO/X86/referenced_by_constant.ll
+++ b/llvm/test/ThinLTO/X86/referenced_by_constant.ll
@@ -3,14 +3,13 @@
 ; RUN: opt -module-summary %p/Inputs/referenced_by_constant.ll -o %t2.bc
 ; RUN: llvm-lto -thinlto-action=thinlink -o %t3.bc %t.bc %t2.bc
 
-; Check the import side: we currently only import bar() (with a future
-; enhancement to identify constants in the summary, we should mark
-; @someglobal/@someglobal2 for import as a local copy, which would
-; cause @referencedbyglobal and @localreferencedbyglobal to be exported
-; and promoted).
+; Check the import side: we currently import bar() and also promote/import
+; referenced constant objects. There is stll a room for improvement: we
+; can make a local copy of someglobal and someglobal2 because they are both
+; 'unnamed_addr' constants. This should eventually be done as well.
 ; RUN: llvm-lto -thinlto-action=import %t.bc -thinlto-index=%t3.bc -o - | llvm-dis -o -   | FileCheck %s --check-prefix=IMPORT
-; IMPORT: @someglobal.llvm.0 = external hidden unnamed_addr constant
-; IMPORT: @someglobal2.llvm.0 = external hidden unnamed_addr constant
+; IMPORT: @someglobal.llvm.0 = available_externally hidden unnamed_addr constant i8* bitcast (void ()* @referencedbyglobal to i8*)
+; IMPORT: @someglobal2.llvm.0 = available_externally hidden unnamed_addr constant i8* bitcast (void ()* @localreferencedbyglobal.llvm.0 to i8*)
 ; IMPORT: define available_externally void @bar()
 
 ; Check the export side: we currently only export bar(), which causes
@@ -19,7 +18,7 @@
 ; EXPORT: @someglobal.llvm.0 = hidden unnamed_addr constant
 ; EXPORT: @someglobal2.llvm.0 = hidden unnamed_addr constant
 ; EXPORT: define void @referencedbyglobal()
-; EXPORT: define internal void @localreferencedbyglobal()
+; EXPORT: define hidden void @localreferencedbyglobal.llvm
 
 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-apple-macosx10.11.0"


        


More information about the llvm-commits mailing list