2014-07-21 18:55:33 +02:00
|
|
|
//===-- SIShrinkInstructions.cpp - Shrink Instructions --------------------===//
|
|
|
|
//
|
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
|
2014-07-21 18:55:33 +02:00
|
|
|
//
|
|
|
|
/// The pass tries to use the 32-bit encoding for instructions when possible.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "AMDGPU.h"
|
2014-08-04 23:25:23 +02:00
|
|
|
#include "AMDGPUSubtarget.h"
|
2014-07-21 18:55:33 +02:00
|
|
|
#include "SIInstrInfo.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"
|
2014-07-21 18:55:33 +02:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2014-08-01 02:32:33 +02:00
|
|
|
#include "llvm/IR/Constants.h"
|
2014-07-21 18:55:33 +02:00
|
|
|
#include "llvm/IR/Function.h"
|
2015-03-23 19:07:13 +01:00
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2014-07-21 18:55:33 +02:00
|
|
|
#include "llvm/Support/Debug.h"
|
2015-03-23 19:07:13 +01:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2014-07-21 18:55:33 +02:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "si-shrink-instructions"
|
|
|
|
|
|
|
|
STATISTIC(NumInstructionsShrunk,
|
|
|
|
"Number of 64-bit instruction reduced to 32-bit.");
|
2014-08-01 02:32:33 +02:00
|
|
|
STATISTIC(NumLiteralConstantsFolded,
|
|
|
|
"Number of literal constants folded into 32-bit instructions.");
|
2014-07-21 18:55:33 +02:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class SIShrinkInstructions : public MachineFunctionPass {
|
|
|
|
public:
|
|
|
|
static char ID;
|
|
|
|
|
2019-05-01 18:32:58 +02:00
|
|
|
void shrinkMIMG(MachineInstr &MI);
|
|
|
|
|
2014-07-21 18:55:33 +02:00
|
|
|
public:
|
|
|
|
SIShrinkInstructions() : MachineFunctionPass(ID) {
|
|
|
|
}
|
|
|
|
|
2014-08-30 18:48:34 +02:00
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
2014-07-21 18:55:33 +02:00
|
|
|
|
2016-10-01 04:56:57 +02:00
|
|
|
StringRef getPassName() const override { return "SI Shrink Instructions"; }
|
2014-07-21 18:55:33 +02:00
|
|
|
|
2014-08-30 18:48:34 +02:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
2014-07-21 18:55:33 +02:00
|
|
|
AU.setPreservesCFG();
|
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // End anonymous namespace.
|
|
|
|
|
2016-06-10 01:18:47 +02:00
|
|
|
INITIALIZE_PASS(SIShrinkInstructions, DEBUG_TYPE,
|
|
|
|
"SI Shrink Instructions", false, false)
|
2014-07-21 18:55:33 +02:00
|
|
|
|
|
|
|
char SIShrinkInstructions::ID = 0;
|
|
|
|
|
|
|
|
FunctionPass *llvm::createSIShrinkInstructionsPass() {
|
|
|
|
return new SIShrinkInstructions();
|
|
|
|
}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// This function checks \p MI for operands defined by a move immediate
|
2014-08-01 02:32:33 +02:00
|
|
|
/// instruction and then folds the literal constant into the instruction if it
|
2017-07-10 21:53:57 +02:00
|
|
|
/// can. This function assumes that \p MI is a VOP1, VOP2, or VOPC instructions.
|
|
|
|
static bool foldImmediates(MachineInstr &MI, const SIInstrInfo *TII,
|
2014-08-01 02:32:33 +02:00
|
|
|
MachineRegisterInfo &MRI, bool TryToCommute = true) {
|
2015-10-20 06:35:43 +02:00
|
|
|
assert(TII->isVOP1(MI) || TII->isVOP2(MI) || TII->isVOPC(MI));
|
2014-08-01 02:32:33 +02:00
|
|
|
|
2015-02-13 20:05:03 +01:00
|
|
|
int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
|
2014-08-01 02:32:33 +02:00
|
|
|
|
|
|
|
// Try to fold Src0
|
2016-12-10 01:39:12 +01:00
|
|
|
MachineOperand &Src0 = MI.getOperand(Src0Idx);
|
2017-07-10 21:53:57 +02:00
|
|
|
if (Src0.isReg()) {
|
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 = Src0.getReg();
|
2020-08-20 18:46:16 +02:00
|
|
|
if (Reg.isVirtual() && MRI.hasOneUse(Reg)) {
|
2017-07-10 21:53:57 +02:00
|
|
|
MachineInstr *Def = MRI.getUniqueVRegDef(Reg);
|
|
|
|
if (Def && Def->isMoveImmediate()) {
|
|
|
|
MachineOperand &MovSrc = Def->getOperand(1);
|
|
|
|
bool ConstantFolded = false;
|
|
|
|
|
|
|
|
if (MovSrc.isImm() && (isInt<32>(MovSrc.getImm()) ||
|
|
|
|
isUInt<32>(MovSrc.getImm()))) {
|
|
|
|
Src0.ChangeToImmediate(MovSrc.getImm());
|
|
|
|
ConstantFolded = true;
|
2017-07-10 22:04:35 +02:00
|
|
|
} else if (MovSrc.isFI()) {
|
|
|
|
Src0.ChangeToFrameIndex(MovSrc.getIndex());
|
|
|
|
ConstantFolded = true;
|
AMDGPU: Write LDS objects out as global symbols in code generation
Summary:
The symbols use the processor-specific SHN_AMDGPU_LDS section index
introduced with a previous change. The linker is then expected to resolve
relocations, which are also emitted.
Initially disabled for HSA and PAL environments until they have caught up
in terms of linker and runtime loader.
Some notes:
- The llvm.amdgcn.groupstaticsize intrinsics can no longer be lowered
to a constant at compile times, which means some tests can no longer
be applied.
The current "solution" is a terrible hack, but the intrinsic isn't
used by Mesa, so we can keep it for now.
- We no longer know the full LDS size per kernel at compile time, which
means that we can no longer generate a relevant error message at
compile time. It would be possible to add a check for the size of
individual variables, but ultimately the linker will have to perform
the final check.
Change-Id: If66dbf33fccfbf3609aefefa2558ac0850d42275
Reviewers: arsenm, rampitec, t-tye, b-sumner, jsjodin
Subscribers: qcolombet, kzhuravl, jvesely, wdng, yaxunl, dstuttard, tpr, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D61494
llvm-svn: 364297
2019-06-25 13:52:30 +02:00
|
|
|
} else if (MovSrc.isGlobal()) {
|
|
|
|
Src0.ChangeToGA(MovSrc.getGlobal(), MovSrc.getOffset(),
|
|
|
|
MovSrc.getTargetFlags());
|
|
|
|
ConstantFolded = true;
|
2017-07-10 21:53:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ConstantFolded) {
|
|
|
|
assert(MRI.use_empty(Reg));
|
2014-08-01 02:32:33 +02:00
|
|
|
Def->eraseFromParent();
|
2017-07-10 21:53:57 +02:00
|
|
|
++NumLiteralConstantsFolded;
|
|
|
|
return true;
|
|
|
|
}
|
2014-08-01 02:32:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have failed to fold src0, so commute the instruction and try again.
|
2017-07-10 21:53:57 +02:00
|
|
|
if (TryToCommute && MI.isCommutable()) {
|
|
|
|
if (TII->commuteInstruction(MI)) {
|
|
|
|
if (foldImmediates(MI, TII, MRI, false))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Commute back.
|
|
|
|
TII->commuteInstruction(MI);
|
|
|
|
}
|
|
|
|
}
|
2014-08-01 02:32:33 +02:00
|
|
|
|
2017-07-10 21:53:57 +02:00
|
|
|
return false;
|
2014-08-01 02:32:33 +02:00
|
|
|
}
|
|
|
|
|
2016-04-16 03:46:49 +02:00
|
|
|
static bool isKImmOperand(const SIInstrInfo *TII, const MachineOperand &Src) {
|
2016-12-10 01:39:12 +01:00
|
|
|
return isInt<16>(Src.getImm()) &&
|
|
|
|
!TII->isInlineConstant(*Src.getParent(),
|
|
|
|
Src.getParent()->getOperandNo(&Src));
|
2016-04-16 03:46:49 +02:00
|
|
|
}
|
|
|
|
|
2016-09-16 23:41:16 +02:00
|
|
|
static bool isKUImmOperand(const SIInstrInfo *TII, const MachineOperand &Src) {
|
2016-12-10 01:39:12 +01:00
|
|
|
return isUInt<16>(Src.getImm()) &&
|
|
|
|
!TII->isInlineConstant(*Src.getParent(),
|
|
|
|
Src.getParent()->getOperandNo(&Src));
|
2016-09-16 23:41:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool isKImmOrKUImmOperand(const SIInstrInfo *TII,
|
|
|
|
const MachineOperand &Src,
|
|
|
|
bool &IsUnsigned) {
|
|
|
|
if (isInt<16>(Src.getImm())) {
|
|
|
|
IsUnsigned = false;
|
2016-12-10 01:39:12 +01:00
|
|
|
return !TII->isInlineConstant(Src);
|
2016-09-16 23:41:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isUInt<16>(Src.getImm())) {
|
|
|
|
IsUnsigned = true;
|
2016-12-10 01:39:12 +01:00
|
|
|
return !TII->isInlineConstant(Src);
|
2016-09-16 23:41:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-11-02 00:14:20 +01:00
|
|
|
/// \returns true if the constant in \p Src should be replaced with a bitreverse
|
|
|
|
/// of an inline immediate.
|
|
|
|
static bool isReverseInlineImm(const SIInstrInfo *TII,
|
|
|
|
const MachineOperand &Src,
|
|
|
|
int32_t &ReverseImm) {
|
2016-12-10 01:39:12 +01:00
|
|
|
if (!isInt<32>(Src.getImm()) || TII->isInlineConstant(Src))
|
2016-11-02 00:14:20 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ReverseImm = reverseBits<int32_t>(static_cast<int32_t>(Src.getImm()));
|
|
|
|
return ReverseImm >= -16 && ReverseImm <= 64;
|
|
|
|
}
|
|
|
|
|
2016-09-03 19:25:39 +02:00
|
|
|
/// Copy implicit register operands from specified instruction to this
|
|
|
|
/// instruction that are not part of the instruction definition.
|
|
|
|
static void copyExtraImplicitOps(MachineInstr &NewMI, MachineFunction &MF,
|
|
|
|
const MachineInstr &MI) {
|
|
|
|
for (unsigned i = MI.getDesc().getNumOperands() +
|
|
|
|
MI.getDesc().getNumImplicitUses() +
|
|
|
|
MI.getDesc().getNumImplicitDefs(), e = MI.getNumOperands();
|
|
|
|
i != e; ++i) {
|
|
|
|
const MachineOperand &MO = MI.getOperand(i);
|
|
|
|
if ((MO.isReg() && MO.isImplicit()) || MO.isRegMask())
|
|
|
|
NewMI.addOperand(MF, MO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-16 23:41:16 +02:00
|
|
|
static void shrinkScalarCompare(const SIInstrInfo *TII, MachineInstr &MI) {
|
|
|
|
// cmpk instructions do scc = dst <cc op> imm16, so commute the instruction to
|
|
|
|
// get constants on the RHS.
|
|
|
|
if (!MI.getOperand(0).isReg())
|
|
|
|
TII->commuteInstruction(MI, false, 0, 1);
|
|
|
|
|
2020-07-14 10:03:12 +02:00
|
|
|
// cmpk requires src0 to be a register
|
|
|
|
const MachineOperand &Src0 = MI.getOperand(0);
|
|
|
|
if (!Src0.isReg())
|
|
|
|
return;
|
|
|
|
|
2016-09-16 23:41:16 +02:00
|
|
|
const MachineOperand &Src1 = MI.getOperand(1);
|
|
|
|
if (!Src1.isImm())
|
|
|
|
return;
|
|
|
|
|
|
|
|
int SOPKOpc = AMDGPU::getSOPKOp(MI.getOpcode());
|
|
|
|
if (SOPKOpc == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// eq/ne is special because the imm16 can be treated as signed or unsigned,
|
2016-09-30 03:50:20 +02:00
|
|
|
// and initially selectd to the unsigned versions.
|
|
|
|
if (SOPKOpc == AMDGPU::S_CMPK_EQ_U32 || SOPKOpc == AMDGPU::S_CMPK_LG_U32) {
|
2016-09-16 23:41:16 +02:00
|
|
|
bool HasUImm;
|
|
|
|
if (isKImmOrKUImmOperand(TII, Src1, HasUImm)) {
|
2016-09-30 03:50:20 +02:00
|
|
|
if (!HasUImm) {
|
|
|
|
SOPKOpc = (SOPKOpc == AMDGPU::S_CMPK_EQ_U32) ?
|
|
|
|
AMDGPU::S_CMPK_EQ_I32 : AMDGPU::S_CMPK_LG_I32;
|
2016-09-16 23:41:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
MI.setDesc(TII->get(SOPKOpc));
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const MCInstrDesc &NewDesc = TII->get(SOPKOpc);
|
|
|
|
|
|
|
|
if ((TII->sopkIsZext(SOPKOpc) && isKUImmOperand(TII, Src1)) ||
|
|
|
|
(!TII->sopkIsZext(SOPKOpc) && isKImmOperand(TII, Src1))) {
|
|
|
|
MI.setDesc(NewDesc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-01 18:32:58 +02:00
|
|
|
// Shrink NSA encoded instructions with contiguous VGPRs to non-NSA encoding.
|
|
|
|
void SIShrinkInstructions::shrinkMIMG(MachineInstr &MI) {
|
|
|
|
const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI.getOpcode());
|
2020-06-15 23:10:39 +02:00
|
|
|
if (!Info || Info->MIMGEncoding != AMDGPU::MIMGEncGfx10NSA)
|
2019-05-01 18:32:58 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
MachineFunction *MF = MI.getParent()->getParent();
|
|
|
|
const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
|
|
|
|
const SIInstrInfo *TII = ST.getInstrInfo();
|
|
|
|
const SIRegisterInfo &TRI = TII->getRegisterInfo();
|
|
|
|
int VAddr0Idx =
|
|
|
|
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0);
|
|
|
|
unsigned NewAddrDwords = Info->VAddrDwords;
|
|
|
|
const TargetRegisterClass *RC;
|
|
|
|
|
|
|
|
if (Info->VAddrDwords == 2) {
|
|
|
|
RC = &AMDGPU::VReg_64RegClass;
|
|
|
|
} else if (Info->VAddrDwords == 3) {
|
|
|
|
RC = &AMDGPU::VReg_96RegClass;
|
|
|
|
} else if (Info->VAddrDwords == 4) {
|
|
|
|
RC = &AMDGPU::VReg_128RegClass;
|
|
|
|
} else if (Info->VAddrDwords <= 8) {
|
|
|
|
RC = &AMDGPU::VReg_256RegClass;
|
|
|
|
NewAddrDwords = 8;
|
|
|
|
} else {
|
|
|
|
RC = &AMDGPU::VReg_512RegClass;
|
|
|
|
NewAddrDwords = 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned VgprBase = 0;
|
|
|
|
bool IsUndef = true;
|
|
|
|
bool IsKill = NewAddrDwords == Info->VAddrDwords;
|
|
|
|
for (unsigned i = 0; i < Info->VAddrDwords; ++i) {
|
|
|
|
const MachineOperand &Op = MI.getOperand(VAddr0Idx + i);
|
|
|
|
unsigned Vgpr = TRI.getHWRegIndex(Op.getReg());
|
|
|
|
|
|
|
|
if (i == 0) {
|
|
|
|
VgprBase = Vgpr;
|
|
|
|
} else if (VgprBase + i != Vgpr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!Op.isUndef())
|
|
|
|
IsUndef = false;
|
|
|
|
if (!Op.isKill())
|
|
|
|
IsKill = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VgprBase + NewAddrDwords > 256)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Further check for implicit tied operands - this may be present if TFE is
|
|
|
|
// enabled
|
|
|
|
int TFEIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::tfe);
|
|
|
|
int LWEIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::lwe);
|
2020-09-16 20:09:25 +02:00
|
|
|
unsigned TFEVal = (TFEIdx == -1) ? 0 : MI.getOperand(TFEIdx).getImm();
|
|
|
|
unsigned LWEVal = (LWEIdx == -1) ? 0 : MI.getOperand(LWEIdx).getImm();
|
2019-05-01 18:32:58 +02:00
|
|
|
int ToUntie = -1;
|
|
|
|
if (TFEVal || LWEVal) {
|
|
|
|
// TFE/LWE is enabled so we need to deal with an implicit tied operand
|
|
|
|
for (unsigned i = LWEIdx + 1, e = MI.getNumOperands(); i != e; ++i) {
|
|
|
|
if (MI.getOperand(i).isReg() && MI.getOperand(i).isTied() &&
|
|
|
|
MI.getOperand(i).isImplicit()) {
|
|
|
|
// This is the tied operand
|
|
|
|
assert(
|
|
|
|
ToUntie == -1 &&
|
|
|
|
"found more than one tied implicit operand when expecting only 1");
|
|
|
|
ToUntie = i;
|
|
|
|
MI.untieRegOperand(ToUntie);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned NewOpcode =
|
|
|
|
AMDGPU::getMIMGOpcode(Info->BaseOpcode, AMDGPU::MIMGEncGfx10Default,
|
|
|
|
Info->VDataDwords, NewAddrDwords);
|
|
|
|
MI.setDesc(TII->get(NewOpcode));
|
|
|
|
MI.getOperand(VAddr0Idx).setReg(RC->getRegister(VgprBase));
|
|
|
|
MI.getOperand(VAddr0Idx).setIsUndef(IsUndef);
|
|
|
|
MI.getOperand(VAddr0Idx).setIsKill(IsKill);
|
|
|
|
|
|
|
|
for (unsigned i = 1; i < Info->VAddrDwords; ++i)
|
|
|
|
MI.RemoveOperand(VAddr0Idx + 1);
|
|
|
|
|
|
|
|
if (ToUntie >= 0) {
|
|
|
|
MI.tieOperands(
|
|
|
|
AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata),
|
|
|
|
ToUntie - (Info->VAddrDwords - 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[AMDGPU] Shrink scalar AND, OR, XOR instructions
This change attempts to shrink scalar AND, OR and XOR instructions which take an immediate that isn't inlineable.
It performs:
AND s0, s0, ~(1 << n) -> BITSET0 s0, n
OR s0, s0, (1 << n) -> BITSET1 s0, n
AND s0, s1, x -> ANDN2 s0, s1, ~x
OR s0, s1, x -> ORN2 s0, s1, ~x
XOR s0, s1, x -> XNOR s0, s1, ~x
In particular, this catches setting and clearing the sign bit for fabs (and x, 0x7ffffffff -> bitset0 x, 31 and or x, 0x80000000 -> bitset1 x, 31).
llvm-svn: 348601
2018-12-07 16:33:21 +01:00
|
|
|
/// Attempt to shink AND/OR/XOR operations requiring non-inlineable literals.
|
|
|
|
/// For AND or OR, try using S_BITSET{0,1} to clear or set bits.
|
|
|
|
/// If the inverse of the immediate is legal, use ANDN2, ORN2 or
|
|
|
|
/// XNOR (as a ^ b == ~(a ^ ~b)).
|
|
|
|
/// \returns true if the caller should continue the machine function iterator
|
|
|
|
static bool shrinkScalarLogicOp(const GCNSubtarget &ST,
|
|
|
|
MachineRegisterInfo &MRI,
|
|
|
|
const SIInstrInfo *TII,
|
|
|
|
MachineInstr &MI) {
|
|
|
|
unsigned Opc = MI.getOpcode();
|
|
|
|
const MachineOperand *Dest = &MI.getOperand(0);
|
|
|
|
MachineOperand *Src0 = &MI.getOperand(1);
|
|
|
|
MachineOperand *Src1 = &MI.getOperand(2);
|
|
|
|
MachineOperand *SrcReg = Src0;
|
|
|
|
MachineOperand *SrcImm = Src1;
|
|
|
|
|
2020-04-07 19:22:40 +02:00
|
|
|
if (!SrcImm->isImm() ||
|
|
|
|
AMDGPU::isInlinableLiteral32(SrcImm->getImm(), ST.hasInv2PiInlineImm()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
uint32_t Imm = static_cast<uint32_t>(SrcImm->getImm());
|
|
|
|
uint32_t NewImm = 0;
|
[AMDGPU] Shrink scalar AND, OR, XOR instructions
This change attempts to shrink scalar AND, OR and XOR instructions which take an immediate that isn't inlineable.
It performs:
AND s0, s0, ~(1 << n) -> BITSET0 s0, n
OR s0, s0, (1 << n) -> BITSET1 s0, n
AND s0, s1, x -> ANDN2 s0, s1, ~x
OR s0, s1, x -> ORN2 s0, s1, ~x
XOR s0, s1, x -> XNOR s0, s1, ~x
In particular, this catches setting and clearing the sign bit for fabs (and x, 0x7ffffffff -> bitset0 x, 31 and or x, 0x80000000 -> bitset1 x, 31).
llvm-svn: 348601
2018-12-07 16:33:21 +01:00
|
|
|
|
2020-04-07 19:22:40 +02:00
|
|
|
if (Opc == AMDGPU::S_AND_B32) {
|
|
|
|
if (isPowerOf2_32(~Imm)) {
|
|
|
|
NewImm = countTrailingOnes(Imm);
|
|
|
|
Opc = AMDGPU::S_BITSET0_B32;
|
|
|
|
} else if (AMDGPU::isInlinableLiteral32(~Imm, ST.hasInv2PiInlineImm())) {
|
|
|
|
NewImm = ~Imm;
|
|
|
|
Opc = AMDGPU::S_ANDN2_B32;
|
|
|
|
}
|
|
|
|
} else if (Opc == AMDGPU::S_OR_B32) {
|
|
|
|
if (isPowerOf2_32(Imm)) {
|
|
|
|
NewImm = countTrailingZeros(Imm);
|
|
|
|
Opc = AMDGPU::S_BITSET1_B32;
|
|
|
|
} else if (AMDGPU::isInlinableLiteral32(~Imm, ST.hasInv2PiInlineImm())) {
|
|
|
|
NewImm = ~Imm;
|
|
|
|
Opc = AMDGPU::S_ORN2_B32;
|
|
|
|
}
|
|
|
|
} else if (Opc == AMDGPU::S_XOR_B32) {
|
|
|
|
if (AMDGPU::isInlinableLiteral32(~Imm, ST.hasInv2PiInlineImm())) {
|
|
|
|
NewImm = ~Imm;
|
|
|
|
Opc = AMDGPU::S_XNOR_B32;
|
[AMDGPU] Shrink scalar AND, OR, XOR instructions
This change attempts to shrink scalar AND, OR and XOR instructions which take an immediate that isn't inlineable.
It performs:
AND s0, s0, ~(1 << n) -> BITSET0 s0, n
OR s0, s0, (1 << n) -> BITSET1 s0, n
AND s0, s1, x -> ANDN2 s0, s1, ~x
OR s0, s1, x -> ORN2 s0, s1, ~x
XOR s0, s1, x -> XNOR s0, s1, ~x
In particular, this catches setting and clearing the sign bit for fabs (and x, 0x7ffffffff -> bitset0 x, 31 and or x, 0x80000000 -> bitset1 x, 31).
llvm-svn: 348601
2018-12-07 16:33:21 +01:00
|
|
|
}
|
2020-04-07 19:22:40 +02:00
|
|
|
} else {
|
|
|
|
llvm_unreachable("unexpected opcode");
|
|
|
|
}
|
[AMDGPU] Shrink scalar AND, OR, XOR instructions
This change attempts to shrink scalar AND, OR and XOR instructions which take an immediate that isn't inlineable.
It performs:
AND s0, s0, ~(1 << n) -> BITSET0 s0, n
OR s0, s0, (1 << n) -> BITSET1 s0, n
AND s0, s1, x -> ANDN2 s0, s1, ~x
OR s0, s1, x -> ORN2 s0, s1, ~x
XOR s0, s1, x -> XNOR s0, s1, ~x
In particular, this catches setting and clearing the sign bit for fabs (and x, 0x7ffffffff -> bitset0 x, 31 and or x, 0x80000000 -> bitset1 x, 31).
llvm-svn: 348601
2018-12-07 16:33:21 +01:00
|
|
|
|
2020-04-07 19:22:40 +02:00
|
|
|
if ((Opc == AMDGPU::S_ANDN2_B32 || Opc == AMDGPU::S_ORN2_B32) &&
|
|
|
|
SrcImm == Src0) {
|
|
|
|
if (!TII->commuteInstruction(MI, false, 1, 2))
|
|
|
|
NewImm = 0;
|
|
|
|
}
|
[AMDGPU] Shrink scalar AND, OR, XOR instructions
This change attempts to shrink scalar AND, OR and XOR instructions which take an immediate that isn't inlineable.
It performs:
AND s0, s0, ~(1 << n) -> BITSET0 s0, n
OR s0, s0, (1 << n) -> BITSET1 s0, n
AND s0, s1, x -> ANDN2 s0, s1, ~x
OR s0, s1, x -> ORN2 s0, s1, ~x
XOR s0, s1, x -> XNOR s0, s1, ~x
In particular, this catches setting and clearing the sign bit for fabs (and x, 0x7ffffffff -> bitset0 x, 31 and or x, 0x80000000 -> bitset1 x, 31).
llvm-svn: 348601
2018-12-07 16:33:21 +01:00
|
|
|
|
2020-04-07 19:22:40 +02:00
|
|
|
if (NewImm != 0) {
|
2020-08-20 18:46:16 +02:00
|
|
|
if (Dest->getReg().isVirtual() && SrcReg->isReg()) {
|
2020-04-07 19:22:40 +02:00
|
|
|
MRI.setRegAllocationHint(Dest->getReg(), 0, SrcReg->getReg());
|
|
|
|
MRI.setRegAllocationHint(SrcReg->getReg(), 0, Dest->getReg());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SrcReg->isReg() && SrcReg->getReg() == Dest->getReg()) {
|
2020-08-05 15:42:14 +02:00
|
|
|
const bool IsUndef = SrcReg->isUndef();
|
|
|
|
const bool IsKill = SrcReg->isKill();
|
2020-04-07 19:22:40 +02:00
|
|
|
MI.setDesc(TII->get(Opc));
|
|
|
|
if (Opc == AMDGPU::S_BITSET0_B32 ||
|
|
|
|
Opc == AMDGPU::S_BITSET1_B32) {
|
|
|
|
Src0->ChangeToImmediate(NewImm);
|
|
|
|
// Remove the immediate and add the tied input.
|
2020-08-05 15:42:14 +02:00
|
|
|
MI.getOperand(2).ChangeToRegister(Dest->getReg(), /*IsDef*/ false,
|
|
|
|
/*isImp*/ false, IsKill,
|
|
|
|
/*isDead*/ false, IsUndef);
|
2020-04-07 19:22:40 +02:00
|
|
|
MI.tieOperands(0, 2);
|
|
|
|
} else {
|
|
|
|
SrcImm->setImm(NewImm);
|
[AMDGPU] Shrink scalar AND, OR, XOR instructions
This change attempts to shrink scalar AND, OR and XOR instructions which take an immediate that isn't inlineable.
It performs:
AND s0, s0, ~(1 << n) -> BITSET0 s0, n
OR s0, s0, (1 << n) -> BITSET1 s0, n
AND s0, s1, x -> ANDN2 s0, s1, ~x
OR s0, s1, x -> ORN2 s0, s1, ~x
XOR s0, s1, x -> XNOR s0, s1, ~x
In particular, this catches setting and clearing the sign bit for fabs (and x, 0x7ffffffff -> bitset0 x, 31 and or x, 0x80000000 -> bitset1 x, 31).
llvm-svn: 348601
2018-12-07 16:33:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-10-29 18:26:01 +01:00
|
|
|
// This is the same as MachineInstr::readsRegister/modifiesRegister except
|
|
|
|
// it takes subregs into account.
|
|
|
|
static bool instAccessReg(iterator_range<MachineInstr::const_mop_iterator> &&R,
|
2020-08-20 18:46:16 +02:00
|
|
|
Register Reg, unsigned SubReg,
|
2018-10-29 18:26:01 +01:00
|
|
|
const SIRegisterInfo &TRI) {
|
|
|
|
for (const MachineOperand &MO : R) {
|
|
|
|
if (!MO.isReg())
|
|
|
|
continue;
|
|
|
|
|
2020-08-20 18:46:16 +02:00
|
|
|
if (Reg.isPhysical() && MO.getReg().isPhysical()) {
|
2018-10-29 18:26:01 +01:00
|
|
|
if (TRI.regsOverlap(Reg, MO.getReg()))
|
|
|
|
return true;
|
2020-08-20 18:46:16 +02:00
|
|
|
} else if (MO.getReg() == Reg && Reg.isVirtual()) {
|
2018-10-29 18:26:01 +01:00
|
|
|
LaneBitmask Overlap = TRI.getSubRegIndexLaneMask(SubReg) &
|
|
|
|
TRI.getSubRegIndexLaneMask(MO.getSubReg());
|
|
|
|
if (Overlap.any())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool instReadsReg(const MachineInstr *MI,
|
|
|
|
unsigned Reg, unsigned SubReg,
|
|
|
|
const SIRegisterInfo &TRI) {
|
|
|
|
return instAccessReg(MI->uses(), Reg, SubReg, TRI);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool instModifiesReg(const MachineInstr *MI,
|
|
|
|
unsigned Reg, unsigned SubReg,
|
|
|
|
const SIRegisterInfo &TRI) {
|
|
|
|
return instAccessReg(MI->defs(), Reg, SubReg, TRI);
|
|
|
|
}
|
|
|
|
|
|
|
|
static TargetInstrInfo::RegSubRegPair
|
2020-08-20 18:46:16 +02:00
|
|
|
getSubRegForIndex(Register Reg, unsigned Sub, unsigned I,
|
2018-10-29 18:26:01 +01:00
|
|
|
const SIRegisterInfo &TRI, const MachineRegisterInfo &MRI) {
|
|
|
|
if (TRI.getRegSizeInBits(Reg, MRI) != 32) {
|
2020-08-20 18:46:16 +02:00
|
|
|
if (Reg.isPhysical()) {
|
2018-10-29 18:26:01 +01:00
|
|
|
Reg = TRI.getSubReg(Reg, TRI.getSubRegFromChannel(I));
|
|
|
|
} else {
|
2020-02-06 23:47:10 +01:00
|
|
|
Sub = TRI.getSubRegFromChannel(I + TRI.getChannelFromSubReg(Sub));
|
2018-10-29 18:26:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return TargetInstrInfo::RegSubRegPair(Reg, Sub);
|
|
|
|
}
|
|
|
|
|
2020-10-17 00:22:42 +02:00
|
|
|
static void dropInstructionKeepingImpDefs(MachineInstr &MI,
|
|
|
|
const SIInstrInfo *TII) {
|
|
|
|
for (unsigned i = MI.getDesc().getNumOperands() +
|
|
|
|
MI.getDesc().getNumImplicitUses() +
|
|
|
|
MI.getDesc().getNumImplicitDefs(), e = MI.getNumOperands();
|
|
|
|
i != e; ++i) {
|
|
|
|
const MachineOperand &Op = MI.getOperand(i);
|
|
|
|
if (!Op.isDef())
|
|
|
|
continue;
|
|
|
|
BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
|
|
|
|
TII->get(AMDGPU::IMPLICIT_DEF), Op.getReg());
|
|
|
|
}
|
|
|
|
|
|
|
|
MI.eraseFromParent();
|
|
|
|
}
|
|
|
|
|
2018-10-29 18:26:01 +01:00
|
|
|
// Match:
|
|
|
|
// mov t, x
|
|
|
|
// mov x, y
|
|
|
|
// mov y, t
|
|
|
|
//
|
|
|
|
// =>
|
|
|
|
//
|
|
|
|
// mov t, x (t is potentially dead and move eliminated)
|
|
|
|
// v_swap_b32 x, y
|
|
|
|
//
|
|
|
|
// Returns next valid instruction pointer if was able to create v_swap_b32.
|
|
|
|
//
|
|
|
|
// This shall not be done too early not to prevent possible folding which may
|
|
|
|
// remove matched moves, and this should prefereably be done before RA to
|
|
|
|
// release saved registers and also possibly after RA which can insert copies
|
|
|
|
// too.
|
|
|
|
//
|
|
|
|
// This is really just a generic peephole that is not a canocical shrinking,
|
|
|
|
// although requirements match the pass placement and it reduces code size too.
|
|
|
|
static MachineInstr* matchSwap(MachineInstr &MovT, MachineRegisterInfo &MRI,
|
|
|
|
const SIInstrInfo *TII) {
|
|
|
|
assert(MovT.getOpcode() == AMDGPU::V_MOV_B32_e32 ||
|
|
|
|
MovT.getOpcode() == AMDGPU::COPY);
|
|
|
|
|
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 T = MovT.getOperand(0).getReg();
|
2018-10-29 18:26:01 +01:00
|
|
|
unsigned Tsub = MovT.getOperand(0).getSubReg();
|
|
|
|
MachineOperand &Xop = MovT.getOperand(1);
|
|
|
|
|
|
|
|
if (!Xop.isReg())
|
|
|
|
return nullptr;
|
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 X = Xop.getReg();
|
2018-10-29 18:26:01 +01:00
|
|
|
unsigned Xsub = Xop.getSubReg();
|
|
|
|
|
|
|
|
unsigned Size = TII->getOpSize(MovT, 0) / 4;
|
|
|
|
|
|
|
|
const SIRegisterInfo &TRI = TII->getRegisterInfo();
|
|
|
|
if (!TRI.isVGPR(MRI, X))
|
2018-10-29 18:53:23 +01:00
|
|
|
return nullptr;
|
2018-10-29 18:26:01 +01:00
|
|
|
|
2020-10-17 00:22:42 +02:00
|
|
|
if (MovT.hasRegisterImplicitUseOperand(AMDGPU::M0))
|
|
|
|
return nullptr;
|
|
|
|
|
2020-02-07 20:06:33 +01:00
|
|
|
const unsigned SearchLimit = 16;
|
|
|
|
unsigned Count = 0;
|
2020-10-17 00:22:42 +02:00
|
|
|
bool KilledT = false;
|
2020-02-07 20:06:33 +01:00
|
|
|
for (auto Iter = std::next(MovT.getIterator()),
|
|
|
|
E = MovT.getParent()->instr_end();
|
2020-10-17 00:22:42 +02:00
|
|
|
Iter != E && Count < SearchLimit && !KilledT; ++Iter, ++Count) {
|
2020-02-07 20:06:33 +01:00
|
|
|
|
|
|
|
MachineInstr *MovY = &*Iter;
|
2020-10-17 00:22:42 +02:00
|
|
|
KilledT = MovY->killsRegister(T, &TRI);
|
|
|
|
|
2020-02-07 20:06:33 +01:00
|
|
|
if ((MovY->getOpcode() != AMDGPU::V_MOV_B32_e32 &&
|
|
|
|
MovY->getOpcode() != AMDGPU::COPY) ||
|
|
|
|
!MovY->getOperand(1).isReg() ||
|
|
|
|
MovY->getOperand(1).getReg() != T ||
|
2020-10-17 00:22:42 +02:00
|
|
|
MovY->getOperand(1).getSubReg() != Tsub ||
|
|
|
|
MovY->hasRegisterImplicitUseOperand(AMDGPU::M0))
|
2018-10-29 18:26:01 +01:00
|
|
|
continue;
|
|
|
|
|
2020-02-07 20:06:33 +01:00
|
|
|
Register Y = MovY->getOperand(0).getReg();
|
|
|
|
unsigned Ysub = MovY->getOperand(0).getSubReg();
|
2018-10-29 18:26:01 +01:00
|
|
|
|
2020-02-07 20:06:33 +01:00
|
|
|
if (!TRI.isVGPR(MRI, Y))
|
2018-10-29 18:26:01 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
MachineInstr *MovX = nullptr;
|
2020-02-07 20:06:33 +01:00
|
|
|
for (auto IY = MovY->getIterator(), I = std::next(MovT.getIterator());
|
|
|
|
I != IY; ++I) {
|
|
|
|
if (instReadsReg(&*I, X, Xsub, TRI) ||
|
2018-10-29 18:26:01 +01:00
|
|
|
instModifiesReg(&*I, Y, Ysub, TRI) ||
|
|
|
|
instModifiesReg(&*I, T, Tsub, TRI) ||
|
|
|
|
(MovX && instModifiesReg(&*I, X, Xsub, TRI))) {
|
|
|
|
MovX = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!instReadsReg(&*I, Y, Ysub, TRI)) {
|
|
|
|
if (!MovX && instModifiesReg(&*I, X, Xsub, TRI)) {
|
|
|
|
MovX = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (MovX ||
|
|
|
|
(I->getOpcode() != AMDGPU::V_MOV_B32_e32 &&
|
|
|
|
I->getOpcode() != AMDGPU::COPY) ||
|
|
|
|
I->getOperand(0).getReg() != X ||
|
|
|
|
I->getOperand(0).getSubReg() != Xsub) {
|
|
|
|
MovX = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
2020-10-17 00:22:42 +02:00
|
|
|
// Implicit use of M0 is an indirect move.
|
|
|
|
if (I->hasRegisterImplicitUseOperand(AMDGPU::M0))
|
|
|
|
continue;
|
|
|
|
|
2020-10-26 19:53:40 +01:00
|
|
|
if (Size > 1 && (I->getNumImplicitOperands() > (I->isCopy() ? 0U : 1U)))
|
2020-10-17 00:22:42 +02:00
|
|
|
continue;
|
|
|
|
|
2018-10-29 18:26:01 +01:00
|
|
|
MovX = &*I;
|
|
|
|
}
|
|
|
|
|
2020-02-07 20:06:33 +01:00
|
|
|
if (!MovX)
|
2018-10-29 18:26:01 +01:00
|
|
|
continue;
|
|
|
|
|
2020-10-17 00:22:42 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "Matched v_swap_b32:\n" << MovT << *MovX << *MovY);
|
2018-10-29 18:26:01 +01:00
|
|
|
|
|
|
|
for (unsigned I = 0; I < Size; ++I) {
|
|
|
|
TargetInstrInfo::RegSubRegPair X1, Y1;
|
|
|
|
X1 = getSubRegForIndex(X, Xsub, I, TRI, MRI);
|
|
|
|
Y1 = getSubRegForIndex(Y, Ysub, I, TRI, MRI);
|
2020-10-17 00:22:42 +02:00
|
|
|
MachineBasicBlock &MBB = *MovT.getParent();
|
|
|
|
auto MIB = BuildMI(MBB, MovX->getIterator(), MovT.getDebugLoc(),
|
|
|
|
TII->get(AMDGPU::V_SWAP_B32))
|
2018-10-29 18:26:01 +01:00
|
|
|
.addDef(X1.Reg, 0, X1.SubReg)
|
|
|
|
.addDef(Y1.Reg, 0, Y1.SubReg)
|
|
|
|
.addReg(Y1.Reg, 0, Y1.SubReg)
|
|
|
|
.addReg(X1.Reg, 0, X1.SubReg).getInstr();
|
2020-10-17 00:22:42 +02:00
|
|
|
if (MovX->hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
|
|
|
|
// Drop implicit EXEC.
|
|
|
|
MIB->RemoveOperand(MIB->getNumExplicitOperands());
|
|
|
|
MIB->copyImplicitOps(*MBB.getParent(), *MovX);
|
|
|
|
}
|
2018-10-29 18:26:01 +01:00
|
|
|
}
|
|
|
|
MovX->eraseFromParent();
|
2020-10-17 00:22:42 +02:00
|
|
|
dropInstructionKeepingImpDefs(*MovY, TII);
|
2018-10-29 18:26:01 +01:00
|
|
|
MachineInstr *Next = &*std::next(MovT.getIterator());
|
2020-10-17 00:22:42 +02:00
|
|
|
|
|
|
|
if (MRI.use_nodbg_empty(T)) {
|
|
|
|
dropInstructionKeepingImpDefs(MovT, TII);
|
|
|
|
} else {
|
2018-10-29 18:26:01 +01:00
|
|
|
Xop.setIsKill(false);
|
2020-10-17 00:22:42 +02:00
|
|
|
for (int I = MovT.getNumImplicitOperands() - 1; I >= 0; --I ) {
|
|
|
|
unsigned OpNo = MovT.getNumExplicitOperands() + I;
|
|
|
|
const MachineOperand &Op = MovT.getOperand(OpNo);
|
|
|
|
if (Op.isKill() && TRI.regsOverlap(X, Op.getReg()))
|
|
|
|
MovT.RemoveOperand(OpNo);
|
|
|
|
}
|
|
|
|
}
|
2018-10-29 18:26:01 +01:00
|
|
|
|
|
|
|
return Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-07-21 18:55:33 +02:00
|
|
|
bool SIShrinkInstructions::runOnMachineFunction(MachineFunction &MF) {
|
2017-12-15 23:22:58 +01:00
|
|
|
if (skipFunction(MF.getFunction()))
|
2016-04-26 00:23:44 +02:00
|
|
|
return false;
|
|
|
|
|
2014-07-21 18:55:33 +02:00
|
|
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
2018-07-11 22:59:01 +02:00
|
|
|
const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
|
2016-06-24 08:30:11 +02:00
|
|
|
const SIInstrInfo *TII = ST.getInstrInfo();
|
2019-06-16 19:13:09 +02:00
|
|
|
unsigned VCCReg = ST.isWave32() ? AMDGPU::VCC_LO : AMDGPU::VCC;
|
2016-06-24 08:30:11 +02:00
|
|
|
|
2014-07-21 18:55:33 +02:00
|
|
|
std::vector<unsigned> I1Defs;
|
|
|
|
|
|
|
|
for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
|
|
|
|
BI != BE; ++BI) {
|
|
|
|
|
|
|
|
MachineBasicBlock &MBB = *BI;
|
|
|
|
MachineBasicBlock::iterator I, Next;
|
|
|
|
for (I = MBB.begin(); I != MBB.end(); I = Next) {
|
|
|
|
Next = std::next(I);
|
|
|
|
MachineInstr &MI = *I;
|
|
|
|
|
2016-03-11 08:42:49 +01:00
|
|
|
if (MI.getOpcode() == AMDGPU::V_MOV_B32_e32) {
|
|
|
|
// If this has a literal constant source that is the same as the
|
|
|
|
// reversed bits of an inline immediate, replace with a bitreverse of
|
|
|
|
// that constant. This saves 4 bytes in the common case of materializing
|
|
|
|
// sign bits.
|
|
|
|
|
|
|
|
// Test if we are after regalloc. We only want to do this after any
|
|
|
|
// optimizations happen because this will confuse them.
|
|
|
|
// XXX - not exactly a check for post-regalloc run.
|
|
|
|
MachineOperand &Src = MI.getOperand(1);
|
2020-08-20 18:46:16 +02:00
|
|
|
if (Src.isImm() && MI.getOperand(0).getReg().isPhysical()) {
|
2016-11-02 00:14:20 +01:00
|
|
|
int32_t ReverseImm;
|
|
|
|
if (isReverseInlineImm(TII, Src, ReverseImm)) {
|
|
|
|
MI.setDesc(TII->get(AMDGPU::V_BFREV_B32_e32));
|
|
|
|
Src.setImm(ReverseImm);
|
|
|
|
continue;
|
2016-03-11 08:42:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-29 18:26:01 +01:00
|
|
|
if (ST.hasSwap() && (MI.getOpcode() == AMDGPU::V_MOV_B32_e32 ||
|
|
|
|
MI.getOpcode() == AMDGPU::COPY)) {
|
|
|
|
if (auto *NextMI = matchSwap(MI, MRI, TII)) {
|
|
|
|
Next = NextMI->getIterator();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-16 03:46:49 +02:00
|
|
|
// FIXME: We also need to consider movs of constant operands since
|
|
|
|
// immediate operands are not folded if they have more than one use, and
|
|
|
|
// the operand folding pass is unaware if the immediate will be free since
|
|
|
|
// it won't know if the src == dest constraint will end up being
|
|
|
|
// satisfied.
|
|
|
|
if (MI.getOpcode() == AMDGPU::S_ADD_I32 ||
|
|
|
|
MI.getOpcode() == AMDGPU::S_MUL_I32) {
|
2016-09-08 19:35:41 +02:00
|
|
|
const MachineOperand *Dest = &MI.getOperand(0);
|
|
|
|
MachineOperand *Src0 = &MI.getOperand(1);
|
|
|
|
MachineOperand *Src1 = &MI.getOperand(2);
|
|
|
|
|
|
|
|
if (!Src0->isReg() && Src1->isReg()) {
|
|
|
|
if (TII->commuteInstruction(MI, false, 1, 2))
|
|
|
|
std::swap(Src0, Src1);
|
|
|
|
}
|
2016-04-16 03:46:49 +02:00
|
|
|
|
|
|
|
// FIXME: This could work better if hints worked with subregisters. If
|
|
|
|
// we have a vector add of a constant, we usually don't get the correct
|
|
|
|
// allocation due to the subregister usage.
|
2020-08-20 18:46:16 +02:00
|
|
|
if (Dest->getReg().isVirtual() && Src0->isReg()) {
|
2016-09-08 19:35:41 +02:00
|
|
|
MRI.setRegAllocationHint(Dest->getReg(), 0, Src0->getReg());
|
|
|
|
MRI.setRegAllocationHint(Src0->getReg(), 0, Dest->getReg());
|
2016-04-16 03:46:49 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-09-08 19:35:41 +02:00
|
|
|
if (Src0->isReg() && Src0->getReg() == Dest->getReg()) {
|
|
|
|
if (Src1->isImm() && isKImmOperand(TII, *Src1)) {
|
2016-04-16 03:46:49 +02:00
|
|
|
unsigned Opc = (MI.getOpcode() == AMDGPU::S_ADD_I32) ?
|
|
|
|
AMDGPU::S_ADDK_I32 : AMDGPU::S_MULK_I32;
|
|
|
|
|
|
|
|
MI.setDesc(TII->get(Opc));
|
|
|
|
MI.tieOperands(0, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-16 23:41:16 +02:00
|
|
|
// Try to use s_cmpk_*
|
|
|
|
if (MI.isCompare() && TII->isSOPC(MI)) {
|
|
|
|
shrinkScalarCompare(TII, MI);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-04-16 03:46:49 +02:00
|
|
|
// Try to use S_MOVK_I32, which will save 4 bytes for small immediates.
|
|
|
|
if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
|
2016-11-02 00:14:20 +01:00
|
|
|
const MachineOperand &Dst = MI.getOperand(0);
|
|
|
|
MachineOperand &Src = MI.getOperand(1);
|
2016-04-16 03:46:49 +02:00
|
|
|
|
2020-08-20 18:46:16 +02:00
|
|
|
if (Src.isImm() && Dst.getReg().isPhysical()) {
|
2016-11-02 00:14:20 +01:00
|
|
|
int32_t ReverseImm;
|
|
|
|
if (isKImmOperand(TII, Src))
|
|
|
|
MI.setDesc(TII->get(AMDGPU::S_MOVK_I32));
|
|
|
|
else if (isReverseInlineImm(TII, Src, ReverseImm)) {
|
|
|
|
MI.setDesc(TII->get(AMDGPU::S_BREV_B32));
|
|
|
|
Src.setImm(ReverseImm);
|
|
|
|
}
|
|
|
|
}
|
2016-04-16 03:46:49 +02:00
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
[AMDGPU] Shrink scalar AND, OR, XOR instructions
This change attempts to shrink scalar AND, OR and XOR instructions which take an immediate that isn't inlineable.
It performs:
AND s0, s0, ~(1 << n) -> BITSET0 s0, n
OR s0, s0, (1 << n) -> BITSET1 s0, n
AND s0, s1, x -> ANDN2 s0, s1, ~x
OR s0, s1, x -> ORN2 s0, s1, ~x
XOR s0, s1, x -> XNOR s0, s1, ~x
In particular, this catches setting and clearing the sign bit for fabs (and x, 0x7ffffffff -> bitset0 x, 31 and or x, 0x80000000 -> bitset1 x, 31).
llvm-svn: 348601
2018-12-07 16:33:21 +01:00
|
|
|
// Shrink scalar logic operations.
|
|
|
|
if (MI.getOpcode() == AMDGPU::S_AND_B32 ||
|
|
|
|
MI.getOpcode() == AMDGPU::S_OR_B32 ||
|
|
|
|
MI.getOpcode() == AMDGPU::S_XOR_B32) {
|
|
|
|
if (shrinkScalarLogicOp(ST, MRI, TII, MI))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-05-01 18:32:58 +02:00
|
|
|
if (TII->isMIMG(MI.getOpcode()) &&
|
|
|
|
ST.getGeneration() >= AMDGPUSubtarget::GFX10 &&
|
|
|
|
MF.getProperties().hasProperty(
|
|
|
|
MachineFunctionProperties::Property::NoVRegs)) {
|
|
|
|
shrinkMIMG(MI);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-08-01 02:32:28 +02:00
|
|
|
if (!TII->hasVALU32BitEncoding(MI.getOpcode()))
|
2014-07-21 18:55:33 +02:00
|
|
|
continue;
|
|
|
|
|
2018-08-28 20:22:34 +02:00
|
|
|
if (!TII->canShrink(MI, MRI)) {
|
2014-09-16 20:00:23 +02:00
|
|
|
// Try commuting the instruction and see if that enables us to shrink
|
2014-07-21 18:55:33 +02:00
|
|
|
// it.
|
2016-06-30 02:01:54 +02:00
|
|
|
if (!MI.isCommutable() || !TII->commuteInstruction(MI) ||
|
2018-08-28 20:22:34 +02:00
|
|
|
!TII->canShrink(MI, MRI))
|
2014-07-21 18:55:33 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-01-15 19:42:51 +01:00
|
|
|
// getVOPe32 could be -1 here if we started with an instruction that had
|
2014-08-01 02:32:28 +02:00
|
|
|
// a 32-bit encoding and then commuted it to an instruction that did not.
|
2015-01-15 19:42:51 +01:00
|
|
|
if (!TII->hasVALU32BitEncoding(MI.getOpcode()))
|
2014-08-01 02:32:28 +02:00
|
|
|
continue;
|
|
|
|
|
2015-01-15 19:42:51 +01:00
|
|
|
int Op32 = AMDGPU::getVOPe32(MI.getOpcode());
|
|
|
|
|
2014-07-21 18:55:33 +02:00
|
|
|
if (TII->isVOPC(Op32)) {
|
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 = MI.getOperand(0).getReg();
|
2020-08-20 18:46:16 +02:00
|
|
|
if (DstReg.isVirtual()) {
|
2015-08-08 02:41:45 +02:00
|
|
|
// VOPC instructions can only write to the VCC register. We can't
|
|
|
|
// force them to use VCC here, because this is only one register and
|
|
|
|
// cannot deal with sequences which would require multiple copies of
|
|
|
|
// VCC, e.g. S_AND_B64 (vcc = V_CMP_...), (vcc = V_CMP_...)
|
2014-07-21 18:55:33 +02:00
|
|
|
//
|
2014-09-21 19:27:32 +02:00
|
|
|
// So, instead of forcing the instruction to write to VCC, we provide
|
2018-04-13 13:37:06 +02:00
|
|
|
// a hint to the register allocator to use VCC and then we will run
|
2014-09-21 19:27:32 +02:00
|
|
|
// this pass again after RA and shrink it if it outputs to VCC.
|
2019-06-16 19:13:09 +02:00
|
|
|
MRI.setRegAllocationHint(MI.getOperand(0).getReg(), 0, VCCReg);
|
2014-07-21 18:55:33 +02:00
|
|
|
continue;
|
|
|
|
}
|
2019-06-16 19:13:09 +02:00
|
|
|
if (DstReg != VCCReg)
|
2014-07-21 18:55:33 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-07-14 16:15:03 +02:00
|
|
|
if (Op32 == AMDGPU::V_CNDMASK_B32_e32) {
|
|
|
|
// We shrink V_CNDMASK_B32_e64 using regalloc hints like we do for VOPC
|
|
|
|
// instructions.
|
|
|
|
const MachineOperand *Src2 =
|
|
|
|
TII->getNamedOperand(MI, AMDGPU::OpName::src2);
|
|
|
|
if (!Src2->isReg())
|
|
|
|
continue;
|
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 SReg = Src2->getReg();
|
2020-08-20 18:46:16 +02:00
|
|
|
if (SReg.isVirtual()) {
|
2019-06-16 19:13:09 +02:00
|
|
|
MRI.setRegAllocationHint(SReg, 0, VCCReg);
|
2015-07-14 16:15:03 +02:00
|
|
|
continue;
|
|
|
|
}
|
2019-06-16 19:13:09 +02:00
|
|
|
if (SReg != VCCReg)
|
2015-07-14 16:15:03 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-01-11 23:35:17 +01:00
|
|
|
// Check for the bool flag output for instructions like V_ADD_I32_e64.
|
|
|
|
const MachineOperand *SDst = TII->getNamedOperand(MI,
|
|
|
|
AMDGPU::OpName::sdst);
|
|
|
|
|
2017-01-11 23:58:12 +01:00
|
|
|
// Check the carry-in operand for v_addc_u32_e64.
|
|
|
|
const MachineOperand *Src2 = TII->getNamedOperand(MI,
|
|
|
|
AMDGPU::OpName::src2);
|
|
|
|
|
|
|
|
if (SDst) {
|
2019-06-16 19:13:09 +02:00
|
|
|
bool Next = false;
|
|
|
|
|
|
|
|
if (SDst->getReg() != VCCReg) {
|
2020-08-20 18:46:16 +02:00
|
|
|
if (SDst->getReg().isVirtual())
|
2019-06-16 19:13:09 +02:00
|
|
|
MRI.setRegAllocationHint(SDst->getReg(), 0, VCCReg);
|
|
|
|
Next = true;
|
2017-01-11 23:58:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// All of the instructions with carry outs also have an SGPR input in
|
|
|
|
// src2.
|
2019-06-16 19:13:09 +02:00
|
|
|
if (Src2 && Src2->getReg() != VCCReg) {
|
2020-08-20 18:46:16 +02:00
|
|
|
if (Src2->getReg().isVirtual())
|
2019-06-16 19:13:09 +02:00
|
|
|
MRI.setRegAllocationHint(Src2->getReg(), 0, VCCReg);
|
|
|
|
Next = true;
|
|
|
|
}
|
2017-01-11 23:58:12 +01:00
|
|
|
|
2019-06-16 19:13:09 +02:00
|
|
|
if (Next)
|
2017-01-11 23:58:12 +01:00
|
|
|
continue;
|
2017-01-11 23:35:17 +01:00
|
|
|
}
|
|
|
|
|
2014-07-21 18:55:33 +02:00
|
|
|
// We can shrink this instruction
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "Shrinking " << MI);
|
2014-07-21 18:55:33 +02:00
|
|
|
|
2018-08-28 20:34:24 +02:00
|
|
|
MachineInstr *Inst32 = TII->buildShrunkInst(MI, Op32);
|
2014-07-21 18:55:33 +02:00
|
|
|
++NumInstructionsShrunk;
|
2014-08-01 02:32:33 +02:00
|
|
|
|
2016-07-19 02:35:03 +02:00
|
|
|
// Copy extra operands not present in the instruction definition.
|
2016-09-03 19:25:39 +02:00
|
|
|
copyExtraImplicitOps(*Inst32, MF, MI);
|
2016-07-19 02:35:03 +02:00
|
|
|
|
|
|
|
MI.eraseFromParent();
|
2014-08-01 02:32:33 +02:00
|
|
|
foldImmediates(*Inst32, TII, MRI);
|
2016-07-19 02:35:03 +02:00
|
|
|
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "e32 MI = " << *Inst32 << '\n');
|
2014-07-21 18:55:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|