2012-02-18 20:03:15 +08:00
|
|
|
//===-- ARMSubtarget.cpp - ARM Subtarget Information ----------------------===//
|
2007-01-19 15:51:42 +08:00
|
|
|
//
|
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
|
2007-01-19 15:51:42 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2011-07-02 05:01:15 +08:00
|
|
|
// This file implements the ARM specific subclass of TargetSubtargetInfo.
|
2007-01-19 15:51:42 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-07-01 08:45:45 +08:00
|
|
|
#include "ARM.h"
|
|
|
|
|
|
|
|
#include "ARMCallLowering.h"
|
|
|
|
#include "ARMLegalizerInfo.h"
|
|
|
|
#include "ARMRegisterBankInfo.h"
|
2007-01-19 15:51:42 +08:00
|
|
|
#include "ARMSubtarget.h"
|
2014-06-27 03:30:02 +08:00
|
|
|
#include "ARMFrameLowering.h"
|
|
|
|
#include "ARMInstrInfo.h"
|
|
|
|
#include "ARMSubtarget.h"
|
2014-12-18 10:20:58 +08:00
|
|
|
#include "ARMTargetMachine.h"
|
2017-01-28 07:58:02 +08:00
|
|
|
#include "MCTargetDesc/ARMMCTargetDesc.h"
|
2014-06-27 03:30:02 +08:00
|
|
|
#include "Thumb1FrameLowering.h"
|
|
|
|
#include "Thumb1InstrInfo.h"
|
|
|
|
#include "Thumb2InstrInfo.h"
|
2017-01-28 07:58:02 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/Triple.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
2017-07-01 08:45:45 +08:00
|
|
|
#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
|
2017-01-28 07:58:02 +08:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2013-02-16 06:41:25 +08:00
|
|
|
#include "llvm/IR/Function.h"
|
2014-01-07 19:48:04 +08:00
|
|
|
#include "llvm/IR/GlobalValue.h"
|
2015-11-19 05:10:39 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2017-01-28 07:58:02 +08:00
|
|
|
#include "llvm/MC/MCTargetOptions.h"
|
|
|
|
#include "llvm/Support/CodeGen.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2016-08-17 10:08:28 +08:00
|
|
|
#include "llvm/Support/TargetParser.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/Target/TargetOptions.h"
|
2011-07-02 04:45:01 +08:00
|
|
|
|
2014-04-22 10:03:14 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 06:55:11 +08:00
|
|
|
#define DEBUG_TYPE "arm-subtarget"
|
|
|
|
|
2011-07-02 04:45:01 +08:00
|
|
|
#define GET_SUBTARGETINFO_TARGET_DESC
|
2011-07-08 09:53:10 +08:00
|
|
|
#define GET_SUBTARGETINFO_CTOR
|
2011-07-02 06:36:09 +08:00
|
|
|
#include "ARMGenSubtargetInfo.inc"
|
2011-07-02 04:45:01 +08:00
|
|
|
|
2012-09-30 05:43:49 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
UseFusedMulOps("arm-use-mulops",
|
|
|
|
cl::init(true), cl::Hidden);
|
|
|
|
|
2013-11-14 02:29:49 +08:00
|
|
|
enum ITMode {
|
|
|
|
DefaultIT,
|
|
|
|
RestrictedIT,
|
|
|
|
NoRestrictedIT
|
|
|
|
};
|
|
|
|
|
|
|
|
static cl::opt<ITMode>
|
|
|
|
IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT),
|
|
|
|
cl::ZeroOrMore,
|
|
|
|
cl::values(clEnumValN(DefaultIT, "arm-default-it",
|
|
|
|
"Generate IT block based on arch"),
|
|
|
|
clEnumValN(RestrictedIT, "arm-restrict-it",
|
|
|
|
"Disallow deprecated IT based on ARMv8"),
|
|
|
|
clEnumValN(NoRestrictedIT, "arm-no-restrict-it",
|
2016-10-09 03:41:06 +08:00
|
|
|
"Allow IT blocks based on ARMv7")));
|
2013-11-14 02:29:49 +08:00
|
|
|
|
2015-09-23 17:19:54 +08:00
|
|
|
/// ForceFastISel - Use the fast-isel, even for subtargets where it is not
|
|
|
|
/// currently supported (for testing only).
|
|
|
|
static cl::opt<bool>
|
|
|
|
ForceFastISel("arm-force-fast-isel",
|
|
|
|
cl::init(false), cl::Hidden);
|
|
|
|
|
[LiveInterval] Allow updating subranges with slightly out-dated IR
During register coalescing, we update the live-intervals on-the-fly.
To do that we are in this strange mode where the live-intervals can
be slightly out-of-sync (more precisely they are forward looking)
compared to what the IR actually represents.
This happens because the register coalescer only updates the IR when
it is done with updating the live-intervals and it has to do it this
way because updating the IR on-the-fly would actually clobber some
information on how the live-ranges that are being updated look like.
This is problematic for updates that rely on the IR to accurately
represents the state of the live-ranges. Right now, we have only
one of those: stripValuesNotDefiningMask.
To reconcile this need of out-of-sync IR, this patch introduces a
new argument to LiveInterval::refineSubRanges that allows the code
doing the live range updates to reason about how the code should
look like after the coalescer will have rewritten the registers.
Essentially this captures how a subregister index with be offseted
to match its position in a new register class.
E.g., let say we want to merge:
V1.sub1:<2 x s32> = COPY V2.sub3:<4 x s32>
We do that by choosing a class where sub1:<2 x s32> and sub3:<4 x s32>
overlap, i.e., by choosing a class where we can find "offset + 1 == 3".
Put differently we align V2's sub3 with V1's sub1:
V2: sub0 sub1 sub2 sub3
V1: <offset> sub0 sub1
This offset will look like a composed subregidx in the the class:
V1.(composed sub2 with sub1):<4 x s32> = COPY V2.sub3:<4 x s32>
=> V1.(composed sub2 with sub1):<4 x s32> = COPY V2.sub3:<4 x s32>
Now if we didn't rewrite the uses and def of V1, all the checks for V1
need to account for this offset to match what the live intervals intend
to capture.
Prior to this patch, we would fail to recognize the uses and def of V1
and would end up with machine verifier errors: No live segment at def.
This could lead to miscompile as we would drop some live-ranges and
thus, miss some interferences.
For this problem to trigger, we need to reach stripValuesNotDefiningMask
while having a mismatch between the IR and the live-ranges (i.e.,
we have to apply a subreg offset to the IR.)
This requires the following three conditions:
1. An update of overlapping subreg lanes: e.g., dsub0 == <ssub0, ssub1>
2. An update with Tuple registers with a possibility to coalesce the
subreg index: e.g., v1.dsub_1 == v2.dsub_3
3. Subreg liveness enabled.
looking at the IR to decide what is alive and what is not, i.e., calling
stripValuesNotDefiningMask.
coalescer maintains for the live-ranges information.
None of the targets that currently use subreg liveness (i.e., the targets
that fulfill #3, Hexagon, AMDGPU, PowerPC, and SystemZ IIRC) expose #1 and
and #2, so this patch also artificial enables subreg liveness for ARM,
so that a nice test case can be attached.
2019-11-13 08:32:12 +08:00
|
|
|
static cl::opt<bool> EnableSubRegLiveness("arm-enable-subreg-liveness",
|
|
|
|
cl::init(false), cl::Hidden);
|
|
|
|
|
2014-06-13 08:20:35 +08:00
|
|
|
/// initializeSubtargetDependencies - Initializes using a CPU and feature string
|
|
|
|
/// so that we can use initializer lists for subtarget initialization.
|
|
|
|
ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU,
|
|
|
|
StringRef FS) {
|
2013-02-16 09:36:26 +08:00
|
|
|
initializeEnvironment();
|
2014-09-04 04:36:31 +08:00
|
|
|
initSubtargetFeatures(CPU, FS);
|
2014-06-13 08:20:35 +08:00
|
|
|
return *this;
|
2013-02-16 06:41:25 +08:00
|
|
|
}
|
|
|
|
|
2015-01-27 03:03:15 +08:00
|
|
|
ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU,
|
|
|
|
StringRef FS) {
|
|
|
|
ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS);
|
|
|
|
if (STI.isThumb1Only())
|
|
|
|
return (ARMFrameLowering *)new Thumb1FrameLowering(STI);
|
|
|
|
|
|
|
|
return new ARMFrameLowering(STI);
|
|
|
|
}
|
|
|
|
|
2015-06-10 20:11:26 +08:00
|
|
|
ARMSubtarget::ARMSubtarget(const Triple &TT, const std::string &CPU,
|
2015-01-27 03:03:15 +08:00
|
|
|
const std::string &FS,
|
2019-02-08 15:57:42 +08:00
|
|
|
const ARMBaseTargetMachine &TM, bool IsLittle,
|
|
|
|
bool MinSize)
|
2016-06-27 21:06:10 +08:00
|
|
|
: ARMGenSubtargetInfo(TT, CPU, FS), UseMulOps(UseFusedMulOps),
|
2019-11-30 01:01:05 +08:00
|
|
|
CPUString(CPU), OptMinSize(MinSize), IsLittle(IsLittle),
|
|
|
|
TargetTriple(TT), Options(TM.Options), TM(TM),
|
2019-02-08 15:57:42 +08:00
|
|
|
FrameLowering(initializeFrameLowering(CPU, FS)),
|
2015-01-27 03:03:15 +08:00
|
|
|
// At this point initializeSubtargetDependencies has been called so
|
|
|
|
// we can query directly.
|
2014-06-27 03:30:02 +08:00
|
|
|
InstrInfo(isThumb1Only()
|
|
|
|
? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this)
|
|
|
|
: !isThumb()
|
|
|
|
? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)
|
|
|
|
: (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)),
|
2017-07-01 08:45:45 +08:00
|
|
|
TLInfo(TM, *this) {
|
2017-07-01 11:41:53 +08:00
|
|
|
|
2017-08-16 06:31:51 +08:00
|
|
|
CallLoweringInfo.reset(new ARMCallLowering(*getTargetLowering()));
|
|
|
|
Legalizer.reset(new ARMLegalizerInfo(*this));
|
2017-07-01 08:45:45 +08:00
|
|
|
|
|
|
|
auto *RBI = new ARMRegisterBankInfo(*getRegisterInfo());
|
|
|
|
|
|
|
|
// FIXME: At this point, we can't rely on Subtarget having RBI.
|
|
|
|
// It's awkward to mix passing RBI and the Subtarget; should we pass
|
|
|
|
// TII/TRI as well?
|
2017-08-16 06:31:51 +08:00
|
|
|
InstSelector.reset(createARMInstructionSelector(
|
2017-07-01 08:45:45 +08:00
|
|
|
*static_cast<const ARMBaseTargetMachine *>(&TM), *this, *RBI));
|
|
|
|
|
2017-08-16 06:31:51 +08:00
|
|
|
RegBankInfo.reset(RBI);
|
2017-07-01 08:45:45 +08:00
|
|
|
}
|
2016-11-11 16:27:37 +08:00
|
|
|
|
|
|
|
const CallLowering *ARMSubtarget::getCallLowering() const {
|
2017-08-16 06:31:51 +08:00
|
|
|
return CallLoweringInfo.get();
|
2016-11-11 16:27:37 +08:00
|
|
|
}
|
|
|
|
|
2019-08-13 14:26:59 +08:00
|
|
|
InstructionSelector *ARMSubtarget::getInstructionSelector() const {
|
2017-08-16 06:31:51 +08:00
|
|
|
return InstSelector.get();
|
2016-11-11 16:27:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const LegalizerInfo *ARMSubtarget::getLegalizerInfo() const {
|
2017-08-16 06:31:51 +08:00
|
|
|
return Legalizer.get();
|
2016-11-11 16:27:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const RegisterBankInfo *ARMSubtarget::getRegBankInfo() const {
|
2017-08-16 06:31:51 +08:00
|
|
|
return RegBankInfo.get();
|
2016-11-11 16:27:37 +08:00
|
|
|
}
|
2014-06-13 08:20:35 +08:00
|
|
|
|
2016-09-19 08:54:35 +08:00
|
|
|
bool ARMSubtarget::isXRaySupported() const {
|
|
|
|
// We don't currently suppport Thumb, but Windows requires Thumb.
|
|
|
|
return hasV6Ops() && hasARMOps() && !isTargetWindows();
|
|
|
|
}
|
|
|
|
|
2013-02-16 09:36:26 +08:00
|
|
|
void ARMSubtarget::initializeEnvironment() {
|
2015-11-19 05:10:39 +08:00
|
|
|
// MCAsmInfo isn't always present (e.g. in opt) so we can't initialize this
|
|
|
|
// directly from it, but we can try to make sure they're consistent when both
|
|
|
|
// available.
|
2017-09-29 03:04:14 +08:00
|
|
|
UseSjLjEH = (isTargetDarwin() && !isTargetWatchABI() &&
|
|
|
|
Options.ExceptionModel == ExceptionHandling::None) ||
|
|
|
|
Options.ExceptionModel == ExceptionHandling::SjLj;
|
2015-11-19 05:10:39 +08:00
|
|
|
assert((!TM.getMCAsmInfo() ||
|
|
|
|
(TM.getMCAsmInfo()->getExceptionHandlingType() ==
|
|
|
|
ExceptionHandling::SjLj) == UseSjLjEH) &&
|
|
|
|
"inconsistent sjlj choice between CodeGen and MC");
|
2013-02-16 09:36:26 +08:00
|
|
|
}
|
|
|
|
|
2014-09-04 04:36:31 +08:00
|
|
|
void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
|
2013-09-03 01:09:01 +08:00
|
|
|
if (CPUString.empty()) {
|
2015-10-29 06:46:43 +08:00
|
|
|
CPUString = "generic";
|
|
|
|
|
|
|
|
if (isTargetDarwin()) {
|
|
|
|
StringRef ArchName = TargetTriple.getArchName();
|
[TargetParser] Use enum classes for various ARM kind enums.
Summary:
Using c++11 enum classes ensures that only valid enum values are used
for ArchKind, ProfileKind, VersionKind and ISAKind. This removes the
need for checks that the provided values map to a proper enum value,
allows us to get rid of AK_LAST and prevents comparing values from
different enums. It also removes a bunch of static_cast
from unsigned to enum values and vice versa, at the cost of introducing
static casts to access AArch64ARCHNames and ARMARCHNames by ArchKind.
FPUKind and ArchExtKind are the only remaining old-style enum in
TargetParser.h. I think it's beneficial to keep ArchExtKind as old-style
enum, but FPUKind can be converted too, but this patch is quite big, so
could do this in a follow-up patch. I could also split this patch up a
bit, if people would prefer that.
Reviewers: rengolin, javed.absar, chandlerc, rovka
Reviewed By: rovka
Subscribers: aemerson, kristof.beyls, llvm-commits
Differential Revision: https://reviews.llvm.org/D35882
llvm-svn: 309287
2017-07-28 00:27:56 +08:00
|
|
|
ARM::ArchKind AK = ARM::parseArch(ArchName);
|
|
|
|
if (AK == ARM::ArchKind::ARMV7S)
|
2015-10-29 06:46:43 +08:00
|
|
|
// Default to the Swift CPU when targeting armv7s/thumbv7s.
|
|
|
|
CPUString = "swift";
|
[TargetParser] Use enum classes for various ARM kind enums.
Summary:
Using c++11 enum classes ensures that only valid enum values are used
for ArchKind, ProfileKind, VersionKind and ISAKind. This removes the
need for checks that the provided values map to a proper enum value,
allows us to get rid of AK_LAST and prevents comparing values from
different enums. It also removes a bunch of static_cast
from unsigned to enum values and vice versa, at the cost of introducing
static casts to access AArch64ARCHNames and ARMARCHNames by ArchKind.
FPUKind and ArchExtKind are the only remaining old-style enum in
TargetParser.h. I think it's beneficial to keep ArchExtKind as old-style
enum, but FPUKind can be converted too, but this patch is quite big, so
could do this in a follow-up patch. I could also split this patch up a
bit, if people would prefer that.
Reviewers: rengolin, javed.absar, chandlerc, rovka
Reviewed By: rovka
Subscribers: aemerson, kristof.beyls, llvm-commits
Differential Revision: https://reviews.llvm.org/D35882
llvm-svn: 309287
2017-07-28 00:27:56 +08:00
|
|
|
else if (AK == ARM::ArchKind::ARMV7K)
|
2015-10-29 06:46:43 +08:00
|
|
|
// Default to the Cortex-a7 CPU when targeting armv7k/thumbv7k.
|
|
|
|
// ARMv7k does not use SjLj exception handling.
|
|
|
|
CPUString = "cortex-a7";
|
|
|
|
}
|
2013-09-03 01:09:01 +08:00
|
|
|
}
|
2009-03-08 12:02:49 +08:00
|
|
|
|
2011-06-30 10:12:44 +08:00
|
|
|
// Insert the architecture feature derived from the target triple into the
|
|
|
|
// feature string. This is important for setting features that are implied
|
|
|
|
// based on the architecture version.
|
2015-09-16 00:17:27 +08:00
|
|
|
std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple, CPUString);
|
2011-07-07 08:08:19 +08:00
|
|
|
if (!FS.empty()) {
|
|
|
|
if (!ArchFS.empty())
|
2015-03-30 23:42:36 +08:00
|
|
|
ArchFS = (Twine(ArchFS) + "," + FS).str();
|
2011-07-07 08:08:19 +08:00
|
|
|
else
|
2020-01-29 03:23:46 +08:00
|
|
|
ArchFS = std::string(FS);
|
2011-07-07 08:08:19 +08:00
|
|
|
}
|
2011-07-07 15:07:08 +08:00
|
|
|
ParseSubtargetFeatures(CPUString, ArchFS);
|
2011-07-07 08:08:19 +08:00
|
|
|
|
2013-12-13 19:16:00 +08:00
|
|
|
// FIXME: This used enable V6T2 support implicitly for Thumb2 mode.
|
|
|
|
// Assert this for now to make the change obvious.
|
|
|
|
assert(hasV6T2Ops() || !hasThumb2());
|
2010-11-10 06:50:47 +08:00
|
|
|
|
2016-12-15 15:59:08 +08:00
|
|
|
// Execute only support requires movt support
|
2018-09-28 16:55:19 +08:00
|
|
|
if (genExecuteOnly()) {
|
|
|
|
NoMovt = false;
|
|
|
|
assert(hasV8MBaselineOps() && "Cannot generate execute-only code for this target");
|
|
|
|
}
|
2016-12-15 15:59:08 +08:00
|
|
|
|
2012-08-08 10:44:16 +08:00
|
|
|
// Keep a pointer to static instruction cost data for the specified CPU.
|
|
|
|
SchedModel = getSchedModelForCPU(CPUString);
|
|
|
|
|
2011-07-02 04:45:01 +08:00
|
|
|
// Initialize scheduling itinerary for the specified CPU.
|
|
|
|
InstrItins = getInstrItineraryForCPU(CPUString);
|
|
|
|
|
2014-04-03 04:32:05 +08:00
|
|
|
// FIXME: this is invalid for WindowsCE
|
2014-12-18 10:08:45 +08:00
|
|
|
if (isTargetWindows())
|
2014-04-03 04:32:05 +08:00
|
|
|
NoARM = true;
|
|
|
|
|
2007-02-14 03:52:28 +08:00
|
|
|
if (isAAPCS_ABI())
|
[Alignment][NFC] Use Align for TargetFrameLowering/Subtarget
Summary:
This is patch is part of a series to introduce an Alignment type.
See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html
See this patch for the introduction of the type: https://reviews.llvm.org/D64790
Reviewers: courbet
Subscribers: jholewinski, arsenm, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, hiraditya, aheejin, kbarton, fedor.sergeev, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, jsji, Jim, lenary, s.egerton, pzheng, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68993
llvm-svn: 375084
2019-10-17 15:49:39 +08:00
|
|
|
stackAlignment = Align(8);
|
2015-10-29 06:46:43 +08:00
|
|
|
if (isTargetNaCl() || isAAPCS16_ABI())
|
[Alignment][NFC] Use Align for TargetFrameLowering/Subtarget
Summary:
This is patch is part of a series to introduce an Alignment type.
See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html
See this patch for the introduction of the type: https://reviews.llvm.org/D64790
Reviewers: courbet
Subscribers: jholewinski, arsenm, dschuff, jyknight, dylanmckay, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, hiraditya, aheejin, kbarton, fedor.sergeev, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, jsji, Jim, lenary, s.egerton, pzheng, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68993
llvm-svn: 375084
2019-10-17 15:49:39 +08:00
|
|
|
stackAlignment = Align(16);
|
2007-02-14 03:52:28 +08:00
|
|
|
|
2015-09-28 17:44:11 +08:00
|
|
|
// FIXME: Completely disable sibcall for Thumb1 since ThumbRegisterInfo::
|
|
|
|
// emitEpilogue is not ready for them. Thumb tail calls also use t2B, as
|
|
|
|
// the Thumb1 16-bit unconditional branch doesn't have sufficient relocation
|
|
|
|
// support in the assembler and linker to be used. This would need to be
|
|
|
|
// fixed to fully support tail calls in Thumb1.
|
|
|
|
//
|
2017-02-03 19:15:53 +08:00
|
|
|
// For ARMv8-M, we /do/ implement tail calls. Doing this is tricky for v8-M
|
|
|
|
// baseline, since the LDM/POP instruction on Thumb doesn't take LR. This
|
|
|
|
// means if we need to reload LR, it takes extra instructions, which outweighs
|
|
|
|
// the value of the tail call; but here we don't know yet whether LR is going
|
[ARM] Fix incorrect conversion of a tail call to an ordinary call
When we emit a tail call for Armv8-M, but then discover that the caller needs to
save/restore `LR`, we convert the tail call to an ordinary one, since restoring
`LR` takes extra instructions, which may negate the benefits of the tail
call. If the callee, however, takes stack arguments, this conversion is
incorrect, since nothing has been done to pass the stack arguments.
Thus the patch reverts https://reviews.llvm.org/rL294000
Also, we improve the instruction sequence for popping `LR` in the case when we
couldn't immediately find a scratch low register, but we can use as a temporary
one of the callee-saved low registers and restore `LR` before popping other
callee-saves.
Differential Revision: https://reviews.llvm.org/D39599
llvm-svn: 318143
2017-11-14 18:36:52 +08:00
|
|
|
// to be used. We take the optimistic approach of generating the tail call and
|
|
|
|
// perhaps taking a hit if we need to restore the LR.
|
2015-09-28 17:44:11 +08:00
|
|
|
|
|
|
|
// Thumb1 PIC calls to external symbols use BX, so they can be tail calls,
|
|
|
|
// but we need to make sure there are enough registers; the only valid
|
|
|
|
// registers are the 4 used for parameters. We don't currently do this
|
|
|
|
// case.
|
|
|
|
|
2016-01-15 18:26:17 +08:00
|
|
|
SupportsTailCall = !isThumb() || hasV8MBaselineOps();
|
2015-09-28 17:44:11 +08:00
|
|
|
|
|
|
|
if (isTargetMachO() && isTargetIOS() && getTargetTriple().isOSVersionLT(5, 0))
|
|
|
|
SupportsTailCall = false;
|
2009-10-02 05:46:35 +08:00
|
|
|
|
2013-11-14 02:29:49 +08:00
|
|
|
switch (IT) {
|
|
|
|
case DefaultIT:
|
2015-04-14 23:32:58 +08:00
|
|
|
RestrictIT = hasV8Ops();
|
2013-11-14 02:29:49 +08:00
|
|
|
break;
|
|
|
|
case RestrictedIT:
|
|
|
|
RestrictIT = true;
|
|
|
|
break;
|
|
|
|
case NoRestrictedIT:
|
|
|
|
RestrictIT = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-03-22 02:47:47 +08:00
|
|
|
// NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
|
2015-05-26 18:47:10 +08:00
|
|
|
const FeatureBitset &Bits = getFeatureBits();
|
|
|
|
if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters
|
2013-03-22 02:47:47 +08:00
|
|
|
(Options.UnsafeFPMath || isTargetDarwin()))
|
|
|
|
UseNEONForSinglePrecisionFP = true;
|
2016-06-27 17:08:23 +08:00
|
|
|
|
2019-11-30 01:01:05 +08:00
|
|
|
if (isRWPI())
|
|
|
|
ReserveR9 = true;
|
2016-08-08 23:28:31 +08:00
|
|
|
|
2019-08-14 02:12:08 +08:00
|
|
|
// If MVEVectorCostFactor is still 0 (has not been set to anything else), default it to 2
|
|
|
|
if (MVEVectorCostFactor == 0)
|
|
|
|
MVEVectorCostFactor = 2;
|
|
|
|
|
2016-06-27 17:08:23 +08:00
|
|
|
// FIXME: Teach TableGen to deal with these instead of doing it manually here.
|
|
|
|
switch (ARMProcFamily) {
|
|
|
|
case Others:
|
|
|
|
case CortexA5:
|
|
|
|
break;
|
|
|
|
case CortexA7:
|
|
|
|
LdStMultipleTiming = DoubleIssue;
|
|
|
|
break;
|
|
|
|
case CortexA8:
|
|
|
|
LdStMultipleTiming = DoubleIssue;
|
|
|
|
break;
|
|
|
|
case CortexA9:
|
|
|
|
LdStMultipleTiming = DoubleIssueCheckUnalignedAccess;
|
|
|
|
PreISelOperandLatencyAdjustment = 1;
|
|
|
|
break;
|
|
|
|
case CortexA12:
|
|
|
|
break;
|
|
|
|
case CortexA15:
|
|
|
|
MaxInterleaveFactor = 2;
|
|
|
|
PreISelOperandLatencyAdjustment = 1;
|
2016-07-06 19:22:11 +08:00
|
|
|
PartialUpdateClearance = 12;
|
2016-06-27 17:08:23 +08:00
|
|
|
break;
|
|
|
|
case CortexA17:
|
|
|
|
case CortexA32:
|
|
|
|
case CortexA35:
|
|
|
|
case CortexA53:
|
2017-08-21 16:43:06 +08:00
|
|
|
case CortexA55:
|
2016-06-27 17:08:23 +08:00
|
|
|
case CortexA57:
|
|
|
|
case CortexA72:
|
|
|
|
case CortexA73:
|
2017-08-21 16:43:06 +08:00
|
|
|
case CortexA75:
|
2019-02-25 23:08:27 +08:00
|
|
|
case CortexA76:
|
2016-06-27 17:08:23 +08:00
|
|
|
case CortexR4:
|
|
|
|
case CortexR4F:
|
|
|
|
case CortexR5:
|
|
|
|
case CortexR7:
|
|
|
|
case CortexM3:
|
2016-10-07 21:41:55 +08:00
|
|
|
case CortexR52:
|
2018-09-20 03:51:29 +08:00
|
|
|
break;
|
2018-09-20 03:43:23 +08:00
|
|
|
case Exynos:
|
2018-09-25 00:35:14 +08:00
|
|
|
LdStMultipleTiming = SingleIssuePlusExtras;
|
|
|
|
MaxInterleaveFactor = 4;
|
2018-09-20 03:51:29 +08:00
|
|
|
if (!isThumb())
|
[LLVM][Alignment] Make functions using log of alignment explicit
Summary:
This patch renames functions that takes or returns alignment as log2, this patch will help with the transition to llvm::Align.
The renaming makes it explicit that we deal with log(alignment) instead of a power of two alignment.
A few renames uncovered dubious assignments:
- `MirParser`/`MirPrinter` was expecting powers of two but `MachineFunction` and `MachineBasicBlock` were using deal with log2(align). This patch fixes it and updates the documentation.
- `MachineBlockPlacement` exposes two flags (`align-all-blocks` and `align-all-nofallthru-blocks`) supposedly interpreted as power of two alignments, internally these values are interpreted as log2(align). This patch updates the documentation,
- `MachineFunctionexposes` exposes `align-all-functions` also interpreted as power of two alignment, internally this value is interpreted as log2(align). This patch updates the documentation,
Reviewers: lattner, thegameg, courbet
Subscribers: dschuff, arsenm, jyknight, dylanmckay, sdardis, nemanjai, jvesely, nhaehnle, javed.absar, hiraditya, kbarton, fedor.sergeev, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, dexonsmith, PkmX, jocewei, jsji, Jim, s.egerton, llvm-commits, courbet
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65945
llvm-svn: 371045
2019-09-05 18:00:22 +08:00
|
|
|
PrefLoopLogAlignment = 3;
|
2018-09-20 03:51:29 +08:00
|
|
|
break;
|
2017-04-07 06:47:47 +08:00
|
|
|
case Kryo:
|
2016-06-27 17:08:23 +08:00
|
|
|
break;
|
|
|
|
case Krait:
|
|
|
|
PreISelOperandLatencyAdjustment = 1;
|
|
|
|
break;
|
[ARM][AArch64] Support for Cortex-A65 & A65AE, Neoverse E1 & N1
Summary:
Add support for Cortex-A65, Cortex-A65AE, Neoverse E1 and Neoverse N1.
Neoverse E1 and Cortex-A65(&AE) only implement the AArch64 state of the
Arm architecture. Neoverse N1 implements both AArch32 and AArch64.
Cortex-A65:
https://developer.arm.com/ip-products/processors/cortex-a/cortex-a65
Cortex-A65AE:
https://developer.arm.com/ip-products/processors/cortex-a/cortex-a65ae
Neoverse E1:
https://developer.arm.com/ip-products/processors/neoverse/neoverse-e1
Neoverse N1:
https://developer.arm.com/ip-products/processors/neoverse/neoverse-n1
Patch by Diogo Sampaio and Pablo Barrio
Reviewers: samparker, LukeCheeseman, sbaranga, ostannard
Reviewed By: ostannard
Subscribers: ostannard, javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64406
llvm-svn: 367007
2019-07-25 18:59:45 +08:00
|
|
|
case NeoverseN1:
|
|
|
|
break;
|
2016-06-27 17:08:23 +08:00
|
|
|
case Swift:
|
|
|
|
MaxInterleaveFactor = 2;
|
|
|
|
LdStMultipleTiming = SingleIssuePlusExtras;
|
|
|
|
PreISelOperandLatencyAdjustment = 1;
|
2016-07-06 19:22:11 +08:00
|
|
|
PartialUpdateClearance = 12;
|
2016-06-27 17:08:23 +08:00
|
|
|
break;
|
|
|
|
}
|
2007-01-19 15:51:42 +08:00
|
|
|
}
|
2009-08-29 07:18:09 +08:00
|
|
|
|
2018-07-18 20:36:25 +08:00
|
|
|
bool ARMSubtarget::isTargetHardFloat() const { return TM.isTargetHardFloat(); }
|
|
|
|
|
2014-12-18 10:20:58 +08:00
|
|
|
bool ARMSubtarget::isAPCS_ABI() const {
|
|
|
|
assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
|
|
|
|
return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_APCS;
|
|
|
|
}
|
|
|
|
bool ARMSubtarget::isAAPCS_ABI() const {
|
|
|
|
assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
|
2015-10-29 06:46:43 +08:00
|
|
|
return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS ||
|
|
|
|
TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16;
|
2014-12-18 10:20:58 +08:00
|
|
|
}
|
2015-10-29 06:46:43 +08:00
|
|
|
bool ARMSubtarget::isAAPCS16_ABI() const {
|
|
|
|
assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
|
|
|
|
return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16;
|
|
|
|
}
|
|
|
|
|
2016-08-08 23:28:31 +08:00
|
|
|
bool ARMSubtarget::isROPI() const {
|
|
|
|
return TM.getRelocationModel() == Reloc::ROPI ||
|
|
|
|
TM.getRelocationModel() == Reloc::ROPI_RWPI;
|
|
|
|
}
|
|
|
|
bool ARMSubtarget::isRWPI() const {
|
|
|
|
return TM.getRelocationModel() == Reloc::RWPI ||
|
|
|
|
TM.getRelocationModel() == Reloc::ROPI_RWPI;
|
|
|
|
}
|
|
|
|
|
2016-06-28 23:38:13 +08:00
|
|
|
bool ARMSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {
|
2016-06-28 07:15:57 +08:00
|
|
|
if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
|
2016-05-28 06:41:51 +08:00
|
|
|
return true;
|
2009-09-03 15:04:02 +08:00
|
|
|
|
2016-05-28 06:41:51 +08:00
|
|
|
// 32 bit macho has no relocation for a-b if a is undefined, even if b is in
|
|
|
|
// the section that is being relocated. This means we have to use o load even
|
|
|
|
// for GVs that are known to be local to the dso.
|
2016-08-25 03:02:29 +08:00
|
|
|
if (isTargetMachO() && TM.isPositionIndependent() &&
|
2016-05-28 06:41:51 +08:00
|
|
|
(GV->isDeclarationForLinker() || GV->hasCommonLinkage()))
|
2009-09-03 15:04:02 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
2009-08-29 07:18:09 +08:00
|
|
|
}
|
2009-11-10 08:48:55 +08:00
|
|
|
|
2017-11-14 04:45:38 +08:00
|
|
|
bool ARMSubtarget::isGVInGOT(const GlobalValue *GV) const {
|
|
|
|
return isTargetELF() && TM.isPositionIndependent() &&
|
|
|
|
!TM.shouldAssumeDSOLocal(*GV->getParent(), GV);
|
2017-08-29 17:47:55 +08:00
|
|
|
}
|
|
|
|
|
2010-09-29 05:57:50 +08:00
|
|
|
unsigned ARMSubtarget::getMispredictionPenalty() const {
|
2014-09-03 01:43:54 +08:00
|
|
|
return SchedModel.MispredictPenalty;
|
2010-09-29 05:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-07-18 07:18:30 +08:00
|
|
|
bool ARMSubtarget::enableMachineScheduler() const {
|
2019-05-15 20:58:02 +08:00
|
|
|
// The MachineScheduler can increase register usage, so we use more high
|
|
|
|
// registers and end up with more T2 instructions that cannot be converted to
|
|
|
|
// T1 instructions. At least until we do better at converting to thumb1
|
|
|
|
// instructions, on cortex-m at Oz where we are size-paranoid, don't use the
|
|
|
|
// Machine scheduler, relying on the DAG register pressure scheduler instead.
|
|
|
|
if (isMClass() && hasMinSize())
|
|
|
|
return false;
|
2017-07-28 03:56:44 +08:00
|
|
|
// Enable the MachineScheduler before register allocation for subtargets
|
|
|
|
// with the use-misched feature.
|
|
|
|
return useMachineScheduler();
|
2015-07-18 07:18:30 +08:00
|
|
|
}
|
|
|
|
|
[LiveInterval] Allow updating subranges with slightly out-dated IR
During register coalescing, we update the live-intervals on-the-fly.
To do that we are in this strange mode where the live-intervals can
be slightly out-of-sync (more precisely they are forward looking)
compared to what the IR actually represents.
This happens because the register coalescer only updates the IR when
it is done with updating the live-intervals and it has to do it this
way because updating the IR on-the-fly would actually clobber some
information on how the live-ranges that are being updated look like.
This is problematic for updates that rely on the IR to accurately
represents the state of the live-ranges. Right now, we have only
one of those: stripValuesNotDefiningMask.
To reconcile this need of out-of-sync IR, this patch introduces a
new argument to LiveInterval::refineSubRanges that allows the code
doing the live range updates to reason about how the code should
look like after the coalescer will have rewritten the registers.
Essentially this captures how a subregister index with be offseted
to match its position in a new register class.
E.g., let say we want to merge:
V1.sub1:<2 x s32> = COPY V2.sub3:<4 x s32>
We do that by choosing a class where sub1:<2 x s32> and sub3:<4 x s32>
overlap, i.e., by choosing a class where we can find "offset + 1 == 3".
Put differently we align V2's sub3 with V1's sub1:
V2: sub0 sub1 sub2 sub3
V1: <offset> sub0 sub1
This offset will look like a composed subregidx in the the class:
V1.(composed sub2 with sub1):<4 x s32> = COPY V2.sub3:<4 x s32>
=> V1.(composed sub2 with sub1):<4 x s32> = COPY V2.sub3:<4 x s32>
Now if we didn't rewrite the uses and def of V1, all the checks for V1
need to account for this offset to match what the live intervals intend
to capture.
Prior to this patch, we would fail to recognize the uses and def of V1
and would end up with machine verifier errors: No live segment at def.
This could lead to miscompile as we would drop some live-ranges and
thus, miss some interferences.
For this problem to trigger, we need to reach stripValuesNotDefiningMask
while having a mismatch between the IR and the live-ranges (i.e.,
we have to apply a subreg offset to the IR.)
This requires the following three conditions:
1. An update of overlapping subreg lanes: e.g., dsub0 == <ssub0, ssub1>
2. An update with Tuple registers with a possibility to coalesce the
subreg index: e.g., v1.dsub_1 == v2.dsub_3
3. Subreg liveness enabled.
looking at the IR to decide what is alive and what is not, i.e., calling
stripValuesNotDefiningMask.
coalescer maintains for the live-ranges information.
None of the targets that currently use subreg liveness (i.e., the targets
that fulfill #3, Hexagon, AMDGPU, PowerPC, and SystemZ IIRC) expose #1 and
and #2, so this patch also artificial enables subreg liveness for ARM,
so that a nice test case can be attached.
2019-11-13 08:32:12 +08:00
|
|
|
bool ARMSubtarget::enableSubRegLiveness() const { return EnableSubRegLiveness; }
|
|
|
|
|
2014-07-16 06:39:58 +08:00
|
|
|
// This overrides the PostRAScheduler bit in the SchedModel for any CPU.
|
2015-06-13 11:42:16 +08:00
|
|
|
bool ARMSubtarget::enablePostRAScheduler() const {
|
2019-11-05 17:10:58 +08:00
|
|
|
if (enableMachineScheduler())
|
|
|
|
return false;
|
|
|
|
if (disablePostRAScheduler())
|
|
|
|
return false;
|
|
|
|
// Thumb1 cores will generally not benefit from post-ra scheduling
|
|
|
|
return !isThumb1Only();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ARMSubtarget::enablePostRAMachineScheduler() const {
|
|
|
|
if (!enableMachineScheduler())
|
|
|
|
return false;
|
2017-08-31 16:57:51 +08:00
|
|
|
if (disablePostRAScheduler())
|
2015-07-18 07:18:30 +08:00
|
|
|
return false;
|
2017-08-31 16:57:51 +08:00
|
|
|
return !isThumb1Only();
|
2014-06-04 15:06:27 +08:00
|
|
|
}
|
|
|
|
|
2016-11-04 05:49:08 +08:00
|
|
|
bool ARMSubtarget::enableAtomicExpand() const { return hasAnyDataBarrier(); }
|
2014-06-20 05:03:04 +08:00
|
|
|
|
2019-02-08 15:57:42 +08:00
|
|
|
bool ARMSubtarget::useStride4VFPs() const {
|
2015-10-29 06:56:36 +08:00
|
|
|
// For general targets, the prologue can grow when VFPs are allocated with
|
|
|
|
// stride 4 (more vpush instructions). But WatchOS uses a compact unwind
|
|
|
|
// format which it's more important to get right.
|
2018-08-10 00:13:24 +08:00
|
|
|
return isTargetWatchABI() ||
|
2019-02-08 15:57:42 +08:00
|
|
|
(useWideStrideVFP() && !OptMinSize);
|
2015-08-04 01:20:10 +08:00
|
|
|
}
|
|
|
|
|
2019-02-08 15:57:42 +08:00
|
|
|
bool ARMSubtarget::useMovt() const {
|
2014-07-04 09:55:26 +08:00
|
|
|
// NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit
|
|
|
|
// immediates as it is inherently position independent, and may be out of
|
|
|
|
// range otherwise.
|
2016-01-15 18:25:14 +08:00
|
|
|
return !NoMovt && hasV8MBaselineOps() &&
|
2019-02-08 15:57:42 +08:00
|
|
|
(isTargetWindows() || !OptMinSize || genExecuteOnly());
|
2014-07-04 09:55:26 +08:00
|
|
|
}
|
2015-05-23 09:14:08 +08:00
|
|
|
|
|
|
|
bool ARMSubtarget::useFastISel() const {
|
2015-09-23 17:19:54 +08:00
|
|
|
// Enable fast-isel for any target, for testing only.
|
|
|
|
if (ForceFastISel)
|
|
|
|
return true;
|
|
|
|
|
2015-09-19 04:08:18 +08:00
|
|
|
// Limit fast-isel to the targets that are or have been tested.
|
|
|
|
if (!hasV6Ops())
|
|
|
|
return false;
|
|
|
|
|
2015-05-23 09:14:08 +08:00
|
|
|
// Thumb2 support on iOS; ARM support on iOS, Linux and NaCl.
|
|
|
|
return TM.Options.EnableFastISel &&
|
|
|
|
((isTargetMachO() && !isThumb1Only()) ||
|
|
|
|
(isTargetLinux() && !isThumb()) || (isTargetNaCl() && !isThumb()));
|
|
|
|
}
|
[ARM] Thumb2: favor R4-R7 over R12/LR in allocation order when opt for minsize
For Thumb2, we prefer low regs (costPerUse = 0) to allow narrow
encoding. However, current allocation order is like:
R0-R3, R12, LR, R4-R11
As a result, a lot of instructs that use R12/LR will be wide instrs.
This patch changes the allocation order to:
R0-R7, R12, LR, R8-R11
for thumb2 and -Osize.
In most cases, there is no extra push/pop instrs as they will be folded
into existing ones. There might be slight performance impact due to more
stack usage, so we only enable it when opt for min size.
https://reviews.llvm.org/D30324
llvm-svn: 365014
2019-07-03 17:58:52 +08:00
|
|
|
|
|
|
|
unsigned ARMSubtarget::getGPRAllocationOrder(const MachineFunction &MF) const {
|
|
|
|
// The GPR register class has multiple possible allocation orders, with
|
|
|
|
// tradeoffs preferred by different sub-architectures and optimisation goals.
|
|
|
|
// The allocation orders are:
|
|
|
|
// 0: (the default tablegen order, not used)
|
|
|
|
// 1: r14, r0-r13
|
|
|
|
// 2: r0-r7
|
|
|
|
// 3: r0-r7, r12, lr, r8-r11
|
|
|
|
// Note that the register allocator will change this order so that
|
|
|
|
// callee-saved registers are used later, as they require extra work in the
|
|
|
|
// prologue/epilogue (though we sometimes override that).
|
|
|
|
|
|
|
|
// For thumb1-only targets, only the low registers are allocatable.
|
|
|
|
if (isThumb1Only())
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
// Allocate low registers first, so we can select more 16-bit instructions.
|
|
|
|
// We also (in ignoreCSRForAllocationOrder) override the default behaviour
|
|
|
|
// with regards to callee-saved registers, because pushing extra registers is
|
|
|
|
// much cheaper (in terms of code size) than using high registers. After
|
|
|
|
// that, we allocate r12 (doesn't need to be saved), lr (saving it means we
|
|
|
|
// can return with the pop, don't need an extra "bx lr") and then the rest of
|
|
|
|
// the high registers.
|
|
|
|
if (isThumb2() && MF.getFunction().hasMinSize())
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
// Otherwise, allocate in the default order, using LR first because saving it
|
|
|
|
// allows a shorter epilogue sequence.
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ARMSubtarget::ignoreCSRForAllocationOrder(const MachineFunction &MF,
|
|
|
|
unsigned PhysReg) const {
|
|
|
|
// To minimize code size in Thumb2, we prefer the usage of low regs (lower
|
|
|
|
// cost per use) so we can use narrow encoding. By default, caller-saved
|
|
|
|
// registers (e.g. lr, r12) are always allocated first, regardless of
|
|
|
|
// their cost per use. When optForMinSize, we prefer the low regs even if
|
|
|
|
// they are CSR because usually push/pop can be folded into existing ones.
|
|
|
|
return isThumb2() && MF.getFunction().hasMinSize() &&
|
|
|
|
ARM::GPRRegClass.contains(PhysReg);
|
|
|
|
}
|