2016-07-27 22:31:55 +08:00
|
|
|
//===- llvm/CodeGen/GlobalISel/InstructionSelect.cpp - InstructionSelect ---==//
|
|
|
|
//
|
2019-01-19 16:50:56 +08: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
|
2016-07-27 22:31:55 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \file
|
|
|
|
/// This file implements the InstructionSelect class.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
|
|
|
|
#include "llvm/ADT/PostOrderIterator.h"
|
2021-02-25 14:45:25 +08:00
|
|
|
#include "llvm/ADT/ScopeExit.h"
|
2016-07-27 22:31:55 +08:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2021-02-25 14:45:25 +08:00
|
|
|
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
|
|
|
#include "llvm/Analysis/LazyBlockFrequencyInfo.h"
|
|
|
|
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
2019-08-30 01:24:32 +08:00
|
|
|
#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
|
2016-07-27 22:31:55 +08:00
|
|
|
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
|
2016-10-15 06:18:18 +08:00
|
|
|
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
|
2017-02-24 05:05:42 +08:00
|
|
|
#include "llvm/CodeGen/GlobalISel/Utils.h"
|
2019-09-21 07:52:07 +08:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2021-10-09 01:48:15 +08:00
|
|
|
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
|
2016-07-27 22:31:55 +08:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2019-09-21 07:52:07 +08:00
|
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
#include "llvm/CodeGen/TargetLowering.h"
|
2016-08-27 10:38:24 +08:00
|
|
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
[globalisel][tablegen] Generate rule coverage and use it to identify untested rules
Summary:
This patch adds a LLVM_ENABLE_GISEL_COV which, like LLVM_ENABLE_DAGISEL_COV,
causes TableGen to instrument the generated table to collect rule coverage
information. However, LLVM_ENABLE_GISEL_COV goes a bit further than
LLVM_ENABLE_DAGISEL_COV. The information is written to files
(${CMAKE_BINARY_DIR}/gisel-coverage-* by default). These files can then be
concatenated into ${LLVM_GISEL_COV_PREFIX}-all after which TableGen will
read this information and use it to emit warnings about untested rules.
This technique could also be used by SelectionDAG and can be further
extended to detect hot rules and give them priority over colder rules.
Usage:
* Enable LLVM_ENABLE_GISEL_COV in CMake
* Build the compiler and run some tests
* cat gisel-coverage-[0-9]* > gisel-coverage-all
* Delete lib/Target/*/*GenGlobalISel.inc*
* Build the compiler
Known issues:
* ${LLVM_GISEL_COV_PREFIX}-all must be generated as a manual
step due to a lack of a portable 'cat' command. It should be the
concatenation of all ${LLVM_GISEL_COV_PREFIX}-[0-9]* files.
* There's no mechanism to discard coverage information when the ruleset
changes
Depends on D39742
Reviewers: ab, qcolombet, t.p.northover, aditya_nandakumar, rovka
Reviewed By: rovka
Subscribers: vsk, arsenm, nhaehnle, mgorny, kristof.beyls, javed.absar, igorb, llvm-commits
Differential Revision: https://reviews.llvm.org/D39747
llvm-svn: 318356
2017-11-16 08:46:35 +08:00
|
|
|
#include "llvm/Config/config.h"
|
2017-02-25 05:21:38 +08:00
|
|
|
#include "llvm/IR/Constants.h"
|
2016-07-27 22:31:55 +08:00
|
|
|
#include "llvm/IR/Function.h"
|
2021-10-09 01:48:15 +08:00
|
|
|
#include "llvm/MC/TargetRegistry.h"
|
2016-07-27 22:31:55 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
2020-05-24 02:49:38 +08:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2016-07-27 22:31:55 +08:00
|
|
|
|
|
|
|
#define DEBUG_TYPE "instruction-select"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
[globalisel][tablegen] Generate rule coverage and use it to identify untested rules
Summary:
This patch adds a LLVM_ENABLE_GISEL_COV which, like LLVM_ENABLE_DAGISEL_COV,
causes TableGen to instrument the generated table to collect rule coverage
information. However, LLVM_ENABLE_GISEL_COV goes a bit further than
LLVM_ENABLE_DAGISEL_COV. The information is written to files
(${CMAKE_BINARY_DIR}/gisel-coverage-* by default). These files can then be
concatenated into ${LLVM_GISEL_COV_PREFIX}-all after which TableGen will
read this information and use it to emit warnings about untested rules.
This technique could also be used by SelectionDAG and can be further
extended to detect hot rules and give them priority over colder rules.
Usage:
* Enable LLVM_ENABLE_GISEL_COV in CMake
* Build the compiler and run some tests
* cat gisel-coverage-[0-9]* > gisel-coverage-all
* Delete lib/Target/*/*GenGlobalISel.inc*
* Build the compiler
Known issues:
* ${LLVM_GISEL_COV_PREFIX}-all must be generated as a manual
step due to a lack of a portable 'cat' command. It should be the
concatenation of all ${LLVM_GISEL_COV_PREFIX}-[0-9]* files.
* There's no mechanism to discard coverage information when the ruleset
changes
Depends on D39742
Reviewers: ab, qcolombet, t.p.northover, aditya_nandakumar, rovka
Reviewed By: rovka
Subscribers: vsk, arsenm, nhaehnle, mgorny, kristof.beyls, javed.absar, igorb, llvm-commits
Differential Revision: https://reviews.llvm.org/D39747
llvm-svn: 318356
2017-11-16 08:46:35 +08:00
|
|
|
#ifdef LLVM_GISEL_COV_PREFIX
|
|
|
|
static cl::opt<std::string>
|
|
|
|
CoveragePrefix("gisel-coverage-prefix", cl::init(LLVM_GISEL_COV_PREFIX),
|
|
|
|
cl::desc("Record GlobalISel rule coverage files of this "
|
|
|
|
"prefix if instrumentation was generated"));
|
|
|
|
#else
|
2021-01-13 13:43:46 +08:00
|
|
|
static const std::string CoveragePrefix;
|
[globalisel][tablegen] Generate rule coverage and use it to identify untested rules
Summary:
This patch adds a LLVM_ENABLE_GISEL_COV which, like LLVM_ENABLE_DAGISEL_COV,
causes TableGen to instrument the generated table to collect rule coverage
information. However, LLVM_ENABLE_GISEL_COV goes a bit further than
LLVM_ENABLE_DAGISEL_COV. The information is written to files
(${CMAKE_BINARY_DIR}/gisel-coverage-* by default). These files can then be
concatenated into ${LLVM_GISEL_COV_PREFIX}-all after which TableGen will
read this information and use it to emit warnings about untested rules.
This technique could also be used by SelectionDAG and can be further
extended to detect hot rules and give them priority over colder rules.
Usage:
* Enable LLVM_ENABLE_GISEL_COV in CMake
* Build the compiler and run some tests
* cat gisel-coverage-[0-9]* > gisel-coverage-all
* Delete lib/Target/*/*GenGlobalISel.inc*
* Build the compiler
Known issues:
* ${LLVM_GISEL_COV_PREFIX}-all must be generated as a manual
step due to a lack of a portable 'cat' command. It should be the
concatenation of all ${LLVM_GISEL_COV_PREFIX}-[0-9]* files.
* There's no mechanism to discard coverage information when the ruleset
changes
Depends on D39742
Reviewers: ab, qcolombet, t.p.northover, aditya_nandakumar, rovka
Reviewed By: rovka
Subscribers: vsk, arsenm, nhaehnle, mgorny, kristof.beyls, javed.absar, igorb, llvm-commits
Differential Revision: https://reviews.llvm.org/D39747
llvm-svn: 318356
2017-11-16 08:46:35 +08:00
|
|
|
#endif
|
|
|
|
|
2016-07-27 22:31:55 +08:00
|
|
|
char InstructionSelect::ID = 0;
|
2016-08-27 10:38:24 +08:00
|
|
|
INITIALIZE_PASS_BEGIN(InstructionSelect, DEBUG_TYPE,
|
|
|
|
"Select target instructions out of generic instructions",
|
|
|
|
false, false)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
|
2019-08-31 01:41:58 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
|
2021-02-25 14:45:25 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(LazyBlockFrequencyInfoPass)
|
2016-08-27 10:38:24 +08:00
|
|
|
INITIALIZE_PASS_END(InstructionSelect, DEBUG_TYPE,
|
|
|
|
"Select target instructions out of generic instructions",
|
|
|
|
false, false)
|
2016-07-27 22:31:55 +08:00
|
|
|
|
2021-02-25 14:45:25 +08:00
|
|
|
InstructionSelect::InstructionSelect(CodeGenOpt::Level OL)
|
|
|
|
: MachineFunctionPass(ID), OptLevel(OL) {}
|
|
|
|
|
|
|
|
// In order not to crash when calling getAnalysis during testing with -run-pass
|
|
|
|
// we use the default opt level here instead of None, so that the addRequired()
|
|
|
|
// calls are made in getAnalysisUsage().
|
|
|
|
InstructionSelect::InstructionSelect()
|
|
|
|
: MachineFunctionPass(ID), OptLevel(CodeGenOpt::Default) {}
|
2016-07-27 22:31:55 +08:00
|
|
|
|
2016-08-27 10:38:24 +08:00
|
|
|
void InstructionSelect::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
AU.addRequired<TargetPassConfig>();
|
2022-01-13 04:31:51 +08:00
|
|
|
AU.addRequired<GISelKnownBitsAnalysis>();
|
|
|
|
AU.addPreserved<GISelKnownBitsAnalysis>();
|
|
|
|
|
2021-02-25 14:45:25 +08:00
|
|
|
if (OptLevel != CodeGenOpt::None) {
|
|
|
|
AU.addRequired<ProfileSummaryInfoWrapperPass>();
|
|
|
|
LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
|
|
|
|
}
|
2018-07-13 08:08:38 +08:00
|
|
|
getSelectionDAGFallbackAnalysisUsage(AU);
|
2016-08-27 10:38:24 +08:00
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
|
2016-07-27 22:31:55 +08:00
|
|
|
bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
|
2016-08-27 08:18:24 +08:00
|
|
|
// If the ISel pipeline failed, do not bother running that pass.
|
|
|
|
if (MF.getProperties().hasProperty(
|
|
|
|
MachineFunctionProperties::Property::FailedISel))
|
|
|
|
return false;
|
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Selecting function: " << MF.getName() << '\n');
|
2016-07-27 22:31:55 +08:00
|
|
|
|
2016-08-27 10:38:24 +08:00
|
|
|
const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
|
2019-08-13 14:26:59 +08:00
|
|
|
InstructionSelector *ISel = MF.getSubtarget().getInstructionSelector();
|
2021-02-25 14:45:25 +08:00
|
|
|
|
|
|
|
CodeGenOpt::Level OldOptLevel = OptLevel;
|
|
|
|
auto RestoreOptLevel = make_scope_exit([=]() { OptLevel = OldOptLevel; });
|
|
|
|
OptLevel = MF.getFunction().hasOptNone() ? CodeGenOpt::None
|
|
|
|
: MF.getTarget().getOptLevel();
|
|
|
|
|
2022-01-13 04:31:51 +08:00
|
|
|
GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
|
2021-02-25 14:45:25 +08:00
|
|
|
if (OptLevel != CodeGenOpt::None) {
|
|
|
|
PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
|
|
|
|
if (PSI && PSI->hasProfileSummary())
|
|
|
|
BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
|
|
|
|
}
|
|
|
|
|
[globalisel][tablegen] Generate rule coverage and use it to identify untested rules
Summary:
This patch adds a LLVM_ENABLE_GISEL_COV which, like LLVM_ENABLE_DAGISEL_COV,
causes TableGen to instrument the generated table to collect rule coverage
information. However, LLVM_ENABLE_GISEL_COV goes a bit further than
LLVM_ENABLE_DAGISEL_COV. The information is written to files
(${CMAKE_BINARY_DIR}/gisel-coverage-* by default). These files can then be
concatenated into ${LLVM_GISEL_COV_PREFIX}-all after which TableGen will
read this information and use it to emit warnings about untested rules.
This technique could also be used by SelectionDAG and can be further
extended to detect hot rules and give them priority over colder rules.
Usage:
* Enable LLVM_ENABLE_GISEL_COV in CMake
* Build the compiler and run some tests
* cat gisel-coverage-[0-9]* > gisel-coverage-all
* Delete lib/Target/*/*GenGlobalISel.inc*
* Build the compiler
Known issues:
* ${LLVM_GISEL_COV_PREFIX}-all must be generated as a manual
step due to a lack of a portable 'cat' command. It should be the
concatenation of all ${LLVM_GISEL_COV_PREFIX}-[0-9]* files.
* There's no mechanism to discard coverage information when the ruleset
changes
Depends on D39742
Reviewers: ab, qcolombet, t.p.northover, aditya_nandakumar, rovka
Reviewed By: rovka
Subscribers: vsk, arsenm, nhaehnle, mgorny, kristof.beyls, javed.absar, igorb, llvm-commits
Differential Revision: https://reviews.llvm.org/D39747
llvm-svn: 318356
2017-11-16 08:46:35 +08:00
|
|
|
CodeGenCoverage CoverageInfo;
|
2016-07-27 22:31:55 +08:00
|
|
|
assert(ISel && "Cannot work without InstructionSelector");
|
2021-02-25 14:45:25 +08:00
|
|
|
ISel->setupMF(MF, KB, CoverageInfo, PSI, BFI);
|
2016-07-27 22:31:55 +08:00
|
|
|
|
2017-02-24 05:05:42 +08:00
|
|
|
// An optimization remark emitter. Used to report failures.
|
|
|
|
MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
|
|
|
|
|
2017-05-06 06:04:05 +08:00
|
|
|
// FIXME: There are many other MF/MFI fields we need to initialize.
|
2016-07-27 22:31:55 +08:00
|
|
|
|
2018-05-24 05:12:02 +08:00
|
|
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
2016-07-27 22:31:55 +08:00
|
|
|
#ifndef NDEBUG
|
2016-08-02 23:10:32 +08:00
|
|
|
// Check that our input is fully legal: we require the function to have the
|
|
|
|
// Legalized property, so it should be.
|
[GlobalISel][AArch64] Adding -disable-gisel-legality-check CL option
Currently it's impossible to test InstructionSelect pass with MIR which
is considered illegal by the Legalizer in Assert builds. In early stages
of porting an existing backend from SelectionDAG ISel to GlobalISel,
however, we would have very basic CallLowering, Legalizer, and
RegBankSelect implementations, but rather functional Instruction Select
with quite a few patterns selectable due to the semi-automatic porting
process borrowing them from SelectionDAG ISel.
As we are trying to define legality as a property of being selectable by
the instruction selector, it would be nice to be able to easily check
what the selector can do in its current state w/o the legality check
provided by the Legalizer getting in the way.
It also seems beneficial to have a regression testing set up that would
not allow the selector to silently regress in its support of the MIR not
supported yet by the previous passes in the GlobalISel pipeline.
This commit adds -disable-gisel-legality-check command line option to
llc that disables those legality checks in RegBankSelect and
InstructionSelect passes.
It also adds quite a few MIR test cases for AArch64's Instruction
Selector. Every one of them would fail on the legality check at the
moment, but will select just fine if the check is disabled. Every test
MachineFunction is intended to exercise a specific selection rule and
that rule only, encoded in the MachineFunction's name by the rule's
number, ID, and index of its GIM_Try opcode in TableGen'erated
MatchTable (-optimize-match-table=false).
Reviewers: ab, dsanders, qcolombet, rovka
Reviewed By: bogner
Subscribers: kristof.beyls, volkan, aditya_nandakumar, aemerson,
rengolin, t.p.northover, javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D42886
llvm-svn: 326396
2018-03-01 08:27:48 +08:00
|
|
|
// FIXME: This should be in the MachineVerifier, as the RegBankSelected
|
|
|
|
// property check already is.
|
|
|
|
if (!DisableGISelLegalityCheck)
|
|
|
|
if (const MachineInstr *MI = machineFunctionIsIllegal(MF)) {
|
|
|
|
reportGISelFailure(MF, TPC, MORE, "gisel-select",
|
|
|
|
"instruction is not legal", *MI);
|
|
|
|
return false;
|
|
|
|
}
|
2016-07-27 22:31:55 +08:00
|
|
|
// FIXME: We could introduce new blocks and will need to fix the outer loop.
|
|
|
|
// Until then, keep track of the number of blocks to assert that we don't.
|
|
|
|
const size_t NumBlocks = MF.size();
|
2019-03-16 09:02:10 +08:00
|
|
|
#endif
|
2021-10-06 08:41:21 +08:00
|
|
|
// Keep track of selected blocks, so we can delete unreachable ones later.
|
|
|
|
DenseSet<MachineBasicBlock *> SelectedBlocks;
|
2016-07-27 22:31:55 +08:00
|
|
|
|
|
|
|
for (MachineBasicBlock *MBB : post_order(&MF)) {
|
2021-02-25 14:45:25 +08:00
|
|
|
ISel->CurMBB = MBB;
|
2021-10-06 08:41:21 +08:00
|
|
|
SelectedBlocks.insert(MBB);
|
2016-11-09 03:27:10 +08:00
|
|
|
if (MBB->empty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Select instructions in reverse block order. We permit erasing so have
|
|
|
|
// to resort to manually iterating and recognizing the begin (rend) case.
|
|
|
|
bool ReachedBegin = false;
|
|
|
|
for (auto MII = std::prev(MBB->end()), Begin = MBB->begin();
|
|
|
|
!ReachedBegin;) {
|
2016-11-09 06:03:23 +08:00
|
|
|
#ifndef NDEBUG
|
2016-11-09 03:27:10 +08:00
|
|
|
// Keep track of the insertion range for debug printing.
|
|
|
|
const auto AfterIt = std::next(MII);
|
2016-11-09 06:03:23 +08:00
|
|
|
#endif
|
2016-11-09 03:27:10 +08:00
|
|
|
// Select this instruction.
|
|
|
|
MachineInstr &MI = *MII;
|
|
|
|
|
|
|
|
// And have our iterator point to the next instruction, if there is one.
|
|
|
|
if (MII == Begin)
|
|
|
|
ReachedBegin = true;
|
|
|
|
else
|
|
|
|
--MII;
|
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Selecting: \n " << MI);
|
2016-11-09 03:27:10 +08:00
|
|
|
|
2017-03-20 00:13:00 +08:00
|
|
|
// We could have folded this instruction away already, making it dead.
|
|
|
|
// If so, erase it.
|
|
|
|
if (isTriviallyDead(MI, MRI)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Is dead; erasing.\n");
|
2021-12-06 03:55:20 +08:00
|
|
|
MI.eraseFromParent();
|
2017-03-20 00:13:00 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-01-29 04:27:30 +08:00
|
|
|
// Eliminate hints.
|
|
|
|
if (isPreISelGenericOptimizationHint(MI.getOpcode())) {
|
|
|
|
Register DstReg = MI.getOperand(0).getReg();
|
|
|
|
Register SrcReg = MI.getOperand(1).getReg();
|
2021-01-30 07:33:23 +08:00
|
|
|
|
|
|
|
// At this point, the destination register class of the hint may have
|
|
|
|
// been decided.
|
|
|
|
//
|
|
|
|
// Propagate that through to the source register.
|
|
|
|
const TargetRegisterClass *DstRC = MRI.getRegClassOrNull(DstReg);
|
|
|
|
if (DstRC)
|
|
|
|
MRI.setRegClass(SrcReg, DstRC);
|
|
|
|
assert(canReplaceReg(DstReg, SrcReg, MRI) &&
|
|
|
|
"Must be able to replace dst with src!");
|
2021-01-29 04:27:30 +08:00
|
|
|
MI.eraseFromParent();
|
|
|
|
MRI.replaceRegWith(DstReg, SrcReg);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-08-13 14:26:59 +08:00
|
|
|
if (!ISel->select(MI)) {
|
2017-02-24 05:05:42 +08:00
|
|
|
// FIXME: It would be nice to dump all inserted instructions. It's
|
|
|
|
// not obvious how, esp. considering select() can insert after MI.
|
|
|
|
reportGISelFailure(MF, TPC, MORE, "gisel-select", "cannot select", MI);
|
2017-02-24 03:17:24 +08:00
|
|
|
return false;
|
2016-08-27 10:38:24 +08:00
|
|
|
}
|
2016-11-09 03:27:13 +08:00
|
|
|
|
|
|
|
// Dump the range of instructions that MI expanded into.
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG({
|
2016-11-09 03:27:13 +08:00
|
|
|
auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII);
|
|
|
|
dbgs() << "Into:\n";
|
|
|
|
for (auto &InsertedMI : make_range(InsertedBegin, AfterIt))
|
|
|
|
dbgs() << " " << InsertedMI;
|
|
|
|
dbgs() << '\n';
|
|
|
|
});
|
2016-07-27 22:31:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-24 09:35:26 +08:00
|
|
|
for (MachineBasicBlock &MBB : MF) {
|
|
|
|
if (MBB.empty())
|
|
|
|
continue;
|
|
|
|
|
2021-10-06 08:41:21 +08:00
|
|
|
if (!SelectedBlocks.contains(&MBB)) {
|
|
|
|
// This is an unreachable block and therefore hasn't been selected, since
|
|
|
|
// the main selection loop above uses a postorder block traversal.
|
|
|
|
// We delete all the instructions in this block since it's unreachable.
|
|
|
|
MBB.clear();
|
|
|
|
// Don't delete the block in case the block has it's address taken or is
|
|
|
|
// still being referenced by a phi somewhere.
|
|
|
|
continue;
|
|
|
|
}
|
2018-01-24 09:35:26 +08:00
|
|
|
// Try to find redundant copies b/w vregs of the same register class.
|
|
|
|
bool ReachedBegin = false;
|
|
|
|
for (auto MII = std::prev(MBB.end()), Begin = MBB.begin(); !ReachedBegin;) {
|
|
|
|
// Select this instruction.
|
|
|
|
MachineInstr &MI = *MII;
|
|
|
|
|
|
|
|
// And have our iterator point to the next instruction, if there is one.
|
|
|
|
if (MII == Begin)
|
|
|
|
ReachedBegin = true;
|
|
|
|
else
|
|
|
|
--MII;
|
|
|
|
if (MI.getOpcode() != TargetOpcode::COPY)
|
|
|
|
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-16 03:22:08 +08:00
|
|
|
Register SrcReg = MI.getOperand(1).getReg();
|
|
|
|
Register DstReg = MI.getOperand(0).getReg();
|
2019-08-02 07:27:28 +08:00
|
|
|
if (Register::isVirtualRegister(SrcReg) &&
|
|
|
|
Register::isVirtualRegister(DstReg)) {
|
2018-01-24 09:35:26 +08:00
|
|
|
auto SrcRC = MRI.getRegClass(SrcReg);
|
|
|
|
auto DstRC = MRI.getRegClass(DstReg);
|
|
|
|
if (SrcRC == DstRC) {
|
|
|
|
MRI.replaceRegWith(DstReg, SrcReg);
|
2020-01-29 16:44:02 +08:00
|
|
|
MI.eraseFromParent();
|
2018-01-24 09:35:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-16 09:02:10 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
|
2016-11-09 04:39:03 +08:00
|
|
|
// Now that selection is complete, there are no more generic vregs. Verify
|
|
|
|
// that the size of the now-constrained vreg is unchanged and that it has a
|
|
|
|
// register class.
|
2018-05-24 05:12:02 +08:00
|
|
|
for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
|
2019-08-02 07:27:28 +08:00
|
|
|
unsigned VReg = Register::index2VirtReg(I);
|
2018-05-24 05:12:02 +08:00
|
|
|
|
2017-01-31 03:12:50 +08:00
|
|
|
MachineInstr *MI = nullptr;
|
2017-01-31 04:52:37 +08:00
|
|
|
if (!MRI.def_empty(VReg))
|
2017-01-31 03:12:50 +08:00
|
|
|
MI = &*MRI.def_instr_begin(VReg);
|
2021-12-06 03:55:20 +08:00
|
|
|
else if (!MRI.use_empty(VReg)) {
|
2017-01-31 03:12:50 +08:00
|
|
|
MI = &*MRI.use_instr_begin(VReg);
|
2021-12-06 03:55:20 +08:00
|
|
|
// Debug value instruction is permitted to use undefined vregs.
|
|
|
|
if (MI->isDebugValue())
|
|
|
|
continue;
|
|
|
|
}
|
2018-05-24 05:12:02 +08:00
|
|
|
if (!MI)
|
|
|
|
continue;
|
2017-01-31 03:12:50 +08:00
|
|
|
|
2018-05-24 05:12:02 +08:00
|
|
|
const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg);
|
|
|
|
if (!RC) {
|
2017-02-24 05:05:42 +08:00
|
|
|
reportGISelFailure(MF, TPC, MORE, "gisel-select",
|
|
|
|
"VReg has no regclass after selection", *MI);
|
2017-02-24 03:17:24 +08:00
|
|
|
return false;
|
2018-05-24 05:12:02 +08:00
|
|
|
}
|
2016-11-09 04:39:03 +08:00
|
|
|
|
2018-05-24 05:12:02 +08:00
|
|
|
const LLT Ty = MRI.getType(VReg);
|
|
|
|
if (Ty.isValid() && Ty.getSizeInBits() > TRI.getRegSizeInBits(*RC)) {
|
|
|
|
reportGISelFailure(
|
|
|
|
MF, TPC, MORE, "gisel-select",
|
|
|
|
"VReg's low-level type and register class have different sizes", *MI);
|
2017-02-24 03:17:24 +08:00
|
|
|
return false;
|
2016-11-09 04:39:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-24 03:17:24 +08:00
|
|
|
if (MF.size() != NumBlocks) {
|
2017-02-24 05:05:42 +08:00
|
|
|
MachineOptimizationRemarkMissed R("gisel-select", "GISelFailure",
|
2017-12-16 06:22:58 +08:00
|
|
|
MF.getFunction().getSubprogram(),
|
2017-02-24 08:34:44 +08:00
|
|
|
/*MBB=*/nullptr);
|
2017-02-24 05:05:42 +08:00
|
|
|
R << "inserting blocks is not supported yet";
|
|
|
|
reportGISelFailure(MF, TPC, MORE, R);
|
2016-08-27 10:38:24 +08:00
|
|
|
return false;
|
|
|
|
}
|
2019-03-16 09:02:10 +08:00
|
|
|
#endif
|
2019-09-21 07:52:07 +08:00
|
|
|
// Determine if there are any calls in this machine function. Ported from
|
|
|
|
// SelectionDAG.
|
|
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
for (const auto &MBB : MF) {
|
|
|
|
if (MFI.hasCalls() && MF.hasInlineAsm())
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (const auto &MI : MBB) {
|
|
|
|
if ((MI.isCall() && !MI.isReturn()) || MI.isStackAligningInlineAsm())
|
|
|
|
MFI.setHasCalls(true);
|
|
|
|
if (MI.isInlineAsm())
|
|
|
|
MF.setHasInlineAsm(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-06 11:21:30 +08:00
|
|
|
// FIXME: FinalizeISel pass calls finalizeLowering, so it's called twice.
|
|
|
|
auto &TLI = *MF.getSubtarget().getTargetLowering();
|
|
|
|
TLI.finalizeLowering(MF);
|
2019-09-21 07:52:07 +08:00
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG({
|
2018-04-27 04:22:17 +08:00
|
|
|
dbgs() << "Rules covered by selecting function: " << MF.getName() << ":";
|
|
|
|
for (auto RuleID : CoverageInfo.covered())
|
|
|
|
dbgs() << " id" << RuleID;
|
|
|
|
dbgs() << "\n\n";
|
|
|
|
});
|
[globalisel][tablegen] Generate rule coverage and use it to identify untested rules
Summary:
This patch adds a LLVM_ENABLE_GISEL_COV which, like LLVM_ENABLE_DAGISEL_COV,
causes TableGen to instrument the generated table to collect rule coverage
information. However, LLVM_ENABLE_GISEL_COV goes a bit further than
LLVM_ENABLE_DAGISEL_COV. The information is written to files
(${CMAKE_BINARY_DIR}/gisel-coverage-* by default). These files can then be
concatenated into ${LLVM_GISEL_COV_PREFIX}-all after which TableGen will
read this information and use it to emit warnings about untested rules.
This technique could also be used by SelectionDAG and can be further
extended to detect hot rules and give them priority over colder rules.
Usage:
* Enable LLVM_ENABLE_GISEL_COV in CMake
* Build the compiler and run some tests
* cat gisel-coverage-[0-9]* > gisel-coverage-all
* Delete lib/Target/*/*GenGlobalISel.inc*
* Build the compiler
Known issues:
* ${LLVM_GISEL_COV_PREFIX}-all must be generated as a manual
step due to a lack of a portable 'cat' command. It should be the
concatenation of all ${LLVM_GISEL_COV_PREFIX}-[0-9]* files.
* There's no mechanism to discard coverage information when the ruleset
changes
Depends on D39742
Reviewers: ab, qcolombet, t.p.northover, aditya_nandakumar, rovka
Reviewed By: rovka
Subscribers: vsk, arsenm, nhaehnle, mgorny, kristof.beyls, javed.absar, igorb, llvm-commits
Differential Revision: https://reviews.llvm.org/D39747
llvm-svn: 318356
2017-11-16 08:46:35 +08:00
|
|
|
CoverageInfo.emit(CoveragePrefix,
|
2020-07-06 11:21:30 +08:00
|
|
|
TLI.getTargetMachine().getTarget().getBackendName());
|
[globalisel][tablegen] Generate rule coverage and use it to identify untested rules
Summary:
This patch adds a LLVM_ENABLE_GISEL_COV which, like LLVM_ENABLE_DAGISEL_COV,
causes TableGen to instrument the generated table to collect rule coverage
information. However, LLVM_ENABLE_GISEL_COV goes a bit further than
LLVM_ENABLE_DAGISEL_COV. The information is written to files
(${CMAKE_BINARY_DIR}/gisel-coverage-* by default). These files can then be
concatenated into ${LLVM_GISEL_COV_PREFIX}-all after which TableGen will
read this information and use it to emit warnings about untested rules.
This technique could also be used by SelectionDAG and can be further
extended to detect hot rules and give them priority over colder rules.
Usage:
* Enable LLVM_ENABLE_GISEL_COV in CMake
* Build the compiler and run some tests
* cat gisel-coverage-[0-9]* > gisel-coverage-all
* Delete lib/Target/*/*GenGlobalISel.inc*
* Build the compiler
Known issues:
* ${LLVM_GISEL_COV_PREFIX}-all must be generated as a manual
step due to a lack of a portable 'cat' command. It should be the
concatenation of all ${LLVM_GISEL_COV_PREFIX}-[0-9]* files.
* There's no mechanism to discard coverage information when the ruleset
changes
Depends on D39742
Reviewers: ab, qcolombet, t.p.northover, aditya_nandakumar, rovka
Reviewed By: rovka
Subscribers: vsk, arsenm, nhaehnle, mgorny, kristof.beyls, javed.absar, igorb, llvm-commits
Differential Revision: https://reviews.llvm.org/D39747
llvm-svn: 318356
2017-11-16 08:46:35 +08:00
|
|
|
|
[GlobalISel] Print/Parse FailedISel MachineFunction property
FailedISel MachineFunction property is part of the CodeGen pipeline
state as much as every other property, notably, Legalized,
RegBankSelected, and Selected. Let's make that part of the state also
serializable / de-serializable, so if GlobalISel aborts on some of the
functions of a large module, but not the others, it could be easily seen
and the state of the pipeline could be maintained through llc's
invocations with -stop-after / -start-after.
To make MIR printable and generally to not to break it too much too
soon, this patch also defers cleaning up the vreg -> LLT map until
ResetMachineFunctionPass.
To make MIR with FailedISel: true also machine verifiable, machine
verifier is changed so it treats a MIR-module as non-regbankselected and
non-selected if there is FailedISel property set.
Reviewers: qcolombet, ab
Reviewed By: dsanders
Subscribers: javed.absar, rovka, kristof.beyls, llvm-commits
Differential Revision: https://reviews.llvm.org/D42877
llvm-svn: 326343
2018-03-01 01:55:45 +08:00
|
|
|
// If we successfully selected the function nothing is going to use the vreg
|
|
|
|
// types after us (otherwise MIRPrinter would need them). Make sure the types
|
|
|
|
// disappear.
|
2018-05-24 05:12:02 +08:00
|
|
|
MRI.clearVirtRegTypes();
|
[GlobalISel] Print/Parse FailedISel MachineFunction property
FailedISel MachineFunction property is part of the CodeGen pipeline
state as much as every other property, notably, Legalized,
RegBankSelected, and Selected. Let's make that part of the state also
serializable / de-serializable, so if GlobalISel aborts on some of the
functions of a large module, but not the others, it could be easily seen
and the state of the pipeline could be maintained through llc's
invocations with -stop-after / -start-after.
To make MIR printable and generally to not to break it too much too
soon, this patch also defers cleaning up the vreg -> LLT map until
ResetMachineFunctionPass.
To make MIR with FailedISel: true also machine verifiable, machine
verifier is changed so it treats a MIR-module as non-regbankselected and
non-selected if there is FailedISel property set.
Reviewers: qcolombet, ab
Reviewed By: dsanders
Subscribers: javed.absar, rovka, kristof.beyls, llvm-commits
Differential Revision: https://reviews.llvm.org/D42877
llvm-svn: 326343
2018-03-01 01:55:45 +08:00
|
|
|
|
2016-07-27 22:31:55 +08:00
|
|
|
// FIXME: Should we accurately track changes?
|
|
|
|
return true;
|
|
|
|
}
|