#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
namespace llvm {
/// The new instruction is inserted before MI, and the client is responsible
/// for removing the old instruction.
MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI,
- ArrayRef<unsigned> Ops, int FrameIndex) const;
+ ArrayRef<unsigned> Ops, int FrameIndex,
+ LiveIntervals *LIS = nullptr) const;
/// Same as the previous version except it allows folding of any load and
/// store from / to any address, not just from a specific stack slot.
MachineInstr *foldMemoryOperand(MachineBasicBlock::iterator MI,
ArrayRef<unsigned> Ops,
- MachineInstr *LoadMI) const;
+ MachineInstr *LoadMI,
+ LiveIntervals *LIS = nullptr) const;
/// Return true when there is potentially a faster code sequence
/// for an instruction chain ending in \p Root. All potential patterns are
/// at InsertPt.
virtual MachineInstr *foldMemoryOperandImpl(
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
- MachineBasicBlock::iterator InsertPt, int FrameIndex) const {
+ MachineBasicBlock::iterator InsertPt, int FrameIndex,
+ LiveIntervals *LIS = nullptr) const {
return nullptr;
}
/// at InsertPt.
virtual MachineInstr *foldMemoryOperandImpl(
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
- MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI) const {
+ MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI,
+ LiveIntervals *LIS = nullptr) const {
return nullptr;
}
MachineInstrSpan MIS(MI);
MachineInstr *FoldMI =
- LoadMI ? TII.foldMemoryOperand(MI, FoldOps, LoadMI)
- : TII.foldMemoryOperand(MI, FoldOps, StackSlot);
+ LoadMI ? TII.foldMemoryOperand(MI, FoldOps, LoadMI, &LIS)
+ : TII.foldMemoryOperand(MI, FoldOps, StackSlot, &LIS);
if (!FoldMI)
return false;
if (UseMI->readsWritesVirtualRegister(LI->reg, &Ops).second)
return false;
- MachineInstr *FoldMI = TII.foldMemoryOperand(UseMI, Ops, DefMI);
+ MachineInstr *FoldMI = TII.foldMemoryOperand(UseMI, Ops, DefMI, &LIS);
if (!FoldMI)
return false;
DEBUG(dbgs() << " folded: " << *FoldMI);
/// stream.
MachineInstr *TargetInstrInfo::foldMemoryOperand(MachineBasicBlock::iterator MI,
ArrayRef<unsigned> Ops,
- int FI) const {
+ int FI,
+ LiveIntervals *LIS) const {
unsigned Flags = 0;
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
if (MI->getOperand(Ops[i]).isDef())
MBB->insert(MI, NewMI);
} else {
// Ask the target to do the actual folding.
- NewMI = foldMemoryOperandImpl(MF, MI, Ops, MI, FI);
+ NewMI = foldMemoryOperandImpl(MF, MI, Ops, MI, FI, LIS);
}
if (NewMI) {
/// stack slot.
MachineInstr *TargetInstrInfo::foldMemoryOperand(MachineBasicBlock::iterator MI,
ArrayRef<unsigned> Ops,
- MachineInstr *LoadMI) const {
+ MachineInstr *LoadMI,
+ LiveIntervals *LIS) const {
assert(LoadMI->canFoldAsLoad() && "LoadMI isn't foldable!");
#ifndef NDEBUG
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
NewMI = MBB.insert(MI, NewMI);
} else {
// Ask the target to do the actual folding.
- NewMI = foldMemoryOperandImpl(MF, MI, Ops, MI, LoadMI);
+ NewMI = foldMemoryOperandImpl(MF, MI, Ops, MI, LoadMI, LIS);
}
if (!NewMI) return nullptr;
MachineInstr *AArch64InstrInfo::foldMemoryOperandImpl(
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
- MachineBasicBlock::iterator InsertPt, int FrameIndex) const {
+ MachineBasicBlock::iterator InsertPt, int FrameIndex,
+ LiveIntervals *LIS) const {
// This is a bit of a hack. Consider this instruction:
//
// %vreg0<def> = COPY %SP; GPR64all:%vreg0
MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
ArrayRef<unsigned> Ops,
MachineBasicBlock::iterator InsertPt,
- int FrameIndex) const override;
+ int FrameIndex,
+ LiveIntervals *LIS = nullptr) const override;
bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
#include "SystemZInstrBuilder.h"
#include "SystemZTargetMachine.h"
#include "llvm/CodeGen/LiveVariables.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
using namespace llvm;
MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
- MachineBasicBlock::iterator InsertPt, int FrameIndex) const {
+ MachineBasicBlock::iterator InsertPt, int FrameIndex,
+ LiveIntervals *LIS) const {
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
const MachineFrameInfo *MFI = MF.getFrameInfo();
unsigned Size = MFI->getObjectSize(FrameIndex);
unsigned Opcode = MI->getOpcode();
-// XXX This is an introduction of a CC def and is illegal! Reactivate
-// with a check of liveness of CC reg.
-#if 0
if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) {
- if ((Opcode == SystemZ::LA || Opcode == SystemZ::LAY) &&
+ if (LIS != nullptr &&
+ (Opcode == SystemZ::LA || Opcode == SystemZ::LAY) &&
isInt<8>(MI->getOperand(2).getImm()) &&
!MI->getOperand(3).getReg()) {
- // LA(Y) %reg, CONST(%reg) -> AGSI %mem, CONST
- MachineInstr *BuiltMI =
- BuildMI(*InsertPt->getParent(), InsertPt, MI->getDebugLoc(),
- get(SystemZ::AGSI))
+
+ // Check CC liveness, since new instruction introduces a dead
+ // def of CC.
+ MCRegUnitIterator CCUnit(SystemZ::CC, TRI);
+ LiveRange &CCLiveRange = LIS->getRegUnit(*CCUnit);
+ ++CCUnit;
+ assert (!CCUnit.isValid() && "CC only has one reg unit.");
+ SlotIndex MISlot =
+ LIS->getSlotIndexes()->getInstructionIndex(*MI).getRegSlot();
+ if (!CCLiveRange.liveAt(MISlot)) {
+ // LA(Y) %reg, CONST(%reg) -> AGSI %mem, CONST
+ MachineInstr *BuiltMI =
+ BuildMI(*InsertPt->getParent(), InsertPt, MI->getDebugLoc(),
+ get(SystemZ::AGSI))
.addFrameIndex(FrameIndex)
.addImm(0)
.addImm(MI->getOperand(2).getImm());
- BuiltMI->findRegisterDefOperand(SystemZ::CC)->setIsDead(true);
- return BuiltMI;
+ BuiltMI->findRegisterDefOperand(SystemZ::CC)->setIsDead(true);
+ CCLiveRange.createDeadDef(MISlot, LIS->getVNInfoAllocator());
+ return BuiltMI;
+ }
}
return nullptr;
}
-#endif
// All other cases require a single operand.
if (Ops.size() != 1)
MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
- MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI) const {
+ MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI,
+ LiveIntervals *LIS) const {
return nullptr;
}
MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
ArrayRef<unsigned> Ops,
MachineBasicBlock::iterator InsertPt,
- int FrameIndex) const override;
+ int FrameIndex,
+ LiveIntervals *LIS = nullptr) const override;
MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
ArrayRef<unsigned> Ops,
MachineBasicBlock::iterator InsertPt,
- MachineInstr *LoadMI) const override;
+ MachineInstr *LoadMI,
+ LiveIntervals *LIS = nullptr) const override;
bool expandPostRAPseudo(MachineBasicBlock::iterator MBBI) const override;
bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const
override;
MachineInstr *X86InstrInfo::foldMemoryOperandImpl(
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
- MachineBasicBlock::iterator InsertPt, int FrameIndex) const {
+ MachineBasicBlock::iterator InsertPt, int FrameIndex,
+ LiveIntervals *LIS) const {
// Check switch flag
if (NoFusing)
return nullptr;
MachineInstr *X86InstrInfo::foldMemoryOperandImpl(
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
- MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI) const {
+ MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI,
+ LiveIntervals *LIS) const {
// If loading from a FrameIndex, fold directly from the FrameIndex.
unsigned NumOps = LoadMI->getDesc().getNumOperands();
int FrameIndex;
if (isLoadFromStackSlot(LoadMI, FrameIndex)) {
if (isNonFoldablePartialRegisterLoad(*LoadMI, *MI, MF))
return nullptr;
- return foldMemoryOperandImpl(MF, MI, Ops, InsertPt, FrameIndex);
+ return foldMemoryOperandImpl(MF, MI, Ops, InsertPt, FrameIndex, LIS);
}
// Check switch flag
MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
ArrayRef<unsigned> Ops,
MachineBasicBlock::iterator InsertPt,
- int FrameIndex) const override;
+ int FrameIndex,
+ LiveIntervals *LIS = nullptr) const override;
/// foldMemoryOperand - Same as the previous version except it allows folding
/// of any load and store from / to any address, not just from a specific
MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
ArrayRef<unsigned> Ops,
MachineBasicBlock::iterator InsertPt,
- MachineInstr *LoadMI) const override;
+ MachineInstr *LoadMI,
+ LiveIntervals *LIS = nullptr) const override;
/// unfoldMemoryOperand - Separate a single instruction which folded a load or
/// a store or a load and a store into two or more instruction. If this is
; Check that adding 127 to a spilled value can use AGSI.
define void @f11(i64 *%ptr, i32 %sel) {
; CHECK-LABEL: f11:
-; _CHECK: agsi {{[0-9]+}}(%r15), 127
+; CHECK: agsi {{[0-9]+}}(%r15), 127
; CHECK: br %r14
entry:
%val0 = load volatile i64 , i64 *%ptr