mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[globalisel][legalizer] Separate the deprecated LegalizerInfo from the current one
It's still in use in a few places so we can't delete it yet but there's not many at this point. Differential Revision: https://reviews.llvm.org/D103352
This commit is contained in:
parent
b0a805b25d
commit
71a22fb7f8
479
include/llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h
Normal file
479
include/llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
//===- llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h ------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
/// \file
|
||||||
|
/// Interface for Targets to specify which operations they can successfully
|
||||||
|
/// select and how the others should be expanded most efficiently.
|
||||||
|
/// This implementation has been deprecated for a long time but it still in use
|
||||||
|
/// in a few places.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
|
||||||
|
#define LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/CodeGen/TargetOpcodes.h"
|
||||||
|
#include "llvm/Support/LowLevelTypeImpl.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
struct LegalityQuery;
|
||||||
|
|
||||||
|
namespace LegacyLegalizeActions {
|
||||||
|
enum LegacyLegalizeAction : std::uint8_t {
|
||||||
|
/// The operation is expected to be selectable directly by the target, and
|
||||||
|
/// no transformation is necessary.
|
||||||
|
Legal,
|
||||||
|
|
||||||
|
/// The operation should be synthesized from multiple instructions acting on
|
||||||
|
/// a narrower scalar base-type. For example a 64-bit add might be
|
||||||
|
/// implemented in terms of 32-bit add-with-carry.
|
||||||
|
NarrowScalar,
|
||||||
|
|
||||||
|
/// The operation should be implemented in terms of a wider scalar
|
||||||
|
/// base-type. For example a <2 x s8> add could be implemented as a <2
|
||||||
|
/// x s32> add (ignoring the high bits).
|
||||||
|
WidenScalar,
|
||||||
|
|
||||||
|
/// The (vector) operation should be implemented by splitting it into
|
||||||
|
/// sub-vectors where the operation is legal. For example a <8 x s64> add
|
||||||
|
/// might be implemented as 4 separate <2 x s64> adds.
|
||||||
|
FewerElements,
|
||||||
|
|
||||||
|
/// The (vector) operation should be implemented by widening the input
|
||||||
|
/// vector and ignoring the lanes added by doing so. For example <2 x i8> is
|
||||||
|
/// rarely legal, but you might perform an <8 x i8> and then only look at
|
||||||
|
/// the first two results.
|
||||||
|
MoreElements,
|
||||||
|
|
||||||
|
/// Perform the operation on a different, but equivalently sized type.
|
||||||
|
Bitcast,
|
||||||
|
|
||||||
|
/// The operation itself must be expressed in terms of simpler actions on
|
||||||
|
/// this target. E.g. a SREM replaced by an SDIV and subtraction.
|
||||||
|
Lower,
|
||||||
|
|
||||||
|
/// The operation should be implemented as a call to some kind of runtime
|
||||||
|
/// support library. For example this usually happens on machines that don't
|
||||||
|
/// support floating-point operations natively.
|
||||||
|
Libcall,
|
||||||
|
|
||||||
|
/// The target wants to do something special with this combination of
|
||||||
|
/// operand and type. A callback will be issued when it is needed.
|
||||||
|
Custom,
|
||||||
|
|
||||||
|
/// This operation is completely unsupported on the target. A programming
|
||||||
|
/// error has occurred.
|
||||||
|
Unsupported,
|
||||||
|
|
||||||
|
/// Sentinel value for when no action was found in the specified table.
|
||||||
|
NotFound,
|
||||||
|
};
|
||||||
|
} // end namespace LegacyLegalizeActions
|
||||||
|
|
||||||
|
/// Legalization is decided based on an instruction's opcode, which type slot
|
||||||
|
/// we're considering, and what the existing type is. These aspects are gathered
|
||||||
|
/// together for convenience in the InstrAspect class.
|
||||||
|
struct InstrAspect {
|
||||||
|
unsigned Opcode;
|
||||||
|
unsigned Idx = 0;
|
||||||
|
LLT Type;
|
||||||
|
|
||||||
|
InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {}
|
||||||
|
InstrAspect(unsigned Opcode, unsigned Idx, LLT Type)
|
||||||
|
: Opcode(Opcode), Idx(Idx), Type(Type) {}
|
||||||
|
|
||||||
|
bool operator==(const InstrAspect &RHS) const {
|
||||||
|
return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The result of a query. It either indicates a final answer of Legal or
|
||||||
|
/// Unsupported or describes an action that must be taken to make an operation
|
||||||
|
/// more legal.
|
||||||
|
struct LegacyLegalizeActionStep {
|
||||||
|
/// The action to take or the final answer.
|
||||||
|
LegacyLegalizeActions::LegacyLegalizeAction Action;
|
||||||
|
/// If describing an action, the type index to change. Otherwise zero.
|
||||||
|
unsigned TypeIdx;
|
||||||
|
/// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
|
||||||
|
LLT NewType;
|
||||||
|
|
||||||
|
LegacyLegalizeActionStep(LegacyLegalizeActions::LegacyLegalizeAction Action,
|
||||||
|
unsigned TypeIdx, const LLT NewType)
|
||||||
|
: Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
|
||||||
|
|
||||||
|
bool operator==(const LegacyLegalizeActionStep &RHS) const {
|
||||||
|
return std::tie(Action, TypeIdx, NewType) ==
|
||||||
|
std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LegacyLegalizerInfo {
|
||||||
|
public:
|
||||||
|
using SizeAndAction =
|
||||||
|
std::pair<uint16_t, LegacyLegalizeActions::LegacyLegalizeAction>;
|
||||||
|
using SizeAndActionsVec = std::vector<SizeAndAction>;
|
||||||
|
using SizeChangeStrategy =
|
||||||
|
std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
|
||||||
|
|
||||||
|
LegacyLegalizerInfo();
|
||||||
|
|
||||||
|
static bool needsLegalizingToDifferentSize(
|
||||||
|
const LegacyLegalizeActions::LegacyLegalizeAction Action) {
|
||||||
|
using namespace LegacyLegalizeActions;
|
||||||
|
switch (Action) {
|
||||||
|
case NarrowScalar:
|
||||||
|
case WidenScalar:
|
||||||
|
case FewerElements:
|
||||||
|
case MoreElements:
|
||||||
|
case Unsupported:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute any ancillary tables needed to quickly decide how an operation
|
||||||
|
/// should be handled. This must be called after all "set*Action"methods but
|
||||||
|
/// before any query is made or incorrect results may be returned.
|
||||||
|
void computeTables();
|
||||||
|
|
||||||
|
/// More friendly way to set an action for common types that have an LLT
|
||||||
|
/// representation.
|
||||||
|
/// The LegacyLegalizeAction must be one for which
|
||||||
|
/// NeedsLegalizingToDifferentSize returns false.
|
||||||
|
void setAction(const InstrAspect &Aspect,
|
||||||
|
LegacyLegalizeActions::LegacyLegalizeAction Action) {
|
||||||
|
assert(!needsLegalizingToDifferentSize(Action));
|
||||||
|
TablesInitialized = false;
|
||||||
|
const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
|
||||||
|
if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx)
|
||||||
|
SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1);
|
||||||
|
SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The setAction calls record the non-size-changing legalization actions
|
||||||
|
/// to take on specificly-sized types. The SizeChangeStrategy defines what
|
||||||
|
/// to do when the size of the type needs to be changed to reach a legally
|
||||||
|
/// sized type (i.e., one that was defined through a setAction call).
|
||||||
|
/// e.g.
|
||||||
|
/// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
|
||||||
|
/// setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
/// G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
|
||||||
|
/// will end up defining getAction({G_ADD, 0, T}) to return the following
|
||||||
|
/// actions for different scalar types T:
|
||||||
|
/// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)}
|
||||||
|
/// LLT::scalar(32): {Legal, 0, LLT::scalar(32)}
|
||||||
|
/// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)}
|
||||||
|
///
|
||||||
|
/// If no SizeChangeAction gets defined, through this function,
|
||||||
|
/// the default is unsupportedForDifferentSizes.
|
||||||
|
void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,
|
||||||
|
const unsigned TypeIdx,
|
||||||
|
SizeChangeStrategy S) {
|
||||||
|
const unsigned OpcodeIdx = Opcode - FirstOp;
|
||||||
|
if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
|
||||||
|
ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
|
||||||
|
ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also setLegalizeScalarToDifferentSizeStrategy.
|
||||||
|
/// This function allows to set the SizeChangeStrategy for vector elements.
|
||||||
|
void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode,
|
||||||
|
const unsigned TypeIdx,
|
||||||
|
SizeChangeStrategy S) {
|
||||||
|
const unsigned OpcodeIdx = Opcode - FirstOp;
|
||||||
|
if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
|
||||||
|
VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
|
||||||
|
VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A SizeChangeStrategy for the common case where legalization for a
|
||||||
|
/// particular operation consists of only supporting a specific set of type
|
||||||
|
/// sizes. E.g.
|
||||||
|
/// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
|
||||||
|
/// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
|
||||||
|
/// setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
/// G_DIV, 0, unsupportedForDifferentSizes);
|
||||||
|
/// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,
|
||||||
|
/// and Unsupported for all other scalar types T.
|
||||||
|
static SizeAndActionsVec
|
||||||
|
unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
|
||||||
|
using namespace LegacyLegalizeActions;
|
||||||
|
return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
|
||||||
|
Unsupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A SizeChangeStrategy for the common case where legalization for a
|
||||||
|
/// particular operation consists of widening the type to a large legal type,
|
||||||
|
/// unless there is no such type and then instead it should be narrowed to the
|
||||||
|
/// largest legal type.
|
||||||
|
static SizeAndActionsVec
|
||||||
|
widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
|
||||||
|
using namespace LegacyLegalizeActions;
|
||||||
|
assert(v.size() > 0 &&
|
||||||
|
"At least one size that can be legalized towards is needed"
|
||||||
|
" for this SizeChangeStrategy");
|
||||||
|
return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
|
||||||
|
NarrowScalar);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SizeAndActionsVec
|
||||||
|
widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
|
||||||
|
using namespace LegacyLegalizeActions;
|
||||||
|
return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
|
||||||
|
Unsupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SizeAndActionsVec
|
||||||
|
narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) {
|
||||||
|
using namespace LegacyLegalizeActions;
|
||||||
|
return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
|
||||||
|
Unsupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SizeAndActionsVec
|
||||||
|
narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) {
|
||||||
|
using namespace LegacyLegalizeActions;
|
||||||
|
assert(v.size() > 0 &&
|
||||||
|
"At least one size that can be legalized towards is needed"
|
||||||
|
" for this SizeChangeStrategy");
|
||||||
|
return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
|
||||||
|
WidenScalar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A SizeChangeStrategy for the common case where legalization for a
|
||||||
|
/// particular vector operation consists of having more elements in the
|
||||||
|
/// vector, to a type that is legal. Unless there is no such type and then
|
||||||
|
/// instead it should be legalized towards the widest vector that's still
|
||||||
|
/// legal. E.g.
|
||||||
|
/// setAction({G_ADD, LLT::vector(8, 8)}, Legal);
|
||||||
|
/// setAction({G_ADD, LLT::vector(16, 8)}, Legal);
|
||||||
|
/// setAction({G_ADD, LLT::vector(2, 32)}, Legal);
|
||||||
|
/// setAction({G_ADD, LLT::vector(4, 32)}, Legal);
|
||||||
|
/// setLegalizeVectorElementToDifferentSizeStrategy(
|
||||||
|
/// G_ADD, 0, moreToWiderTypesAndLessToWidest);
|
||||||
|
/// will result in the following getAction results:
|
||||||
|
/// * getAction({G_ADD, LLT::vector(8,8)}) returns
|
||||||
|
/// (Legal, vector(8,8)).
|
||||||
|
/// * getAction({G_ADD, LLT::vector(9,8)}) returns
|
||||||
|
/// (MoreElements, vector(16,8)).
|
||||||
|
/// * getAction({G_ADD, LLT::vector(8,32)}) returns
|
||||||
|
/// (FewerElements, vector(4,32)).
|
||||||
|
static SizeAndActionsVec
|
||||||
|
moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
|
||||||
|
using namespace LegacyLegalizeActions;
|
||||||
|
return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
|
||||||
|
FewerElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to implement many typical SizeChangeStrategy functions.
|
||||||
|
static SizeAndActionsVec increaseToLargerTypesAndDecreaseToLargest(
|
||||||
|
const SizeAndActionsVec &v,
|
||||||
|
LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction,
|
||||||
|
LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction);
|
||||||
|
/// Helper function to implement many typical SizeChangeStrategy functions.
|
||||||
|
static SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest(
|
||||||
|
const SizeAndActionsVec &v,
|
||||||
|
LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction,
|
||||||
|
LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction);
|
||||||
|
|
||||||
|
LegacyLegalizeActionStep getAction(const LegalityQuery &Query) const;
|
||||||
|
|
||||||
|
unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Determine what action should be taken to legalize the given generic
|
||||||
|
/// instruction opcode, type-index and type. Requires computeTables to have
|
||||||
|
/// been called.
|
||||||
|
///
|
||||||
|
/// \returns a pair consisting of the kind of legalization that should be
|
||||||
|
/// performed and the destination type.
|
||||||
|
std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
|
||||||
|
getAspectAction(const InstrAspect &Aspect) const;
|
||||||
|
|
||||||
|
/// The SizeAndActionsVec is a representation mapping between all natural
|
||||||
|
/// numbers and an Action. The natural number represents the bit size of
|
||||||
|
/// the InstrAspect. For example, for a target with native support for 32-bit
|
||||||
|
/// and 64-bit additions, you'd express that as:
|
||||||
|
/// setScalarAction(G_ADD, 0,
|
||||||
|
/// {{1, WidenScalar}, // bit sizes [ 1, 31[
|
||||||
|
/// {32, Legal}, // bit sizes [32, 33[
|
||||||
|
/// {33, WidenScalar}, // bit sizes [33, 64[
|
||||||
|
/// {64, Legal}, // bit sizes [64, 65[
|
||||||
|
/// {65, NarrowScalar} // bit sizes [65, +inf[
|
||||||
|
/// });
|
||||||
|
/// It may be that only 64-bit pointers are supported on your target:
|
||||||
|
/// setPointerAction(G_PTR_ADD, 0, LLT:pointer(1),
|
||||||
|
/// {{1, Unsupported}, // bit sizes [ 1, 63[
|
||||||
|
/// {64, Legal}, // bit sizes [64, 65[
|
||||||
|
/// {65, Unsupported}, // bit sizes [65, +inf[
|
||||||
|
/// });
|
||||||
|
void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,
|
||||||
|
const SizeAndActionsVec &SizeAndActions) {
|
||||||
|
const unsigned OpcodeIdx = Opcode - FirstOp;
|
||||||
|
SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx];
|
||||||
|
setActions(TypeIndex, Actions, SizeAndActions);
|
||||||
|
}
|
||||||
|
void setPointerAction(const unsigned Opcode, const unsigned TypeIndex,
|
||||||
|
const unsigned AddressSpace,
|
||||||
|
const SizeAndActionsVec &SizeAndActions) {
|
||||||
|
const unsigned OpcodeIdx = Opcode - FirstOp;
|
||||||
|
if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) ==
|
||||||
|
AddrSpace2PointerActions[OpcodeIdx].end())
|
||||||
|
AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}};
|
||||||
|
SmallVector<SizeAndActionsVec, 1> &Actions =
|
||||||
|
AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)->second;
|
||||||
|
setActions(TypeIndex, Actions, SizeAndActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If an operation on a given vector type (say <M x iN>) isn't explicitly
|
||||||
|
/// specified, we proceed in 2 stages. First we legalize the underlying scalar
|
||||||
|
/// (so that there's at least one legal vector with that scalar), then we
|
||||||
|
/// adjust the number of elements in the vector so that it is legal. The
|
||||||
|
/// desired action in the first step is controlled by this function.
|
||||||
|
void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex,
|
||||||
|
const SizeAndActionsVec &SizeAndActions) {
|
||||||
|
unsigned OpcodeIdx = Opcode - FirstOp;
|
||||||
|
SmallVector<SizeAndActionsVec, 1> &Actions =
|
||||||
|
ScalarInVectorActions[OpcodeIdx];
|
||||||
|
setActions(TypeIndex, Actions, SizeAndActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also setScalarInVectorAction.
|
||||||
|
/// This function let's you specify the number of elements in a vector that
|
||||||
|
/// are legal for a legal element size.
|
||||||
|
void setVectorNumElementAction(const unsigned Opcode,
|
||||||
|
const unsigned TypeIndex,
|
||||||
|
const unsigned ElementSize,
|
||||||
|
const SizeAndActionsVec &SizeAndActions) {
|
||||||
|
const unsigned OpcodeIdx = Opcode - FirstOp;
|
||||||
|
if (NumElements2Actions[OpcodeIdx].find(ElementSize) ==
|
||||||
|
NumElements2Actions[OpcodeIdx].end())
|
||||||
|
NumElements2Actions[OpcodeIdx][ElementSize] = {{}};
|
||||||
|
SmallVector<SizeAndActionsVec, 1> &Actions =
|
||||||
|
NumElements2Actions[OpcodeIdx].find(ElementSize)->second;
|
||||||
|
setActions(TypeIndex, Actions, SizeAndActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
|
||||||
|
/// i.e. it's OK if it doesn't start from size 1.
|
||||||
|
static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) {
|
||||||
|
using namespace LegacyLegalizeActions;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// The sizes should be in increasing order
|
||||||
|
int prev_size = -1;
|
||||||
|
for(auto SizeAndAction: v) {
|
||||||
|
assert(SizeAndAction.first > prev_size);
|
||||||
|
prev_size = SizeAndAction.first;
|
||||||
|
}
|
||||||
|
// - for every Widen action, there should be a larger bitsize that
|
||||||
|
// can be legalized towards (e.g. Legal, Lower, Libcall or Custom
|
||||||
|
// action).
|
||||||
|
// - for every Narrow action, there should be a smaller bitsize that
|
||||||
|
// can be legalized towards.
|
||||||
|
int SmallestNarrowIdx = -1;
|
||||||
|
int LargestWidenIdx = -1;
|
||||||
|
int SmallestLegalizableToSameSizeIdx = -1;
|
||||||
|
int LargestLegalizableToSameSizeIdx = -1;
|
||||||
|
for(size_t i=0; i<v.size(); ++i) {
|
||||||
|
switch (v[i].second) {
|
||||||
|
case FewerElements:
|
||||||
|
case NarrowScalar:
|
||||||
|
if (SmallestNarrowIdx == -1)
|
||||||
|
SmallestNarrowIdx = i;
|
||||||
|
break;
|
||||||
|
case WidenScalar:
|
||||||
|
case MoreElements:
|
||||||
|
LargestWidenIdx = i;
|
||||||
|
break;
|
||||||
|
case Unsupported:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (SmallestLegalizableToSameSizeIdx == -1)
|
||||||
|
SmallestLegalizableToSameSizeIdx = i;
|
||||||
|
LargestLegalizableToSameSizeIdx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (SmallestNarrowIdx != -1) {
|
||||||
|
assert(SmallestLegalizableToSameSizeIdx != -1);
|
||||||
|
assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx);
|
||||||
|
}
|
||||||
|
if (LargestWidenIdx != -1)
|
||||||
|
assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with
|
||||||
|
/// from size 1.
|
||||||
|
static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Data structure invariant: The first bit size must be size 1.
|
||||||
|
assert(v.size() >= 1);
|
||||||
|
assert(v[0].first == 1);
|
||||||
|
checkPartialSizeAndActionsVector(v);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets actions for all bit sizes on a particular generic opcode, type
|
||||||
|
/// index and scalar or pointer type.
|
||||||
|
void setActions(unsigned TypeIndex,
|
||||||
|
SmallVector<SizeAndActionsVec, 1> &Actions,
|
||||||
|
const SizeAndActionsVec &SizeAndActions) {
|
||||||
|
checkFullSizeAndActionsVector(SizeAndActions);
|
||||||
|
if (Actions.size() <= TypeIndex)
|
||||||
|
Actions.resize(TypeIndex + 1);
|
||||||
|
Actions[TypeIndex] = SizeAndActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SizeAndAction findAction(const SizeAndActionsVec &Vec,
|
||||||
|
const uint32_t Size);
|
||||||
|
|
||||||
|
/// Returns the next action needed to get the scalar or pointer type closer
|
||||||
|
/// to being legal
|
||||||
|
/// E.g. findLegalAction({G_REM, 13}) should return
|
||||||
|
/// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
|
||||||
|
/// probably be called, which should return (Lower, 32).
|
||||||
|
/// This is assuming the setScalarAction on G_REM was something like:
|
||||||
|
/// setScalarAction(G_REM, 0,
|
||||||
|
/// {{1, WidenScalar}, // bit sizes [ 1, 31[
|
||||||
|
/// {32, Lower}, // bit sizes [32, 33[
|
||||||
|
/// {33, NarrowScalar} // bit sizes [65, +inf[
|
||||||
|
/// });
|
||||||
|
std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
|
||||||
|
findScalarLegalAction(const InstrAspect &Aspect) const;
|
||||||
|
|
||||||
|
/// Returns the next action needed towards legalizing the vector type.
|
||||||
|
std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
|
||||||
|
findVectorLegalAction(const InstrAspect &Aspect) const;
|
||||||
|
|
||||||
|
static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
|
||||||
|
static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
|
||||||
|
|
||||||
|
// Data structures used temporarily during construction of legality data:
|
||||||
|
using TypeMap = DenseMap<LLT, LegacyLegalizeActions::LegacyLegalizeAction>;
|
||||||
|
SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
|
||||||
|
SmallVector<SizeChangeStrategy, 1>
|
||||||
|
ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
|
||||||
|
SmallVector<SizeChangeStrategy, 1>
|
||||||
|
VectorElementSizeChangeStrategies[LastOp - FirstOp + 1];
|
||||||
|
bool TablesInitialized;
|
||||||
|
|
||||||
|
// Data structures used by getAction:
|
||||||
|
SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];
|
||||||
|
SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];
|
||||||
|
std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
|
||||||
|
AddrSpace2PointerActions[LastOp - FirstOp + 1];
|
||||||
|
std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
|
||||||
|
NumElements2Actions[LastOp - FirstOp + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
|
#endif // define LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
|
@ -20,6 +20,7 @@
|
|||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SmallBitVector.h"
|
#include "llvm/ADT/SmallBitVector.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/CodeGen/TargetOpcodes.h"
|
#include "llvm/CodeGen/TargetOpcodes.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
@ -100,23 +101,6 @@ raw_ostream &operator<<(raw_ostream &OS, LegalizeActions::LegalizeAction Action)
|
|||||||
|
|
||||||
using LegalizeActions::LegalizeAction;
|
using LegalizeActions::LegalizeAction;
|
||||||
|
|
||||||
/// Legalization is decided based on an instruction's opcode, which type slot
|
|
||||||
/// we're considering, and what the existing type is. These aspects are gathered
|
|
||||||
/// together for convenience in the InstrAspect class.
|
|
||||||
struct InstrAspect {
|
|
||||||
unsigned Opcode;
|
|
||||||
unsigned Idx = 0;
|
|
||||||
LLT Type;
|
|
||||||
|
|
||||||
InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {}
|
|
||||||
InstrAspect(unsigned Opcode, unsigned Idx, LLT Type)
|
|
||||||
: Opcode(Opcode), Idx(Idx), Type(Type) {}
|
|
||||||
|
|
||||||
bool operator==(const InstrAspect &RHS) const {
|
|
||||||
return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The LegalityQuery object bundles together all the information that's needed
|
/// The LegalityQuery object bundles together all the information that's needed
|
||||||
/// to decide whether a given operation is legal or not.
|
/// to decide whether a given operation is legal or not.
|
||||||
/// For efficiency, it doesn't make a copy of Types so care must be taken not
|
/// For efficiency, it doesn't make a copy of Types so care must be taken not
|
||||||
@ -159,6 +143,45 @@ struct LegalizeActionStep {
|
|||||||
const LLT NewType)
|
const LLT NewType)
|
||||||
: Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
|
: Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
|
||||||
|
|
||||||
|
LegalizeActionStep(LegacyLegalizeActionStep Step)
|
||||||
|
: TypeIdx(Step.TypeIdx), NewType(Step.NewType) {
|
||||||
|
switch (Step.Action) {
|
||||||
|
case LegacyLegalizeActions::Legal:
|
||||||
|
Action = LegalizeActions::Legal;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::NarrowScalar:
|
||||||
|
Action = LegalizeActions::NarrowScalar;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::WidenScalar:
|
||||||
|
Action = LegalizeActions::WidenScalar;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::FewerElements:
|
||||||
|
Action = LegalizeActions::FewerElements;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::MoreElements:
|
||||||
|
Action = LegalizeActions::MoreElements;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::Bitcast:
|
||||||
|
Action = LegalizeActions::Bitcast;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::Lower:
|
||||||
|
Action = LegalizeActions::Lower;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::Libcall:
|
||||||
|
Action = LegalizeActions::Libcall;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::Custom:
|
||||||
|
Action = LegalizeActions::Custom;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::Unsupported:
|
||||||
|
Action = LegalizeActions::Unsupported;
|
||||||
|
break;
|
||||||
|
case LegacyLegalizeActions::NotFound:
|
||||||
|
Action = LegalizeActions::NotFound;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const LegalizeActionStep &RHS) const {
|
bool operator==(const LegalizeActionStep &RHS) const {
|
||||||
return std::tie(Action, TypeIdx, NewType) ==
|
return std::tie(Action, TypeIdx, NewType) ==
|
||||||
std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
|
std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
|
||||||
@ -1057,179 +1080,20 @@ public:
|
|||||||
|
|
||||||
class LegalizerInfo {
|
class LegalizerInfo {
|
||||||
public:
|
public:
|
||||||
LegalizerInfo();
|
|
||||||
virtual ~LegalizerInfo() = default;
|
virtual ~LegalizerInfo() = default;
|
||||||
|
|
||||||
|
const LegacyLegalizerInfo &getLegacyLegalizerInfo() const {
|
||||||
|
return LegacyInfo;
|
||||||
|
}
|
||||||
|
LegacyLegalizerInfo &getLegacyLegalizerInfo() { return LegacyInfo; }
|
||||||
|
|
||||||
unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
|
unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
|
||||||
unsigned getActionDefinitionsIdx(unsigned Opcode) const;
|
unsigned getActionDefinitionsIdx(unsigned Opcode) const;
|
||||||
|
|
||||||
/// Compute any ancillary tables needed to quickly decide how an operation
|
|
||||||
/// should be handled. This must be called after all "set*Action"methods but
|
|
||||||
/// before any query is made or incorrect results may be returned.
|
|
||||||
void computeTables();
|
|
||||||
|
|
||||||
/// Perform simple self-diagnostic and assert if there is anything obviously
|
/// Perform simple self-diagnostic and assert if there is anything obviously
|
||||||
/// wrong with the actions set up.
|
/// wrong with the actions set up.
|
||||||
void verify(const MCInstrInfo &MII) const;
|
void verify(const MCInstrInfo &MII) const;
|
||||||
|
|
||||||
static bool needsLegalizingToDifferentSize(const LegalizeAction Action) {
|
|
||||||
using namespace LegalizeActions;
|
|
||||||
switch (Action) {
|
|
||||||
case NarrowScalar:
|
|
||||||
case WidenScalar:
|
|
||||||
case FewerElements:
|
|
||||||
case MoreElements:
|
|
||||||
case Unsupported:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using SizeAndAction = std::pair<uint16_t, LegalizeAction>;
|
|
||||||
using SizeAndActionsVec = std::vector<SizeAndAction>;
|
|
||||||
using SizeChangeStrategy =
|
|
||||||
std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
|
|
||||||
|
|
||||||
/// More friendly way to set an action for common types that have an LLT
|
|
||||||
/// representation.
|
|
||||||
/// The LegalizeAction must be one for which NeedsLegalizingToDifferentSize
|
|
||||||
/// returns false.
|
|
||||||
void setAction(const InstrAspect &Aspect, LegalizeAction Action) {
|
|
||||||
assert(!needsLegalizingToDifferentSize(Action));
|
|
||||||
TablesInitialized = false;
|
|
||||||
const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
|
|
||||||
if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx)
|
|
||||||
SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1);
|
|
||||||
SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The setAction calls record the non-size-changing legalization actions
|
|
||||||
/// to take on specificly-sized types. The SizeChangeStrategy defines what
|
|
||||||
/// to do when the size of the type needs to be changed to reach a legally
|
|
||||||
/// sized type (i.e., one that was defined through a setAction call).
|
|
||||||
/// e.g.
|
|
||||||
/// setAction ({G_ADD, 0, LLT::scalar(32)}, Legal);
|
|
||||||
/// setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
/// G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
|
|
||||||
/// will end up defining getAction({G_ADD, 0, T}) to return the following
|
|
||||||
/// actions for different scalar types T:
|
|
||||||
/// LLT::scalar(1)..LLT::scalar(31): {WidenScalar, 0, LLT::scalar(32)}
|
|
||||||
/// LLT::scalar(32): {Legal, 0, LLT::scalar(32)}
|
|
||||||
/// LLT::scalar(33)..: {NarrowScalar, 0, LLT::scalar(32)}
|
|
||||||
///
|
|
||||||
/// If no SizeChangeAction gets defined, through this function,
|
|
||||||
/// the default is unsupportedForDifferentSizes.
|
|
||||||
void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,
|
|
||||||
const unsigned TypeIdx,
|
|
||||||
SizeChangeStrategy S) {
|
|
||||||
const unsigned OpcodeIdx = Opcode - FirstOp;
|
|
||||||
if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
|
|
||||||
ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
|
|
||||||
ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also setLegalizeScalarToDifferentSizeStrategy.
|
|
||||||
/// This function allows to set the SizeChangeStrategy for vector elements.
|
|
||||||
void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode,
|
|
||||||
const unsigned TypeIdx,
|
|
||||||
SizeChangeStrategy S) {
|
|
||||||
const unsigned OpcodeIdx = Opcode - FirstOp;
|
|
||||||
if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
|
|
||||||
VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
|
|
||||||
VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A SizeChangeStrategy for the common case where legalization for a
|
|
||||||
/// particular operation consists of only supporting a specific set of type
|
|
||||||
/// sizes. E.g.
|
|
||||||
/// setAction ({G_DIV, 0, LLT::scalar(32)}, Legal);
|
|
||||||
/// setAction ({G_DIV, 0, LLT::scalar(64)}, Legal);
|
|
||||||
/// setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
/// G_DIV, 0, unsupportedForDifferentSizes);
|
|
||||||
/// will result in getAction({G_DIV, 0, T}) to return Legal for s32 and s64,
|
|
||||||
/// and Unsupported for all other scalar types T.
|
|
||||||
static SizeAndActionsVec
|
|
||||||
unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
|
|
||||||
using namespace LegalizeActions;
|
|
||||||
return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
|
|
||||||
Unsupported);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A SizeChangeStrategy for the common case where legalization for a
|
|
||||||
/// particular operation consists of widening the type to a large legal type,
|
|
||||||
/// unless there is no such type and then instead it should be narrowed to the
|
|
||||||
/// largest legal type.
|
|
||||||
static SizeAndActionsVec
|
|
||||||
widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
|
|
||||||
using namespace LegalizeActions;
|
|
||||||
assert(v.size() > 0 &&
|
|
||||||
"At least one size that can be legalized towards is needed"
|
|
||||||
" for this SizeChangeStrategy");
|
|
||||||
return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
|
|
||||||
NarrowScalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SizeAndActionsVec
|
|
||||||
widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
|
|
||||||
using namespace LegalizeActions;
|
|
||||||
return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
|
|
||||||
Unsupported);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SizeAndActionsVec
|
|
||||||
narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) {
|
|
||||||
using namespace LegalizeActions;
|
|
||||||
return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
|
|
||||||
Unsupported);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SizeAndActionsVec
|
|
||||||
narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) {
|
|
||||||
using namespace LegalizeActions;
|
|
||||||
assert(v.size() > 0 &&
|
|
||||||
"At least one size that can be legalized towards is needed"
|
|
||||||
" for this SizeChangeStrategy");
|
|
||||||
return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
|
|
||||||
WidenScalar);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A SizeChangeStrategy for the common case where legalization for a
|
|
||||||
/// particular vector operation consists of having more elements in the
|
|
||||||
/// vector, to a type that is legal. Unless there is no such type and then
|
|
||||||
/// instead it should be legalized towards the widest vector that's still
|
|
||||||
/// legal. E.g.
|
|
||||||
/// setAction({G_ADD, LLT::vector(8, 8)}, Legal);
|
|
||||||
/// setAction({G_ADD, LLT::vector(16, 8)}, Legal);
|
|
||||||
/// setAction({G_ADD, LLT::vector(2, 32)}, Legal);
|
|
||||||
/// setAction({G_ADD, LLT::vector(4, 32)}, Legal);
|
|
||||||
/// setLegalizeVectorElementToDifferentSizeStrategy(
|
|
||||||
/// G_ADD, 0, moreToWiderTypesAndLessToWidest);
|
|
||||||
/// will result in the following getAction results:
|
|
||||||
/// * getAction({G_ADD, LLT::vector(8,8)}) returns
|
|
||||||
/// (Legal, vector(8,8)).
|
|
||||||
/// * getAction({G_ADD, LLT::vector(9,8)}) returns
|
|
||||||
/// (MoreElements, vector(16,8)).
|
|
||||||
/// * getAction({G_ADD, LLT::vector(8,32)}) returns
|
|
||||||
/// (FewerElements, vector(4,32)).
|
|
||||||
static SizeAndActionsVec
|
|
||||||
moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
|
|
||||||
using namespace LegalizeActions;
|
|
||||||
return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
|
|
||||||
FewerElements);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper function to implement many typical SizeChangeStrategy functions.
|
|
||||||
static SizeAndActionsVec
|
|
||||||
increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec &v,
|
|
||||||
LegalizeAction IncreaseAction,
|
|
||||||
LegalizeAction DecreaseAction);
|
|
||||||
/// Helper function to implement many typical SizeChangeStrategy functions.
|
|
||||||
static SizeAndActionsVec
|
|
||||||
decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v,
|
|
||||||
LegalizeAction DecreaseAction,
|
|
||||||
LegalizeAction IncreaseAction);
|
|
||||||
|
|
||||||
/// Get the action definitions for the given opcode. Use this to run a
|
/// Get the action definitions for the given opcode. Use this to run a
|
||||||
/// LegalityQuery through the definitions.
|
/// LegalityQuery through the definitions.
|
||||||
const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const;
|
const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const;
|
||||||
@ -1306,191 +1170,11 @@ public:
|
|||||||
virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const;
|
virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Determine what action should be taken to legalize the given generic
|
|
||||||
/// instruction opcode, type-index and type. Requires computeTables to have
|
|
||||||
/// been called.
|
|
||||||
///
|
|
||||||
/// \returns a pair consisting of the kind of legalization that should be
|
|
||||||
/// performed and the destination type.
|
|
||||||
std::pair<LegalizeAction, LLT>
|
|
||||||
getAspectAction(const InstrAspect &Aspect) const;
|
|
||||||
|
|
||||||
/// The SizeAndActionsVec is a representation mapping between all natural
|
|
||||||
/// numbers and an Action. The natural number represents the bit size of
|
|
||||||
/// the InstrAspect. For example, for a target with native support for 32-bit
|
|
||||||
/// and 64-bit additions, you'd express that as:
|
|
||||||
/// setScalarAction(G_ADD, 0,
|
|
||||||
/// {{1, WidenScalar}, // bit sizes [ 1, 31[
|
|
||||||
/// {32, Legal}, // bit sizes [32, 33[
|
|
||||||
/// {33, WidenScalar}, // bit sizes [33, 64[
|
|
||||||
/// {64, Legal}, // bit sizes [64, 65[
|
|
||||||
/// {65, NarrowScalar} // bit sizes [65, +inf[
|
|
||||||
/// });
|
|
||||||
/// It may be that only 64-bit pointers are supported on your target:
|
|
||||||
/// setPointerAction(G_PTR_ADD, 0, LLT:pointer(1),
|
|
||||||
/// {{1, Unsupported}, // bit sizes [ 1, 63[
|
|
||||||
/// {64, Legal}, // bit sizes [64, 65[
|
|
||||||
/// {65, Unsupported}, // bit sizes [65, +inf[
|
|
||||||
/// });
|
|
||||||
void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,
|
|
||||||
const SizeAndActionsVec &SizeAndActions) {
|
|
||||||
const unsigned OpcodeIdx = Opcode - FirstOp;
|
|
||||||
SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx];
|
|
||||||
setActions(TypeIndex, Actions, SizeAndActions);
|
|
||||||
}
|
|
||||||
void setPointerAction(const unsigned Opcode, const unsigned TypeIndex,
|
|
||||||
const unsigned AddressSpace,
|
|
||||||
const SizeAndActionsVec &SizeAndActions) {
|
|
||||||
const unsigned OpcodeIdx = Opcode - FirstOp;
|
|
||||||
if (AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace) ==
|
|
||||||
AddrSpace2PointerActions[OpcodeIdx].end())
|
|
||||||
AddrSpace2PointerActions[OpcodeIdx][AddressSpace] = {{}};
|
|
||||||
SmallVector<SizeAndActionsVec, 1> &Actions =
|
|
||||||
AddrSpace2PointerActions[OpcodeIdx].find(AddressSpace)->second;
|
|
||||||
setActions(TypeIndex, Actions, SizeAndActions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If an operation on a given vector type (say <M x iN>) isn't explicitly
|
|
||||||
/// specified, we proceed in 2 stages. First we legalize the underlying scalar
|
|
||||||
/// (so that there's at least one legal vector with that scalar), then we
|
|
||||||
/// adjust the number of elements in the vector so that it is legal. The
|
|
||||||
/// desired action in the first step is controlled by this function.
|
|
||||||
void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex,
|
|
||||||
const SizeAndActionsVec &SizeAndActions) {
|
|
||||||
unsigned OpcodeIdx = Opcode - FirstOp;
|
|
||||||
SmallVector<SizeAndActionsVec, 1> &Actions =
|
|
||||||
ScalarInVectorActions[OpcodeIdx];
|
|
||||||
setActions(TypeIndex, Actions, SizeAndActions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also setScalarInVectorAction.
|
|
||||||
/// This function let's you specify the number of elements in a vector that
|
|
||||||
/// are legal for a legal element size.
|
|
||||||
void setVectorNumElementAction(const unsigned Opcode,
|
|
||||||
const unsigned TypeIndex,
|
|
||||||
const unsigned ElementSize,
|
|
||||||
const SizeAndActionsVec &SizeAndActions) {
|
|
||||||
const unsigned OpcodeIdx = Opcode - FirstOp;
|
|
||||||
if (NumElements2Actions[OpcodeIdx].find(ElementSize) ==
|
|
||||||
NumElements2Actions[OpcodeIdx].end())
|
|
||||||
NumElements2Actions[OpcodeIdx][ElementSize] = {{}};
|
|
||||||
SmallVector<SizeAndActionsVec, 1> &Actions =
|
|
||||||
NumElements2Actions[OpcodeIdx].find(ElementSize)->second;
|
|
||||||
setActions(TypeIndex, Actions, SizeAndActions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A partial SizeAndActionsVec potentially doesn't cover all bit sizes,
|
|
||||||
/// i.e. it's OK if it doesn't start from size 1.
|
|
||||||
static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) {
|
|
||||||
using namespace LegalizeActions;
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// The sizes should be in increasing order
|
|
||||||
int prev_size = -1;
|
|
||||||
for(auto SizeAndAction: v) {
|
|
||||||
assert(SizeAndAction.first > prev_size);
|
|
||||||
prev_size = SizeAndAction.first;
|
|
||||||
}
|
|
||||||
// - for every Widen action, there should be a larger bitsize that
|
|
||||||
// can be legalized towards (e.g. Legal, Lower, Libcall or Custom
|
|
||||||
// action).
|
|
||||||
// - for every Narrow action, there should be a smaller bitsize that
|
|
||||||
// can be legalized towards.
|
|
||||||
int SmallestNarrowIdx = -1;
|
|
||||||
int LargestWidenIdx = -1;
|
|
||||||
int SmallestLegalizableToSameSizeIdx = -1;
|
|
||||||
int LargestLegalizableToSameSizeIdx = -1;
|
|
||||||
for(size_t i=0; i<v.size(); ++i) {
|
|
||||||
switch (v[i].second) {
|
|
||||||
case FewerElements:
|
|
||||||
case NarrowScalar:
|
|
||||||
if (SmallestNarrowIdx == -1)
|
|
||||||
SmallestNarrowIdx = i;
|
|
||||||
break;
|
|
||||||
case WidenScalar:
|
|
||||||
case MoreElements:
|
|
||||||
LargestWidenIdx = i;
|
|
||||||
break;
|
|
||||||
case Unsupported:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (SmallestLegalizableToSameSizeIdx == -1)
|
|
||||||
SmallestLegalizableToSameSizeIdx = i;
|
|
||||||
LargestLegalizableToSameSizeIdx = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (SmallestNarrowIdx != -1) {
|
|
||||||
assert(SmallestLegalizableToSameSizeIdx != -1);
|
|
||||||
assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx);
|
|
||||||
}
|
|
||||||
if (LargestWidenIdx != -1)
|
|
||||||
assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A full SizeAndActionsVec must cover all bit sizes, i.e. must start with
|
|
||||||
/// from size 1.
|
|
||||||
static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) {
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// Data structure invariant: The first bit size must be size 1.
|
|
||||||
assert(v.size() >= 1);
|
|
||||||
assert(v[0].first == 1);
|
|
||||||
checkPartialSizeAndActionsVector(v);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets actions for all bit sizes on a particular generic opcode, type
|
|
||||||
/// index and scalar or pointer type.
|
|
||||||
void setActions(unsigned TypeIndex,
|
|
||||||
SmallVector<SizeAndActionsVec, 1> &Actions,
|
|
||||||
const SizeAndActionsVec &SizeAndActions) {
|
|
||||||
checkFullSizeAndActionsVector(SizeAndActions);
|
|
||||||
if (Actions.size() <= TypeIndex)
|
|
||||||
Actions.resize(TypeIndex + 1);
|
|
||||||
Actions[TypeIndex] = SizeAndActions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SizeAndAction findAction(const SizeAndActionsVec &Vec,
|
|
||||||
const uint32_t Size);
|
|
||||||
|
|
||||||
/// Returns the next action needed to get the scalar or pointer type closer
|
|
||||||
/// to being legal
|
|
||||||
/// E.g. findLegalAction({G_REM, 13}) should return
|
|
||||||
/// (WidenScalar, 32). After that, findLegalAction({G_REM, 32}) will
|
|
||||||
/// probably be called, which should return (Lower, 32).
|
|
||||||
/// This is assuming the setScalarAction on G_REM was something like:
|
|
||||||
/// setScalarAction(G_REM, 0,
|
|
||||||
/// {{1, WidenScalar}, // bit sizes [ 1, 31[
|
|
||||||
/// {32, Lower}, // bit sizes [32, 33[
|
|
||||||
/// {33, NarrowScalar} // bit sizes [65, +inf[
|
|
||||||
/// });
|
|
||||||
std::pair<LegalizeAction, LLT>
|
|
||||||
findScalarLegalAction(const InstrAspect &Aspect) const;
|
|
||||||
|
|
||||||
/// Returns the next action needed towards legalizing the vector type.
|
|
||||||
std::pair<LegalizeAction, LLT>
|
|
||||||
findVectorLegalAction(const InstrAspect &Aspect) const;
|
|
||||||
|
|
||||||
static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
|
static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
|
||||||
static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
|
static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
|
||||||
|
|
||||||
// Data structures used temporarily during construction of legality data:
|
|
||||||
using TypeMap = DenseMap<LLT, LegalizeAction>;
|
|
||||||
SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
|
|
||||||
SmallVector<SizeChangeStrategy, 1>
|
|
||||||
ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
|
|
||||||
SmallVector<SizeChangeStrategy, 1>
|
|
||||||
VectorElementSizeChangeStrategies[LastOp - FirstOp + 1];
|
|
||||||
bool TablesInitialized;
|
|
||||||
|
|
||||||
// Data structures used by getAction:
|
|
||||||
SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];
|
|
||||||
SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];
|
|
||||||
std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
|
|
||||||
AddrSpace2PointerActions[LastOp - FirstOp + 1];
|
|
||||||
std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
|
|
||||||
NumElements2Actions[LastOp - FirstOp + 1];
|
|
||||||
|
|
||||||
LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1];
|
LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1];
|
||||||
|
LegacyLegalizerInfo LegacyInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -16,6 +16,7 @@ add_llvm_component_library(LLVMGlobalISel
|
|||||||
Legalizer.cpp
|
Legalizer.cpp
|
||||||
LegalizerHelper.cpp
|
LegalizerHelper.cpp
|
||||||
LegalizerInfo.cpp
|
LegalizerInfo.cpp
|
||||||
|
LegacyLegalizerInfo.cpp
|
||||||
Localizer.cpp
|
Localizer.cpp
|
||||||
LostDebugLocObserver.cpp
|
LostDebugLocObserver.cpp
|
||||||
MachineIRBuilder.cpp
|
MachineIRBuilder.cpp
|
||||||
|
344
lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp
Normal file
344
lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
//===- lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp - Legalizer ---------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Implement an interface to specify and query how an illegal operation on a
|
||||||
|
// given type should be expanded.
|
||||||
|
//
|
||||||
|
// Issues to be resolved:
|
||||||
|
// + Make it fast.
|
||||||
|
// + Support weird types like i3, <7 x i3>, ...
|
||||||
|
// + Operations with more than one type (ICMP, CMPXCHG, intrinsics, ...)
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using namespace LegacyLegalizeActions;
|
||||||
|
|
||||||
|
#define DEBUG_TYPE "legalizer-info"
|
||||||
|
|
||||||
|
LegacyLegalizerInfo::LegacyLegalizerInfo() : TablesInitialized(false) {
|
||||||
|
// Set defaults.
|
||||||
|
// FIXME: these two (G_ANYEXT and G_TRUNC?) can be legalized to the
|
||||||
|
// fundamental load/store Jakob proposed. Once loads & stores are supported.
|
||||||
|
setScalarAction(TargetOpcode::G_ANYEXT, 1, {{1, Legal}});
|
||||||
|
setScalarAction(TargetOpcode::G_ZEXT, 1, {{1, Legal}});
|
||||||
|
setScalarAction(TargetOpcode::G_SEXT, 1, {{1, Legal}});
|
||||||
|
setScalarAction(TargetOpcode::G_TRUNC, 0, {{1, Legal}});
|
||||||
|
setScalarAction(TargetOpcode::G_TRUNC, 1, {{1, Legal}});
|
||||||
|
|
||||||
|
setScalarAction(TargetOpcode::G_INTRINSIC, 0, {{1, Legal}});
|
||||||
|
setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1, Legal}});
|
||||||
|
|
||||||
|
setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
TargetOpcode::G_IMPLICIT_DEF, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
||||||
|
setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
TargetOpcode::G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
|
||||||
|
setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
TargetOpcode::G_OR, 0, widenToLargerTypesAndNarrowToLargest);
|
||||||
|
setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
TargetOpcode::G_LOAD, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
||||||
|
setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
TargetOpcode::G_STORE, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
||||||
|
|
||||||
|
setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
TargetOpcode::G_BRCOND, 0, widenToLargerTypesUnsupportedOtherwise);
|
||||||
|
setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
TargetOpcode::G_INSERT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
||||||
|
setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
TargetOpcode::G_EXTRACT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
||||||
|
setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
TargetOpcode::G_EXTRACT, 1, narrowToSmallerAndUnsupportedIfTooSmall);
|
||||||
|
setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}});
|
||||||
|
}
|
||||||
|
|
||||||
|
void LegacyLegalizerInfo::computeTables() {
|
||||||
|
assert(TablesInitialized == false);
|
||||||
|
|
||||||
|
for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {
|
||||||
|
const unsigned Opcode = FirstOp + OpcodeIdx;
|
||||||
|
for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();
|
||||||
|
++TypeIdx) {
|
||||||
|
// 0. Collect information specified through the setAction API, i.e.
|
||||||
|
// for specific bit sizes.
|
||||||
|
// For scalar types:
|
||||||
|
SizeAndActionsVec ScalarSpecifiedActions;
|
||||||
|
// For pointer types:
|
||||||
|
std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;
|
||||||
|
// For vector types:
|
||||||
|
std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
|
||||||
|
for (auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
|
||||||
|
const LLT Type = LLT2Action.first;
|
||||||
|
const LegacyLegalizeAction Action = LLT2Action.second;
|
||||||
|
|
||||||
|
auto SizeAction = std::make_pair(Type.getSizeInBits(), Action);
|
||||||
|
if (Type.isPointer())
|
||||||
|
AddressSpace2SpecifiedActions[Type.getAddressSpace()].push_back(
|
||||||
|
SizeAction);
|
||||||
|
else if (Type.isVector())
|
||||||
|
ElemSize2SpecifiedActions[Type.getElementType().getSizeInBits()]
|
||||||
|
.push_back(SizeAction);
|
||||||
|
else
|
||||||
|
ScalarSpecifiedActions.push_back(SizeAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Handle scalar types
|
||||||
|
{
|
||||||
|
// Decide how to handle bit sizes for which no explicit specification
|
||||||
|
// was given.
|
||||||
|
SizeChangeStrategy S = &unsupportedForDifferentSizes;
|
||||||
|
if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].size() &&
|
||||||
|
ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
|
||||||
|
S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];
|
||||||
|
llvm::sort(ScalarSpecifiedActions);
|
||||||
|
checkPartialSizeAndActionsVector(ScalarSpecifiedActions);
|
||||||
|
setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Handle pointer types
|
||||||
|
for (auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {
|
||||||
|
llvm::sort(PointerSpecifiedActions.second);
|
||||||
|
checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);
|
||||||
|
// For pointer types, we assume that there isn't a meaningfull way
|
||||||
|
// to change the number of bits used in the pointer.
|
||||||
|
setPointerAction(
|
||||||
|
Opcode, TypeIdx, PointerSpecifiedActions.first,
|
||||||
|
unsupportedForDifferentSizes(PointerSpecifiedActions.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Handle vector types
|
||||||
|
SizeAndActionsVec ElementSizesSeen;
|
||||||
|
for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
|
||||||
|
llvm::sort(VectorSpecifiedActions.second);
|
||||||
|
const uint16_t ElementSize = VectorSpecifiedActions.first;
|
||||||
|
ElementSizesSeen.push_back({ElementSize, Legal});
|
||||||
|
checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);
|
||||||
|
// For vector types, we assume that the best way to adapt the number
|
||||||
|
// of elements is to the next larger number of elements type for which
|
||||||
|
// the vector type is legal, unless there is no such type. In that case,
|
||||||
|
// legalize towards a vector type with a smaller number of elements.
|
||||||
|
SizeAndActionsVec NumElementsActions;
|
||||||
|
for (SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {
|
||||||
|
assert(BitsizeAndAction.first % ElementSize == 0);
|
||||||
|
const uint16_t NumElements = BitsizeAndAction.first / ElementSize;
|
||||||
|
NumElementsActions.push_back({NumElements, BitsizeAndAction.second});
|
||||||
|
}
|
||||||
|
setVectorNumElementAction(
|
||||||
|
Opcode, TypeIdx, ElementSize,
|
||||||
|
moreToWiderTypesAndLessToWidest(NumElementsActions));
|
||||||
|
}
|
||||||
|
llvm::sort(ElementSizesSeen);
|
||||||
|
SizeChangeStrategy VectorElementSizeChangeStrategy =
|
||||||
|
&unsupportedForDifferentSizes;
|
||||||
|
if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].size() &&
|
||||||
|
VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
|
||||||
|
VectorElementSizeChangeStrategy =
|
||||||
|
VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
|
||||||
|
setScalarInVectorAction(
|
||||||
|
Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TablesInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: inefficient implementation for now. Without ComputeValueVTs we're
|
||||||
|
// probably going to need specialized lookup structures for various types before
|
||||||
|
// we have any hope of doing well with something like <13 x i3>. Even the common
|
||||||
|
// cases should do better than what we have now.
|
||||||
|
std::pair<LegacyLegalizeAction, LLT>
|
||||||
|
LegacyLegalizerInfo::getAspectAction(const InstrAspect &Aspect) const {
|
||||||
|
assert(TablesInitialized && "backend forgot to call computeTables");
|
||||||
|
// These *have* to be implemented for now, they're the fundamental basis of
|
||||||
|
// how everything else is transformed.
|
||||||
|
if (Aspect.Type.isScalar() || Aspect.Type.isPointer())
|
||||||
|
return findScalarLegalAction(Aspect);
|
||||||
|
assert(Aspect.Type.isVector());
|
||||||
|
return findVectorLegalAction(Aspect);
|
||||||
|
}
|
||||||
|
|
||||||
|
LegacyLegalizerInfo::SizeAndActionsVec
|
||||||
|
LegacyLegalizerInfo::increaseToLargerTypesAndDecreaseToLargest(
|
||||||
|
const SizeAndActionsVec &v, LegacyLegalizeAction IncreaseAction,
|
||||||
|
LegacyLegalizeAction DecreaseAction) {
|
||||||
|
SizeAndActionsVec result;
|
||||||
|
unsigned LargestSizeSoFar = 0;
|
||||||
|
if (v.size() >= 1 && v[0].first != 1)
|
||||||
|
result.push_back({1, IncreaseAction});
|
||||||
|
for (size_t i = 0; i < v.size(); ++i) {
|
||||||
|
result.push_back(v[i]);
|
||||||
|
LargestSizeSoFar = v[i].first;
|
||||||
|
if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {
|
||||||
|
result.push_back({LargestSizeSoFar + 1, IncreaseAction});
|
||||||
|
LargestSizeSoFar = v[i].first + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push_back({LargestSizeSoFar + 1, DecreaseAction});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LegacyLegalizerInfo::SizeAndActionsVec
|
||||||
|
LegacyLegalizerInfo::decreaseToSmallerTypesAndIncreaseToSmallest(
|
||||||
|
const SizeAndActionsVec &v, LegacyLegalizeAction DecreaseAction,
|
||||||
|
LegacyLegalizeAction IncreaseAction) {
|
||||||
|
SizeAndActionsVec result;
|
||||||
|
if (v.size() == 0 || v[0].first != 1)
|
||||||
|
result.push_back({1, IncreaseAction});
|
||||||
|
for (size_t i = 0; i < v.size(); ++i) {
|
||||||
|
result.push_back(v[i]);
|
||||||
|
if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {
|
||||||
|
result.push_back({v[i].first + 1, DecreaseAction});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LegacyLegalizerInfo::SizeAndAction
|
||||||
|
LegacyLegalizerInfo::findAction(const SizeAndActionsVec &Vec, const uint32_t Size) {
|
||||||
|
assert(Size >= 1);
|
||||||
|
// Find the last element in Vec that has a bitsize equal to or smaller than
|
||||||
|
// the requested bit size.
|
||||||
|
// That is the element just before the first element that is bigger than Size.
|
||||||
|
auto It = partition_point(
|
||||||
|
Vec, [=](const SizeAndAction &A) { return A.first <= Size; });
|
||||||
|
assert(It != Vec.begin() && "Does Vec not start with size 1?");
|
||||||
|
int VecIdx = It - Vec.begin() - 1;
|
||||||
|
|
||||||
|
LegacyLegalizeAction Action = Vec[VecIdx].second;
|
||||||
|
switch (Action) {
|
||||||
|
case Legal:
|
||||||
|
case Bitcast:
|
||||||
|
case Lower:
|
||||||
|
case Libcall:
|
||||||
|
case Custom:
|
||||||
|
return {Size, Action};
|
||||||
|
case FewerElements:
|
||||||
|
// FIXME: is this special case still needed and correct?
|
||||||
|
// Special case for scalarization:
|
||||||
|
if (Vec == SizeAndActionsVec({{1, FewerElements}}))
|
||||||
|
return {1, FewerElements};
|
||||||
|
LLVM_FALLTHROUGH;
|
||||||
|
case NarrowScalar: {
|
||||||
|
// The following needs to be a loop, as for now, we do allow needing to
|
||||||
|
// go over "Unsupported" bit sizes before finding a legalizable bit size.
|
||||||
|
// e.g. (s8, WidenScalar), (s9, Unsupported), (s32, Legal). if Size==8,
|
||||||
|
// we need to iterate over s9, and then to s32 to return (s32, Legal).
|
||||||
|
// If we want to get rid of the below loop, we should have stronger asserts
|
||||||
|
// when building the SizeAndActionsVecs, probably not allowing
|
||||||
|
// "Unsupported" unless at the ends of the vector.
|
||||||
|
for (int i = VecIdx - 1; i >= 0; --i)
|
||||||
|
if (!needsLegalizingToDifferentSize(Vec[i].second) &&
|
||||||
|
Vec[i].second != Unsupported)
|
||||||
|
return {Vec[i].first, Action};
|
||||||
|
llvm_unreachable("");
|
||||||
|
}
|
||||||
|
case WidenScalar:
|
||||||
|
case MoreElements: {
|
||||||
|
// See above, the following needs to be a loop, at least for now.
|
||||||
|
for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
|
||||||
|
if (!needsLegalizingToDifferentSize(Vec[i].second) &&
|
||||||
|
Vec[i].second != Unsupported)
|
||||||
|
return {Vec[i].first, Action};
|
||||||
|
llvm_unreachable("");
|
||||||
|
}
|
||||||
|
case Unsupported:
|
||||||
|
return {Size, Unsupported};
|
||||||
|
case NotFound:
|
||||||
|
llvm_unreachable("NotFound");
|
||||||
|
}
|
||||||
|
llvm_unreachable("Action has an unknown enum value");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<LegacyLegalizeAction, LLT>
|
||||||
|
LegacyLegalizerInfo::findScalarLegalAction(const InstrAspect &Aspect) const {
|
||||||
|
assert(Aspect.Type.isScalar() || Aspect.Type.isPointer());
|
||||||
|
if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
|
||||||
|
return {NotFound, LLT()};
|
||||||
|
const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
|
||||||
|
if (Aspect.Type.isPointer() &&
|
||||||
|
AddrSpace2PointerActions[OpcodeIdx].find(Aspect.Type.getAddressSpace()) ==
|
||||||
|
AddrSpace2PointerActions[OpcodeIdx].end()) {
|
||||||
|
return {NotFound, LLT()};
|
||||||
|
}
|
||||||
|
const SmallVector<SizeAndActionsVec, 1> &Actions =
|
||||||
|
Aspect.Type.isPointer()
|
||||||
|
? AddrSpace2PointerActions[OpcodeIdx]
|
||||||
|
.find(Aspect.Type.getAddressSpace())
|
||||||
|
->second
|
||||||
|
: ScalarActions[OpcodeIdx];
|
||||||
|
if (Aspect.Idx >= Actions.size())
|
||||||
|
return {NotFound, LLT()};
|
||||||
|
const SizeAndActionsVec &Vec = Actions[Aspect.Idx];
|
||||||
|
// FIXME: speed up this search, e.g. by using a results cache for repeated
|
||||||
|
// queries?
|
||||||
|
auto SizeAndAction = findAction(Vec, Aspect.Type.getSizeInBits());
|
||||||
|
return {SizeAndAction.second,
|
||||||
|
Aspect.Type.isScalar() ? LLT::scalar(SizeAndAction.first)
|
||||||
|
: LLT::pointer(Aspect.Type.getAddressSpace(),
|
||||||
|
SizeAndAction.first)};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<LegacyLegalizeAction, LLT>
|
||||||
|
LegacyLegalizerInfo::findVectorLegalAction(const InstrAspect &Aspect) const {
|
||||||
|
assert(Aspect.Type.isVector());
|
||||||
|
// First legalize the vector element size, then legalize the number of
|
||||||
|
// lanes in the vector.
|
||||||
|
if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
|
||||||
|
return {NotFound, Aspect.Type};
|
||||||
|
const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
|
||||||
|
const unsigned TypeIdx = Aspect.Idx;
|
||||||
|
if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].size())
|
||||||
|
return {NotFound, Aspect.Type};
|
||||||
|
const SizeAndActionsVec &ElemSizeVec =
|
||||||
|
ScalarInVectorActions[OpcodeIdx][TypeIdx];
|
||||||
|
|
||||||
|
LLT IntermediateType;
|
||||||
|
auto ElementSizeAndAction =
|
||||||
|
findAction(ElemSizeVec, Aspect.Type.getScalarSizeInBits());
|
||||||
|
IntermediateType =
|
||||||
|
LLT::vector(Aspect.Type.getNumElements(), ElementSizeAndAction.first);
|
||||||
|
if (ElementSizeAndAction.second != Legal)
|
||||||
|
return {ElementSizeAndAction.second, IntermediateType};
|
||||||
|
|
||||||
|
auto i = NumElements2Actions[OpcodeIdx].find(
|
||||||
|
IntermediateType.getScalarSizeInBits());
|
||||||
|
if (i == NumElements2Actions[OpcodeIdx].end()) {
|
||||||
|
return {NotFound, IntermediateType};
|
||||||
|
}
|
||||||
|
const SizeAndActionsVec &NumElementsVec = (*i).second[TypeIdx];
|
||||||
|
auto NumElementsAndAction =
|
||||||
|
findAction(NumElementsVec, IntermediateType.getNumElements());
|
||||||
|
return {NumElementsAndAction.second,
|
||||||
|
LLT::vector(NumElementsAndAction.first,
|
||||||
|
IntermediateType.getScalarSizeInBits())};
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned LegacyLegalizerInfo::getOpcodeIdxForOpcode(unsigned Opcode) const {
|
||||||
|
assert(Opcode >= FirstOp && Opcode <= LastOp && "Unsupported opcode");
|
||||||
|
return Opcode - FirstOp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LegacyLegalizeActionStep
|
||||||
|
LegacyLegalizerInfo::getAction(const LegalityQuery &Query) const {
|
||||||
|
for (unsigned i = 0; i < Query.Types.size(); ++i) {
|
||||||
|
auto Action = getAspectAction({Query.Opcode, i, Query.Types[i]});
|
||||||
|
if (Action.first != Legal) {
|
||||||
|
LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Action="
|
||||||
|
<< Action.first << ", " << Action.second << "\n");
|
||||||
|
return {Action.first, i, Action.second};
|
||||||
|
} else
|
||||||
|
LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Legal\n");
|
||||||
|
}
|
||||||
|
LLVM_DEBUG(dbgs() << ".. (legacy) Legal\n");
|
||||||
|
return {Legal, 0, LLT{}};
|
||||||
|
}
|
||||||
|
|
@ -9,11 +9,6 @@
|
|||||||
// Implement an interface to specify and query how an illegal operation on a
|
// Implement an interface to specify and query how an illegal operation on a
|
||||||
// given type should be expanded.
|
// given type should be expanded.
|
||||||
//
|
//
|
||||||
// Issues to be resolved:
|
|
||||||
// + Make it fast.
|
|
||||||
// + Support weird types like i3, <7 x i3>, ...
|
|
||||||
// + Operations with more than one type (ICMP, CMPXCHG, intrinsics, ...)
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
|
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
|
||||||
@ -256,146 +251,6 @@ bool LegalizeRuleSet::verifyImmIdxsCoverage(unsigned NumImmIdxs) const {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
LegalizerInfo::LegalizerInfo() : TablesInitialized(false) {
|
|
||||||
// Set defaults.
|
|
||||||
// FIXME: these two (G_ANYEXT and G_TRUNC?) can be legalized to the
|
|
||||||
// fundamental load/store Jakob proposed. Once loads & stores are supported.
|
|
||||||
setScalarAction(TargetOpcode::G_ANYEXT, 1, {{1, Legal}});
|
|
||||||
setScalarAction(TargetOpcode::G_ZEXT, 1, {{1, Legal}});
|
|
||||||
setScalarAction(TargetOpcode::G_SEXT, 1, {{1, Legal}});
|
|
||||||
setScalarAction(TargetOpcode::G_TRUNC, 0, {{1, Legal}});
|
|
||||||
setScalarAction(TargetOpcode::G_TRUNC, 1, {{1, Legal}});
|
|
||||||
|
|
||||||
setScalarAction(TargetOpcode::G_INTRINSIC, 0, {{1, Legal}});
|
|
||||||
setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1, Legal}});
|
|
||||||
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
TargetOpcode::G_IMPLICIT_DEF, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
TargetOpcode::G_ADD, 0, widenToLargerTypesAndNarrowToLargest);
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
TargetOpcode::G_OR, 0, widenToLargerTypesAndNarrowToLargest);
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
TargetOpcode::G_LOAD, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
TargetOpcode::G_STORE, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
|
||||||
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
TargetOpcode::G_BRCOND, 0, widenToLargerTypesUnsupportedOtherwise);
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
TargetOpcode::G_INSERT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
TargetOpcode::G_EXTRACT, 0, narrowToSmallerAndUnsupportedIfTooSmall);
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
|
||||||
TargetOpcode::G_EXTRACT, 1, narrowToSmallerAndUnsupportedIfTooSmall);
|
|
||||||
setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}});
|
|
||||||
}
|
|
||||||
|
|
||||||
void LegalizerInfo::computeTables() {
|
|
||||||
assert(TablesInitialized == false);
|
|
||||||
|
|
||||||
for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {
|
|
||||||
const unsigned Opcode = FirstOp + OpcodeIdx;
|
|
||||||
for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();
|
|
||||||
++TypeIdx) {
|
|
||||||
// 0. Collect information specified through the setAction API, i.e.
|
|
||||||
// for specific bit sizes.
|
|
||||||
// For scalar types:
|
|
||||||
SizeAndActionsVec ScalarSpecifiedActions;
|
|
||||||
// For pointer types:
|
|
||||||
std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;
|
|
||||||
// For vector types:
|
|
||||||
std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
|
|
||||||
for (auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
|
|
||||||
const LLT Type = LLT2Action.first;
|
|
||||||
const LegalizeAction Action = LLT2Action.second;
|
|
||||||
|
|
||||||
auto SizeAction = std::make_pair(Type.getSizeInBits(), Action);
|
|
||||||
if (Type.isPointer())
|
|
||||||
AddressSpace2SpecifiedActions[Type.getAddressSpace()].push_back(
|
|
||||||
SizeAction);
|
|
||||||
else if (Type.isVector())
|
|
||||||
ElemSize2SpecifiedActions[Type.getElementType().getSizeInBits()]
|
|
||||||
.push_back(SizeAction);
|
|
||||||
else
|
|
||||||
ScalarSpecifiedActions.push_back(SizeAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. Handle scalar types
|
|
||||||
{
|
|
||||||
// Decide how to handle bit sizes for which no explicit specification
|
|
||||||
// was given.
|
|
||||||
SizeChangeStrategy S = &unsupportedForDifferentSizes;
|
|
||||||
if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].size() &&
|
|
||||||
ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
|
|
||||||
S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];
|
|
||||||
llvm::sort(ScalarSpecifiedActions);
|
|
||||||
checkPartialSizeAndActionsVector(ScalarSpecifiedActions);
|
|
||||||
setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Handle pointer types
|
|
||||||
for (auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {
|
|
||||||
llvm::sort(PointerSpecifiedActions.second);
|
|
||||||
checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);
|
|
||||||
// For pointer types, we assume that there isn't a meaningfull way
|
|
||||||
// to change the number of bits used in the pointer.
|
|
||||||
setPointerAction(
|
|
||||||
Opcode, TypeIdx, PointerSpecifiedActions.first,
|
|
||||||
unsupportedForDifferentSizes(PointerSpecifiedActions.second));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Handle vector types
|
|
||||||
SizeAndActionsVec ElementSizesSeen;
|
|
||||||
for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
|
|
||||||
llvm::sort(VectorSpecifiedActions.second);
|
|
||||||
const uint16_t ElementSize = VectorSpecifiedActions.first;
|
|
||||||
ElementSizesSeen.push_back({ElementSize, Legal});
|
|
||||||
checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);
|
|
||||||
// For vector types, we assume that the best way to adapt the number
|
|
||||||
// of elements is to the next larger number of elements type for which
|
|
||||||
// the vector type is legal, unless there is no such type. In that case,
|
|
||||||
// legalize towards a vector type with a smaller number of elements.
|
|
||||||
SizeAndActionsVec NumElementsActions;
|
|
||||||
for (SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {
|
|
||||||
assert(BitsizeAndAction.first % ElementSize == 0);
|
|
||||||
const uint16_t NumElements = BitsizeAndAction.first / ElementSize;
|
|
||||||
NumElementsActions.push_back({NumElements, BitsizeAndAction.second});
|
|
||||||
}
|
|
||||||
setVectorNumElementAction(
|
|
||||||
Opcode, TypeIdx, ElementSize,
|
|
||||||
moreToWiderTypesAndLessToWidest(NumElementsActions));
|
|
||||||
}
|
|
||||||
llvm::sort(ElementSizesSeen);
|
|
||||||
SizeChangeStrategy VectorElementSizeChangeStrategy =
|
|
||||||
&unsupportedForDifferentSizes;
|
|
||||||
if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].size() &&
|
|
||||||
VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
|
|
||||||
VectorElementSizeChangeStrategy =
|
|
||||||
VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
|
|
||||||
setScalarInVectorAction(
|
|
||||||
Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TablesInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: inefficient implementation for now. Without ComputeValueVTs we're
|
|
||||||
// probably going to need specialized lookup structures for various types before
|
|
||||||
// we have any hope of doing well with something like <13 x i3>. Even the common
|
|
||||||
// cases should do better than what we have now.
|
|
||||||
std::pair<LegalizeAction, LLT>
|
|
||||||
LegalizerInfo::getAspectAction(const InstrAspect &Aspect) const {
|
|
||||||
assert(TablesInitialized && "backend forgot to call computeTables");
|
|
||||||
// These *have* to be implemented for now, they're the fundamental basis of
|
|
||||||
// how everything else is transformed.
|
|
||||||
if (Aspect.Type.isScalar() || Aspect.Type.isPointer())
|
|
||||||
return findScalarLegalAction(Aspect);
|
|
||||||
assert(Aspect.Type.isVector());
|
|
||||||
return findVectorLegalAction(Aspect);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper function to get LLT for the given type index.
|
/// Helper function to get LLT for the given type index.
|
||||||
static LLT getTypeFromTypeIdx(const MachineInstr &MI,
|
static LLT getTypeFromTypeIdx(const MachineInstr &MI,
|
||||||
const MachineRegisterInfo &MRI, unsigned OpIdx,
|
const MachineRegisterInfo &MRI, unsigned OpIdx,
|
||||||
@ -469,17 +324,7 @@ LegalizerInfo::getAction(const LegalityQuery &Query) const {
|
|||||||
return Step;
|
return Step;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < Query.Types.size(); ++i) {
|
return getLegacyLegalizerInfo().getAction(Query);
|
||||||
auto Action = getAspectAction({Query.Opcode, i, Query.Types[i]});
|
|
||||||
if (Action.first != Legal) {
|
|
||||||
LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Action="
|
|
||||||
<< Action.first << ", " << Action.second << "\n");
|
|
||||||
return {Action.first, i, Action.second};
|
|
||||||
} else
|
|
||||||
LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Legal\n");
|
|
||||||
}
|
|
||||||
LLVM_DEBUG(dbgs() << ".. (legacy) Legal\n");
|
|
||||||
return {Legal, 0, LLT{}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LegalizeActionStep
|
LegalizeActionStep
|
||||||
@ -526,163 +371,6 @@ bool LegalizerInfo::isLegalOrCustom(const MachineInstr &MI,
|
|||||||
return Action == Legal || Action == Custom;
|
return Action == Legal || Action == Custom;
|
||||||
}
|
}
|
||||||
|
|
||||||
LegalizerInfo::SizeAndActionsVec
|
|
||||||
LegalizerInfo::increaseToLargerTypesAndDecreaseToLargest(
|
|
||||||
const SizeAndActionsVec &v, LegalizeAction IncreaseAction,
|
|
||||||
LegalizeAction DecreaseAction) {
|
|
||||||
SizeAndActionsVec result;
|
|
||||||
unsigned LargestSizeSoFar = 0;
|
|
||||||
if (v.size() >= 1 && v[0].first != 1)
|
|
||||||
result.push_back({1, IncreaseAction});
|
|
||||||
for (size_t i = 0; i < v.size(); ++i) {
|
|
||||||
result.push_back(v[i]);
|
|
||||||
LargestSizeSoFar = v[i].first;
|
|
||||||
if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {
|
|
||||||
result.push_back({LargestSizeSoFar + 1, IncreaseAction});
|
|
||||||
LargestSizeSoFar = v[i].first + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.push_back({LargestSizeSoFar + 1, DecreaseAction});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
LegalizerInfo::SizeAndActionsVec
|
|
||||||
LegalizerInfo::decreaseToSmallerTypesAndIncreaseToSmallest(
|
|
||||||
const SizeAndActionsVec &v, LegalizeAction DecreaseAction,
|
|
||||||
LegalizeAction IncreaseAction) {
|
|
||||||
SizeAndActionsVec result;
|
|
||||||
if (v.size() == 0 || v[0].first != 1)
|
|
||||||
result.push_back({1, IncreaseAction});
|
|
||||||
for (size_t i = 0; i < v.size(); ++i) {
|
|
||||||
result.push_back(v[i]);
|
|
||||||
if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {
|
|
||||||
result.push_back({v[i].first + 1, DecreaseAction});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
LegalizerInfo::SizeAndAction
|
|
||||||
LegalizerInfo::findAction(const SizeAndActionsVec &Vec, const uint32_t Size) {
|
|
||||||
assert(Size >= 1);
|
|
||||||
// Find the last element in Vec that has a bitsize equal to or smaller than
|
|
||||||
// the requested bit size.
|
|
||||||
// That is the element just before the first element that is bigger than Size.
|
|
||||||
auto It = partition_point(
|
|
||||||
Vec, [=](const SizeAndAction &A) { return A.first <= Size; });
|
|
||||||
assert(It != Vec.begin() && "Does Vec not start with size 1?");
|
|
||||||
int VecIdx = It - Vec.begin() - 1;
|
|
||||||
|
|
||||||
LegalizeAction Action = Vec[VecIdx].second;
|
|
||||||
switch (Action) {
|
|
||||||
case Legal:
|
|
||||||
case Bitcast:
|
|
||||||
case Lower:
|
|
||||||
case Libcall:
|
|
||||||
case Custom:
|
|
||||||
return {Size, Action};
|
|
||||||
case FewerElements:
|
|
||||||
// FIXME: is this special case still needed and correct?
|
|
||||||
// Special case for scalarization:
|
|
||||||
if (Vec == SizeAndActionsVec({{1, FewerElements}}))
|
|
||||||
return {1, FewerElements};
|
|
||||||
LLVM_FALLTHROUGH;
|
|
||||||
case NarrowScalar: {
|
|
||||||
// The following needs to be a loop, as for now, we do allow needing to
|
|
||||||
// go over "Unsupported" bit sizes before finding a legalizable bit size.
|
|
||||||
// e.g. (s8, WidenScalar), (s9, Unsupported), (s32, Legal). if Size==8,
|
|
||||||
// we need to iterate over s9, and then to s32 to return (s32, Legal).
|
|
||||||
// If we want to get rid of the below loop, we should have stronger asserts
|
|
||||||
// when building the SizeAndActionsVecs, probably not allowing
|
|
||||||
// "Unsupported" unless at the ends of the vector.
|
|
||||||
for (int i = VecIdx - 1; i >= 0; --i)
|
|
||||||
if (!needsLegalizingToDifferentSize(Vec[i].second) &&
|
|
||||||
Vec[i].second != Unsupported)
|
|
||||||
return {Vec[i].first, Action};
|
|
||||||
llvm_unreachable("");
|
|
||||||
}
|
|
||||||
case WidenScalar:
|
|
||||||
case MoreElements: {
|
|
||||||
// See above, the following needs to be a loop, at least for now.
|
|
||||||
for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
|
|
||||||
if (!needsLegalizingToDifferentSize(Vec[i].second) &&
|
|
||||||
Vec[i].second != Unsupported)
|
|
||||||
return {Vec[i].first, Action};
|
|
||||||
llvm_unreachable("");
|
|
||||||
}
|
|
||||||
case Unsupported:
|
|
||||||
return {Size, Unsupported};
|
|
||||||
case NotFound:
|
|
||||||
case UseLegacyRules:
|
|
||||||
llvm_unreachable("NotFound");
|
|
||||||
}
|
|
||||||
llvm_unreachable("Action has an unknown enum value");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<LegalizeAction, LLT>
|
|
||||||
LegalizerInfo::findScalarLegalAction(const InstrAspect &Aspect) const {
|
|
||||||
assert(Aspect.Type.isScalar() || Aspect.Type.isPointer());
|
|
||||||
if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
|
|
||||||
return {NotFound, LLT()};
|
|
||||||
const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
|
|
||||||
if (Aspect.Type.isPointer() &&
|
|
||||||
AddrSpace2PointerActions[OpcodeIdx].find(Aspect.Type.getAddressSpace()) ==
|
|
||||||
AddrSpace2PointerActions[OpcodeIdx].end()) {
|
|
||||||
return {NotFound, LLT()};
|
|
||||||
}
|
|
||||||
const SmallVector<SizeAndActionsVec, 1> &Actions =
|
|
||||||
Aspect.Type.isPointer()
|
|
||||||
? AddrSpace2PointerActions[OpcodeIdx]
|
|
||||||
.find(Aspect.Type.getAddressSpace())
|
|
||||||
->second
|
|
||||||
: ScalarActions[OpcodeIdx];
|
|
||||||
if (Aspect.Idx >= Actions.size())
|
|
||||||
return {NotFound, LLT()};
|
|
||||||
const SizeAndActionsVec &Vec = Actions[Aspect.Idx];
|
|
||||||
// FIXME: speed up this search, e.g. by using a results cache for repeated
|
|
||||||
// queries?
|
|
||||||
auto SizeAndAction = findAction(Vec, Aspect.Type.getSizeInBits());
|
|
||||||
return {SizeAndAction.second,
|
|
||||||
Aspect.Type.isScalar() ? LLT::scalar(SizeAndAction.first)
|
|
||||||
: LLT::pointer(Aspect.Type.getAddressSpace(),
|
|
||||||
SizeAndAction.first)};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<LegalizeAction, LLT>
|
|
||||||
LegalizerInfo::findVectorLegalAction(const InstrAspect &Aspect) const {
|
|
||||||
assert(Aspect.Type.isVector());
|
|
||||||
// First legalize the vector element size, then legalize the number of
|
|
||||||
// lanes in the vector.
|
|
||||||
if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
|
|
||||||
return {NotFound, Aspect.Type};
|
|
||||||
const unsigned OpcodeIdx = getOpcodeIdxForOpcode(Aspect.Opcode);
|
|
||||||
const unsigned TypeIdx = Aspect.Idx;
|
|
||||||
if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].size())
|
|
||||||
return {NotFound, Aspect.Type};
|
|
||||||
const SizeAndActionsVec &ElemSizeVec =
|
|
||||||
ScalarInVectorActions[OpcodeIdx][TypeIdx];
|
|
||||||
|
|
||||||
LLT IntermediateType;
|
|
||||||
auto ElementSizeAndAction =
|
|
||||||
findAction(ElemSizeVec, Aspect.Type.getScalarSizeInBits());
|
|
||||||
IntermediateType =
|
|
||||||
LLT::vector(Aspect.Type.getNumElements(), ElementSizeAndAction.first);
|
|
||||||
if (ElementSizeAndAction.second != Legal)
|
|
||||||
return {ElementSizeAndAction.second, IntermediateType};
|
|
||||||
|
|
||||||
auto i = NumElements2Actions[OpcodeIdx].find(
|
|
||||||
IntermediateType.getScalarSizeInBits());
|
|
||||||
if (i == NumElements2Actions[OpcodeIdx].end()) {
|
|
||||||
return {NotFound, IntermediateType};
|
|
||||||
}
|
|
||||||
const SizeAndActionsVec &NumElementsVec = (*i).second[TypeIdx];
|
|
||||||
auto NumElementsAndAction =
|
|
||||||
findAction(NumElementsVec, IntermediateType.getNumElements());
|
|
||||||
return {NumElementsAndAction.second,
|
|
||||||
LLT::vector(NumElementsAndAction.first,
|
|
||||||
IntermediateType.getScalarSizeInBits())};
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned LegalizerInfo::getExtOpcodeForWideningConstant(LLT SmallTy) const {
|
unsigned LegalizerInfo::getExtOpcodeForWideningConstant(LLT SmallTy) const {
|
||||||
return SmallTy.isByteSized() ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
|
return SmallTy.isByteSized() ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
|
|||||||
|
|
||||||
// FIXME: support subtargets which have neon/fp-armv8 disabled.
|
// FIXME: support subtargets which have neon/fp-armv8 disabled.
|
||||||
if (!ST.hasNEON() || !ST.hasFPARMv8()) {
|
if (!ST.hasNEON() || !ST.hasFPARMv8()) {
|
||||||
computeTables();
|
getLegacyLegalizerInfo().computeTables();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,7 +751,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
|
|||||||
.maxScalarEltSameAsIf(always, 1, 0)
|
.maxScalarEltSameAsIf(always, 1, 0)
|
||||||
.customFor({{s32, s32}, {s64, s64}});
|
.customFor({{s32, s32}, {s64, s64}});
|
||||||
|
|
||||||
computeTables();
|
getLegacyLegalizerInfo().computeTables();
|
||||||
verify(*ST.getInstrInfo());
|
verify(*ST.getInstrInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,8 +501,11 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
|
|||||||
|
|
||||||
const LLT MinScalarFPTy = ST.has16BitInsts() ? S16 : S32;
|
const LLT MinScalarFPTy = ST.has16BitInsts() ? S16 : S32;
|
||||||
|
|
||||||
setAction({G_BRCOND, S1}, Legal); // VCC branches
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
setAction({G_BRCOND, S32}, Legal); // SCC branches
|
LegacyInfo.setAction({G_BRCOND, S1},
|
||||||
|
LegacyLegalizeActions::Legal); // VCC branches
|
||||||
|
LegacyInfo.setAction({G_BRCOND, S32},
|
||||||
|
LegacyLegalizeActions::Legal); // SCC branches
|
||||||
|
|
||||||
// TODO: All multiples of 32, vectors of pointers, all v2s16 pairs, more
|
// TODO: All multiples of 32, vectors of pointers, all v2s16 pairs, more
|
||||||
// elements for v3s16
|
// elements for v3s16
|
||||||
@ -650,7 +653,8 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
|
|||||||
.widenScalarToNextPow2(0, 32)
|
.widenScalarToNextPow2(0, 32)
|
||||||
.clampMaxNumElements(0, S32, 16);
|
.clampMaxNumElements(0, S32, 16);
|
||||||
|
|
||||||
setAction({G_FRAME_INDEX, PrivatePtr}, Legal);
|
LegacyInfo.setAction({G_FRAME_INDEX, PrivatePtr},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// If the amount is divergent, we have to do a wave reduction to get the
|
// If the amount is divergent, we have to do a wave reduction to get the
|
||||||
// maximum value, so this is expanded during RegBankSelect.
|
// maximum value, so this is expanded during RegBankSelect.
|
||||||
@ -660,7 +664,7 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
|
|||||||
getActionDefinitionsBuilder(G_GLOBAL_VALUE)
|
getActionDefinitionsBuilder(G_GLOBAL_VALUE)
|
||||||
.customIf(typeIsNot(0, PrivatePtr));
|
.customIf(typeIsNot(0, PrivatePtr));
|
||||||
|
|
||||||
setAction({G_BLOCK_ADDR, CodePtr}, Legal);
|
LegacyInfo.setAction({G_BLOCK_ADDR, CodePtr}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
auto &FPOpActions = getActionDefinitionsBuilder(
|
auto &FPOpActions = getActionDefinitionsBuilder(
|
||||||
{ G_FADD, G_FMUL, G_FMA, G_FCANONICALIZE})
|
{ G_FADD, G_FMUL, G_FMA, G_FCANONICALIZE})
|
||||||
@ -1664,7 +1668,7 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
|
|||||||
G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
|
G_INDEXED_ZEXTLOAD, G_INDEXED_STORE})
|
||||||
.unsupported();
|
.unsupported();
|
||||||
|
|
||||||
computeTables();
|
getLegacyLegalizerInfo().computeTables();
|
||||||
verify(*ST.getInstrInfo());
|
verify(*ST.getInstrInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,29 +33,30 @@ using namespace LegalizeActions;
|
|||||||
/// In practice, not specifying those isn't a problem, and the below functions
|
/// In practice, not specifying those isn't a problem, and the below functions
|
||||||
/// should disappear quickly as we add support for legalizing non-power-of-2
|
/// should disappear quickly as we add support for legalizing non-power-of-2
|
||||||
/// sized types further.
|
/// sized types further.
|
||||||
static void
|
static void addAndInterleaveWithUnsupported(
|
||||||
addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result,
|
LegacyLegalizerInfo::SizeAndActionsVec &result,
|
||||||
const LegalizerInfo::SizeAndActionsVec &v) {
|
const LegacyLegalizerInfo::SizeAndActionsVec &v) {
|
||||||
for (unsigned i = 0; i < v.size(); ++i) {
|
for (unsigned i = 0; i < v.size(); ++i) {
|
||||||
result.push_back(v[i]);
|
result.push_back(v[i]);
|
||||||
if (i + 1 < v[i].first && i + 1 < v.size() &&
|
if (i + 1 < v[i].first && i + 1 < v.size() &&
|
||||||
v[i + 1].first != v[i].first + 1)
|
v[i + 1].first != v[i].first + 1)
|
||||||
result.push_back({v[i].first + 1, Unsupported});
|
result.push_back({v[i].first + 1, LegacyLegalizeActions::Unsupported});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static LegalizerInfo::SizeAndActionsVec
|
static LegacyLegalizerInfo::SizeAndActionsVec
|
||||||
widen_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
|
widen_8_16(const LegacyLegalizerInfo::SizeAndActionsVec &v) {
|
||||||
assert(v.size() >= 1);
|
assert(v.size() >= 1);
|
||||||
assert(v[0].first > 17);
|
assert(v[0].first > 17);
|
||||||
LegalizerInfo::SizeAndActionsVec result = {{1, Unsupported},
|
LegacyLegalizerInfo::SizeAndActionsVec result = {
|
||||||
{8, WidenScalar},
|
{1, LegacyLegalizeActions::Unsupported},
|
||||||
{9, Unsupported},
|
{8, LegacyLegalizeActions::WidenScalar},
|
||||||
{16, WidenScalar},
|
{9, LegacyLegalizeActions::Unsupported},
|
||||||
{17, Unsupported}};
|
{16, LegacyLegalizeActions::WidenScalar},
|
||||||
|
{17, LegacyLegalizeActions::Unsupported}};
|
||||||
addAndInterleaveWithUnsupported(result, v);
|
addAndInterleaveWithUnsupported(result, v);
|
||||||
auto Largest = result.back().first;
|
auto Largest = result.back().first;
|
||||||
result.push_back({Largest + 1, Unsupported});
|
result.push_back({Largest + 1, LegacyLegalizeActions::Unsupported});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,9 +75,10 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
|
|||||||
const LLT s32 = LLT::scalar(32);
|
const LLT s32 = LLT::scalar(32);
|
||||||
const LLT s64 = LLT::scalar(64);
|
const LLT s64 = LLT::scalar(64);
|
||||||
|
|
||||||
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
if (ST.isThumb1Only()) {
|
if (ST.isThumb1Only()) {
|
||||||
// Thumb1 is not supported yet.
|
// Thumb1 is not supported yet.
|
||||||
computeTables();
|
LegacyInfo.computeTables();
|
||||||
verify(*ST.getInstrInfo());
|
verify(*ST.getInstrInfo());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -116,13 +118,13 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
|
|||||||
.clampScalar(0, s32, s32);
|
.clampScalar(0, s32, s32);
|
||||||
|
|
||||||
for (unsigned Op : {G_SREM, G_UREM}) {
|
for (unsigned Op : {G_SREM, G_UREM}) {
|
||||||
setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
|
||||||
if (HasHWDivide)
|
if (HasHWDivide)
|
||||||
setAction({Op, s32}, Lower);
|
LegacyInfo.setAction({Op, s32}, LegacyLegalizeActions::Lower);
|
||||||
else if (AEABI(ST))
|
else if (AEABI(ST))
|
||||||
setAction({Op, s32}, Custom);
|
LegacyInfo.setAction({Op, s32}, LegacyLegalizeActions::Custom);
|
||||||
else
|
else
|
||||||
setAction({Op, s32}, Libcall);
|
LegacyInfo.setAction({Op, s32}, LegacyLegalizeActions::Libcall);
|
||||||
}
|
}
|
||||||
|
|
||||||
getActionDefinitionsBuilder(G_INTTOPTR)
|
getActionDefinitionsBuilder(G_INTTOPTR)
|
||||||
@ -198,7 +200,7 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
|
|||||||
LoadStoreBuilder.maxScalar(0, s32);
|
LoadStoreBuilder.maxScalar(0, s32);
|
||||||
|
|
||||||
for (auto Ty : {s32, s64})
|
for (auto Ty : {s32, s64})
|
||||||
setAction({G_FNEG, Ty}, Lower);
|
LegacyInfo.setAction({G_FNEG, Ty}, LegacyLegalizeActions::Lower);
|
||||||
|
|
||||||
getActionDefinitionsBuilder(G_FCONSTANT).customFor({s32, s64});
|
getActionDefinitionsBuilder(G_FCONSTANT).customFor({s32, s64});
|
||||||
|
|
||||||
@ -246,7 +248,7 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
|
|||||||
.clampScalar(0, s32, s32);
|
.clampScalar(0, s32, s32);
|
||||||
}
|
}
|
||||||
|
|
||||||
computeTables();
|
LegacyInfo.computeTables();
|
||||||
verify(*ST.getInstrInfo());
|
verify(*ST.getInstrInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
|
|||||||
|
|
||||||
getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
|
getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
|
||||||
|
|
||||||
computeTables();
|
getLegacyLegalizerInfo().computeTables();
|
||||||
verify(*ST.getInstrInfo());
|
verify(*ST.getInstrInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,4 +17,6 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace LegalizeActions;
|
using namespace LegalizeActions;
|
||||||
|
|
||||||
PPCLegalizerInfo::PPCLegalizerInfo(const PPCSubtarget &ST) { computeTables(); }
|
PPCLegalizerInfo::PPCLegalizerInfo(const PPCSubtarget &ST) {
|
||||||
|
getLegacyLegalizerInfo().computeTables();
|
||||||
|
}
|
||||||
|
@ -19,5 +19,5 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
|
RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
|
||||||
computeTables();
|
getLegacyLegalizerInfo().computeTables();
|
||||||
}
|
}
|
||||||
|
@ -32,26 +32,27 @@ using namespace LegalizeActions;
|
|||||||
/// In practice, not specifying those isn't a problem, and the below functions
|
/// In practice, not specifying those isn't a problem, and the below functions
|
||||||
/// should disappear quickly as we add support for legalizing non-power-of-2
|
/// should disappear quickly as we add support for legalizing non-power-of-2
|
||||||
/// sized types further.
|
/// sized types further.
|
||||||
static void
|
static void addAndInterleaveWithUnsupported(
|
||||||
addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result,
|
LegacyLegalizerInfo::SizeAndActionsVec &result,
|
||||||
const LegalizerInfo::SizeAndActionsVec &v) {
|
const LegacyLegalizerInfo::SizeAndActionsVec &v) {
|
||||||
for (unsigned i = 0; i < v.size(); ++i) {
|
for (unsigned i = 0; i < v.size(); ++i) {
|
||||||
result.push_back(v[i]);
|
result.push_back(v[i]);
|
||||||
if (i + 1 < v[i].first && i + 1 < v.size() &&
|
if (i + 1 < v[i].first && i + 1 < v.size() &&
|
||||||
v[i + 1].first != v[i].first + 1)
|
v[i + 1].first != v[i].first + 1)
|
||||||
result.push_back({v[i].first + 1, Unsupported});
|
result.push_back({v[i].first + 1, LegacyLegalizeActions::Unsupported});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static LegalizerInfo::SizeAndActionsVec
|
static LegacyLegalizerInfo::SizeAndActionsVec
|
||||||
widen_1(const LegalizerInfo::SizeAndActionsVec &v) {
|
widen_1(const LegacyLegalizerInfo::SizeAndActionsVec &v) {
|
||||||
assert(v.size() >= 1);
|
assert(v.size() >= 1);
|
||||||
assert(v[0].first > 1);
|
assert(v[0].first > 1);
|
||||||
LegalizerInfo::SizeAndActionsVec result = {{1, WidenScalar},
|
LegacyLegalizerInfo::SizeAndActionsVec result = {
|
||||||
{2, Unsupported}};
|
{1, LegacyLegalizeActions::WidenScalar},
|
||||||
|
{2, LegacyLegalizeActions::Unsupported}};
|
||||||
addAndInterleaveWithUnsupported(result, v);
|
addAndInterleaveWithUnsupported(result, v);
|
||||||
auto Largest = result.back().first;
|
auto Largest = result.back().first;
|
||||||
result.push_back({Largest + 1, Unsupported});
|
result.push_back({Largest + 1, LegacyLegalizeActions::Unsupported});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,20 +76,23 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
|
|||||||
.minScalar(0, LLT::scalar(32))
|
.minScalar(0, LLT::scalar(32))
|
||||||
.libcall();
|
.libcall();
|
||||||
|
|
||||||
setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1);
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(G_PHI, 0, widen_1);
|
||||||
for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR})
|
for (unsigned BinOp : {G_SUB, G_MUL, G_AND, G_OR, G_XOR})
|
||||||
setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1);
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(BinOp, 0, widen_1);
|
||||||
for (unsigned MemOp : {G_LOAD, G_STORE})
|
for (unsigned MemOp : {G_LOAD, G_STORE})
|
||||||
setLegalizeScalarToDifferentSizeStrategy(MemOp, 0,
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
|
||||||
narrowToSmallerAndWidenToSmallest);
|
MemOp, 0, LegacyLegalizerInfo::narrowToSmallerAndWidenToSmallest);
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
|
||||||
G_PTR_ADD, 1, widenToLargerTypesUnsupportedOtherwise);
|
G_PTR_ADD, 1,
|
||||||
setLegalizeScalarToDifferentSizeStrategy(
|
LegacyLegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
|
||||||
G_CONSTANT, 0, widenToLargerTypesAndNarrowToLargest);
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
G_CONSTANT, 0,
|
||||||
|
LegacyLegalizerInfo::widenToLargerTypesAndNarrowToLargest);
|
||||||
|
|
||||||
getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
|
getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
|
||||||
|
|
||||||
computeTables();
|
LegacyInfo.computeTables();
|
||||||
verify(*STI.getInstrInfo());
|
verify(*STI.getInstrInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,35 +111,37 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
|
|||||||
const LLT s64 = LLT::scalar(64);
|
const LLT s64 = LLT::scalar(64);
|
||||||
const LLT s128 = LLT::scalar(128);
|
const LLT s128 = LLT::scalar(128);
|
||||||
|
|
||||||
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
for (auto Ty : {p0, s1, s8, s16, s32})
|
for (auto Ty : {p0, s1, s8, s16, s32})
|
||||||
setAction({G_IMPLICIT_DEF, Ty}, Legal);
|
LegacyInfo.setAction({G_IMPLICIT_DEF, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (auto Ty : {s8, s16, s32, p0})
|
for (auto Ty : {s8, s16, s32, p0})
|
||||||
setAction({G_PHI, Ty}, Legal);
|
LegacyInfo.setAction({G_PHI, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
|
for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
|
||||||
for (auto Ty : {s8, s16, s32})
|
for (auto Ty : {s8, s16, s32})
|
||||||
setAction({BinOp, Ty}, Legal);
|
LegacyInfo.setAction({BinOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (unsigned Op : {G_UADDE}) {
|
for (unsigned Op : {G_UADDE}) {
|
||||||
setAction({Op, s32}, Legal);
|
LegacyInfo.setAction({Op, s32}, LegacyLegalizeActions::Legal);
|
||||||
setAction({Op, 1, s1}, Legal);
|
LegacyInfo.setAction({Op, 1, s1}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned MemOp : {G_LOAD, G_STORE}) {
|
for (unsigned MemOp : {G_LOAD, G_STORE}) {
|
||||||
for (auto Ty : {s8, s16, s32, p0})
|
for (auto Ty : {s8, s16, s32, p0})
|
||||||
setAction({MemOp, Ty}, Legal);
|
LegacyInfo.setAction({MemOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// And everything's fine in addrspace 0.
|
// And everything's fine in addrspace 0.
|
||||||
setAction({MemOp, 1, p0}, Legal);
|
LegacyInfo.setAction({MemOp, 1, p0}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointer-handling
|
// Pointer-handling
|
||||||
setAction({G_FRAME_INDEX, p0}, Legal);
|
LegacyInfo.setAction({G_FRAME_INDEX, p0}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_GLOBAL_VALUE, p0}, Legal);
|
LegacyInfo.setAction({G_GLOBAL_VALUE, p0}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
setAction({G_PTR_ADD, p0}, Legal);
|
LegacyInfo.setAction({G_PTR_ADD, p0}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_PTR_ADD, 1, s32}, Legal);
|
LegacyInfo.setAction({G_PTR_ADD, 1, s32}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
if (!Subtarget.is64Bit()) {
|
if (!Subtarget.is64Bit()) {
|
||||||
getActionDefinitionsBuilder(G_PTRTOINT)
|
getActionDefinitionsBuilder(G_PTRTOINT)
|
||||||
@ -163,29 +169,31 @@ void X86LegalizerInfo::setLegalizerInfo32bit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Control-flow
|
// Control-flow
|
||||||
setAction({G_BRCOND, s1}, Legal);
|
LegacyInfo.setAction({G_BRCOND, s1}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
for (auto Ty : {s8, s16, s32, p0})
|
for (auto Ty : {s8, s16, s32, p0})
|
||||||
setAction({TargetOpcode::G_CONSTANT, Ty}, Legal);
|
LegacyInfo.setAction({TargetOpcode::G_CONSTANT, Ty},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
for (auto Ty : {s8, s16, s32}) {
|
for (auto Ty : {s8, s16, s32}) {
|
||||||
setAction({G_ZEXT, Ty}, Legal);
|
LegacyInfo.setAction({G_ZEXT, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_SEXT, Ty}, Legal);
|
LegacyInfo.setAction({G_SEXT, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_ANYEXT, Ty}, Legal);
|
LegacyInfo.setAction({G_ANYEXT, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
setAction({G_ANYEXT, s128}, Legal);
|
LegacyInfo.setAction({G_ANYEXT, s128}, LegacyLegalizeActions::Legal);
|
||||||
getActionDefinitionsBuilder(G_SEXT_INREG).lower();
|
getActionDefinitionsBuilder(G_SEXT_INREG).lower();
|
||||||
|
|
||||||
// Merge/Unmerge
|
// Merge/Unmerge
|
||||||
for (const auto &Ty : {s16, s32, s64}) {
|
for (const auto &Ty : {s16, s32, s64}) {
|
||||||
setAction({G_MERGE_VALUES, Ty}, Legal);
|
LegacyInfo.setAction({G_MERGE_VALUES, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_UNMERGE_VALUES, 1, Ty},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
for (const auto &Ty : {s8, s16, s32}) {
|
for (const auto &Ty : {s8, s16, s32}) {
|
||||||
setAction({G_MERGE_VALUES, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_MERGE_VALUES, 1, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_UNMERGE_VALUES, Ty}, Legal);
|
LegacyInfo.setAction({G_UNMERGE_VALUES, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,21 +210,23 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
|
|||||||
const LLT s64 = LLT::scalar(64);
|
const LLT s64 = LLT::scalar(64);
|
||||||
const LLT s128 = LLT::scalar(128);
|
const LLT s128 = LLT::scalar(128);
|
||||||
|
|
||||||
setAction({G_IMPLICIT_DEF, s64}, Legal);
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
|
LegacyInfo.setAction({G_IMPLICIT_DEF, s64}, LegacyLegalizeActions::Legal);
|
||||||
// Need to have that, as tryFoldImplicitDef will create this pattern:
|
// Need to have that, as tryFoldImplicitDef will create this pattern:
|
||||||
// s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF
|
// s128 = EXTEND (G_IMPLICIT_DEF s32/s64) -> s128 = G_IMPLICIT_DEF
|
||||||
setAction({G_IMPLICIT_DEF, s128}, Legal);
|
LegacyInfo.setAction({G_IMPLICIT_DEF, s128}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
setAction({G_PHI, s64}, Legal);
|
LegacyInfo.setAction({G_PHI, s64}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
|
for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
|
||||||
setAction({BinOp, s64}, Legal);
|
LegacyInfo.setAction({BinOp, s64}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (unsigned MemOp : {G_LOAD, G_STORE})
|
for (unsigned MemOp : {G_LOAD, G_STORE})
|
||||||
setAction({MemOp, s64}, Legal);
|
LegacyInfo.setAction({MemOp, s64}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// Pointer-handling
|
// Pointer-handling
|
||||||
setAction({G_PTR_ADD, 1, s64}, Legal);
|
LegacyInfo.setAction({G_PTR_ADD, 1, s64}, LegacyLegalizeActions::Legal);
|
||||||
getActionDefinitionsBuilder(G_PTRTOINT)
|
getActionDefinitionsBuilder(G_PTRTOINT)
|
||||||
.legalForCartesianProduct({s1, s8, s16, s32, s64}, {p0})
|
.legalForCartesianProduct({s1, s8, s16, s32, s64}, {p0})
|
||||||
.maxScalar(0, s64)
|
.maxScalar(0, s64)
|
||||||
@ -224,11 +234,12 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
|
|||||||
getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s64}});
|
getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s64}});
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
setAction({TargetOpcode::G_CONSTANT, s64}, Legal);
|
LegacyInfo.setAction({TargetOpcode::G_CONSTANT, s64},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// Extensions
|
// Extensions
|
||||||
for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
|
for (unsigned extOp : {G_ZEXT, G_SEXT, G_ANYEXT}) {
|
||||||
setAction({extOp, s64}, Legal);
|
LegacyInfo.setAction({extOp, s64}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
getActionDefinitionsBuilder(G_SITOFP)
|
getActionDefinitionsBuilder(G_SITOFP)
|
||||||
@ -270,10 +281,11 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
|
|||||||
.clampScalar(1, s8, s8);
|
.clampScalar(1, s8, s8);
|
||||||
|
|
||||||
// Merge/Unmerge
|
// Merge/Unmerge
|
||||||
setAction({G_MERGE_VALUES, s128}, Legal);
|
LegacyInfo.setAction({G_MERGE_VALUES, s128}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_UNMERGE_VALUES, 1, s128}, Legal);
|
LegacyInfo.setAction({G_UNMERGE_VALUES, 1, s128},
|
||||||
setAction({G_MERGE_VALUES, 1, s128}, Legal);
|
LegacyLegalizeActions::Legal);
|
||||||
setAction({G_UNMERGE_VALUES, s128}, Legal);
|
LegacyInfo.setAction({G_MERGE_VALUES, 1, s128}, LegacyLegalizeActions::Legal);
|
||||||
|
LegacyInfo.setAction({G_UNMERGE_VALUES, s128}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86LegalizerInfo::setLegalizerInfoSSE1() {
|
void X86LegalizerInfo::setLegalizerInfoSSE1() {
|
||||||
@ -285,24 +297,28 @@ void X86LegalizerInfo::setLegalizerInfoSSE1() {
|
|||||||
const LLT v4s32 = LLT::vector(4, 32);
|
const LLT v4s32 = LLT::vector(4, 32);
|
||||||
const LLT v2s64 = LLT::vector(2, 64);
|
const LLT v2s64 = LLT::vector(2, 64);
|
||||||
|
|
||||||
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
|
for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
|
||||||
for (auto Ty : {s32, v4s32})
|
for (auto Ty : {s32, v4s32})
|
||||||
setAction({BinOp, Ty}, Legal);
|
LegacyInfo.setAction({BinOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (unsigned MemOp : {G_LOAD, G_STORE})
|
for (unsigned MemOp : {G_LOAD, G_STORE})
|
||||||
for (auto Ty : {v4s32, v2s64})
|
for (auto Ty : {v4s32, v2s64})
|
||||||
setAction({MemOp, Ty}, Legal);
|
LegacyInfo.setAction({MemOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
setAction({TargetOpcode::G_FCONSTANT, s32}, Legal);
|
LegacyInfo.setAction({TargetOpcode::G_FCONSTANT, s32},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// Merge/Unmerge
|
// Merge/Unmerge
|
||||||
for (const auto &Ty : {v4s32, v2s64}) {
|
for (const auto &Ty : {v4s32, v2s64}) {
|
||||||
setAction({G_CONCAT_VECTORS, Ty}, Legal);
|
LegacyInfo.setAction({G_CONCAT_VECTORS, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_UNMERGE_VALUES, 1, Ty},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
setAction({G_MERGE_VALUES, 1, s64}, Legal);
|
LegacyInfo.setAction({G_MERGE_VALUES, 1, s64}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_UNMERGE_VALUES, s64}, Legal);
|
LegacyInfo.setAction({G_UNMERGE_VALUES, s64}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86LegalizerInfo::setLegalizerInfoSSE2() {
|
void X86LegalizerInfo::setLegalizerInfoSSE2() {
|
||||||
@ -321,34 +337,39 @@ void X86LegalizerInfo::setLegalizerInfoSSE2() {
|
|||||||
const LLT v8s32 = LLT::vector(8, 32);
|
const LLT v8s32 = LLT::vector(8, 32);
|
||||||
const LLT v4s64 = LLT::vector(4, 64);
|
const LLT v4s64 = LLT::vector(4, 64);
|
||||||
|
|
||||||
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
|
for (unsigned BinOp : {G_FADD, G_FSUB, G_FMUL, G_FDIV})
|
||||||
for (auto Ty : {s64, v2s64})
|
for (auto Ty : {s64, v2s64})
|
||||||
setAction({BinOp, Ty}, Legal);
|
LegacyInfo.setAction({BinOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (unsigned BinOp : {G_ADD, G_SUB})
|
for (unsigned BinOp : {G_ADD, G_SUB})
|
||||||
for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
|
for (auto Ty : {v16s8, v8s16, v4s32, v2s64})
|
||||||
setAction({BinOp, Ty}, Legal);
|
LegacyInfo.setAction({BinOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
setAction({G_MUL, v8s16}, Legal);
|
LegacyInfo.setAction({G_MUL, v8s16}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
setAction({G_FPEXT, s64}, Legal);
|
LegacyInfo.setAction({G_FPEXT, s64}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_FPEXT, 1, s32}, Legal);
|
LegacyInfo.setAction({G_FPEXT, 1, s32}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
setAction({G_FPTRUNC, s32}, Legal);
|
LegacyInfo.setAction({G_FPTRUNC, s32}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_FPTRUNC, 1, s64}, Legal);
|
LegacyInfo.setAction({G_FPTRUNC, 1, s64}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
setAction({TargetOpcode::G_FCONSTANT, s64}, Legal);
|
LegacyInfo.setAction({TargetOpcode::G_FCONSTANT, s64},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// Merge/Unmerge
|
// Merge/Unmerge
|
||||||
for (const auto &Ty :
|
for (const auto &Ty :
|
||||||
{v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
|
{v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
|
||||||
setAction({G_CONCAT_VECTORS, Ty}, Legal);
|
LegacyInfo.setAction({G_CONCAT_VECTORS, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_UNMERGE_VALUES, 1, Ty},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) {
|
for (const auto &Ty : {v16s8, v8s16, v4s32, v2s64}) {
|
||||||
setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_CONCAT_VECTORS, 1, Ty},
|
||||||
setAction({G_UNMERGE_VALUES, Ty}, Legal);
|
LegacyLegalizeActions::Legal);
|
||||||
|
LegacyInfo.setAction({G_UNMERGE_VALUES, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +379,9 @@ void X86LegalizerInfo::setLegalizerInfoSSE41() {
|
|||||||
|
|
||||||
const LLT v4s32 = LLT::vector(4, 32);
|
const LLT v4s32 = LLT::vector(4, 32);
|
||||||
|
|
||||||
setAction({G_MUL, v4s32}, Legal);
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
|
LegacyInfo.setAction({G_MUL, v4s32}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86LegalizerInfo::setLegalizerInfoAVX() {
|
void X86LegalizerInfo::setLegalizerInfoAVX() {
|
||||||
@ -379,28 +402,32 @@ void X86LegalizerInfo::setLegalizerInfoAVX() {
|
|||||||
const LLT v4s64 = LLT::vector(4, 64);
|
const LLT v4s64 = LLT::vector(4, 64);
|
||||||
const LLT v8s64 = LLT::vector(8, 64);
|
const LLT v8s64 = LLT::vector(8, 64);
|
||||||
|
|
||||||
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
for (unsigned MemOp : {G_LOAD, G_STORE})
|
for (unsigned MemOp : {G_LOAD, G_STORE})
|
||||||
for (auto Ty : {v8s32, v4s64})
|
for (auto Ty : {v8s32, v4s64})
|
||||||
setAction({MemOp, Ty}, Legal);
|
LegacyInfo.setAction({MemOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
|
for (auto Ty : {v32s8, v16s16, v8s32, v4s64}) {
|
||||||
setAction({G_INSERT, Ty}, Legal);
|
LegacyInfo.setAction({G_INSERT, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_EXTRACT, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_EXTRACT, 1, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
|
for (auto Ty : {v16s8, v8s16, v4s32, v2s64}) {
|
||||||
setAction({G_INSERT, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_INSERT, 1, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_EXTRACT, Ty}, Legal);
|
LegacyInfo.setAction({G_EXTRACT, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
// Merge/Unmerge
|
// Merge/Unmerge
|
||||||
for (const auto &Ty :
|
for (const auto &Ty :
|
||||||
{v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) {
|
{v32s8, v64s8, v16s16, v32s16, v8s32, v16s32, v4s64, v8s64}) {
|
||||||
setAction({G_CONCAT_VECTORS, Ty}, Legal);
|
LegacyInfo.setAction({G_CONCAT_VECTORS, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_UNMERGE_VALUES, 1, Ty},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
for (const auto &Ty :
|
for (const auto &Ty :
|
||||||
{v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
|
{v16s8, v32s8, v8s16, v16s16, v4s32, v8s32, v2s64, v4s64}) {
|
||||||
setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_CONCAT_VECTORS, 1, Ty},
|
||||||
setAction({G_UNMERGE_VALUES, Ty}, Legal);
|
LegacyLegalizeActions::Legal);
|
||||||
|
LegacyInfo.setAction({G_UNMERGE_VALUES, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,21 +445,25 @@ void X86LegalizerInfo::setLegalizerInfoAVX2() {
|
|||||||
const LLT v16s32 = LLT::vector(16, 32);
|
const LLT v16s32 = LLT::vector(16, 32);
|
||||||
const LLT v8s64 = LLT::vector(8, 64);
|
const LLT v8s64 = LLT::vector(8, 64);
|
||||||
|
|
||||||
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
for (unsigned BinOp : {G_ADD, G_SUB})
|
for (unsigned BinOp : {G_ADD, G_SUB})
|
||||||
for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
|
for (auto Ty : {v32s8, v16s16, v8s32, v4s64})
|
||||||
setAction({BinOp, Ty}, Legal);
|
LegacyInfo.setAction({BinOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (auto Ty : {v16s16, v8s32})
|
for (auto Ty : {v16s16, v8s32})
|
||||||
setAction({G_MUL, Ty}, Legal);
|
LegacyInfo.setAction({G_MUL, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
// Merge/Unmerge
|
// Merge/Unmerge
|
||||||
for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) {
|
for (const auto &Ty : {v64s8, v32s16, v16s32, v8s64}) {
|
||||||
setAction({G_CONCAT_VECTORS, Ty}, Legal);
|
LegacyInfo.setAction({G_CONCAT_VECTORS, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_UNMERGE_VALUES, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_UNMERGE_VALUES, 1, Ty},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) {
|
for (const auto &Ty : {v32s8, v16s16, v8s32, v4s64}) {
|
||||||
setAction({G_CONCAT_VECTORS, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_CONCAT_VECTORS, 1, Ty},
|
||||||
setAction({G_UNMERGE_VALUES, Ty}, Legal);
|
LegacyLegalizeActions::Legal);
|
||||||
|
LegacyInfo.setAction({G_UNMERGE_VALUES, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,23 +486,25 @@ void X86LegalizerInfo::setLegalizerInfoAVX512() {
|
|||||||
const LLT v16s32 = LLT::vector(16, 32);
|
const LLT v16s32 = LLT::vector(16, 32);
|
||||||
const LLT v8s64 = LLT::vector(8, 64);
|
const LLT v8s64 = LLT::vector(8, 64);
|
||||||
|
|
||||||
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
for (unsigned BinOp : {G_ADD, G_SUB})
|
for (unsigned BinOp : {G_ADD, G_SUB})
|
||||||
for (auto Ty : {v16s32, v8s64})
|
for (auto Ty : {v16s32, v8s64})
|
||||||
setAction({BinOp, Ty}, Legal);
|
LegacyInfo.setAction({BinOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
setAction({G_MUL, v16s32}, Legal);
|
LegacyInfo.setAction({G_MUL, v16s32}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (unsigned MemOp : {G_LOAD, G_STORE})
|
for (unsigned MemOp : {G_LOAD, G_STORE})
|
||||||
for (auto Ty : {v16s32, v8s64})
|
for (auto Ty : {v16s32, v8s64})
|
||||||
setAction({MemOp, Ty}, Legal);
|
LegacyInfo.setAction({MemOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
|
for (auto Ty : {v64s8, v32s16, v16s32, v8s64}) {
|
||||||
setAction({G_INSERT, Ty}, Legal);
|
LegacyInfo.setAction({G_INSERT, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_EXTRACT, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_EXTRACT, 1, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
|
for (auto Ty : {v32s8, v16s16, v8s32, v4s64, v16s8, v8s16, v4s32, v2s64}) {
|
||||||
setAction({G_INSERT, 1, Ty}, Legal);
|
LegacyInfo.setAction({G_INSERT, 1, Ty}, LegacyLegalizeActions::Legal);
|
||||||
setAction({G_EXTRACT, Ty}, Legal);
|
LegacyInfo.setAction({G_EXTRACT, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************ VLX *******************/
|
/************ VLX *******************/
|
||||||
@ -479,7 +512,7 @@ void X86LegalizerInfo::setLegalizerInfoAVX512() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto Ty : {v4s32, v8s32})
|
for (auto Ty : {v4s32, v8s32})
|
||||||
setAction({G_MUL, Ty}, Legal);
|
LegacyInfo.setAction({G_MUL, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
|
void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
|
||||||
@ -488,7 +521,9 @@ void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
|
|||||||
|
|
||||||
const LLT v8s64 = LLT::vector(8, 64);
|
const LLT v8s64 = LLT::vector(8, 64);
|
||||||
|
|
||||||
setAction({G_MUL, v8s64}, Legal);
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
|
LegacyInfo.setAction({G_MUL, v8s64}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
/************ VLX *******************/
|
/************ VLX *******************/
|
||||||
if (!Subtarget.hasVLX())
|
if (!Subtarget.hasVLX())
|
||||||
@ -498,7 +533,7 @@ void X86LegalizerInfo::setLegalizerInfoAVX512DQ() {
|
|||||||
const LLT v4s64 = LLT::vector(4, 64);
|
const LLT v4s64 = LLT::vector(4, 64);
|
||||||
|
|
||||||
for (auto Ty : {v2s64, v4s64})
|
for (auto Ty : {v2s64, v4s64})
|
||||||
setAction({G_MUL, Ty}, Legal);
|
LegacyInfo.setAction({G_MUL, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
|
void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
|
||||||
@ -508,11 +543,13 @@ void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
|
|||||||
const LLT v64s8 = LLT::vector(64, 8);
|
const LLT v64s8 = LLT::vector(64, 8);
|
||||||
const LLT v32s16 = LLT::vector(32, 16);
|
const LLT v32s16 = LLT::vector(32, 16);
|
||||||
|
|
||||||
|
auto &LegacyInfo = getLegacyLegalizerInfo();
|
||||||
|
|
||||||
for (unsigned BinOp : {G_ADD, G_SUB})
|
for (unsigned BinOp : {G_ADD, G_SUB})
|
||||||
for (auto Ty : {v64s8, v32s16})
|
for (auto Ty : {v64s8, v32s16})
|
||||||
setAction({BinOp, Ty}, Legal);
|
LegacyInfo.setAction({BinOp, Ty}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
setAction({G_MUL, v32s16}, Legal);
|
LegacyInfo.setAction({G_MUL, v32s16}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
/************ VLX *******************/
|
/************ VLX *******************/
|
||||||
if (!Subtarget.hasVLX())
|
if (!Subtarget.hasVLX())
|
||||||
@ -522,5 +559,5 @@ void X86LegalizerInfo::setLegalizerInfoAVX512BW() {
|
|||||||
const LLT v16s16 = LLT::vector(16, 16);
|
const LLT v16s16 = LLT::vector(16, 16);
|
||||||
|
|
||||||
for (auto Ty : {v8s16, v16s16})
|
for (auto Ty : {v8s16, v16s16})
|
||||||
setAction({G_MUL, Ty}, Legal);
|
LegacyInfo.setAction({G_MUL, Ty}, LegacyLegalizeActions::Legal);
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ class AMDGPUGISelMITest : public GISelMITest {
|
|||||||
(void)s128; \
|
(void)s128; \
|
||||||
do \
|
do \
|
||||||
SettingUpActionsBlock while (0); \
|
SettingUpActionsBlock while (0); \
|
||||||
computeTables(); \
|
getLegacyLegalizerInfo().computeTables(); \
|
||||||
verify(*ST.getInstrInfo()); \
|
verify(*ST.getInstrInfo()); \
|
||||||
} \
|
} \
|
||||||
};
|
};
|
||||||
|
@ -1409,7 +1409,7 @@ TEST_F(AArch64GISelMITest, MoreElementsAnd) {
|
|||||||
LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
|
LI.getActionDefinitionsBuilder(TargetOpcode::G_AND)
|
||||||
.legalFor({v6s32})
|
.legalFor({v6s32})
|
||||||
.clampMinNumElements(0, s32, 6);
|
.clampMinNumElements(0, s32, 6);
|
||||||
LI.computeTables();
|
LI.getLegacyLegalizerInfo().computeTables();
|
||||||
|
|
||||||
DummyGISelObserver Observer;
|
DummyGISelObserver Observer;
|
||||||
LegalizerHelper Helper(*MF, LI, Observer, B);
|
LegalizerHelper Helper(*MF, LI, Observer, B);
|
||||||
@ -1454,7 +1454,7 @@ TEST_F(AArch64GISelMITest, FewerElementsPhi) {
|
|||||||
LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
|
LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI)
|
||||||
.legalFor({v2s32})
|
.legalFor({v2s32})
|
||||||
.clampMinNumElements(0, s32, 2);
|
.clampMinNumElements(0, s32, 2);
|
||||||
LI.computeTables();
|
LI.getLegacyLegalizerInfo().computeTables();
|
||||||
|
|
||||||
LLT PhiTy = v5s32;
|
LLT PhiTy = v5s32;
|
||||||
DummyGISelObserver Observer;
|
DummyGISelObserver Observer;
|
||||||
|
@ -48,15 +48,17 @@ namespace {
|
|||||||
TEST(LegalizerInfoTest, ScalarRISC) {
|
TEST(LegalizerInfoTest, ScalarRISC) {
|
||||||
using namespace TargetOpcode;
|
using namespace TargetOpcode;
|
||||||
LegalizerInfo L;
|
LegalizerInfo L;
|
||||||
|
auto &LegacyInfo = L.getLegacyLegalizerInfo();
|
||||||
// Typical RISCy set of operations based on AArch64.
|
// Typical RISCy set of operations based on AArch64.
|
||||||
for (unsigned Op : {G_ADD, G_SUB}) {
|
for (unsigned Op : {G_ADD, G_SUB}) {
|
||||||
for (unsigned Size : {32, 64})
|
for (unsigned Size : {32, 64})
|
||||||
L.setAction({Op, 0, LLT::scalar(Size)}, Legal);
|
LegacyInfo.setAction({Op, 0, LLT::scalar(Size)},
|
||||||
L.setLegalizeScalarToDifferentSizeStrategy(
|
LegacyLegalizeActions::Legal);
|
||||||
Op, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest);
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
|
||||||
|
Op, 0, LegacyLegalizerInfo::widenToLargerTypesAndNarrowToLargest);
|
||||||
}
|
}
|
||||||
|
|
||||||
L.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
for (unsigned opcode : {G_ADD, G_SUB}) {
|
for (unsigned opcode : {G_ADD, G_SUB}) {
|
||||||
// Check we infer the correct types and actually do what we're told.
|
// Check we infer the correct types and actually do what we're told.
|
||||||
@ -89,20 +91,28 @@ TEST(LegalizerInfoTest, ScalarRISC) {
|
|||||||
TEST(LegalizerInfoTest, VectorRISC) {
|
TEST(LegalizerInfoTest, VectorRISC) {
|
||||||
using namespace TargetOpcode;
|
using namespace TargetOpcode;
|
||||||
LegalizerInfo L;
|
LegalizerInfo L;
|
||||||
|
auto &LegacyInfo = L.getLegacyLegalizerInfo();
|
||||||
// Typical RISCy set of operations based on ARM.
|
// Typical RISCy set of operations based on ARM.
|
||||||
L.setAction({G_ADD, LLT::vector(8, 8)}, Legal);
|
LegacyInfo.setAction({G_ADD, LLT::vector(8, 8)},
|
||||||
L.setAction({G_ADD, LLT::vector(16, 8)}, Legal);
|
LegacyLegalizeActions::Legal);
|
||||||
L.setAction({G_ADD, LLT::vector(4, 16)}, Legal);
|
LegacyInfo.setAction({G_ADD, LLT::vector(16, 8)},
|
||||||
L.setAction({G_ADD, LLT::vector(8, 16)}, Legal);
|
LegacyLegalizeActions::Legal);
|
||||||
L.setAction({G_ADD, LLT::vector(2, 32)}, Legal);
|
LegacyInfo.setAction({G_ADD, LLT::vector(4, 16)},
|
||||||
L.setAction({G_ADD, LLT::vector(4, 32)}, Legal);
|
LegacyLegalizeActions::Legal);
|
||||||
|
LegacyInfo.setAction({G_ADD, LLT::vector(8, 16)},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
LegacyInfo.setAction({G_ADD, LLT::vector(2, 32)},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
LegacyInfo.setAction({G_ADD, LLT::vector(4, 32)},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
L.setLegalizeVectorElementToDifferentSizeStrategy(
|
LegacyInfo.setLegalizeVectorElementToDifferentSizeStrategy(
|
||||||
G_ADD, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
|
G_ADD, 0, LegacyLegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
|
||||||
|
|
||||||
L.setAction({G_ADD, 0, LLT::scalar(32)}, Legal);
|
LegacyInfo.setAction({G_ADD, 0, LLT::scalar(32)},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
L.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
// Check we infer the correct types and actually do what we're told for some
|
// Check we infer the correct types and actually do what we're told for some
|
||||||
// simple cases.
|
// simple cases.
|
||||||
@ -124,17 +134,18 @@ TEST(LegalizerInfoTest, VectorRISC) {
|
|||||||
TEST(LegalizerInfoTest, MultipleTypes) {
|
TEST(LegalizerInfoTest, MultipleTypes) {
|
||||||
using namespace TargetOpcode;
|
using namespace TargetOpcode;
|
||||||
LegalizerInfo L;
|
LegalizerInfo L;
|
||||||
|
auto &LegacyInfo = L.getLegacyLegalizerInfo();
|
||||||
LLT p0 = LLT::pointer(0, 64);
|
LLT p0 = LLT::pointer(0, 64);
|
||||||
LLT s64 = LLT::scalar(64);
|
LLT s64 = LLT::scalar(64);
|
||||||
|
|
||||||
// Typical RISCy set of operations based on AArch64.
|
// Typical RISCy set of operations based on AArch64.
|
||||||
L.setAction({G_PTRTOINT, 0, s64}, Legal);
|
LegacyInfo.setAction({G_PTRTOINT, 0, s64}, LegacyLegalizeActions::Legal);
|
||||||
L.setAction({G_PTRTOINT, 1, p0}, Legal);
|
LegacyInfo.setAction({G_PTRTOINT, 1, p0}, LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
L.setLegalizeScalarToDifferentSizeStrategy(
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
|
||||||
G_PTRTOINT, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest);
|
G_PTRTOINT, 0, LegacyLegalizerInfo::widenToLargerTypesAndNarrowToLargest);
|
||||||
|
|
||||||
L.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
// Check we infer the correct types and actually do what we're told.
|
// Check we infer the correct types and actually do what we're told.
|
||||||
EXPECT_EQ(L.getAction({G_PTRTOINT, {s64, p0}}),
|
EXPECT_EQ(L.getAction({G_PTRTOINT, {s64, p0}}),
|
||||||
@ -152,15 +163,16 @@ TEST(LegalizerInfoTest, MultipleTypes) {
|
|||||||
TEST(LegalizerInfoTest, MultipleSteps) {
|
TEST(LegalizerInfoTest, MultipleSteps) {
|
||||||
using namespace TargetOpcode;
|
using namespace TargetOpcode;
|
||||||
LegalizerInfo L;
|
LegalizerInfo L;
|
||||||
|
auto &LegacyInfo = L.getLegacyLegalizerInfo();
|
||||||
LLT s32 = LLT::scalar(32);
|
LLT s32 = LLT::scalar(32);
|
||||||
LLT s64 = LLT::scalar(64);
|
LLT s64 = LLT::scalar(64);
|
||||||
|
|
||||||
L.setLegalizeScalarToDifferentSizeStrategy(
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
|
||||||
G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
|
G_UREM, 0, LegacyLegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
|
||||||
L.setAction({G_UREM, 0, s32}, Lower);
|
LegacyInfo.setAction({G_UREM, 0, s32}, LegacyLegalizeActions::Lower);
|
||||||
L.setAction({G_UREM, 0, s64}, Lower);
|
LegacyInfo.setAction({G_UREM, 0, s64}, LegacyLegalizeActions::Lower);
|
||||||
|
|
||||||
L.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(16)}}),
|
EXPECT_EQ(L.getAction({G_UREM, {LLT::scalar(16)}}),
|
||||||
LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
|
LegalizeActionStep(WidenScalar, 0, LLT::scalar(32)));
|
||||||
@ -171,12 +183,14 @@ TEST(LegalizerInfoTest, MultipleSteps) {
|
|||||||
TEST(LegalizerInfoTest, SizeChangeStrategy) {
|
TEST(LegalizerInfoTest, SizeChangeStrategy) {
|
||||||
using namespace TargetOpcode;
|
using namespace TargetOpcode;
|
||||||
LegalizerInfo L;
|
LegalizerInfo L;
|
||||||
|
auto &LegacyInfo = L.getLegacyLegalizerInfo();
|
||||||
for (unsigned Size : {1, 8, 16, 32})
|
for (unsigned Size : {1, 8, 16, 32})
|
||||||
L.setAction({G_UREM, 0, LLT::scalar(Size)}, Legal);
|
LegacyInfo.setAction({G_UREM, 0, LLT::scalar(Size)},
|
||||||
|
LegacyLegalizeActions::Legal);
|
||||||
|
|
||||||
L.setLegalizeScalarToDifferentSizeStrategy(
|
LegacyInfo.setLegalizeScalarToDifferentSizeStrategy(
|
||||||
G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
|
G_UREM, 0, LegacyLegalizerInfo::widenToLargerTypesUnsupportedOtherwise);
|
||||||
L.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
// Check we infer the correct types and actually do what we're told.
|
// Check we infer the correct types and actually do what we're told.
|
||||||
for (unsigned Size : {1, 8, 16, 32}) {
|
for (unsigned Size : {1, 8, 16, 32}) {
|
||||||
@ -229,11 +243,12 @@ TEST(LegalizerInfoTest, RuleSets) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
|
|
||||||
LI.getActionDefinitionsBuilder(G_IMPLICIT_DEF)
|
LI.getActionDefinitionsBuilder(G_IMPLICIT_DEF)
|
||||||
.legalFor({v4s32, v4p0})
|
.legalFor({v4s32, v4p0})
|
||||||
.moreElementsToNextPow2(0);
|
.moreElementsToNextPow2(0);
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_IMPLICIT_DEF, {s32}));
|
EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_IMPLICIT_DEF, {s32}));
|
||||||
EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_IMPLICIT_DEF, {v2s32}));
|
EXPECT_ACTION(Unsupported, 0, LLT(), LegalityQuery(G_IMPLICIT_DEF, {v2s32}));
|
||||||
@ -244,10 +259,11 @@ TEST(LegalizerInfoTest, RuleSets) {
|
|||||||
// Test minScalarOrElt
|
// Test minScalarOrElt
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
LI.getActionDefinitionsBuilder(G_OR)
|
LI.getActionDefinitionsBuilder(G_OR)
|
||||||
.legalFor({s32})
|
.legalFor({s32})
|
||||||
.minScalarOrElt(0, s32);
|
.minScalarOrElt(0, s32);
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_OR, {s16}));
|
EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_OR, {s16}));
|
||||||
EXPECT_ACTION(WidenScalar, 0, v2s32, LegalityQuery(G_OR, {v2s16}));
|
EXPECT_ACTION(WidenScalar, 0, v2s32, LegalityQuery(G_OR, {v2s16}));
|
||||||
@ -256,10 +272,11 @@ TEST(LegalizerInfoTest, RuleSets) {
|
|||||||
// Test maxScalarOrELt
|
// Test maxScalarOrELt
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
LI.getActionDefinitionsBuilder(G_AND)
|
LI.getActionDefinitionsBuilder(G_AND)
|
||||||
.legalFor({s16})
|
.legalFor({s16})
|
||||||
.maxScalarOrElt(0, s16);
|
.maxScalarOrElt(0, s16);
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
EXPECT_ACTION(NarrowScalar, 0, s16, LegalityQuery(G_AND, {s32}));
|
EXPECT_ACTION(NarrowScalar, 0, s16, LegalityQuery(G_AND, {s32}));
|
||||||
EXPECT_ACTION(NarrowScalar, 0, v2s16, LegalityQuery(G_AND, {v2s32}));
|
EXPECT_ACTION(NarrowScalar, 0, v2s16, LegalityQuery(G_AND, {v2s32}));
|
||||||
@ -268,10 +285,11 @@ TEST(LegalizerInfoTest, RuleSets) {
|
|||||||
// Test clampScalarOrElt
|
// Test clampScalarOrElt
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
LI.getActionDefinitionsBuilder(G_XOR)
|
LI.getActionDefinitionsBuilder(G_XOR)
|
||||||
.legalFor({s16})
|
.legalFor({s16})
|
||||||
.clampScalarOrElt(0, s16, s32);
|
.clampScalarOrElt(0, s16, s32);
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
EXPECT_ACTION(NarrowScalar, 0, s32, LegalityQuery(G_XOR, {s64}));
|
EXPECT_ACTION(NarrowScalar, 0, s32, LegalityQuery(G_XOR, {s64}));
|
||||||
EXPECT_ACTION(WidenScalar, 0, s16, LegalityQuery(G_XOR, {s8}));
|
EXPECT_ACTION(WidenScalar, 0, s16, LegalityQuery(G_XOR, {s8}));
|
||||||
@ -284,10 +302,11 @@ TEST(LegalizerInfoTest, RuleSets) {
|
|||||||
// Test minScalar
|
// Test minScalar
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
LI.getActionDefinitionsBuilder(G_OR)
|
LI.getActionDefinitionsBuilder(G_OR)
|
||||||
.legalFor({s32})
|
.legalFor({s32})
|
||||||
.minScalar(0, s32);
|
.minScalar(0, s32);
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
// Only handle scalars, ignore vectors.
|
// Only handle scalars, ignore vectors.
|
||||||
EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_OR, {s16}));
|
EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_OR, {s16}));
|
||||||
@ -297,10 +316,11 @@ TEST(LegalizerInfoTest, RuleSets) {
|
|||||||
// Test maxScalar
|
// Test maxScalar
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
LI.getActionDefinitionsBuilder(G_AND)
|
LI.getActionDefinitionsBuilder(G_AND)
|
||||||
.legalFor({s16})
|
.legalFor({s16})
|
||||||
.maxScalar(0, s16);
|
.maxScalar(0, s16);
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
// Only handle scalars, ignore vectors.
|
// Only handle scalars, ignore vectors.
|
||||||
EXPECT_ACTION(NarrowScalar, 0, s16, LegalityQuery(G_AND, {s32}));
|
EXPECT_ACTION(NarrowScalar, 0, s16, LegalityQuery(G_AND, {s32}));
|
||||||
@ -310,11 +330,12 @@ TEST(LegalizerInfoTest, RuleSets) {
|
|||||||
// Test clampScalar
|
// Test clampScalar
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
|
|
||||||
LI.getActionDefinitionsBuilder(G_XOR)
|
LI.getActionDefinitionsBuilder(G_XOR)
|
||||||
.legalFor({s16})
|
.legalFor({s16})
|
||||||
.clampScalar(0, s16, s32);
|
.clampScalar(0, s16, s32);
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
EXPECT_ACTION(NarrowScalar, 0, s32, LegalityQuery(G_XOR, {s64}));
|
EXPECT_ACTION(NarrowScalar, 0, s32, LegalityQuery(G_XOR, {s64}));
|
||||||
EXPECT_ACTION(WidenScalar, 0, s16, LegalityQuery(G_XOR, {s8}));
|
EXPECT_ACTION(WidenScalar, 0, s16, LegalityQuery(G_XOR, {s8}));
|
||||||
@ -327,11 +348,12 @@ TEST(LegalizerInfoTest, RuleSets) {
|
|||||||
// Test widenScalarOrEltToNextPow2
|
// Test widenScalarOrEltToNextPow2
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
|
|
||||||
LI.getActionDefinitionsBuilder(G_AND)
|
LI.getActionDefinitionsBuilder(G_AND)
|
||||||
.legalFor({s32})
|
.legalFor({s32})
|
||||||
.widenScalarOrEltToNextPow2(0, 32);
|
.widenScalarOrEltToNextPow2(0, 32);
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
// Handle scalars and vectors
|
// Handle scalars and vectors
|
||||||
EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_AND, {s5}));
|
EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_AND, {s5}));
|
||||||
@ -343,11 +365,12 @@ TEST(LegalizerInfoTest, RuleSets) {
|
|||||||
// Test widenScalarToNextPow2
|
// Test widenScalarToNextPow2
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
|
|
||||||
LI.getActionDefinitionsBuilder(G_AND)
|
LI.getActionDefinitionsBuilder(G_AND)
|
||||||
.legalFor({s32})
|
.legalFor({s32})
|
||||||
.widenScalarToNextPow2(0, 32);
|
.widenScalarToNextPow2(0, 32);
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_AND, {s5}));
|
EXPECT_ACTION(WidenScalar, 0, s32, LegalityQuery(G_AND, {s5}));
|
||||||
EXPECT_ACTION(WidenScalar, 0, s64, LegalityQuery(G_AND, {s33}));
|
EXPECT_ACTION(WidenScalar, 0, s64, LegalityQuery(G_AND, {s33}));
|
||||||
@ -366,10 +389,11 @@ TEST(LegalizerInfoTest, MMOAlignment) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
LI.getActionDefinitionsBuilder(G_LOAD)
|
LI.getActionDefinitionsBuilder(G_LOAD)
|
||||||
.legalForTypesWithMemDesc({{s32, p0, 32, 32}});
|
.legalForTypesWithMemDesc({{s32, p0, 32, 32}});
|
||||||
|
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
EXPECT_ACTION(Legal, 0, LLT(),
|
EXPECT_ACTION(Legal, 0, LLT(),
|
||||||
LegalityQuery(G_LOAD, {s32, p0},
|
LegalityQuery(G_LOAD, {s32, p0},
|
||||||
@ -391,10 +415,11 @@ TEST(LegalizerInfoTest, MMOAlignment) {
|
|||||||
const uint64_t MaxAlignment = UINT64_C(1) << 29;
|
const uint64_t MaxAlignment = UINT64_C(1) << 29;
|
||||||
const uint64_t MaxAlignInBits = 8 * MaxAlignment;
|
const uint64_t MaxAlignInBits = 8 * MaxAlignment;
|
||||||
LegalizerInfo LI;
|
LegalizerInfo LI;
|
||||||
|
auto &LegacyInfo = LI.getLegacyLegalizerInfo();
|
||||||
LI.getActionDefinitionsBuilder(G_LOAD)
|
LI.getActionDefinitionsBuilder(G_LOAD)
|
||||||
.legalForTypesWithMemDesc({{s32, p0, 32, MaxAlignInBits}});
|
.legalForTypesWithMemDesc({{s32, p0, 32, MaxAlignInBits}});
|
||||||
|
|
||||||
LI.computeTables();
|
LegacyInfo.computeTables();
|
||||||
|
|
||||||
EXPECT_ACTION(Legal, 0, LLT(),
|
EXPECT_ACTION(Legal, 0, LLT(),
|
||||||
LegalityQuery(G_LOAD, {s32, p0},
|
LegalityQuery(G_LOAD, {s32, p0},
|
||||||
|
Loading…
Reference in New Issue
Block a user