mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-29 13:24:25 +00:00
Enable rematerialization of constants using AliasAnalysis::pointsToConstantMemory,
and knowledge of PseudoSourceValues. This unfortunately isn't sufficient to allow constants to be rematerialized in PIC mode -- the extra indirection is a complication. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54000 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class AliasAnalysis;
|
||||||
class LiveVariables;
|
class LiveVariables;
|
||||||
class MachineLoopInfo;
|
class MachineLoopInfo;
|
||||||
class TargetRegisterInfo;
|
class TargetRegisterInfo;
|
||||||
@ -61,6 +62,7 @@ namespace llvm {
|
|||||||
const TargetMachine* tm_;
|
const TargetMachine* tm_;
|
||||||
const TargetRegisterInfo* tri_;
|
const TargetRegisterInfo* tri_;
|
||||||
const TargetInstrInfo* tii_;
|
const TargetInstrInfo* tii_;
|
||||||
|
AliasAnalysis *aa_;
|
||||||
LiveVariables* lv_;
|
LiveVariables* lv_;
|
||||||
|
|
||||||
/// Special pool allocator for VNInfo's (LiveInterval val#).
|
/// Special pool allocator for VNInfo's (LiveInterval val#).
|
||||||
|
@ -206,6 +206,14 @@ public:
|
|||||||
liveout_iterator liveout_begin() const { return LiveOuts.begin(); }
|
liveout_iterator liveout_begin() const { return LiveOuts.begin(); }
|
||||||
liveout_iterator liveout_end() const { return LiveOuts.end(); }
|
liveout_iterator liveout_end() const { return LiveOuts.end(); }
|
||||||
bool liveout_empty() const { return LiveOuts.empty(); }
|
bool liveout_empty() const { return LiveOuts.empty(); }
|
||||||
|
|
||||||
|
bool isLiveIn(unsigned Reg) const {
|
||||||
|
for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I)
|
||||||
|
if (I->first == Reg || I->second == Reg)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void HandleVRegListReallocation();
|
void HandleVRegListReallocation();
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include "llvm/Value.h"
|
#include "llvm/Value.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class MachineFrameInfo;
|
||||||
|
|
||||||
/// PseudoSourceValue - Special value supplied for machine level alias
|
/// PseudoSourceValue - Special value supplied for machine level alias
|
||||||
/// analysis. It indicates that the a memory access references the functions
|
/// analysis. It indicates that the a memory access references the functions
|
||||||
/// stack frame (e.g., a spill slot), below the stack frame (e.g., argument
|
/// stack frame (e.g., a spill slot), below the stack frame (e.g., argument
|
||||||
@ -27,6 +29,10 @@ namespace llvm {
|
|||||||
|
|
||||||
virtual void print(std::ostream &OS) const;
|
virtual void print(std::ostream &OS) const;
|
||||||
|
|
||||||
|
/// isConstant - Test whether this PseudoSourceValue has a constant value.
|
||||||
|
///
|
||||||
|
virtual bool isConstant(const MachineFrameInfo *) const;
|
||||||
|
|
||||||
/// classof - Methods for support type inquiry through isa, cast, and
|
/// classof - Methods for support type inquiry through isa, cast, and
|
||||||
/// dyn_cast:
|
/// dyn_cast:
|
||||||
///
|
///
|
||||||
|
@ -19,12 +19,14 @@
|
|||||||
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
||||||
#include "VirtRegMap.h"
|
#include "VirtRegMap.h"
|
||||||
#include "llvm/Value.h"
|
#include "llvm/Value.h"
|
||||||
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
#include "llvm/CodeGen/LiveVariables.h"
|
#include "llvm/CodeGen/LiveVariables.h"
|
||||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
#include "llvm/CodeGen/MachineInstr.h"
|
#include "llvm/CodeGen/MachineInstr.h"
|
||||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/CodeGen/Passes.h"
|
#include "llvm/CodeGen/Passes.h"
|
||||||
|
#include "llvm/CodeGen/PseudoSourceValue.h"
|
||||||
#include "llvm/Target/TargetRegisterInfo.h"
|
#include "llvm/Target/TargetRegisterInfo.h"
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
#include "llvm/Target/TargetInstrInfo.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
@ -54,6 +56,8 @@ char LiveIntervals::ID = 0;
|
|||||||
static RegisterPass<LiveIntervals> X("liveintervals", "Live Interval Analysis");
|
static RegisterPass<LiveIntervals> X("liveintervals", "Live Interval Analysis");
|
||||||
|
|
||||||
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
|
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
|
AU.addRequired<AliasAnalysis>();
|
||||||
|
AU.addPreserved<AliasAnalysis>();
|
||||||
AU.addPreserved<LiveVariables>();
|
AU.addPreserved<LiveVariables>();
|
||||||
AU.addRequired<LiveVariables>();
|
AU.addRequired<LiveVariables>();
|
||||||
AU.addPreservedID(MachineLoopInfoID);
|
AU.addPreservedID(MachineLoopInfoID);
|
||||||
@ -212,6 +216,7 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
|
|||||||
tm_ = &fn.getTarget();
|
tm_ = &fn.getTarget();
|
||||||
tri_ = tm_->getRegisterInfo();
|
tri_ = tm_->getRegisterInfo();
|
||||||
tii_ = tm_->getInstrInfo();
|
tii_ = tm_->getInstrInfo();
|
||||||
|
aa_ = &getAnalysis<AliasAnalysis>();
|
||||||
lv_ = &getAnalysis<LiveVariables>();
|
lv_ = &getAnalysis<LiveVariables>();
|
||||||
allocatableRegs_ = tri_->getAllocatableSet(fn);
|
allocatableRegs_ = tri_->getAllocatableSet(fn);
|
||||||
|
|
||||||
@ -750,7 +755,9 @@ unsigned LiveIntervals::getReMatImplicitUse(const LiveInterval &li,
|
|||||||
assert(!RegOp &&
|
assert(!RegOp &&
|
||||||
"Can't rematerialize instruction with multiple register operand!");
|
"Can't rematerialize instruction with multiple register operand!");
|
||||||
RegOp = MO.getReg();
|
RegOp = MO.getReg();
|
||||||
|
#ifndef NDEBUG
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return RegOp;
|
return RegOp;
|
||||||
}
|
}
|
||||||
@ -773,7 +780,6 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
|
|||||||
if (DisableReMat)
|
if (DisableReMat)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
isLoad = false;
|
|
||||||
if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
|
if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -786,9 +792,80 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
|
|||||||
// This is a load from fixed stack slot. It can be rematerialized.
|
// This is a load from fixed stack slot. It can be rematerialized.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (tii_->isTriviallyReMaterializable(MI)) {
|
// If the target-specific rules don't identify an instruction as
|
||||||
|
// being trivially rematerializable, use some target-independent
|
||||||
|
// rules.
|
||||||
|
if (!MI->getDesc().isRematerializable() ||
|
||||||
|
!tii_->isTriviallyReMaterializable(MI)) {
|
||||||
|
|
||||||
|
// If the instruction access memory but the memoperands have been lost,
|
||||||
|
// we can't analyze it.
|
||||||
const TargetInstrDesc &TID = MI->getDesc();
|
const TargetInstrDesc &TID = MI->getDesc();
|
||||||
isLoad = TID.isSimpleLoad();
|
if ((TID.mayLoad() || TID.mayStore()) && MI->memoperands_empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Avoid instructions obviously unsafe for remat.
|
||||||
|
if (TID.hasUnmodeledSideEffects() || TID.isNotDuplicable())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If the instruction accesses memory and the memory could be non-constant,
|
||||||
|
// assume the instruction is not rematerializable.
|
||||||
|
for (alist<MachineMemOperand>::const_iterator I = MI->memoperands_begin(),
|
||||||
|
E = MI->memoperands_end(); I != E; ++I) {
|
||||||
|
const MachineMemOperand &MMO = *I;
|
||||||
|
if (MMO.isVolatile() || MMO.isStore())
|
||||||
|
return false;
|
||||||
|
const Value *V = MMO.getValue();
|
||||||
|
if (!V)
|
||||||
|
return false;
|
||||||
|
if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V)) {
|
||||||
|
if (!PSV->isConstant(mf_->getFrameInfo()))
|
||||||
|
return false;
|
||||||
|
} else if (!aa_->pointsToConstantMemory(V))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any of the registers accessed are non-constant, conservatively assume
|
||||||
|
// the instruction is not rematerializable.
|
||||||
|
unsigned ImpUse = 0;
|
||||||
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
|
const MachineOperand &MO = MI->getOperand(i);
|
||||||
|
if (MO.isReg()) {
|
||||||
|
unsigned Reg = MO.getReg();
|
||||||
|
if (Reg == 0)
|
||||||
|
continue;
|
||||||
|
if (TargetRegisterInfo::isPhysicalRegister(Reg))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Only allow one def, and that in the first operand.
|
||||||
|
if (MO.isDef() != (i == 0))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Only allow constant-valued registers.
|
||||||
|
bool IsLiveIn = mri_->isLiveIn(Reg);
|
||||||
|
MachineRegisterInfo::def_iterator I = mri_->def_begin(Reg),
|
||||||
|
E = mri_->def_end();
|
||||||
|
|
||||||
|
// For the def, it should be the only def.
|
||||||
|
if (MO.isDef() && (next(I) != E || IsLiveIn))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (MO.isUse()) {
|
||||||
|
// Only allow one use other register use, as that's all the
|
||||||
|
// remat mechanisms support currently.
|
||||||
|
if (Reg != li.reg) {
|
||||||
|
if (ImpUse == 0)
|
||||||
|
ImpUse = Reg;
|
||||||
|
else if (Reg != ImpUse)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// For uses, there should be only one associate def.
|
||||||
|
if (I != E && (next(I) != E || IsLiveIn))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned ImpUse = getReMatImplicitUse(li, MI);
|
unsigned ImpUse = getReMatImplicitUse(li, MI);
|
||||||
if (ImpUse) {
|
if (ImpUse) {
|
||||||
@ -804,9 +881,6 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isReMaterializable - Returns true if every definition of MI of every
|
/// isReMaterializable - Returns true if every definition of MI of every
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
#include "llvm/CodeGen/PseudoSourceValue.h"
|
#include "llvm/CodeGen/PseudoSourceValue.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
@ -51,6 +52,9 @@ namespace llvm {
|
|||||||
const int FI;
|
const int FI;
|
||||||
public:
|
public:
|
||||||
explicit FixedStackPseudoSourceValue(int fi) : FI(fi) {}
|
explicit FixedStackPseudoSourceValue(int fi) : FI(fi) {}
|
||||||
|
|
||||||
|
virtual bool isConstant(const MachineFrameInfo *MFI) const;
|
||||||
|
|
||||||
virtual void print(std::ostream &OS) const {
|
virtual void print(std::ostream &OS) const {
|
||||||
OS << "FixedStack" << FI;
|
OS << "FixedStack" << FI;
|
||||||
}
|
}
|
||||||
@ -64,4 +68,20 @@ namespace llvm {
|
|||||||
V = new FixedStackPseudoSourceValue(FI);
|
V = new FixedStackPseudoSourceValue(FI);
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PseudoSourceValue::isConstant(const MachineFrameInfo *) const {
|
||||||
|
if (this == getStack())
|
||||||
|
return false;
|
||||||
|
if (this == getGOT() ||
|
||||||
|
this == getConstantPool() ||
|
||||||
|
this == getJumpTable())
|
||||||
|
return true;
|
||||||
|
assert(0 && "Unknown PseudoSourceValue!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FixedStackPseudoSourceValue::isConstant(const MachineFrameInfo *MFI) const {
|
||||||
|
return MFI && MFI->isImmutableObjectIndex(FI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
15
test/CodeGen/X86/remat-constant.ll
Normal file
15
test/CodeGen/X86/remat-constant.ll
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -march=x86-64 -relocation-model=static | grep xmm | count 2
|
||||||
|
|
||||||
|
declare void @bar() nounwind
|
||||||
|
|
||||||
|
@a = external constant float
|
||||||
|
|
||||||
|
declare void @qux(float %f) nounwind
|
||||||
|
|
||||||
|
define void @foo() nounwind {
|
||||||
|
%f = load float* @a
|
||||||
|
call void @bar()
|
||||||
|
call void @qux(float %f)
|
||||||
|
call void @qux(float %f)
|
||||||
|
ret void
|
||||||
|
}
|
Reference in New Issue
Block a user