mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
5ff776bfde
The common code in the post-RA scheduler to break anti-dependencies on the critical path contained a flaw. In the reported case, an anti-dependency between the overlapping registers %X4 and %R4 exists: %X29<def> = OR8 %X4, %X4 %R4<def>, %X3<def,dead,tied3> = LBZU 1, %X3<kill,tied1> The unpatched code breaks the dependency by replacing %R4 and its uses with %R3, the first register on the available list. However, %R3 and %X3 overlap, so this creates two overlapping definitions on the same instruction. The fix is straightforward, preventing selection of a register that overlaps any other defined register on the same instruction. The test case is reduced from the bug report, and verifies that we no longer produce "lbzu 3, 1(3)" when breaking this anti-dependency. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173706 91177308-0d34-0410-b5e6-96231b3b80d8
111 lines
4.2 KiB
C++
111 lines
4.2 KiB
C++
//=- llvm/CodeGen/CriticalAntiDepBreaker.h - Anti-Dep Support -*- C++ -*-=//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the CriticalAntiDepBreaker class, which
|
|
// implements register anti-dependence breaking along a blocks
|
|
// critical path during post-RA scheduler.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CODEGEN_CRITICALANTIDEPBREAKER_H
|
|
#define LLVM_CODEGEN_CRITICALANTIDEPBREAKER_H
|
|
|
|
#include "AntiDepBreaker.h"
|
|
#include "llvm/ADT/BitVector.h"
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/CodeGen/RegisterClassInfo.h"
|
|
#include "llvm/CodeGen/ScheduleDAG.h"
|
|
#include <map>
|
|
|
|
namespace llvm {
|
|
class RegisterClassInfo;
|
|
class TargetInstrInfo;
|
|
class TargetRegisterInfo;
|
|
|
|
class CriticalAntiDepBreaker : public AntiDepBreaker {
|
|
MachineFunction& MF;
|
|
MachineRegisterInfo &MRI;
|
|
const TargetInstrInfo *TII;
|
|
const TargetRegisterInfo *TRI;
|
|
const RegisterClassInfo &RegClassInfo;
|
|
|
|
/// AllocatableSet - The set of allocatable registers.
|
|
/// We'll be ignoring anti-dependencies on non-allocatable registers,
|
|
/// because they may not be safe to break.
|
|
const BitVector AllocatableSet;
|
|
|
|
/// Classes - For live regs that are only used in one register class in a
|
|
/// live range, the register class. If the register is not live, the
|
|
/// corresponding value is null. If the register is live but used in
|
|
/// multiple register classes, the corresponding value is -1 casted to a
|
|
/// pointer.
|
|
std::vector<const TargetRegisterClass*> Classes;
|
|
|
|
/// RegRefs - Map registers to all their references within a live range.
|
|
std::multimap<unsigned, MachineOperand *> RegRefs;
|
|
typedef std::multimap<unsigned, MachineOperand *>::const_iterator
|
|
RegRefIter;
|
|
|
|
/// KillIndices - The index of the most recent kill (proceding bottom-up),
|
|
/// or ~0u if the register is not live.
|
|
std::vector<unsigned> KillIndices;
|
|
|
|
/// DefIndices - The index of the most recent complete def (proceding bottom
|
|
/// up), or ~0u if the register is live.
|
|
std::vector<unsigned> DefIndices;
|
|
|
|
/// KeepRegs - A set of registers which are live and cannot be changed to
|
|
/// break anti-dependencies.
|
|
BitVector KeepRegs;
|
|
|
|
public:
|
|
CriticalAntiDepBreaker(MachineFunction& MFi, const RegisterClassInfo&);
|
|
~CriticalAntiDepBreaker();
|
|
|
|
/// Start - Initialize anti-dep breaking for a new basic block.
|
|
void StartBlock(MachineBasicBlock *BB);
|
|
|
|
/// BreakAntiDependencies - Identifiy anti-dependencies along the critical
|
|
/// path
|
|
/// of the ScheduleDAG and break them by renaming registers.
|
|
///
|
|
unsigned BreakAntiDependencies(const std::vector<SUnit>& SUnits,
|
|
MachineBasicBlock::iterator Begin,
|
|
MachineBasicBlock::iterator End,
|
|
unsigned InsertPosIndex,
|
|
DbgValueVector &DbgValues);
|
|
|
|
/// Observe - Update liveness information to account for the current
|
|
/// instruction, which will not be scheduled.
|
|
///
|
|
void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex);
|
|
|
|
/// Finish - Finish anti-dep breaking for a basic block.
|
|
void FinishBlock();
|
|
|
|
private:
|
|
void PrescanInstruction(MachineInstr *MI);
|
|
void ScanInstruction(MachineInstr *MI, unsigned Count);
|
|
bool isNewRegClobberedByRefs(RegRefIter RegRefBegin,
|
|
RegRefIter RegRefEnd,
|
|
unsigned NewReg);
|
|
unsigned findSuitableFreeRegister(RegRefIter RegRefBegin,
|
|
RegRefIter RegRefEnd,
|
|
unsigned AntiDepReg,
|
|
unsigned LastNewReg,
|
|
const TargetRegisterClass *RC,
|
|
SmallVector<unsigned, 2> &Forbid);
|
|
};
|
|
}
|
|
|
|
#endif
|