2017-08-10 02:46:15 +02:00
|
|
|
//===- R600MergeVectorRegisters.cpp ---------------------------------------===//
|
2013-06-05 23:38:04 +02:00
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2013-06-05 23:38:04 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
/// \file
|
|
|
|
/// This pass merges inputs of swizzeable instructions into vector sharing
|
|
|
|
/// common data and/or have enough undef subreg using swizzle abilities.
|
|
|
|
///
|
|
|
|
/// For instance let's consider the following pseudo code :
|
2017-12-07 11:40:31 +01:00
|
|
|
/// %5 = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3
|
2013-06-05 23:38:04 +02:00
|
|
|
/// ...
|
2017-12-07 11:40:31 +01:00
|
|
|
/// %7 = REG_SEQ %1, sub0, %3, sub1, undef, sub2, %4, sub3
|
2017-11-30 13:12:19 +01:00
|
|
|
/// (swizzable Inst) %7, SwizzleMask : sub0, sub1, sub2, sub3
|
2013-06-05 23:38:04 +02:00
|
|
|
///
|
|
|
|
/// is turned into :
|
2017-12-07 11:40:31 +01:00
|
|
|
/// %5 = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3
|
2013-06-05 23:38:04 +02:00
|
|
|
/// ...
|
2017-12-07 11:40:31 +01:00
|
|
|
/// %7 = INSERT_SUBREG %4, sub3
|
2017-11-30 13:12:19 +01:00
|
|
|
/// (swizzable Inst) %7, SwizzleMask : sub0, sub2, sub1, sub3
|
2013-06-05 23:38:04 +02:00
|
|
|
///
|
|
|
|
/// This allow regalloc to reduce register pressure for vector registers and
|
|
|
|
/// to reduce MOV count.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "AMDGPU.h"
|
2014-08-04 23:25:23 +02:00
|
|
|
#include "AMDGPUSubtarget.h"
|
2016-06-24 08:30:11 +02:00
|
|
|
#include "R600Defines.h"
|
2015-03-23 20:32:43 +01:00
|
|
|
#include "R600InstrInfo.h"
|
AMDGPU: Remove #include "MCTargetDesc/AMDGPUMCTargetDesc.h" from common headers
Summary:
MCTargetDesc/AMDGPUMCTargetDesc.h contains enums for all the instuction
and register defintions, which are huge so we only want to include
them where needed.
This will also make it easier if we want to split the R600 and GCN
definitions into separate tablegenerated files.
I was unable to remove AMDGPUMCTargetDesc.h from SIMachineFunctionInfo.h
because it uses some enums from the header to initialize default values
for the SIMachineFunction class, so I ended up having to remove includes of
SIMachineFunctionInfo.h from headers too.
Reviewers: arsenm, nhaehnle
Reviewed By: nhaehnle
Subscribers: MatzeB, kzhuravl, wdng, yaxunl, dstuttard, tpr, t-tye, javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D46272
llvm-svn: 332930
2018-05-22 04:03:23 +02:00
|
|
|
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
|
2016-12-12 23:23:53 +01:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
2013-06-05 23:38:04 +02:00
|
|
|
#include "llvm/CodeGen/MachineDominators.h"
|
2016-12-12 23:23:53 +01:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2013-06-05 23:38:04 +02:00
|
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
2016-12-12 23:23:53 +01:00
|
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
2014-01-07 12:48:04 +01:00
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
2013-06-05 23:38:04 +02:00
|
|
|
#include "llvm/CodeGen/MachineLoopInfo.h"
|
2016-12-12 23:23:53 +01:00
|
|
|
#include "llvm/CodeGen/MachineOperand.h"
|
2014-01-07 12:48:04 +01:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2016-12-12 23:23:53 +01:00
|
|
|
#include "llvm/IR/DebugLoc.h"
|
2017-08-10 02:46:15 +02:00
|
|
|
#include "llvm/Pass.h"
|
2015-03-23 20:32:43 +01:00
|
|
|
#include "llvm/Support/Debug.h"
|
2016-12-12 23:23:53 +01:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2013-06-05 23:38:04 +02:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2016-12-12 23:23:53 +01:00
|
|
|
#include <cassert>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2013-06-05 23:38:04 +02:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 04:41:26 +02:00
|
|
|
#define DEBUG_TYPE "vec-merger"
|
|
|
|
|
2019-05-20 18:22:11 +02:00
|
|
|
static bool isImplicitlyDef(MachineRegisterInfo &MRI, unsigned Reg) {
|
|
|
|
assert(MRI.isSSA());
|
2019-08-02 01:27:28 +02:00
|
|
|
if (Register::isPhysicalRegister(Reg))
|
2013-08-16 03:11:55 +02:00
|
|
|
return false;
|
2019-05-20 18:22:11 +02:00
|
|
|
const MachineInstr *MI = MRI.getUniqueVRegDef(Reg);
|
|
|
|
return MI && MI->isImplicitDef();
|
2013-06-05 23:38:04 +02:00
|
|
|
}
|
|
|
|
|
2016-12-12 23:23:53 +01:00
|
|
|
namespace {
|
|
|
|
|
2013-06-05 23:38:04 +02:00
|
|
|
class RegSeqInfo {
|
|
|
|
public:
|
|
|
|
MachineInstr *Instr;
|
|
|
|
DenseMap<unsigned, unsigned> RegToChan;
|
|
|
|
std::vector<unsigned> UndefReg;
|
2016-12-12 23:23:53 +01:00
|
|
|
|
2013-06-05 23:38:04 +02:00
|
|
|
RegSeqInfo(MachineRegisterInfo &MRI, MachineInstr *MI) : Instr(MI) {
|
AMDGPU: Separate R600 and GCN TableGen files
Summary:
We now have two sets of generated TableGen files, one for R600 and one
for GCN, so each sub-target now has its own tables of instructions,
registers, ISel patterns, etc. This should help reduce compile time
since each sub-target now only has to consider information that
is specific to itself. This will also help prevent the R600
sub-target from slowing down new features for GCN, like disassembler
support, GlobalISel, etc.
Reviewers: arsenm, nhaehnle, jvesely
Reviewed By: arsenm
Subscribers: MatzeB, kzhuravl, wdng, mgorny, yaxunl, dstuttard, tpr, t-tye, javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D46365
llvm-svn: 335942
2018-06-29 01:47:12 +02:00
|
|
|
assert(MI->getOpcode() == R600::REG_SEQUENCE);
|
2013-06-05 23:38:04 +02:00
|
|
|
for (unsigned i = 1, e = Instr->getNumOperands(); i < e; i+=2) {
|
|
|
|
MachineOperand &MO = Instr->getOperand(i);
|
|
|
|
unsigned Chan = Instr->getOperand(i + 1).getImm();
|
|
|
|
if (isImplicitlyDef(MRI, MO.getReg()))
|
|
|
|
UndefReg.push_back(Chan);
|
|
|
|
else
|
|
|
|
RegToChan[MO.getReg()] = Chan;
|
|
|
|
}
|
|
|
|
}
|
2016-12-12 23:23:53 +01:00
|
|
|
|
|
|
|
RegSeqInfo() = default;
|
2013-06-05 23:38:04 +02:00
|
|
|
|
|
|
|
bool operator==(const RegSeqInfo &RSI) const {
|
|
|
|
return RSI.Instr == Instr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class R600VectorRegMerger : public MachineFunctionPass {
|
|
|
|
private:
|
2017-08-10 02:46:15 +02:00
|
|
|
using InstructionSetMap = DenseMap<unsigned, std::vector<MachineInstr *>>;
|
|
|
|
|
2013-06-05 23:38:04 +02:00
|
|
|
MachineRegisterInfo *MRI;
|
2017-08-10 02:46:15 +02:00
|
|
|
const R600InstrInfo *TII = nullptr;
|
|
|
|
DenseMap<MachineInstr *, RegSeqInfo> PreviousRegSeq;
|
|
|
|
InstructionSetMap PreviousRegSeqByReg;
|
|
|
|
InstructionSetMap PreviousRegSeqByUndefCount;
|
2016-12-12 23:23:53 +01:00
|
|
|
|
|
|
|
bool canSwizzle(const MachineInstr &MI) const;
|
2013-06-05 23:38:04 +02:00
|
|
|
bool areAllUsesSwizzeable(unsigned Reg) const;
|
|
|
|
void SwizzleInput(MachineInstr &,
|
2016-12-12 23:23:53 +01:00
|
|
|
const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const;
|
|
|
|
bool tryMergeVector(const RegSeqInfo *Untouched, RegSeqInfo *ToMerge,
|
|
|
|
std::vector<std::pair<unsigned, unsigned>> &Remap) const;
|
2013-06-05 23:38:04 +02:00
|
|
|
bool tryMergeUsingCommonSlot(RegSeqInfo &RSI, RegSeqInfo &CompatibleRSI,
|
2016-12-12 23:23:53 +01:00
|
|
|
std::vector<std::pair<unsigned, unsigned>> &RemapChan);
|
2013-06-05 23:38:04 +02:00
|
|
|
bool tryMergeUsingFreeSlot(RegSeqInfo &RSI, RegSeqInfo &CompatibleRSI,
|
2016-12-12 23:23:53 +01:00
|
|
|
std::vector<std::pair<unsigned, unsigned>> &RemapChan);
|
|
|
|
MachineInstr *RebuildVector(RegSeqInfo *MI, const RegSeqInfo *BaseVec,
|
|
|
|
const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const;
|
2013-06-05 23:38:04 +02:00
|
|
|
void RemoveMI(MachineInstr *);
|
|
|
|
void trackRSI(const RegSeqInfo &RSI);
|
|
|
|
|
|
|
|
public:
|
|
|
|
static char ID;
|
2016-12-12 23:23:53 +01:00
|
|
|
|
2017-08-10 02:46:15 +02:00
|
|
|
R600VectorRegMerger() : MachineFunctionPass(ID) {}
|
2013-06-05 23:38:04 +02:00
|
|
|
|
2014-04-29 09:57:24 +02:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
2013-06-05 23:38:04 +02:00
|
|
|
AU.setPreservesCFG();
|
|
|
|
AU.addRequired<MachineDominatorTree>();
|
|
|
|
AU.addPreserved<MachineDominatorTree>();
|
|
|
|
AU.addRequired<MachineLoopInfo>();
|
|
|
|
AU.addPreserved<MachineLoopInfo>();
|
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
|
2016-10-01 04:56:57 +02:00
|
|
|
StringRef getPassName() const override {
|
2013-06-05 23:38:04 +02:00
|
|
|
return "R600 Vector Registers Merge Pass";
|
|
|
|
}
|
|
|
|
|
2014-04-29 09:57:24 +02:00
|
|
|
bool runOnMachineFunction(MachineFunction &Fn) override;
|
2013-06-05 23:38:04 +02:00
|
|
|
};
|
|
|
|
|
2017-08-10 02:46:15 +02:00
|
|
|
} // end anonymous namespace
|
2016-12-12 23:23:53 +01:00
|
|
|
|
2017-08-03 00:19:45 +02:00
|
|
|
INITIALIZE_PASS_BEGIN(R600VectorRegMerger, DEBUG_TYPE,
|
|
|
|
"R600 Vector Reg Merger", false, false)
|
|
|
|
INITIALIZE_PASS_END(R600VectorRegMerger, DEBUG_TYPE,
|
|
|
|
"R600 Vector Reg Merger", false, false)
|
|
|
|
|
2013-06-05 23:38:04 +02:00
|
|
|
char R600VectorRegMerger::ID = 0;
|
|
|
|
|
2017-08-03 00:19:45 +02:00
|
|
|
char &llvm::R600VectorRegMergerID = R600VectorRegMerger::ID;
|
|
|
|
|
2013-06-05 23:38:04 +02:00
|
|
|
bool R600VectorRegMerger::canSwizzle(const MachineInstr &MI)
|
|
|
|
const {
|
|
|
|
if (TII->get(MI.getOpcode()).TSFlags & R600_InstFlag::TEX_INST)
|
|
|
|
return true;
|
|
|
|
switch (MI.getOpcode()) {
|
AMDGPU: Separate R600 and GCN TableGen files
Summary:
We now have two sets of generated TableGen files, one for R600 and one
for GCN, so each sub-target now has its own tables of instructions,
registers, ISel patterns, etc. This should help reduce compile time
since each sub-target now only has to consider information that
is specific to itself. This will also help prevent the R600
sub-target from slowing down new features for GCN, like disassembler
support, GlobalISel, etc.
Reviewers: arsenm, nhaehnle, jvesely
Reviewed By: arsenm
Subscribers: MatzeB, kzhuravl, wdng, mgorny, yaxunl, dstuttard, tpr, t-tye, javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D46365
llvm-svn: 335942
2018-06-29 01:47:12 +02:00
|
|
|
case R600::R600_ExportSwz:
|
|
|
|
case R600::EG_ExportSwz:
|
2013-06-05 23:38:04 +02:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool R600VectorRegMerger::tryMergeVector(const RegSeqInfo *Untouched,
|
2016-12-12 23:23:53 +01:00
|
|
|
RegSeqInfo *ToMerge, std::vector< std::pair<unsigned, unsigned>> &Remap)
|
2013-06-05 23:38:04 +02:00
|
|
|
const {
|
|
|
|
unsigned CurrentUndexIdx = 0;
|
|
|
|
for (DenseMap<unsigned, unsigned>::iterator It = ToMerge->RegToChan.begin(),
|
|
|
|
E = ToMerge->RegToChan.end(); It != E; ++It) {
|
|
|
|
DenseMap<unsigned, unsigned>::const_iterator PosInUntouched =
|
|
|
|
Untouched->RegToChan.find((*It).first);
|
|
|
|
if (PosInUntouched != Untouched->RegToChan.end()) {
|
|
|
|
Remap.push_back(std::pair<unsigned, unsigned>
|
|
|
|
((*It).second, (*PosInUntouched).second));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (CurrentUndexIdx >= Untouched->UndefReg.size())
|
|
|
|
return false;
|
|
|
|
Remap.push_back(std::pair<unsigned, unsigned>
|
|
|
|
((*It).second, Untouched->UndefReg[CurrentUndexIdx++]));
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-06-07 01:08:32 +02:00
|
|
|
static
|
|
|
|
unsigned getReassignedChan(
|
2016-12-12 23:23:53 +01:00
|
|
|
const std::vector<std::pair<unsigned, unsigned>> &RemapChan,
|
2013-06-07 01:08:32 +02:00
|
|
|
unsigned Chan) {
|
|
|
|
for (unsigned j = 0, je = RemapChan.size(); j < je; j++) {
|
2013-06-07 17:44:53 +02:00
|
|
|
if (RemapChan[j].first == Chan)
|
2013-06-07 01:08:32 +02:00
|
|
|
return RemapChan[j].second;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Chan wasn't reassigned");
|
|
|
|
}
|
|
|
|
|
2013-06-05 23:38:04 +02:00
|
|
|
MachineInstr *R600VectorRegMerger::RebuildVector(
|
|
|
|
RegSeqInfo *RSI, const RegSeqInfo *BaseRSI,
|
2016-12-12 23:23:53 +01:00
|
|
|
const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const {
|
Apply llvm-prefer-register-over-unsigned from clang-tidy to LLVM
Summary:
This clang-tidy check is looking for unsigned integer variables whose initializer
starts with an implicit cast from llvm::Register and changes the type of the
variable to llvm::Register (dropping the llvm:: where possible).
Partial reverts in:
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
X86FixupLEAs.cpp - Some functions return unsigned and arguably should be MCRegister
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
HexagonBitSimplify.cpp - Function takes BitTracker::RegisterRef which appears to be unsigned&
MachineVerifier.cpp - Ambiguous operator==() given MCRegister and const Register
PPCFastISel.cpp - No Register::operator-=()
PeepholeOptimizer.cpp - TargetInstrInfo::optimizeLoadInstr() takes an unsigned&
MachineTraceMetrics.cpp - MachineTraceMetrics lacks a suitable constructor
Manual fixups in:
ARMFastISel.cpp - ARMEmitLoad() now takes a Register& instead of unsigned&
HexagonSplitDouble.cpp - Ternary operator was ambiguous between unsigned/Register
HexagonConstExtenders.cpp - Has a local class named Register, used llvm::Register instead of Register.
PPCFastISel.cpp - PPCEmitLoad() now takes a Register& instead of unsigned&
Depends on D65919
Reviewers: arsenm, bogner, craig.topper, RKSimon
Reviewed By: arsenm
Subscribers: RKSimon, craig.topper, lenary, aemerson, wuzish, jholewinski, MatzeB, qcolombet, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, wdng, nhaehnle, sbc100, jgravelle-google, kristof.beyls, hiraditya, aheejin, kbarton, fedor.sergeev, javed.absar, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, tpr, PkmX, jocewei, jsji, Petar.Avramovic, asbirlea, Jim, s.egerton, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65962
llvm-svn: 369041
2019-08-15 21:22:08 +02:00
|
|
|
Register Reg = RSI->Instr->getOperand(0).getReg();
|
2013-06-05 23:38:04 +02:00
|
|
|
MachineBasicBlock::iterator Pos = RSI->Instr;
|
|
|
|
MachineBasicBlock &MBB = *Pos->getParent();
|
|
|
|
DebugLoc DL = Pos->getDebugLoc();
|
|
|
|
|
Apply llvm-prefer-register-over-unsigned from clang-tidy to LLVM
Summary:
This clang-tidy check is looking for unsigned integer variables whose initializer
starts with an implicit cast from llvm::Register and changes the type of the
variable to llvm::Register (dropping the llvm:: where possible).
Partial reverts in:
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
X86FixupLEAs.cpp - Some functions return unsigned and arguably should be MCRegister
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
HexagonBitSimplify.cpp - Function takes BitTracker::RegisterRef which appears to be unsigned&
MachineVerifier.cpp - Ambiguous operator==() given MCRegister and const Register
PPCFastISel.cpp - No Register::operator-=()
PeepholeOptimizer.cpp - TargetInstrInfo::optimizeLoadInstr() takes an unsigned&
MachineTraceMetrics.cpp - MachineTraceMetrics lacks a suitable constructor
Manual fixups in:
ARMFastISel.cpp - ARMEmitLoad() now takes a Register& instead of unsigned&
HexagonSplitDouble.cpp - Ternary operator was ambiguous between unsigned/Register
HexagonConstExtenders.cpp - Has a local class named Register, used llvm::Register instead of Register.
PPCFastISel.cpp - PPCEmitLoad() now takes a Register& instead of unsigned&
Depends on D65919
Reviewers: arsenm, bogner, craig.topper, RKSimon
Reviewed By: arsenm
Subscribers: RKSimon, craig.topper, lenary, aemerson, wuzish, jholewinski, MatzeB, qcolombet, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, wdng, nhaehnle, sbc100, jgravelle-google, kristof.beyls, hiraditya, aheejin, kbarton, fedor.sergeev, javed.absar, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, tpr, PkmX, jocewei, jsji, Petar.Avramovic, asbirlea, Jim, s.egerton, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65962
llvm-svn: 369041
2019-08-15 21:22:08 +02:00
|
|
|
Register SrcVec = BaseRSI->Instr->getOperand(0).getReg();
|
2013-06-05 23:38:04 +02:00
|
|
|
DenseMap<unsigned, unsigned> UpdatedRegToChan = BaseRSI->RegToChan;
|
|
|
|
std::vector<unsigned> UpdatedUndef = BaseRSI->UndefReg;
|
|
|
|
for (DenseMap<unsigned, unsigned>::iterator It = RSI->RegToChan.begin(),
|
|
|
|
E = RSI->RegToChan.end(); It != E; ++It) {
|
Apply llvm-prefer-register-over-unsigned from clang-tidy to LLVM
Summary:
This clang-tidy check is looking for unsigned integer variables whose initializer
starts with an implicit cast from llvm::Register and changes the type of the
variable to llvm::Register (dropping the llvm:: where possible).
Partial reverts in:
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
X86FixupLEAs.cpp - Some functions return unsigned and arguably should be MCRegister
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
HexagonBitSimplify.cpp - Function takes BitTracker::RegisterRef which appears to be unsigned&
MachineVerifier.cpp - Ambiguous operator==() given MCRegister and const Register
PPCFastISel.cpp - No Register::operator-=()
PeepholeOptimizer.cpp - TargetInstrInfo::optimizeLoadInstr() takes an unsigned&
MachineTraceMetrics.cpp - MachineTraceMetrics lacks a suitable constructor
Manual fixups in:
ARMFastISel.cpp - ARMEmitLoad() now takes a Register& instead of unsigned&
HexagonSplitDouble.cpp - Ternary operator was ambiguous between unsigned/Register
HexagonConstExtenders.cpp - Has a local class named Register, used llvm::Register instead of Register.
PPCFastISel.cpp - PPCEmitLoad() now takes a Register& instead of unsigned&
Depends on D65919
Reviewers: arsenm, bogner, craig.topper, RKSimon
Reviewed By: arsenm
Subscribers: RKSimon, craig.topper, lenary, aemerson, wuzish, jholewinski, MatzeB, qcolombet, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, wdng, nhaehnle, sbc100, jgravelle-google, kristof.beyls, hiraditya, aheejin, kbarton, fedor.sergeev, javed.absar, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, tpr, PkmX, jocewei, jsji, Petar.Avramovic, asbirlea, Jim, s.egerton, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65962
llvm-svn: 369041
2019-08-15 21:22:08 +02:00
|
|
|
Register DstReg = MRI->createVirtualRegister(&R600::R600_Reg128RegClass);
|
2013-06-05 23:38:04 +02:00
|
|
|
unsigned SubReg = (*It).first;
|
|
|
|
unsigned Swizzle = (*It).second;
|
2013-06-07 01:08:32 +02:00
|
|
|
unsigned Chan = getReassignedChan(RemapChan, Swizzle);
|
|
|
|
|
AMDGPU: Separate R600 and GCN TableGen files
Summary:
We now have two sets of generated TableGen files, one for R600 and one
for GCN, so each sub-target now has its own tables of instructions,
registers, ISel patterns, etc. This should help reduce compile time
since each sub-target now only has to consider information that
is specific to itself. This will also help prevent the R600
sub-target from slowing down new features for GCN, like disassembler
support, GlobalISel, etc.
Reviewers: arsenm, nhaehnle, jvesely
Reviewed By: arsenm
Subscribers: MatzeB, kzhuravl, wdng, mgorny, yaxunl, dstuttard, tpr, t-tye, javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D46365
llvm-svn: 335942
2018-06-29 01:47:12 +02:00
|
|
|
MachineInstr *Tmp = BuildMI(MBB, Pos, DL, TII->get(R600::INSERT_SUBREG),
|
2013-06-05 23:38:04 +02:00
|
|
|
DstReg)
|
|
|
|
.addReg(SrcVec)
|
|
|
|
.addReg(SubReg)
|
|
|
|
.addImm(Chan);
|
|
|
|
UpdatedRegToChan[SubReg] = Chan;
|
2016-12-12 23:23:53 +01:00
|
|
|
std::vector<unsigned>::iterator ChanPos = llvm::find(UpdatedUndef, Chan);
|
2013-06-07 20:18:12 +02:00
|
|
|
if (ChanPos != UpdatedUndef.end())
|
|
|
|
UpdatedUndef.erase(ChanPos);
|
2016-08-12 00:21:41 +02:00
|
|
|
assert(!is_contained(UpdatedUndef, Chan) &&
|
2013-06-07 20:18:12 +02:00
|
|
|
"UpdatedUndef shouldn't contain Chan more than once!");
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << " ->"; Tmp->dump(););
|
2013-06-06 04:15:06 +02:00
|
|
|
(void)Tmp;
|
2013-06-05 23:38:04 +02:00
|
|
|
SrcVec = DstReg;
|
|
|
|
}
|
2016-07-08 21:16:05 +02:00
|
|
|
MachineInstr *NewMI =
|
AMDGPU: Separate R600 and GCN TableGen files
Summary:
We now have two sets of generated TableGen files, one for R600 and one
for GCN, so each sub-target now has its own tables of instructions,
registers, ISel patterns, etc. This should help reduce compile time
since each sub-target now only has to consider information that
is specific to itself. This will also help prevent the R600
sub-target from slowing down new features for GCN, like disassembler
support, GlobalISel, etc.
Reviewers: arsenm, nhaehnle, jvesely
Reviewed By: arsenm
Subscribers: MatzeB, kzhuravl, wdng, mgorny, yaxunl, dstuttard, tpr, t-tye, javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D46365
llvm-svn: 335942
2018-06-29 01:47:12 +02:00
|
|
|
BuildMI(MBB, Pos, DL, TII->get(R600::COPY), Reg).addReg(SrcVec);
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << " ->"; NewMI->dump(););
|
2013-06-05 23:38:04 +02:00
|
|
|
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << " Updating Swizzle:\n");
|
2014-03-14 00:12:04 +01:00
|
|
|
for (MachineRegisterInfo::use_instr_iterator It = MRI->use_instr_begin(Reg),
|
|
|
|
E = MRI->use_instr_end(); It != E; ++It) {
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << " "; (*It).dump(); dbgs() << " ->");
|
2013-06-05 23:38:04 +02:00
|
|
|
SwizzleInput(*It, RemapChan);
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG((*It).dump());
|
2013-06-05 23:38:04 +02:00
|
|
|
}
|
|
|
|
RSI->Instr->eraseFromParent();
|
|
|
|
|
|
|
|
// Update RSI
|
2016-07-08 21:16:05 +02:00
|
|
|
RSI->Instr = NewMI;
|
2013-06-05 23:38:04 +02:00
|
|
|
RSI->RegToChan = UpdatedRegToChan;
|
|
|
|
RSI->UndefReg = UpdatedUndef;
|
|
|
|
|
2016-07-08 21:16:05 +02:00
|
|
|
return NewMI;
|
2013-06-05 23:38:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void R600VectorRegMerger::RemoveMI(MachineInstr *MI) {
|
|
|
|
for (InstructionSetMap::iterator It = PreviousRegSeqByReg.begin(),
|
|
|
|
E = PreviousRegSeqByReg.end(); It != E; ++It) {
|
|
|
|
std::vector<MachineInstr *> &MIs = (*It).second;
|
2016-12-12 23:23:53 +01:00
|
|
|
MIs.erase(llvm::find(MIs, MI), MIs.end());
|
2013-06-05 23:38:04 +02:00
|
|
|
}
|
|
|
|
for (InstructionSetMap::iterator It = PreviousRegSeqByUndefCount.begin(),
|
|
|
|
E = PreviousRegSeqByUndefCount.end(); It != E; ++It) {
|
|
|
|
std::vector<MachineInstr *> &MIs = (*It).second;
|
2016-12-12 23:23:53 +01:00
|
|
|
MIs.erase(llvm::find(MIs, MI), MIs.end());
|
2013-06-05 23:38:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void R600VectorRegMerger::SwizzleInput(MachineInstr &MI,
|
2016-12-12 23:23:53 +01:00
|
|
|
const std::vector<std::pair<unsigned, unsigned>> &RemapChan) const {
|
2013-06-05 23:38:04 +02:00
|
|
|
unsigned Offset;
|
|
|
|
if (TII->get(MI.getOpcode()).TSFlags & R600_InstFlag::TEX_INST)
|
|
|
|
Offset = 2;
|
|
|
|
else
|
|
|
|
Offset = 3;
|
|
|
|
for (unsigned i = 0; i < 4; i++) {
|
|
|
|
unsigned Swizzle = MI.getOperand(i + Offset).getImm() + 1;
|
|
|
|
for (unsigned j = 0, e = RemapChan.size(); j < e; j++) {
|
|
|
|
if (RemapChan[j].first == Swizzle) {
|
|
|
|
MI.getOperand(i + Offset).setImm(RemapChan[j].second - 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool R600VectorRegMerger::areAllUsesSwizzeable(unsigned Reg) const {
|
2014-03-14 00:12:04 +01:00
|
|
|
for (MachineRegisterInfo::use_instr_iterator It = MRI->use_instr_begin(Reg),
|
|
|
|
E = MRI->use_instr_end(); It != E; ++It) {
|
2013-06-05 23:38:04 +02:00
|
|
|
if (!canSwizzle(*It))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool R600VectorRegMerger::tryMergeUsingCommonSlot(RegSeqInfo &RSI,
|
|
|
|
RegSeqInfo &CompatibleRSI,
|
2016-12-12 23:23:53 +01:00
|
|
|
std::vector<std::pair<unsigned, unsigned>> &RemapChan) {
|
2013-06-05 23:38:04 +02:00
|
|
|
for (MachineInstr::mop_iterator MOp = RSI.Instr->operands_begin(),
|
|
|
|
MOE = RSI.Instr->operands_end(); MOp != MOE; ++MOp) {
|
|
|
|
if (!MOp->isReg())
|
|
|
|
continue;
|
|
|
|
if (PreviousRegSeqByReg[MOp->getReg()].empty())
|
|
|
|
continue;
|
2014-10-03 20:33:16 +02:00
|
|
|
for (MachineInstr *MI : PreviousRegSeqByReg[MOp->getReg()]) {
|
|
|
|
CompatibleRSI = PreviousRegSeq[MI];
|
2013-06-05 23:38:04 +02:00
|
|
|
if (RSI == CompatibleRSI)
|
|
|
|
continue;
|
|
|
|
if (tryMergeVector(&CompatibleRSI, &RSI, RemapChan))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool R600VectorRegMerger::tryMergeUsingFreeSlot(RegSeqInfo &RSI,
|
|
|
|
RegSeqInfo &CompatibleRSI,
|
2016-12-12 23:23:53 +01:00
|
|
|
std::vector<std::pair<unsigned, unsigned>> &RemapChan) {
|
2013-06-05 23:38:04 +02:00
|
|
|
unsigned NeededUndefs = 4 - RSI.UndefReg.size();
|
|
|
|
if (PreviousRegSeqByUndefCount[NeededUndefs].empty())
|
|
|
|
return false;
|
|
|
|
std::vector<MachineInstr *> &MIs =
|
|
|
|
PreviousRegSeqByUndefCount[NeededUndefs];
|
|
|
|
CompatibleRSI = PreviousRegSeq[MIs.back()];
|
|
|
|
tryMergeVector(&CompatibleRSI, &RSI, RemapChan);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void R600VectorRegMerger::trackRSI(const RegSeqInfo &RSI) {
|
|
|
|
for (DenseMap<unsigned, unsigned>::const_iterator
|
|
|
|
It = RSI.RegToChan.begin(), E = RSI.RegToChan.end(); It != E; ++It) {
|
|
|
|
PreviousRegSeqByReg[(*It).first].push_back(RSI.Instr);
|
|
|
|
}
|
|
|
|
PreviousRegSeqByUndefCount[RSI.UndefReg.size()].push_back(RSI.Instr);
|
|
|
|
PreviousRegSeq[RSI.Instr] = RSI;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool R600VectorRegMerger::runOnMachineFunction(MachineFunction &Fn) {
|
2017-12-15 23:22:58 +01:00
|
|
|
if (skipFunction(Fn.getFunction()))
|
2016-04-26 00:23:44 +02:00
|
|
|
return false;
|
|
|
|
|
2016-06-24 08:30:11 +02:00
|
|
|
const R600Subtarget &ST = Fn.getSubtarget<R600Subtarget>();
|
|
|
|
TII = ST.getInstrInfo();
|
|
|
|
MRI = &Fn.getRegInfo();
|
|
|
|
|
2013-06-05 23:38:04 +02:00
|
|
|
for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
|
|
|
|
MBB != MBBe; ++MBB) {
|
2015-10-13 22:07:10 +02:00
|
|
|
MachineBasicBlock *MB = &*MBB;
|
2013-06-05 23:38:04 +02:00
|
|
|
PreviousRegSeq.clear();
|
|
|
|
PreviousRegSeqByReg.clear();
|
|
|
|
PreviousRegSeqByUndefCount.clear();
|
|
|
|
|
|
|
|
for (MachineBasicBlock::iterator MII = MB->begin(), MIIE = MB->end();
|
|
|
|
MII != MIIE; ++MII) {
|
2016-07-08 21:16:05 +02:00
|
|
|
MachineInstr &MI = *MII;
|
AMDGPU: Separate R600 and GCN TableGen files
Summary:
We now have two sets of generated TableGen files, one for R600 and one
for GCN, so each sub-target now has its own tables of instructions,
registers, ISel patterns, etc. This should help reduce compile time
since each sub-target now only has to consider information that
is specific to itself. This will also help prevent the R600
sub-target from slowing down new features for GCN, like disassembler
support, GlobalISel, etc.
Reviewers: arsenm, nhaehnle, jvesely
Reviewed By: arsenm
Subscribers: MatzeB, kzhuravl, wdng, mgorny, yaxunl, dstuttard, tpr, t-tye, javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D46365
llvm-svn: 335942
2018-06-29 01:47:12 +02:00
|
|
|
if (MI.getOpcode() != R600::REG_SEQUENCE) {
|
2016-07-08 21:16:05 +02:00
|
|
|
if (TII->get(MI.getOpcode()).TSFlags & R600_InstFlag::TEX_INST) {
|
Apply llvm-prefer-register-over-unsigned from clang-tidy to LLVM
Summary:
This clang-tidy check is looking for unsigned integer variables whose initializer
starts with an implicit cast from llvm::Register and changes the type of the
variable to llvm::Register (dropping the llvm:: where possible).
Partial reverts in:
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
X86FixupLEAs.cpp - Some functions return unsigned and arguably should be MCRegister
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
HexagonBitSimplify.cpp - Function takes BitTracker::RegisterRef which appears to be unsigned&
MachineVerifier.cpp - Ambiguous operator==() given MCRegister and const Register
PPCFastISel.cpp - No Register::operator-=()
PeepholeOptimizer.cpp - TargetInstrInfo::optimizeLoadInstr() takes an unsigned&
MachineTraceMetrics.cpp - MachineTraceMetrics lacks a suitable constructor
Manual fixups in:
ARMFastISel.cpp - ARMEmitLoad() now takes a Register& instead of unsigned&
HexagonSplitDouble.cpp - Ternary operator was ambiguous between unsigned/Register
HexagonConstExtenders.cpp - Has a local class named Register, used llvm::Register instead of Register.
PPCFastISel.cpp - PPCEmitLoad() now takes a Register& instead of unsigned&
Depends on D65919
Reviewers: arsenm, bogner, craig.topper, RKSimon
Reviewed By: arsenm
Subscribers: RKSimon, craig.topper, lenary, aemerson, wuzish, jholewinski, MatzeB, qcolombet, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, wdng, nhaehnle, sbc100, jgravelle-google, kristof.beyls, hiraditya, aheejin, kbarton, fedor.sergeev, javed.absar, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, tpr, PkmX, jocewei, jsji, Petar.Avramovic, asbirlea, Jim, s.egerton, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65962
llvm-svn: 369041
2019-08-15 21:22:08 +02:00
|
|
|
Register Reg = MI.getOperand(1).getReg();
|
2014-03-14 00:12:04 +01:00
|
|
|
for (MachineRegisterInfo::def_instr_iterator
|
|
|
|
It = MRI->def_instr_begin(Reg), E = MRI->def_instr_end();
|
|
|
|
It != E; ++It) {
|
2013-07-31 21:32:12 +02:00
|
|
|
RemoveMI(&(*It));
|
|
|
|
}
|
|
|
|
}
|
2013-06-05 23:38:04 +02:00
|
|
|
continue;
|
2013-07-31 21:32:12 +02:00
|
|
|
}
|
|
|
|
|
2016-07-08 21:16:05 +02:00
|
|
|
RegSeqInfo RSI(*MRI, &MI);
|
2013-06-05 23:38:04 +02:00
|
|
|
|
|
|
|
// All uses of MI are swizzeable ?
|
Apply llvm-prefer-register-over-unsigned from clang-tidy to LLVM
Summary:
This clang-tidy check is looking for unsigned integer variables whose initializer
starts with an implicit cast from llvm::Register and changes the type of the
variable to llvm::Register (dropping the llvm:: where possible).
Partial reverts in:
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
X86FixupLEAs.cpp - Some functions return unsigned and arguably should be MCRegister
X86FrameLowering.cpp - Some functions return unsigned and arguably should be MCRegister
HexagonBitSimplify.cpp - Function takes BitTracker::RegisterRef which appears to be unsigned&
MachineVerifier.cpp - Ambiguous operator==() given MCRegister and const Register
PPCFastISel.cpp - No Register::operator-=()
PeepholeOptimizer.cpp - TargetInstrInfo::optimizeLoadInstr() takes an unsigned&
MachineTraceMetrics.cpp - MachineTraceMetrics lacks a suitable constructor
Manual fixups in:
ARMFastISel.cpp - ARMEmitLoad() now takes a Register& instead of unsigned&
HexagonSplitDouble.cpp - Ternary operator was ambiguous between unsigned/Register
HexagonConstExtenders.cpp - Has a local class named Register, used llvm::Register instead of Register.
PPCFastISel.cpp - PPCEmitLoad() now takes a Register& instead of unsigned&
Depends on D65919
Reviewers: arsenm, bogner, craig.topper, RKSimon
Reviewed By: arsenm
Subscribers: RKSimon, craig.topper, lenary, aemerson, wuzish, jholewinski, MatzeB, qcolombet, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, wdng, nhaehnle, sbc100, jgravelle-google, kristof.beyls, hiraditya, aheejin, kbarton, fedor.sergeev, javed.absar, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, tpr, PkmX, jocewei, jsji, Petar.Avramovic, asbirlea, Jim, s.egerton, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65962
llvm-svn: 369041
2019-08-15 21:22:08 +02:00
|
|
|
Register Reg = MI.getOperand(0).getReg();
|
2013-06-05 23:38:04 +02:00
|
|
|
if (!areAllUsesSwizzeable(Reg))
|
|
|
|
continue;
|
|
|
|
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG({
|
2016-07-08 21:16:05 +02:00
|
|
|
dbgs() << "Trying to optimize ";
|
|
|
|
MI.dump();
|
|
|
|
});
|
2013-06-05 23:38:04 +02:00
|
|
|
|
|
|
|
RegSeqInfo CandidateRSI;
|
2016-12-12 23:23:53 +01:00
|
|
|
std::vector<std::pair<unsigned, unsigned>> RemapChan;
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "Using common slots...\n";);
|
2013-06-05 23:38:04 +02:00
|
|
|
if (tryMergeUsingCommonSlot(RSI, CandidateRSI, RemapChan)) {
|
|
|
|
// Remove CandidateRSI mapping
|
|
|
|
RemoveMI(CandidateRSI.Instr);
|
|
|
|
MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
|
|
|
|
trackRSI(RSI);
|
|
|
|
continue;
|
|
|
|
}
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "Using free slots...\n";);
|
2013-06-05 23:38:04 +02:00
|
|
|
RemapChan.clear();
|
|
|
|
if (tryMergeUsingFreeSlot(RSI, CandidateRSI, RemapChan)) {
|
|
|
|
RemoveMI(CandidateRSI.Instr);
|
|
|
|
MII = RebuildVector(&RSI, &CandidateRSI, RemapChan);
|
|
|
|
trackRSI(RSI);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
//Failed to merge
|
|
|
|
trackRSI(RSI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-05-18 19:21:13 +02:00
|
|
|
llvm::FunctionPass *llvm::createR600VectorRegMerger() {
|
|
|
|
return new R600VectorRegMerger();
|
2013-06-05 23:38:04 +02:00
|
|
|
}
|