summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2008-07-25 00:02:30 +0000
committerDan Gohman <gohman@apple.com>2008-07-25 00:02:30 +0000
commit6d69ba8a6901c69d78488cbc41f8dbf080618fde (patch)
treed3561769602cb34fb08db592e6576877e3be6165 /lib
parent3eee6542f5c65dce299361fa5435340513cf3fe4 (diff)
downloadllvm-6d69ba8a6901c69d78488cbc41f8dbf080618fde.tar.gz
llvm-6d69ba8a6901c69d78488cbc41f8dbf080618fde.tar.bz2
llvm-6d69ba8a6901c69d78488cbc41f8dbf080618fde.tar.xz
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
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp104
-rw-r--r--lib/CodeGen/PseudoSourceValue.cpp20
2 files changed, 109 insertions, 15 deletions
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index 1f29055e2f..adc1e207b5 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -19,12 +19,14 @@
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "VirtRegMap.h"
#include "llvm/Value.h"
+#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
@@ -54,6 +56,8 @@ char LiveIntervals::ID = 0;
static RegisterPass<LiveIntervals> X("liveintervals", "Live Interval Analysis");
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<AliasAnalysis>();
+ AU.addPreserved<AliasAnalysis>();
AU.addPreserved<LiveVariables>();
AU.addRequired<LiveVariables>();
AU.addPreservedID(MachineLoopInfoID);
@@ -212,6 +216,7 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
tm_ = &fn.getTarget();
tri_ = tm_->getRegisterInfo();
tii_ = tm_->getInstrInfo();
+ aa_ = &getAnalysis<AliasAnalysis>();
lv_ = &getAnalysis<LiveVariables>();
allocatableRegs_ = tri_->getAllocatableSet(fn);
@@ -750,7 +755,9 @@ unsigned LiveIntervals::getReMatImplicitUse(const LiveInterval &li,
assert(!RegOp &&
"Can't rematerialize instruction with multiple register operand!");
RegOp = MO.getReg();
+#ifndef NDEBUG
break;
+#endif
}
return RegOp;
}
@@ -773,7 +780,6 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
if (DisableReMat)
return false;
- isLoad = false;
if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
return true;
@@ -786,27 +792,95 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
// This is a load from fixed stack slot. It can be rematerialized.
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();
- isLoad = TID.isSimpleLoad();
-
- unsigned ImpUse = getReMatImplicitUse(li, MI);
- if (ImpUse) {
- const LiveInterval &ImpLi = getInterval(ImpUse);
- for (MachineRegisterInfo::use_iterator ri = mri_->use_begin(li.reg),
- re = mri_->use_end(); ri != re; ++ri) {
- MachineInstr *UseMI = &*ri;
- unsigned UseIdx = getInstructionIndex(UseMI);
- if (li.FindLiveRangeContaining(UseIdx)->valno != ValNo)
+ 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 (!isValNoAvailableAt(ImpLi, MI, UseIdx))
+ 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;
+ }
}
}
- return true;
}
- return false;
+ unsigned ImpUse = getReMatImplicitUse(li, MI);
+ if (ImpUse) {
+ const LiveInterval &ImpLi = getInterval(ImpUse);
+ for (MachineRegisterInfo::use_iterator ri = mri_->use_begin(li.reg),
+ re = mri_->use_end(); ri != re; ++ri) {
+ MachineInstr *UseMI = &*ri;
+ unsigned UseIdx = getInstructionIndex(UseMI);
+ if (li.FindLiveRangeContaining(UseIdx)->valno != ValNo)
+ continue;
+ if (!isValNoAvailableAt(ImpLi, MI, UseIdx))
+ return false;
+ }
+ }
+ return true;
}
/// isReMaterializable - Returns true if every definition of MI of every
diff --git a/lib/CodeGen/PseudoSourceValue.cpp b/lib/CodeGen/PseudoSourceValue.cpp
index 27995547c6..bcf4ea8fb7 100644
--- a/lib/CodeGen/PseudoSourceValue.cpp
+++ b/lib/CodeGen/PseudoSourceValue.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Support/Compiler.h"
@@ -51,6 +52,9 @@ namespace llvm {
const int FI;
public:
explicit FixedStackPseudoSourceValue(int fi) : FI(fi) {}
+
+ virtual bool isConstant(const MachineFrameInfo *MFI) const;
+
virtual void print(std::ostream &OS) const {
OS << "FixedStack" << FI;
}
@@ -64,4 +68,20 @@ namespace llvm {
V = new FixedStackPseudoSourceValue(FI);
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);
+ }
}