Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/include/llvm/IR/GlobalObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ class GlobalObject : public GlobalValue {
SmallVectorImpl<MDNode *> &MDs) const;
/// @}

LLVM_ABI bool hasMetadataOtherThanDebugLoc() const;
LLVM_ABI bool hasMetadataOtherThanDebugLocAndGuid() const;

/// Copy metadata from Src, adjusting offsets by Offset.
LLVM_ABI void copyMetadata(const GlobalObject *Src, unsigned Offset);
Expand Down
7 changes: 7 additions & 0 deletions llvm/include/llvm/Transforms/Utils/AssignGUID.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#ifndef LLVM_TRANSFORMS_UTILS_ASSIGNGUID_H
#define LLVM_TRANSFORMS_UTILS_ASSIGNGUID_H

#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/Debug.h"
Expand All @@ -35,6 +37,11 @@ class AssignGUIDPass : public PassInfoMixin<AssignGUIDPass> {
}

static bool isRequired() { return true; }

// Let GlobalMerge assign a GUID for merged GVs, instead of needing to
// traverse all the module; or instead of making GlobalValue::assignGUID
// public.
static void assignGUIDForMergedGV(GlobalVariable &GV);
};

} // end namespace llvm
Expand Down
20 changes: 12 additions & 8 deletions llvm/lib/CodeGen/GlobalMerge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
Expand All @@ -94,6 +95,7 @@
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/AssignGUID.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
Expand Down Expand Up @@ -605,6 +607,7 @@ bool GlobalMergeImpl::doMerge(const SmallVectorImpl<GlobalVariable *> &Globals,

NumMerged++;
}
AssignGUIDPass::assignGUIDForMergedGV(*MergedGV);
Changed = true;
i = j;
}
Expand Down Expand Up @@ -726,14 +729,15 @@ bool GlobalMergeImpl::run(Module &M) {
if (GV.isTagged())
continue;

// Don't merge globals with metadata other than !dbg, as this is essentially
// equivalent to adding metadata to an existing global, which is not
// necessarily a correct transformation depending on the specific metadata's
// semantics. We will later use copyMetadata() to copy metadata from
// component globals to the combined global, which only knows how to do this
// correctly for !dbg (and !type, but by this point LowerTypeTests will have
// already run).
if (GV.hasMetadataOtherThanDebugLoc())
// Don't merge globals with metadata other than !dbg or !guid, as this is
// essentially equivalent to adding metadata to an existing global, which is
// not necessarily a correct transformation depending on the specific
// metadata's semantics. We will later use copyMetadata() to copy metadata
// from component globals to the combined global, which only knows how to do
// this correctly for !dbg (and !type, but by this point LowerTypeTests will
// have already run).
// Note that a new !guid will be created as part of doMerge
if (GV.hasMetadataOtherThanDebugLocAndGuid())
Comment thread
mtrofin marked this conversation as resolved.
continue;

Type *Ty = GV.getValueType();
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/IR/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,11 +452,11 @@ bool GlobalObject::canIncreaseAlignment() const {
return true;
}

bool GlobalObject::hasMetadataOtherThanDebugLoc() const {
bool GlobalObject::hasMetadataOtherThanDebugLocAndGuid() const {
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
getAllMetadata(MDs);
for (const auto &V : MDs)
if (V.first != LLVMContext::MD_dbg)
if (V.first != LLVMContext::MD_dbg && V.first != LLVMContext::MD_unique_id)
return true;
return false;
}
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Transforms/IPO/ConstantMerge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ enum class CanMerge { No, Yes };
static CanMerge makeMergeable(GlobalVariable *Old, GlobalVariable *New) {
if (!Old->hasGlobalUnnamedAddr() && !New->hasGlobalUnnamedAddr())
return CanMerge::No;
if (Old->hasMetadataOtherThanDebugLoc())
if (Old->hasMetadataOtherThanDebugLocAndGuid())
return CanMerge::No;
assert(!New->hasMetadataOtherThanDebugLoc());
assert(!New->hasMetadataOtherThanDebugLocAndGuid());

// Merging constants with different comdats means one group cannot in general
// be dropped independently without the other group now having an invalid
Expand Down Expand Up @@ -175,8 +175,8 @@ static bool mergeConstants(Module &M) {
if (GV.isWeakForLinker())
continue;

// Don't touch globals with metadata other then !dbg.
if (GV.hasMetadataOtherThanDebugLoc())
// Don't touch globals with metadata other than !dbg or !guid.
if (GV.hasMetadataOtherThanDebugLocAndGuid())
Comment thread
mtrofin marked this conversation as resolved.
continue;

Constant *Init = GV.getInitializer();
Expand Down
11 changes: 10 additions & 1 deletion llvm/lib/Transforms/Utils/AssignGUID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,13 @@ void AssignGUIDPass::runOnModule(Module &M) {
continue;
F.assignGUID();
}
}
}

void AssignGUIDPass::assignGUIDForMergedGV(GlobalVariable &GV) {
// FIXME: merging adds all the guids of the original GVs. We currently drop
// that metadata from GV first, but we may want to remember those later, if
// we had a motivation for that. In that case, we need some other metadata
// to maintain that association.
GV.eraseMetadata(LLVMContext::MD_unique_id);
GV.assignGUID();
}
1 change: 1 addition & 0 deletions llvm/test/Transforms/ConstantMerge/merge-dbg.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
; RUN: opt < %s -passes=constmerge -S | FileCheck %s
; RUN: opt < %s -passes=assign-guid,constmerge -S | FileCheck %s

; CHECK: = constant i32 1, !dbg [[A:![0-9]+]], !dbg [[B:![0-9]+]]
@a = internal constant i32 1, !dbg !0
Expand Down
38 changes: 38 additions & 0 deletions llvm/test/Transforms/GlobalMerge/guid.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
; We can merge globals with a guid metadata, and the guid of the merged object
; is different from that of the original objects.
; RUN: opt -passes='global-merge<max-offset=100>' -S -o - %s | FileCheck %s

target datalayout = "e-p:64:64"
target triple = "x86_64-unknown-linux-gnu"

; CHECK: @_MergedGlobals = private global <{ i32, i32 }> <{ i32 1, i32 2 }>, align 4, !guid !0
; CHECK: @_MergedGlobals.1 = private global <{ i32, i32 }> <{ i32 3, i32 4 }>, section "foo", align 4, !guid !1

; CHECK-DAG: @a = internal alias i32, ptr @_MergedGlobals{{$}}
@a = internal global i32 1, !guid !{i64 1}

; CHECK-DAG: @b = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1)
@b = internal global i32 2, !guid !{i64 2}

; CHECK-DAG: @c = internal alias i32, ptr @_MergedGlobals.1{{$}}
@c = internal global i32 3, section "foo", !guid !{i64 3}

; CHECK-DAG: @d = internal alias i32, getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals.1, i32 0, i32 1)
@d = internal global i32 4, section "foo", !guid !{i64 4}

; CHECK: define void @use() !guid !2
define void @use() !guid !{i64 5} {
; CHECK: load i32, ptr @_MergedGlobals,
%x = load i32, ptr @a
; CHECK: load i32, ptr getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1)
%y = load i32, ptr @b
; CHECK: load i32, ptr @_MergedGlobals.1
%z1 = load i32, ptr @c
; CHECK: load i32, ptr getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals.1, i32 0, i32 1)
%z2 = load i32, ptr @d
ret void
}

; CHECK: !0 = !{i64 {{-?[0-9][0-9]+}}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not compare against the exact guid values we expect in !0 and !1?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We expect anything but 0 or 1 - because these are supposed to be freshly recomputed. The module name is test-dependent, and, anyway, will be a large int, so we check that we have 2 or more digits.

; CHECK: !1 = !{i64 {{-?[0-9][0-9]+}}}
; CHECK: !2 = !{i64 5}