mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-25 21:18:19 +00:00
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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user