aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/TargetInstrInfoImpl.cpp
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-10-09 23:27:56 +0000
committerDan Gohman <gohman@apple.com>2009-10-09 23:27:56 +0000
commita70dca156fa76d452f54829b5c5f962ddfd94ef2 (patch)
tree31322fbef91a904807aea13e1bc2ab409c0042c6 /lib/CodeGen/TargetInstrInfoImpl.cpp
parentac1ceb3dd33cb79ecb0dbd64b6abafa7ce067c5f (diff)
Factor out LiveIntervalAnalysis' code to determine whether an instruction
is trivially rematerializable and integrate it into TargetInstrInfo::isTriviallyReMaterializable. This way, all places that need to know whether an instruction is rematerializable will get the same answer. This enables the useful parts of the aggressive-remat option by default -- using AliasAnalysis to determine whether a memory location is invariant, and removes the questionable parts -- rematting operations with virtual register inputs that may not be live everywhere. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83687 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/TargetInstrInfoImpl.cpp')
-rw-r--r--lib/CodeGen/TargetInstrInfoImpl.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/lib/CodeGen/TargetInstrInfoImpl.cpp b/lib/CodeGen/TargetInstrInfoImpl.cpp
index ab67cd2a08..2211308856 100644
--- a/lib/CodeGen/TargetInstrInfoImpl.cpp
+++ b/lib/CodeGen/TargetInstrInfoImpl.cpp
@@ -13,11 +13,14 @@
//===----------------------------------------------------------------------===//
#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -238,3 +241,88 @@ TargetInstrInfo::foldMemoryOperand(MachineFunction &MF,
return NewMI;
}
+
+bool
+TargetInstrInfo::isReallyTriviallyReMaterializableGeneric(const MachineInstr *
+ MI,
+ AliasAnalysis *
+ AA) const {
+ const MachineFunction &MF = *MI->getParent()->getParent();
+ const MachineRegisterInfo &MRI = MF.getRegInfo();
+ const TargetMachine &TM = MF.getTarget();
+ const TargetInstrInfo &TII = *TM.getInstrInfo();
+ const TargetRegisterInfo &TRI = *TM.getRegisterInfo();
+
+ // A load from a fixed stack slot can be rematerialized. This may be
+ // redundant with subsequent checks, but it's target-independent,
+ // simple, and a common case.
+ int FrameIdx = 0;
+ if (TII.isLoadFromStackSlot(MI, FrameIdx) &&
+ MF.getFrameInfo()->isImmutableObjectIndex(FrameIdx))
+ return true;
+
+ const TargetInstrDesc &TID = MI->getDesc();
+
+ // Avoid instructions obviously unsafe for remat.
+ if (TID.hasUnmodeledSideEffects() || TID.isNotDuplicable() ||
+ TID.mayStore())
+ return false;
+
+ // Avoid instructions which load from potentially varying memory.
+ if (TID.mayLoad() && !MI->isInvariantLoad(AA))
+ return false;
+
+ // If any of the registers accessed are non-constant, conservatively assume
+ // the instruction is not rematerializable.
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ if (!MO.isReg()) continue;
+ unsigned Reg = MO.getReg();
+ if (Reg == 0)
+ continue;
+
+ // Check for a well-behaved physical register.
+ if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
+ if (MO.isUse()) {
+ // If the physreg has no defs anywhere, it's just an ambient register
+ // and we can freely move its uses. Alternatively, if it's allocatable,
+ // it could get allocated to something with a def during allocation.
+ if (!MRI.def_empty(Reg))
+ return false;
+ BitVector AllocatableRegs = TRI.getAllocatableSet(MF, 0);
+ if (AllocatableRegs.test(Reg))
+ return false;
+ // Check for a def among the register's aliases too.
+ for (const unsigned *Alias = TRI.getAliasSet(Reg); *Alias; ++Alias) {
+ unsigned AliasReg = *Alias;
+ if (!MRI.def_empty(AliasReg))
+ return false;
+ if (AllocatableRegs.test(AliasReg))
+ return false;
+ }
+ } else {
+ // A physreg def. We can't remat it.
+ return false;
+ }
+ continue;
+ }
+
+ // Only allow one virtual-register def, and that in the first operand.
+ if (MO.isDef() != (i == 0))
+ return false;
+
+ // For the def, it should be the only def of that register.
+ if (MO.isDef() && (next(MRI.def_begin(Reg)) != MRI.def_end() ||
+ MRI.isLiveIn(Reg)))
+ return false;
+
+ // Don't allow any virtual-register uses. Rematting an instruction with
+ // virtual register uses would length the live ranges of the uses, which
+ // is not necessarily a good idea, certainly not "trivial".
+ if (MO.isUse())
+ return false;
+ }
+
+ // Everything checked out.
+ return true;
+}