mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Teach the ConstantMerge pass about alignment. Fixes PR10514!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136250 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
84e7f7e267
commit
e511186183
@ -23,7 +23,9 @@
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
using namespace llvm;
|
||||
@ -37,10 +39,18 @@ namespace {
|
||||
initializeConstantMergePass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
// run - For this pass, process all of the globals in the module,
|
||||
// eliminating duplicate constants.
|
||||
//
|
||||
// For this pass, process all of the globals in the module, eliminating
|
||||
// duplicate constants.
|
||||
bool runOnModule(Module &M);
|
||||
|
||||
// Return true iff we can determine the alignment of this global variable.
|
||||
bool hasKnownAlignment(GlobalVariable *GV) const;
|
||||
|
||||
// Return the alignment of the global, including converting the default
|
||||
// alignment to a concrete value.
|
||||
unsigned getAlignment(GlobalVariable *GV) const;
|
||||
|
||||
const TargetData *TD;
|
||||
};
|
||||
}
|
||||
|
||||
@ -77,15 +87,28 @@ static bool IsBetterCannonical(const GlobalVariable &A,
|
||||
return A.hasUnnamedAddr();
|
||||
}
|
||||
|
||||
bool ConstantMerge::hasKnownAlignment(GlobalVariable *GV) const {
|
||||
return TD || GV->getAlignment() != 0;
|
||||
}
|
||||
|
||||
unsigned ConstantMerge::getAlignment(GlobalVariable *GV) const {
|
||||
if (TD)
|
||||
return TD->getPreferredAlignment(GV);
|
||||
return GV->getAlignment();
|
||||
}
|
||||
|
||||
bool ConstantMerge::runOnModule(Module &M) {
|
||||
TD = getAnalysisIfAvailable<TargetData>();
|
||||
|
||||
// Find all the globals that are marked "used". These cannot be merged.
|
||||
SmallPtrSet<const GlobalValue*, 8> UsedGlobals;
|
||||
FindUsedValues(M.getGlobalVariable("llvm.used"), UsedGlobals);
|
||||
FindUsedValues(M.getGlobalVariable("llvm.compiler.used"), UsedGlobals);
|
||||
|
||||
// Map unique constant/section pairs to globals. We don't want to merge
|
||||
// globals in different sections.
|
||||
DenseMap<Constant*, GlobalVariable*> CMap;
|
||||
// Map unique <constants, has-unknown-alignment> pairs to globals. We don't
|
||||
// want to merge globals of unknown alignment with those of explicit
|
||||
// alignment. If we have TargetData, we always know the alignment.
|
||||
DenseMap<PointerIntPair<Constant*, 1, bool>, GlobalVariable*> CMap;
|
||||
|
||||
// Replacements - This vector contains a list of replacements to perform.
|
||||
SmallVector<std::pair<GlobalVariable*, GlobalVariable*>, 32> Replacements;
|
||||
@ -120,7 +143,8 @@ bool ConstantMerge::runOnModule(Module &M) {
|
||||
Constant *Init = GV->getInitializer();
|
||||
|
||||
// Check to see if the initializer is already known.
|
||||
GlobalVariable *&Slot = CMap[Init];
|
||||
PointerIntPair<Constant*, 1, bool> Pair(Init, hasKnownAlignment(GV));
|
||||
GlobalVariable *&Slot = CMap[Pair];
|
||||
|
||||
// If this is the first constant we find or if the old on is local,
|
||||
// replace with the current one. It the current is externally visible
|
||||
@ -152,7 +176,8 @@ bool ConstantMerge::runOnModule(Module &M) {
|
||||
Constant *Init = GV->getInitializer();
|
||||
|
||||
// Check to see if the initializer is already known.
|
||||
GlobalVariable *Slot = CMap[Init];
|
||||
PointerIntPair<Constant*, 1, bool> Pair(Init, hasKnownAlignment(GV));
|
||||
GlobalVariable *Slot = CMap[Pair];
|
||||
|
||||
if (!Slot || Slot == GV)
|
||||
continue;
|
||||
@ -175,6 +200,14 @@ bool ConstantMerge::runOnModule(Module &M) {
|
||||
// now. This avoid invalidating the pointers in CMap, which are unneeded
|
||||
// now.
|
||||
for (unsigned i = 0, e = Replacements.size(); i != e; ++i) {
|
||||
// Bump the alignment if necessary.
|
||||
if (Replacements[i].first->getAlignment() ||
|
||||
Replacements[i].second->getAlignment()) {
|
||||
Replacements[i].second->setAlignment(std::max(
|
||||
Replacements[i].first->getAlignment(),
|
||||
Replacements[i].second->getAlignment()));
|
||||
}
|
||||
|
||||
// Eliminate any uses of the dead global.
|
||||
Replacements[i].first->replaceAllUsesWith(Replacements[i].second);
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
; RUN: opt -constmerge %s -S -o - | FileCheck %s
|
||||
; Test that in one run var3 is merged into var2 and var1 into var4.
|
||||
; Test that we merge @var5 and @var6 into one with the higher alignment, and
|
||||
; don't merge var7/var8 into var5/var6.
|
||||
|
||||
declare void @zed(%struct.foobar*, %struct.foobar*)
|
||||
|
||||
@ -14,13 +16,24 @@ declare void @zed(%struct.foobar*, %struct.foobar*)
|
||||
; CHECK-NOT: @
|
||||
; CHECK: @var2 = constant %struct.foobar { i32 2 }
|
||||
; CHECK-NEXT: @var4 = constant %struct.foobar { i32 2 }
|
||||
; CHECK-NOT: @
|
||||
; CHECK: declare void @zed(%struct.foobar*, %struct.foobar*)
|
||||
|
||||
declare void @helper([16 x i8]*)
|
||||
@var5 = internal constant [16 x i8] c"foo1bar2foo3bar\00", align 16
|
||||
@var6 = private unnamed_addr constant [16 x i8] c"foo1bar2foo3bar\00", align 1
|
||||
@var7 = internal constant [16 x i8] c"foo1bar2foo3bar\00"
|
||||
@var8 = private unnamed_addr constant [16 x i8] c"foo1bar2foo3bar\00"
|
||||
|
||||
; CHECK-NEXT: @var6 = private constant [16 x i8] c"foo1bar2foo3bar\00", align 16
|
||||
; CHECK-NEXT: @var8 = private constant [16 x i8] c"foo1bar2foo3bar\00"
|
||||
|
||||
define i32 @main() {
|
||||
entry:
|
||||
call void @zed(%struct.foobar* @var1, %struct.foobar* @var2)
|
||||
call void @zed(%struct.foobar* @var3, %struct.foobar* @var4)
|
||||
call void @helper([16 x i8]* @var5)
|
||||
call void @helper([16 x i8]* @var6)
|
||||
call void @helper([16 x i8]* @var7)
|
||||
call void @helper([16 x i8]* @var8)
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user