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/DerivedTypes.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -37,10 +39,18 @@ namespace {
|
|||||||
initializeConstantMergePass(*PassRegistry::getPassRegistry());
|
initializeConstantMergePass(*PassRegistry::getPassRegistry());
|
||||||
}
|
}
|
||||||
|
|
||||||
// run - For this pass, process all of the globals in the module,
|
// For this pass, process all of the globals in the module, eliminating
|
||||||
// eliminating duplicate constants.
|
// duplicate constants.
|
||||||
//
|
|
||||||
bool runOnModule(Module &M);
|
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();
|
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) {
|
bool ConstantMerge::runOnModule(Module &M) {
|
||||||
|
TD = getAnalysisIfAvailable<TargetData>();
|
||||||
|
|
||||||
// Find all the globals that are marked "used". These cannot be merged.
|
// Find all the globals that are marked "used". These cannot be merged.
|
||||||
SmallPtrSet<const GlobalValue*, 8> UsedGlobals;
|
SmallPtrSet<const GlobalValue*, 8> UsedGlobals;
|
||||||
FindUsedValues(M.getGlobalVariable("llvm.used"), UsedGlobals);
|
FindUsedValues(M.getGlobalVariable("llvm.used"), UsedGlobals);
|
||||||
FindUsedValues(M.getGlobalVariable("llvm.compiler.used"), UsedGlobals);
|
FindUsedValues(M.getGlobalVariable("llvm.compiler.used"), UsedGlobals);
|
||||||
|
|
||||||
// Map unique constant/section pairs to globals. We don't want to merge
|
// Map unique <constants, has-unknown-alignment> pairs to globals. We don't
|
||||||
// globals in different sections.
|
// want to merge globals of unknown alignment with those of explicit
|
||||||
DenseMap<Constant*, GlobalVariable*> CMap;
|
// 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.
|
// Replacements - This vector contains a list of replacements to perform.
|
||||||
SmallVector<std::pair<GlobalVariable*, GlobalVariable*>, 32> Replacements;
|
SmallVector<std::pair<GlobalVariable*, GlobalVariable*>, 32> Replacements;
|
||||||
@ -120,7 +143,8 @@ bool ConstantMerge::runOnModule(Module &M) {
|
|||||||
Constant *Init = GV->getInitializer();
|
Constant *Init = GV->getInitializer();
|
||||||
|
|
||||||
// Check to see if the initializer is already known.
|
// 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,
|
// 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
|
// replace with the current one. It the current is externally visible
|
||||||
@ -152,7 +176,8 @@ bool ConstantMerge::runOnModule(Module &M) {
|
|||||||
Constant *Init = GV->getInitializer();
|
Constant *Init = GV->getInitializer();
|
||||||
|
|
||||||
// Check to see if the initializer is already known.
|
// 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)
|
if (!Slot || Slot == GV)
|
||||||
continue;
|
continue;
|
||||||
@ -175,6 +200,14 @@ bool ConstantMerge::runOnModule(Module &M) {
|
|||||||
// now. This avoid invalidating the pointers in CMap, which are unneeded
|
// now. This avoid invalidating the pointers in CMap, which are unneeded
|
||||||
// now.
|
// now.
|
||||||
for (unsigned i = 0, e = Replacements.size(); i != e; ++i) {
|
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.
|
// Eliminate any uses of the dead global.
|
||||||
Replacements[i].first->replaceAllUsesWith(Replacements[i].second);
|
Replacements[i].first->replaceAllUsesWith(Replacements[i].second);
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
; RUN: opt -constmerge %s -S -o - | FileCheck %s
|
; RUN: opt -constmerge %s -S -o - | FileCheck %s
|
||||||
; Test that in one run var3 is merged into var2 and var1 into var4.
|
; 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*)
|
declare void @zed(%struct.foobar*, %struct.foobar*)
|
||||||
|
|
||||||
@ -14,13 +16,24 @@ declare void @zed(%struct.foobar*, %struct.foobar*)
|
|||||||
; CHECK-NOT: @
|
; CHECK-NOT: @
|
||||||
; CHECK: @var2 = constant %struct.foobar { i32 2 }
|
; CHECK: @var2 = constant %struct.foobar { i32 2 }
|
||||||
; CHECK-NEXT: @var4 = 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() {
|
define i32 @main() {
|
||||||
entry:
|
entry:
|
||||||
call void @zed(%struct.foobar* @var1, %struct.foobar* @var2)
|
call void @zed(%struct.foobar* @var1, %struct.foobar* @var2)
|
||||||
call void @zed(%struct.foobar* @var3, %struct.foobar* @var4)
|
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
|
ret i32 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user