2017-09-22 01:20:16 +02:00
|
|
|
//===- LegalizeVectorOps.cpp - Implement SelectionDAG::LegalizeVectors ----===//
|
2009-05-23 14:35:30 +02:00
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-05-23 14:35:30 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the SelectionDAG::LegalizeVectors method.
|
|
|
|
//
|
|
|
|
// The vector legalizer looks for vector operations which might need to be
|
2009-05-27 09:58:35 +02:00
|
|
|
// scalarized and legalizes them. This is a separate step from Legalize because
|
|
|
|
// scalarizing can introduce illegal types. For example, suppose we have an
|
2009-05-23 14:35:30 +02:00
|
|
|
// ISD::SDIV of type v2i64 on x86-32. The type is legal (for example, addition
|
|
|
|
// on a v2i64 is legal), but ISD::SDIV isn't legal, so we have to unroll the
|
|
|
|
// operation, which introduces nodes with the illegal type i64 which must be
|
|
|
|
// expanded. Similarly, suppose we have an ISD::SRA of type v16i8 on PowerPC;
|
|
|
|
// the operation must be unrolled, which introduces nodes with the illegal
|
|
|
|
// type i8 which must be promoted.
|
|
|
|
//
|
|
|
|
// This does not legalize vector manipulations like ISD::BUILD_VECTOR,
|
Major calling convention code refactoring.
Instead of awkwardly encoding calling-convention information with ISD::CALL,
ISD::FORMAL_ARGUMENTS, ISD::RET, and ISD::ARG_FLAGS nodes, TargetLowering
provides three virtual functions for targets to override:
LowerFormalArguments, LowerCall, and LowerRet, which replace the custom
lowering done on the special nodes. They provide the same information, but
in a more immediately usable format.
This also reworks much of the target-independent tail call logic. The
decision of whether or not to perform a tail call is now cleanly split
between target-independent portions, and the target dependent portion
in IsEligibleForTailCallOptimization.
This also synchronizes all in-tree targets, to help enable future
refactoring and feature work.
llvm-svn: 78142
2009-08-05 03:29:28 +02:00
|
|
|
// or operations that happen to take a vector which are custom-lowered;
|
|
|
|
// the legalization for such operations never produces nodes
|
2009-05-23 14:35:30 +02:00
|
|
|
// with illegal types, so it's okay to put off legalizing them until
|
|
|
|
// SelectionDAG::Legalize runs.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-09-22 01:20:16 +02:00
|
|
|
#include "llvm/ADT/APInt.h"
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
|
|
#include "llvm/CodeGen/ISDOpcodes.h"
|
|
|
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
2009-05-23 14:35:30 +02:00
|
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
2017-09-22 01:20:16 +02:00
|
|
|
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
2017-11-17 02:07:10 +01:00
|
|
|
#include "llvm/CodeGen/TargetLowering.h"
|
2018-03-29 19:21:10 +02:00
|
|
|
#include "llvm/CodeGen/ValueTypes.h"
|
2017-09-22 01:20:16 +02:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
2019-10-19 03:31:09 +02:00
|
|
|
#include "llvm/Support/Debug.h"
|
2017-09-22 01:20:16 +02:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2018-03-24 00:58:25 +01:00
|
|
|
#include "llvm/Support/MachineValueType.h"
|
2017-09-22 01:20:16 +02:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <iterator>
|
|
|
|
#include <utility>
|
|
|
|
|
2009-05-23 14:35:30 +02:00
|
|
|
using namespace llvm;
|
|
|
|
|
2017-12-28 20:46:01 +01:00
|
|
|
#define DEBUG_TYPE "legalizevectorops"
|
|
|
|
|
2009-05-23 14:35:30 +02:00
|
|
|
namespace {
|
2017-09-22 01:20:16 +02:00
|
|
|
|
2009-05-23 14:35:30 +02:00
|
|
|
class VectorLegalizer {
|
|
|
|
SelectionDAG& DAG;
|
2010-04-17 17:26:15 +02:00
|
|
|
const TargetLowering &TLI;
|
2017-09-22 01:20:16 +02:00
|
|
|
bool Changed = false; // Keep track of whether anything changed
|
2009-05-23 14:35:30 +02:00
|
|
|
|
2014-07-02 04:16:57 +02:00
|
|
|
/// For nodes that are of legal width, and that have more than one use, this
|
|
|
|
/// map indicates what regularized operand to use. This allows us to avoid
|
|
|
|
/// legalizing the same thing more than once.
|
2013-01-25 16:18:54 +01:00
|
|
|
SmallDenseMap<SDValue, SDValue, 64> LegalizedNodes;
|
2009-05-23 14:35:30 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Adds a node to the translation cache.
|
2009-05-23 14:35:30 +02:00
|
|
|
void AddLegalizedOperand(SDValue From, SDValue To) {
|
|
|
|
LegalizedNodes.insert(std::make_pair(From, To));
|
|
|
|
// If someone requests legalization of the new node, return itself.
|
|
|
|
if (From != To)
|
|
|
|
LegalizedNodes.insert(std::make_pair(To, To));
|
|
|
|
}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Legalizes the given node.
|
2009-05-23 14:35:30 +02:00
|
|
|
SDValue LegalizeOp(SDValue Op);
|
2014-07-02 04:16:57 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Assuming the node is legal, "legalize" the results.
|
2020-01-10 19:13:45 +01:00
|
|
|
SDValue TranslateLegalizeResults(SDValue Op, SDNode *Result);
|
|
|
|
|
|
|
|
/// Make sure Results are legal and update the translation cache.
|
|
|
|
SDValue RecursivelyLegalizeResults(SDValue Op,
|
|
|
|
MutableArrayRef<SDValue> Results);
|
|
|
|
|
|
|
|
/// Wrapper to interface LowerOperation with a vector of Results.
|
|
|
|
/// Returns false if the target wants to use default expansion. Otherwise
|
|
|
|
/// returns true. If return is true and the Results are empty, then the
|
|
|
|
/// target wants to keep the input node as is.
|
|
|
|
bool LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results);
|
2014-07-02 04:16:57 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implements unrolling a VSETCC.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue UnrollVSETCC(SDNode *Node);
|
2014-07-02 04:16:57 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implement expand-based legalization of vector operations.
|
2014-07-02 08:23:34 +02:00
|
|
|
///
|
|
|
|
/// This is just a high-level routine to dispatch to specific code paths for
|
|
|
|
/// operations to legalize them.
|
2020-01-10 19:13:45 +01:00
|
|
|
void Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2014-07-02 08:23:34 +02:00
|
|
|
|
2018-10-28 14:07:25 +01:00
|
|
|
/// Implements expansion for FP_TO_UINT; falls back to UnrollVectorOp if
|
|
|
|
/// FP_TO_SINT isn't legal.
|
2020-01-11 20:36:50 +01:00
|
|
|
void ExpandFP_TO_UINT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2018-10-28 14:07:25 +01:00
|
|
|
|
2014-07-02 04:16:57 +02:00
|
|
|
/// Implements expansion for UINT_TO_FLOAT; falls back to UnrollVectorOp if
|
|
|
|
/// SINT_TO_FLOAT and SHR on vectors isn't legal.
|
2020-01-11 20:36:50 +01:00
|
|
|
void ExpandUINT_TO_FLOAT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2014-07-02 04:16:57 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implement expansion for SIGN_EXTEND_INREG using SRL and SRA.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue ExpandSEXTINREG(SDNode *Node);
|
2014-07-02 04:16:57 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implement expansion for ANY_EXTEND_VECTOR_INREG.
|
2014-07-10 14:32:32 +02:00
|
|
|
///
|
|
|
|
/// Shuffles the low lanes of the operand into place and bitcasts to the proper
|
|
|
|
/// type. The contents of the bits in the extended part of each element are
|
|
|
|
/// undef.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node);
|
2014-07-10 14:32:32 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implement expansion for SIGN_EXTEND_VECTOR_INREG.
|
2014-07-10 14:32:32 +02:00
|
|
|
///
|
|
|
|
/// Shuffles the low lanes of the operand into place, bitcasts to the proper
|
|
|
|
/// type, then shifts left and arithmetic shifts right to introduce a sign
|
|
|
|
/// extension.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node);
|
2014-07-10 14:32:32 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implement expansion for ZERO_EXTEND_VECTOR_INREG.
|
2014-07-09 12:58:18 +02:00
|
|
|
///
|
|
|
|
/// Shuffles the low lanes of the operand into place and blends zeros into
|
|
|
|
/// the remaining lanes, finally bitcasting to the proper type.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node);
|
2014-07-09 12:58:18 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Expand bswap of vectors into a shuffle if legal.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue ExpandBSWAP(SDNode *Node);
|
2014-07-02 04:16:57 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implement vselect in terms of XOR, AND, OR when blend is not
|
2014-07-02 04:16:57 +02:00
|
|
|
/// supported by the target.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue ExpandVSELECT(SDNode *Node);
|
|
|
|
SDValue ExpandSELECT(SDNode *Node);
|
2020-01-10 19:13:45 +01:00
|
|
|
std::pair<SDValue, SDValue> ExpandLoad(SDNode *N);
|
|
|
|
SDValue ExpandStore(SDNode *N);
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue ExpandFNEG(SDNode *Node);
|
2020-01-11 21:12:53 +01:00
|
|
|
void ExpandFSUB(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
|
|
|
void ExpandBITREVERSE(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2020-01-11 20:36:50 +01:00
|
|
|
void ExpandUADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
|
|
|
void ExpandSADDSUBO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
|
|
|
void ExpandMULO(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2019-12-16 15:25:52 +01:00
|
|
|
void ExpandFixedPointDiv(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue ExpandStrictFPOp(SDNode *Node);
|
|
|
|
void ExpandStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
|
|
|
|
|
|
|
void UnrollStrictFPOp(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2020-01-05 02:03:33 +01:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implements vector promotion.
|
2014-07-02 04:16:57 +02:00
|
|
|
///
|
|
|
|
/// This is essentially just bitcasting the operands to a different type and
|
|
|
|
/// bitcasting the result back to the original type.
|
2020-01-10 19:13:45 +01:00
|
|
|
void Promote(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2014-07-02 04:16:57 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implements [SU]INT_TO_FP vector promotion.
|
2014-07-02 04:16:57 +02:00
|
|
|
///
|
2018-01-01 20:21:35 +01:00
|
|
|
/// This is a [zs]ext of the input operand to a larger integer type.
|
2020-01-11 20:36:50 +01:00
|
|
|
void PromoteINT_TO_FP(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2014-07-02 04:16:57 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Implements FP_TO_[SU]INT vector promotion of the result type.
|
2014-07-02 04:16:57 +02:00
|
|
|
///
|
2018-01-01 20:21:35 +01:00
|
|
|
/// It is promoted to a larger integer type. The result is then
|
2014-07-02 04:16:57 +02:00
|
|
|
/// truncated back to the original type.
|
2020-01-11 20:36:50 +01:00
|
|
|
void PromoteFP_TO_INT(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
2009-05-23 14:35:30 +02:00
|
|
|
|
2014-07-02 04:16:57 +02:00
|
|
|
public:
|
2017-09-22 01:20:16 +02:00
|
|
|
VectorLegalizer(SelectionDAG& dag) :
|
|
|
|
DAG(dag), TLI(dag.getTargetLoweringInfo()) {}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Begin legalizer the vector operations in the DAG.
|
2009-05-23 14:35:30 +02:00
|
|
|
bool Run();
|
|
|
|
};
|
|
|
|
|
2017-09-22 01:20:16 +02:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
2009-05-23 14:35:30 +02:00
|
|
|
bool VectorLegalizer::Run() {
|
2013-02-23 00:33:30 +01:00
|
|
|
// Before we start legalizing vector nodes, check if there are any vectors.
|
|
|
|
bool HasVectors = false;
|
|
|
|
for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
|
2014-03-02 13:27:27 +01:00
|
|
|
E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I) {
|
2013-02-23 00:33:30 +01:00
|
|
|
// Check if the values of the nodes contain vectors. We don't need to check
|
|
|
|
// the operands because we are going to check their values at some point.
|
2020-02-26 17:54:18 +01:00
|
|
|
HasVectors = llvm::any_of(I->values(), [](EVT T) { return T.isVector(); });
|
2013-02-23 00:33:30 +01:00
|
|
|
|
|
|
|
// If we found a vector node we can start the legalization.
|
|
|
|
if (HasVectors)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this basic block has no vectors then no need to legalize vectors.
|
|
|
|
if (!HasVectors)
|
|
|
|
return false;
|
|
|
|
|
2009-05-23 14:35:30 +02:00
|
|
|
// The legalize process is inherently a bottom-up recursive process (users
|
|
|
|
// legalize their uses before themselves). Given infinite stack space, we
|
|
|
|
// could just start legalizing on the root and traverse the whole graph. In
|
|
|
|
// practice however, this causes us to run out of stack space on large basic
|
|
|
|
// blocks. To avoid this problem, compute an ordering of the nodes where each
|
|
|
|
// node is only legalized after all of its operands are legalized.
|
|
|
|
DAG.AssignTopologicalOrder();
|
|
|
|
for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
|
2014-03-02 13:27:27 +01:00
|
|
|
E = std::prev(DAG.allnodes_end()); I != std::next(E); ++I)
|
2015-10-13 21:47:46 +02:00
|
|
|
LegalizeOp(SDValue(&*I, 0));
|
2009-05-23 14:35:30 +02:00
|
|
|
|
|
|
|
// Finally, it's possible the root changed. Get the new root.
|
|
|
|
SDValue OldRoot = DAG.getRoot();
|
|
|
|
assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?");
|
|
|
|
DAG.setRoot(LegalizedNodes[OldRoot]);
|
|
|
|
|
|
|
|
LegalizedNodes.clear();
|
|
|
|
|
|
|
|
// Remove dead nodes now.
|
|
|
|
DAG.RemoveDeadNodes();
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
SDValue VectorLegalizer::TranslateLegalizeResults(SDValue Op, SDNode *Result) {
|
|
|
|
assert(Op->getNumValues() == Result->getNumValues() &&
|
|
|
|
"Unexpected number of results");
|
2009-05-23 14:35:30 +02:00
|
|
|
// Generic legalization: just pass the operand through.
|
2020-01-10 19:13:45 +01:00
|
|
|
for (unsigned i = 0, e = Op->getNumValues(); i != e; ++i)
|
|
|
|
AddLegalizedOperand(Op.getValue(i), SDValue(Result, i));
|
|
|
|
return SDValue(Result, Op.getResNo());
|
|
|
|
}
|
|
|
|
|
|
|
|
SDValue
|
|
|
|
VectorLegalizer::RecursivelyLegalizeResults(SDValue Op,
|
|
|
|
MutableArrayRef<SDValue> Results) {
|
|
|
|
assert(Results.size() == Op->getNumValues() &&
|
|
|
|
"Unexpected number of results");
|
|
|
|
// Make sure that the generated code is itself legal.
|
|
|
|
for (unsigned i = 0, e = Results.size(); i != e; ++i) {
|
|
|
|
Results[i] = LegalizeOp(Results[i]);
|
|
|
|
AddLegalizedOperand(Op.getValue(i), Results[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Results[Op.getResNo()];
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
|
|
|
|
// Note that LegalizeOp may be reentered even from single-use nodes, which
|
|
|
|
// means that we always must cache transformed nodes.
|
|
|
|
DenseMap<SDValue, SDValue>::iterator I = LegalizedNodes.find(Op);
|
|
|
|
if (I != LegalizedNodes.end()) return I->second;
|
|
|
|
|
|
|
|
// Legalize the operands
|
|
|
|
SmallVector<SDValue, 8> Ops;
|
2020-01-10 19:13:45 +01:00
|
|
|
for (const SDValue &Oper : Op->op_values())
|
|
|
|
Ops.push_back(LegalizeOp(Oper));
|
2009-05-23 14:35:30 +02:00
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
SDNode *Node = DAG.UpdateNodeOperands(Op.getNode(), Ops);
|
2009-05-23 14:35:30 +02:00
|
|
|
|
2011-10-15 09:41:10 +02:00
|
|
|
if (Op.getOpcode() == ISD::LOAD) {
|
2020-01-10 19:13:45 +01:00
|
|
|
LoadSDNode *LD = cast<LoadSDNode>(Node);
|
2011-10-15 09:41:10 +02:00
|
|
|
ISD::LoadExtType ExtType = LD->getExtensionType();
|
2017-12-28 20:46:01 +01:00
|
|
|
if (LD->getMemoryVT().isVector() && ExtType != ISD::NON_EXTLOAD) {
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "\nLegalizing extending vector load: ";
|
|
|
|
Node->dump(&DAG));
|
[SelectionDAG] Allow targets to specify legality of extloads' result
type (in addition to the memory type).
The *LoadExt* legalization handling used to only have one type, the
memory type. This forced users to assume that as long as the extload
for the memory type was declared legal, and the result type was legal,
the whole extload was legal.
However, this isn't always the case. For instance, on X86, with AVX,
this is legal:
v4i32 load, zext from v4i8
but this isn't:
v4i64 load, zext from v4i8
Whereas v4i64 is (arguably) legal, even without AVX2.
Note that the same thing was done a while ago for truncstores (r46140),
but I assume no one needed it yet for extloads, so here we go.
Calls to getLoadExtAction were changed to add the value type, found
manually in the surrounding code.
Calls to setLoadExtAction were mechanically changed, by wrapping the
call in a loop, to match previous behavior. The loop iterates over
the MVT subrange corresponding to the memory type (FP vectors, etc...).
I also pulled neighboring setTruncStoreActions into some of the loops;
those shouldn't make a difference, as the additional types are illegal.
(e.g., i128->i1 truncstores on PPC.)
No functional change intended.
Differential Revision: http://reviews.llvm.org/D6532
llvm-svn: 225421
2015-01-08 01:51:32 +01:00
|
|
|
switch (TLI.getLoadExtAction(LD->getExtensionType(), LD->getValueType(0),
|
|
|
|
LD->getMemoryVT())) {
|
[x86] Make vector legalization of extloads work more like the "normal"
vector operation legalization with support for custom target lowering
and fallback to expand when it fails, and use this to implement sext and
anyext load lowering for x86 in a more principled way.
Previously, the x86 backend relied on a target DAG combine to "combine
away" sextload and extload nodes prior to legalization, or would expand
them during legalization with terrible code. This is particularly
problematic because the DAG combine relies on running over non-canonical
DAG nodes at just the right time to match several common and important
patterns. It used a combine rather than lowering because we didn't have
good lowering support, and to expose some tricks being employed to more
combine phases.
With this change it becomes a proper lowering operation, the backend
marks that it can lower these nodes, and I've added support for handling
the canonical forms that don't have direct legal representations such as
sextload of a v4i8 -> v4i64 on AVX1. With this change, our test cases
for this behavior continue to pass even after the DAG combiner beigns
running more systematically over every node.
There is some noise caused by this in the test suite where we actually
use vector extends instead of subregister extraction. This doesn't
really seem like the right thing to do, but is unlikely to be a critical
regression. We do regress in one case where by lowering to the
target-specific patterns early we were able to combine away extraneous
legal math nodes. However, this regression is completely addressed by
switching to a widening based legalization which is what I'm working
toward anyways, so I've just switched the test to that mode.
Differential Revision: http://reviews.llvm.org/D4654
llvm-svn: 213897
2014-07-25 00:09:56 +02:00
|
|
|
default: llvm_unreachable("This action is not supported yet!");
|
|
|
|
case TargetLowering::Legal:
|
2020-01-10 19:13:45 +01:00
|
|
|
return TranslateLegalizeResults(Op, Node);
|
|
|
|
case TargetLowering::Custom: {
|
|
|
|
SmallVector<SDValue, 2> ResultVals;
|
|
|
|
if (LowerOperationWrapper(Node, ResultVals)) {
|
|
|
|
if (ResultVals.empty())
|
|
|
|
return TranslateLegalizeResults(Op, Node);
|
|
|
|
|
|
|
|
Changed = true;
|
|
|
|
return RecursivelyLegalizeResults(Op, ResultVals);
|
[x86] Make vector legalization of extloads work more like the "normal"
vector operation legalization with support for custom target lowering
and fallback to expand when it fails, and use this to implement sext and
anyext load lowering for x86 in a more principled way.
Previously, the x86 backend relied on a target DAG combine to "combine
away" sextload and extload nodes prior to legalization, or would expand
them during legalization with terrible code. This is particularly
problematic because the DAG combine relies on running over non-canonical
DAG nodes at just the right time to match several common and important
patterns. It used a combine rather than lowering because we didn't have
good lowering support, and to expose some tricks being employed to more
combine phases.
With this change it becomes a proper lowering operation, the backend
marks that it can lower these nodes, and I've added support for handling
the canonical forms that don't have direct legal representations such as
sextload of a v4i8 -> v4i64 on AVX1. With this change, our test cases
for this behavior continue to pass even after the DAG combiner beigns
running more systematically over every node.
There is some noise caused by this in the test suite where we actually
use vector extends instead of subregister extraction. This doesn't
really seem like the right thing to do, but is unlikely to be a critical
regression. We do regress in one case where by lowering to the
target-specific patterns early we were able to combine away extraneous
legal math nodes. However, this regression is completely addressed by
switching to a widening based legalization which is what I'm working
toward anyways, so I've just switched the test to that mode.
Differential Revision: http://reviews.llvm.org/D4654
llvm-svn: 213897
2014-07-25 00:09:56 +02:00
|
|
|
}
|
2017-06-03 07:11:14 +02:00
|
|
|
LLVM_FALLTHROUGH;
|
2020-01-10 19:13:45 +01:00
|
|
|
}
|
2020-01-03 20:52:18 +01:00
|
|
|
case TargetLowering::Expand: {
|
[x86] Make vector legalization of extloads work more like the "normal"
vector operation legalization with support for custom target lowering
and fallback to expand when it fails, and use this to implement sext and
anyext load lowering for x86 in a more principled way.
Previously, the x86 backend relied on a target DAG combine to "combine
away" sextload and extload nodes prior to legalization, or would expand
them during legalization with terrible code. This is particularly
problematic because the DAG combine relies on running over non-canonical
DAG nodes at just the right time to match several common and important
patterns. It used a combine rather than lowering because we didn't have
good lowering support, and to expose some tricks being employed to more
combine phases.
With this change it becomes a proper lowering operation, the backend
marks that it can lower these nodes, and I've added support for handling
the canonical forms that don't have direct legal representations such as
sextload of a v4i8 -> v4i64 on AVX1. With this change, our test cases
for this behavior continue to pass even after the DAG combiner beigns
running more systematically over every node.
There is some noise caused by this in the test suite where we actually
use vector extends instead of subregister extraction. This doesn't
really seem like the right thing to do, but is unlikely to be a critical
regression. We do regress in one case where by lowering to the
target-specific patterns early we were able to combine away extraneous
legal math nodes. However, this regression is completely addressed by
switching to a widening based legalization which is what I'm working
toward anyways, so I've just switched the test to that mode.
Differential Revision: http://reviews.llvm.org/D4654
llvm-svn: 213897
2014-07-25 00:09:56 +02:00
|
|
|
Changed = true;
|
2020-01-10 19:13:45 +01:00
|
|
|
std::pair<SDValue, SDValue> Tmp = ExpandLoad(Node);
|
2020-01-03 20:52:18 +01:00
|
|
|
AddLegalizedOperand(Op.getValue(0), Tmp.first);
|
|
|
|
AddLegalizedOperand(Op.getValue(1), Tmp.second);
|
|
|
|
return Op.getResNo() ? Tmp.first : Tmp.second;
|
|
|
|
}
|
[x86] Make vector legalization of extloads work more like the "normal"
vector operation legalization with support for custom target lowering
and fallback to expand when it fails, and use this to implement sext and
anyext load lowering for x86 in a more principled way.
Previously, the x86 backend relied on a target DAG combine to "combine
away" sextload and extload nodes prior to legalization, or would expand
them during legalization with terrible code. This is particularly
problematic because the DAG combine relies on running over non-canonical
DAG nodes at just the right time to match several common and important
patterns. It used a combine rather than lowering because we didn't have
good lowering support, and to expose some tricks being employed to more
combine phases.
With this change it becomes a proper lowering operation, the backend
marks that it can lower these nodes, and I've added support for handling
the canonical forms that don't have direct legal representations such as
sextload of a v4i8 -> v4i64 on AVX1. With this change, our test cases
for this behavior continue to pass even after the DAG combiner beigns
running more systematically over every node.
There is some noise caused by this in the test suite where we actually
use vector extends instead of subregister extraction. This doesn't
really seem like the right thing to do, but is unlikely to be a critical
regression. We do regress in one case where by lowering to the
target-specific patterns early we were able to combine away extraneous
legal math nodes. However, this regression is completely addressed by
switching to a widening based legalization which is what I'm working
toward anyways, so I've just switched the test to that mode.
Differential Revision: http://reviews.llvm.org/D4654
llvm-svn: 213897
2014-07-25 00:09:56 +02:00
|
|
|
}
|
2017-12-28 20:46:01 +01:00
|
|
|
}
|
2011-10-15 09:41:10 +02:00
|
|
|
} else if (Op.getOpcode() == ISD::STORE) {
|
2020-01-10 19:13:45 +01:00
|
|
|
StoreSDNode *ST = cast<StoreSDNode>(Node);
|
2011-10-15 09:41:10 +02:00
|
|
|
EVT StVT = ST->getMemoryVT();
|
2012-12-19 09:28:51 +01:00
|
|
|
MVT ValVT = ST->getValue().getSimpleValueType();
|
2017-12-28 20:46:01 +01:00
|
|
|
if (StVT.isVector() && ST->isTruncatingStore()) {
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "\nLegalizing truncating vector store: ";
|
|
|
|
Node->dump(&DAG));
|
2015-11-25 10:11:53 +01:00
|
|
|
switch (TLI.getTruncStoreAction(ValVT, StVT)) {
|
2012-02-05 09:31:47 +01:00
|
|
|
default: llvm_unreachable("This action is not supported yet!");
|
2011-10-15 09:41:10 +02:00
|
|
|
case TargetLowering::Legal:
|
2020-01-10 19:13:45 +01:00
|
|
|
return TranslateLegalizeResults(Op, Node);
|
[SDAG] Handle LowerOperation returning its input consistently
For almost all node types, if the target requested custom lowering, and
LowerOperation returned its input, we'd treat the original node as legal. This
did not work, however, for many loads and stores, because they follow
slightly different code paths, and we did not account for the possibility of
LowerOperation returning its input at those call sites.
I think that we now handle this consistently everywhere. At the call sites in
LegalizeDAG, we used to assert in this case, so there's no functional change
for any existing code there. For the call sites in LegalizeVectorOps, this
really only affects whether or not we set Changed = true, but I think makes the
semantics clearer.
No test case here, but it will be covered by an upcoming PowerPC commit adding
QPX support.
llvm-svn: 230332
2015-02-24 13:59:47 +01:00
|
|
|
case TargetLowering::Custom: {
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVector<SDValue, 1> ResultVals;
|
|
|
|
if (LowerOperationWrapper(Node, ResultVals)) {
|
|
|
|
if (ResultVals.empty())
|
|
|
|
return TranslateLegalizeResults(Op, Node);
|
|
|
|
|
2018-11-16 22:04:58 +01:00
|
|
|
Changed = true;
|
2020-01-10 19:13:45 +01:00
|
|
|
return RecursivelyLegalizeResults(Op, ResultVals);
|
2018-11-16 22:04:58 +01:00
|
|
|
}
|
2020-01-10 19:13:45 +01:00
|
|
|
LLVM_FALLTHROUGH;
|
[SDAG] Handle LowerOperation returning its input consistently
For almost all node types, if the target requested custom lowering, and
LowerOperation returned its input, we'd treat the original node as legal. This
did not work, however, for many loads and stores, because they follow
slightly different code paths, and we did not account for the possibility of
LowerOperation returning its input at those call sites.
I think that we now handle this consistently everywhere. At the call sites in
LegalizeDAG, we used to assert in this case, so there's no functional change
for any existing code there. For the call sites in LegalizeVectorOps, this
really only affects whether or not we set Changed = true, but I think makes the
semantics clearer.
No test case here, but it will be covered by an upcoming PowerPC commit adding
QPX support.
llvm-svn: 230332
2015-02-24 13:59:47 +01:00
|
|
|
}
|
2020-01-03 20:52:18 +01:00
|
|
|
case TargetLowering::Expand: {
|
2011-10-15 09:41:10 +02:00
|
|
|
Changed = true;
|
2020-01-10 19:13:45 +01:00
|
|
|
SDValue Chain = ExpandStore(Node);
|
2020-01-03 20:52:18 +01:00
|
|
|
AddLegalizedOperand(Op, Chain);
|
|
|
|
return Chain;
|
|
|
|
}
|
2011-10-15 09:41:10 +02:00
|
|
|
}
|
2017-12-28 20:46:01 +01:00
|
|
|
}
|
2018-10-08 02:04:55 +02:00
|
|
|
}
|
2011-10-15 09:41:10 +02:00
|
|
|
|
2020-02-26 17:54:18 +01:00
|
|
|
bool HasVectorValueOrOp =
|
|
|
|
llvm::any_of(Node->values(), [](EVT T) { return T.isVector(); }) ||
|
|
|
|
llvm::any_of(Node->op_values(),
|
|
|
|
[](SDValue O) { return O.getValueType().isVector(); });
|
[SDAG][AArch64] Legalize VECREDUCE
Fixes https://bugs.llvm.org/show_bug.cgi?id=36796.
Implement basic legalizations (PromoteIntRes, PromoteIntOp,
ExpandIntRes, ScalarizeVecOp, WidenVecOp) for VECREDUCE opcodes.
There are more legalizations missing (esp float legalizations),
but there's no way to test them right now, so I'm not adding them.
This also includes a few more changes to make this work somewhat
reasonably:
* Add support for expanding VECREDUCE in SDAG. Usually
experimental.vector.reduce is expanded prior to codegen, but if the
target does have native vector reduce, it may of course still be
necessary to expand due to legalization issues. This uses a shuffle
reduction if possible, followed by a naive scalar reduction.
* Allow the result type of integer VECREDUCE to be larger than the
vector element type. For example we need to be able to reduce a v8i8
into an (nominally) i32 result type on AArch64.
* Use the vector operand type rather than the scalar result type to
determine the action, so we can control exactly which vector types are
supported. Also change the legalize vector op code to handle
operations that only have vector operands, but no vector results, as
is the case for VECREDUCE.
* Default VECREDUCE to Expand. On AArch64 (only target using VECREDUCE),
explicitly specify for which vector types the reductions are supported.
This does not handle anything related to VECREDUCE_STRICT_*.
Differential Revision: https://reviews.llvm.org/D58015
llvm-svn: 355860
2019-03-11 21:22:13 +01:00
|
|
|
if (!HasVectorValueOrOp)
|
2020-01-10 19:13:45 +01:00
|
|
|
return TranslateLegalizeResults(Op, Node);
|
2009-05-23 14:35:30 +02:00
|
|
|
|
2018-06-13 16:32:12 +02:00
|
|
|
TargetLowering::LegalizeAction Action = TargetLowering::Legal;
|
2019-10-16 21:24:47 +02:00
|
|
|
EVT ValVT;
|
2009-05-23 14:35:30 +02:00
|
|
|
switch (Op.getOpcode()) {
|
|
|
|
default:
|
2020-01-10 19:13:45 +01:00
|
|
|
return TranslateLegalizeResults(Op, Node);
|
2020-01-12 01:04:28 +01:00
|
|
|
case ISD::MERGE_VALUES:
|
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
|
|
|
|
// This operation lies about being legal: when it claims to be legal,
|
|
|
|
// it should actually be expanded.
|
|
|
|
if (Action == TargetLowering::Legal)
|
|
|
|
Action = TargetLowering::Expand;
|
|
|
|
break;
|
2020-01-17 03:32:30 +01:00
|
|
|
#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
|
2019-11-05 14:42:16 +01:00
|
|
|
case ISD::STRICT_##DAGN:
|
|
|
|
#include "llvm/IR/ConstrainedOps.def"
|
2019-10-16 21:24:47 +02:00
|
|
|
ValVT = Node->getValueType(0);
|
|
|
|
if (Op.getOpcode() == ISD::STRICT_SINT_TO_FP ||
|
|
|
|
Op.getOpcode() == ISD::STRICT_UINT_TO_FP)
|
|
|
|
ValVT = Node->getOperand(1).getValueType();
|
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(), ValVT);
|
2019-08-06 12:43:13 +02:00
|
|
|
// If we're asked to expand a strict vector floating-point operation,
|
|
|
|
// by default we're going to simply unroll it. That is usually the
|
|
|
|
// best approach, except in the case where the resulting strict (scalar)
|
|
|
|
// operations would themselves use the fallback mutation to non-strict.
|
|
|
|
// In that specific case, just do the fallback on the vector op.
|
2019-11-22 02:17:19 +01:00
|
|
|
if (Action == TargetLowering::Expand && !TLI.isStrictFPEnabled() &&
|
2019-10-16 21:24:47 +02:00
|
|
|
TLI.getStrictFPOperationAction(Node->getOpcode(), ValVT) ==
|
|
|
|
TargetLowering::Legal) {
|
|
|
|
EVT EltVT = ValVT.getVectorElementType();
|
2019-08-06 12:43:13 +02:00
|
|
|
if (TLI.getOperationAction(Node->getOpcode(), EltVT)
|
|
|
|
== TargetLowering::Expand &&
|
|
|
|
TLI.getStrictFPOperationAction(Node->getOpcode(), EltVT)
|
|
|
|
== TargetLowering::Legal)
|
|
|
|
Action = TargetLowering::Legal;
|
|
|
|
}
|
2018-06-13 16:32:12 +02:00
|
|
|
break;
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::ADD:
|
|
|
|
case ISD::SUB:
|
|
|
|
case ISD::MUL:
|
2018-11-29 20:36:17 +01:00
|
|
|
case ISD::MULHS:
|
|
|
|
case ISD::MULHU:
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::SDIV:
|
|
|
|
case ISD::UDIV:
|
|
|
|
case ISD::SREM:
|
|
|
|
case ISD::UREM:
|
Combining DIV+REM->DIVREM doesn't belong in LegalizeDAG; move it over into DAGCombiner.
Summary:
In addition to moving the code over, this patch amends the DIV,REM -> DIVREM
combining to run on all affected nodes at once: if the nodes are converted
to DIVREM one at a time, then the resulting DIVREM may get legalized by the
backend into something target-specific that we won't be able to recognize
and correlate with the remaining nodes.
The motivation is to "prepare terrain" for D13862: when we set DIV and REM
to be legalized to libcalls, instead of the DIVREM, we otherwise lose the
ability to combine them together. To prevent this, we need to take the
DIV,REM -> DIVREM combining out of the lowering stage.
Reviewers: RKSimon, eli.friedman, rengolin
Subscribers: john.brawn, rengolin, llvm-commits
Differential Revision: http://reviews.llvm.org/D13733
llvm-svn: 250825
2015-10-20 15:06:02 +02:00
|
|
|
case ISD::SDIVREM:
|
|
|
|
case ISD::UDIVREM:
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::FADD:
|
|
|
|
case ISD::FSUB:
|
|
|
|
case ISD::FMUL:
|
|
|
|
case ISD::FDIV:
|
|
|
|
case ISD::FREM:
|
|
|
|
case ISD::AND:
|
|
|
|
case ISD::OR:
|
|
|
|
case ISD::XOR:
|
|
|
|
case ISD::SHL:
|
|
|
|
case ISD::SRA:
|
|
|
|
case ISD::SRL:
|
2019-01-06 08:06:35 +01:00
|
|
|
case ISD::FSHL:
|
|
|
|
case ISD::FSHR:
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::ROTL:
|
|
|
|
case ISD::ROTR:
|
2019-01-12 10:59:32 +01:00
|
|
|
case ISD::ABS:
|
2014-02-03 18:27:25 +01:00
|
|
|
case ISD::BSWAP:
|
2015-12-14 18:25:38 +01:00
|
|
|
case ISD::BITREVERSE:
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::CTLZ:
|
2011-12-13 02:56:10 +01:00
|
|
|
case ISD::CTTZ:
|
|
|
|
case ISD::CTLZ_ZERO_UNDEF:
|
|
|
|
case ISD::CTTZ_ZERO_UNDEF:
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::CTPOP:
|
|
|
|
case ISD::SELECT:
|
2011-09-13 21:17:42 +02:00
|
|
|
case ISD::VSELECT:
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::SELECT_CC:
|
2011-09-06 21:07:46 +02:00
|
|
|
case ISD::SETCC:
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::ZERO_EXTEND:
|
|
|
|
case ISD::ANY_EXTEND:
|
|
|
|
case ISD::TRUNCATE:
|
|
|
|
case ISD::SIGN_EXTEND:
|
|
|
|
case ISD::FP_TO_SINT:
|
|
|
|
case ISD::FP_TO_UINT:
|
|
|
|
case ISD::FNEG:
|
|
|
|
case ISD::FABS:
|
2014-10-22 01:01:01 +02:00
|
|
|
case ISD::FMINNUM:
|
|
|
|
case ISD::FMAXNUM:
|
2018-10-22 18:27:27 +02:00
|
|
|
case ISD::FMINNUM_IEEE:
|
|
|
|
case ISD::FMAXNUM_IEEE:
|
[NFC] Rename minnan and maxnan to minimum and maximum
Summary:
Changes all uses of minnan/maxnan to minimum/maximum
globally. These names emphasize that the semantic difference between
these operations is more than just NaN-propagation.
Reviewers: arsenm, aheejin, dschuff, javed.absar
Subscribers: jholewinski, sdardis, wdng, sbc100, jgravelle-google, jrtc27, atanasyan, llvm-commits
Differential Revision: https://reviews.llvm.org/D53112
llvm-svn: 345218
2018-10-25 00:49:55 +02:00
|
|
|
case ISD::FMINIMUM:
|
|
|
|
case ISD::FMAXIMUM:
|
Add a llvm.copysign intrinsic
This adds a llvm.copysign intrinsic; We already have Libfunc recognition for
copysign (which is turned into the FCOPYSIGN SDAG node). In order to
autovectorize calls to copysign in the loop vectorizer, we need a corresponding
intrinsic as well.
In addition to the expected changes to the language reference, the loop
vectorizer, BasicTTI, and the SDAG builder (the intrinsic is transformed into
an FCOPYSIGN node, just like the function call), this also adds FCOPYSIGN to a
few lists in LegalizeVector{Ops,Types} so that vector copysigns can be
expanded.
In TargetLoweringBase::initActions, I've made the default action for FCOPYSIGN
be Expand for vector types. This seems correct for all in-tree targets, and I
think is the right thing to do because, previously, there was no way to generate
vector-values FCOPYSIGN nodes (and most targets don't specify an action for
vector-typed FCOPYSIGN).
llvm-svn: 188728
2013-08-20 01:35:46 +02:00
|
|
|
case ISD::FCOPYSIGN:
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::FSQRT:
|
|
|
|
case ISD::FSIN:
|
|
|
|
case ISD::FCOS:
|
|
|
|
case ISD::FPOWI:
|
|
|
|
case ISD::FPOW:
|
|
|
|
case ISD::FLOG:
|
|
|
|
case ISD::FLOG2:
|
|
|
|
case ISD::FLOG10:
|
|
|
|
case ISD::FEXP:
|
|
|
|
case ISD::FEXP2:
|
|
|
|
case ISD::FCEIL:
|
|
|
|
case ISD::FTRUNC:
|
|
|
|
case ISD::FRINT:
|
|
|
|
case ISD::FNEARBYINT:
|
2013-08-08 00:49:12 +02:00
|
|
|
case ISD::FROUND:
|
2009-05-23 14:35:30 +02:00
|
|
|
case ISD::FFLOOR:
|
2012-11-15 23:44:27 +01:00
|
|
|
case ISD::FP_ROUND:
|
2012-11-17 02:52:46 +01:00
|
|
|
case ISD::FP_EXTEND:
|
2012-08-30 09:34:22 +02:00
|
|
|
case ISD::FMA:
|
2011-07-14 13:11:14 +02:00
|
|
|
case ISD::SIGN_EXTEND_INREG:
|
2014-07-10 14:32:32 +02:00
|
|
|
case ISD::ANY_EXTEND_VECTOR_INREG:
|
|
|
|
case ISD::SIGN_EXTEND_VECTOR_INREG:
|
2014-07-09 12:58:18 +02:00
|
|
|
case ISD::ZERO_EXTEND_VECTOR_INREG:
|
2015-05-15 11:03:15 +02:00
|
|
|
case ISD::SMIN:
|
|
|
|
case ISD::SMAX:
|
|
|
|
case ISD::UMIN:
|
|
|
|
case ISD::UMAX:
|
[SelectionDAG] Add expansion and promotion of [US]MUL_LOHI
Summary:
Most targets set the action for these nodes to Expand even though there
isn't actually any code for them in ExpandNode. Instead, targets simply
relied on the fact that no code generates these nodes as long as the
nodes aren't legal or custom.
However, generating these nodes can be useful e.g. for divide-by-constant
in wider integer types.
Expand of [US]MUL_LOHI will use MULH[US] when legal or custom, and
a sequence of half-width multiplications otherwise. Promote uses a wider
multiply.
This patch intends to not change the generated code, but indirect effects
are possible since expansions/promotions that were previously done in
DAGCombine may now be done in LegalizeDAG.
See D24822 for a change that actually uses the new expansion.
Reviewers: spatel, bkramer, venkatra, efriedma, hfinkel, ast, nadav, tstellarAMD
Subscribers: arsenm, jyknight, nemanjai, wdng, nhaehnle, llvm-commits
Differential Revision: https://reviews.llvm.org/D24956
llvm-svn: 289050
2016-12-08 15:08:14 +01:00
|
|
|
case ISD::SMUL_LOHI:
|
|
|
|
case ISD::UMUL_LOHI:
|
2019-05-20 18:09:22 +02:00
|
|
|
case ISD::SADDO:
|
|
|
|
case ISD::UADDO:
|
|
|
|
case ISD::SSUBO:
|
|
|
|
case ISD::USUBO:
|
2019-02-20 21:41:44 +01:00
|
|
|
case ISD::SMULO:
|
|
|
|
case ISD::UMULO:
|
2018-04-26 21:21:37 +02:00
|
|
|
case ISD::FCANONICALIZE:
|
2018-10-16 19:35:41 +02:00
|
|
|
case ISD::SADDSAT:
|
2018-10-23 01:08:40 +02:00
|
|
|
case ISD::UADDSAT:
|
2018-10-29 17:54:37 +01:00
|
|
|
case ISD::SSUBSAT:
|
|
|
|
case ISD::USUBSAT:
|
2018-06-13 16:32:12 +02:00
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
|
2009-06-06 05:27:50 +02:00
|
|
|
break;
|
2019-02-04 18:18:11 +01:00
|
|
|
case ISD::SMULFIX:
|
2019-05-21 21:17:19 +02:00
|
|
|
case ISD::SMULFIXSAT:
|
[Intrinsic] Add the llvm.umul.fix.sat intrinsic
Summary:
Add an intrinsic that takes 2 unsigned integers with
the scale of them provided as the third argument and
performs fixed point multiplication on them. The
result is saturated and clamped between the largest and
smallest representable values of the first 2 operands.
This is a part of implementing fixed point arithmetic
in clang where some of the more complex operations
will be implemented as intrinsics.
Patch by: leonardchan, bjope
Reviewers: RKSimon, craig.topper, bevinh, leonardchan, lebedev.ri, spatel
Reviewed By: leonardchan
Subscribers: ychen, wuzish, nemanjai, MaskRay, jsji, jdoerfert, Ka-Ka, hiraditya, rjmccall, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57836
llvm-svn: 371308
2019-09-07 14:16:14 +02:00
|
|
|
case ISD::UMULFIX:
|
2020-01-08 15:05:03 +01:00
|
|
|
case ISD::UMULFIXSAT:
|
|
|
|
case ISD::SDIVFIX:
|
2019-12-16 15:25:52 +01:00
|
|
|
case ISD::SDIVFIXSAT:
|
|
|
|
case ISD::UDIVFIX:
|
|
|
|
case ISD::UDIVFIXSAT: {
|
2018-12-12 07:29:14 +01:00
|
|
|
unsigned Scale = Node->getConstantOperandVal(2);
|
|
|
|
Action = TLI.getFixedPointOperationAction(Node->getOpcode(),
|
|
|
|
Node->getValueType(0), Scale);
|
|
|
|
break;
|
|
|
|
}
|
2009-06-06 05:27:50 +02:00
|
|
|
case ISD::SINT_TO_FP:
|
|
|
|
case ISD::UINT_TO_FP:
|
[SDAG][AArch64] Legalize VECREDUCE
Fixes https://bugs.llvm.org/show_bug.cgi?id=36796.
Implement basic legalizations (PromoteIntRes, PromoteIntOp,
ExpandIntRes, ScalarizeVecOp, WidenVecOp) for VECREDUCE opcodes.
There are more legalizations missing (esp float legalizations),
but there's no way to test them right now, so I'm not adding them.
This also includes a few more changes to make this work somewhat
reasonably:
* Add support for expanding VECREDUCE in SDAG. Usually
experimental.vector.reduce is expanded prior to codegen, but if the
target does have native vector reduce, it may of course still be
necessary to expand due to legalization issues. This uses a shuffle
reduction if possible, followed by a naive scalar reduction.
* Allow the result type of integer VECREDUCE to be larger than the
vector element type. For example we need to be able to reduce a v8i8
into an (nominally) i32 result type on AArch64.
* Use the vector operand type rather than the scalar result type to
determine the action, so we can control exactly which vector types are
supported. Also change the legalize vector op code to handle
operations that only have vector operands, but no vector results, as
is the case for VECREDUCE.
* Default VECREDUCE to Expand. On AArch64 (only target using VECREDUCE),
explicitly specify for which vector types the reductions are supported.
This does not handle anything related to VECREDUCE_STRICT_*.
Differential Revision: https://reviews.llvm.org/D58015
llvm-svn: 355860
2019-03-11 21:22:13 +01:00
|
|
|
case ISD::VECREDUCE_ADD:
|
|
|
|
case ISD::VECREDUCE_MUL:
|
|
|
|
case ISD::VECREDUCE_AND:
|
|
|
|
case ISD::VECREDUCE_OR:
|
|
|
|
case ISD::VECREDUCE_XOR:
|
|
|
|
case ISD::VECREDUCE_SMAX:
|
|
|
|
case ISD::VECREDUCE_SMIN:
|
|
|
|
case ISD::VECREDUCE_UMAX:
|
|
|
|
case ISD::VECREDUCE_UMIN:
|
|
|
|
case ISD::VECREDUCE_FADD:
|
|
|
|
case ISD::VECREDUCE_FMUL:
|
|
|
|
case ISD::VECREDUCE_FMAX:
|
|
|
|
case ISD::VECREDUCE_FMIN:
|
2018-07-30 21:41:25 +02:00
|
|
|
Action = TLI.getOperationAction(Node->getOpcode(),
|
2018-06-13 16:32:12 +02:00
|
|
|
Node->getOperand(0).getValueType());
|
2009-05-23 14:35:30 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "\nLegalizing vector op: "; Node->dump(&DAG));
|
2017-12-28 20:46:01 +01:00
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVector<SDValue, 8> ResultVals;
|
2018-06-13 16:32:12 +02:00
|
|
|
switch (Action) {
|
2015-10-20 17:06:37 +02:00
|
|
|
default: llvm_unreachable("This action is not supported yet!");
|
2009-05-23 14:35:30 +02:00
|
|
|
case TargetLowering::Promote:
|
2020-01-10 19:13:45 +01:00
|
|
|
LLVM_DEBUG(dbgs() << "Promoting\n");
|
|
|
|
Promote(Node, ResultVals);
|
|
|
|
assert(!ResultVals.empty() && "No results for promotion?");
|
2014-07-02 05:07:15 +02:00
|
|
|
break;
|
|
|
|
case TargetLowering::Legal:
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "Legal node: nothing to do\n");
|
2009-05-23 14:35:30 +02:00
|
|
|
break;
|
2020-01-10 19:13:45 +01:00
|
|
|
case TargetLowering::Custom:
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "Trying custom legalization\n");
|
2020-01-10 19:13:45 +01:00
|
|
|
if (LowerOperationWrapper(Node, ResultVals))
|
2009-05-23 14:35:30 +02:00
|
|
|
break;
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "Could not custom legalize node\n");
|
2016-08-17 22:30:52 +02:00
|
|
|
LLVM_FALLTHROUGH;
|
2009-05-23 14:35:30 +02:00
|
|
|
case TargetLowering::Expand:
|
2020-01-10 19:13:45 +01:00
|
|
|
LLVM_DEBUG(dbgs() << "Expanding\n");
|
|
|
|
Expand(Node, ResultVals);
|
|
|
|
break;
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
if (ResultVals.empty())
|
|
|
|
return TranslateLegalizeResults(Op, Node);
|
|
|
|
|
|
|
|
Changed = true;
|
|
|
|
return RecursivelyLegalizeResults(Op, ResultVals);
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIME: This is very similar to the X86 override of
|
|
|
|
// TargetLowering::LowerOperationWrapper. Can we merge them somehow?
|
|
|
|
bool VectorLegalizer::LowerOperationWrapper(SDNode *Node,
|
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
|
|
|
SDValue Res = TLI.LowerOperation(SDValue(Node, 0), DAG);
|
|
|
|
|
|
|
|
if (!Res.getNode())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (Res == SDValue(Node, 0))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// If the original node has one result, take the return value from
|
|
|
|
// LowerOperation as is. It might not be result number 0.
|
|
|
|
if (Node->getNumValues() == 1) {
|
|
|
|
Results.push_back(Res);
|
|
|
|
return true;
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
// If the original node has multiple results, then the return node should
|
|
|
|
// have the same number of results.
|
|
|
|
assert((Node->getNumValues() == Res->getNumValues()) &&
|
|
|
|
"Lowering returned the wrong number of results!");
|
|
|
|
|
|
|
|
// Places new result values base on N result number.
|
|
|
|
for (unsigned I = 0, E = Node->getNumValues(); I != E; ++I)
|
|
|
|
Results.push_back(Res.getValue(I));
|
|
|
|
|
|
|
|
return true;
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
void VectorLegalizer::Promote(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
|
2014-07-02 05:07:15 +02:00
|
|
|
// For a few operations there is a specific concept for promotion based on
|
|
|
|
// the operand's type.
|
2020-01-11 20:36:50 +01:00
|
|
|
switch (Node->getOpcode()) {
|
2014-07-02 05:07:15 +02:00
|
|
|
case ISD::SINT_TO_FP:
|
|
|
|
case ISD::UINT_TO_FP:
|
2019-12-24 02:44:22 +01:00
|
|
|
case ISD::STRICT_SINT_TO_FP:
|
|
|
|
case ISD::STRICT_UINT_TO_FP:
|
2014-07-02 05:07:15 +02:00
|
|
|
// "Promote" the operation by extending the operand.
|
2020-01-11 20:36:50 +01:00
|
|
|
PromoteINT_TO_FP(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-02 05:07:15 +02:00
|
|
|
case ISD::FP_TO_UINT:
|
|
|
|
case ISD::FP_TO_SINT:
|
2019-12-19 07:43:45 +01:00
|
|
|
case ISD::STRICT_FP_TO_UINT:
|
|
|
|
case ISD::STRICT_FP_TO_SINT:
|
2014-07-02 05:07:15 +02:00
|
|
|
// Promote the operation by extending the operand.
|
2020-01-11 20:36:50 +01:00
|
|
|
PromoteFP_TO_INT(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2019-12-31 23:04:09 +01:00
|
|
|
case ISD::FP_ROUND:
|
|
|
|
case ISD::FP_EXTEND:
|
|
|
|
// These operations are used to do promotion so they can't be promoted
|
|
|
|
// themselves.
|
|
|
|
llvm_unreachable("Don't know how to promote this operation!");
|
2014-07-02 05:07:15 +02:00
|
|
|
}
|
|
|
|
|
2014-08-27 18:16:04 +02:00
|
|
|
// There are currently two cases of vector promotion:
|
|
|
|
// 1) Bitcasting a vector of integers to a different type to a vector of the
|
2015-03-27 22:45:18 +01:00
|
|
|
// same overall length. For example, x86 promotes ISD::AND v2i32 to v1i64.
|
|
|
|
// 2) Extending a vector of floats to a vector of the same number of larger
|
2014-08-27 18:16:04 +02:00
|
|
|
// floats. For example, AArch64 promotes ISD::FADD on v4f16 to v4f32.
|
2020-01-11 20:36:50 +01:00
|
|
|
assert(Node->getNumValues() == 1 &&
|
2009-05-23 14:35:30 +02:00
|
|
|
"Can't promote a vector with multiple results!");
|
2020-01-11 20:36:50 +01:00
|
|
|
MVT VT = Node->getSimpleValueType(0);
|
|
|
|
MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
|
|
|
|
SDLoc dl(Node);
|
|
|
|
SmallVector<SDValue, 4> Operands(Node->getNumOperands());
|
|
|
|
|
|
|
|
for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
|
|
|
|
if (Node->getOperand(j).getValueType().isVector())
|
|
|
|
if (Node->getOperand(j)
|
2014-08-27 18:16:04 +02:00
|
|
|
.getValueType()
|
|
|
|
.getVectorElementType()
|
2015-02-12 23:43:52 +01:00
|
|
|
.isFloatingPoint() &&
|
|
|
|
NVT.isVector() && NVT.getVectorElementType().isFloatingPoint())
|
2020-01-11 20:36:50 +01:00
|
|
|
Operands[j] = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(j));
|
2014-08-27 18:16:04 +02:00
|
|
|
else
|
2020-01-11 20:36:50 +01:00
|
|
|
Operands[j] = DAG.getNode(ISD::BITCAST, dl, NVT, Node->getOperand(j));
|
2009-05-23 14:35:30 +02:00
|
|
|
else
|
2020-01-11 20:36:50 +01:00
|
|
|
Operands[j] = Node->getOperand(j);
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
2015-12-14 18:25:38 +01:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Res =
|
|
|
|
DAG.getNode(Node->getOpcode(), dl, NVT, Operands, Node->getFlags());
|
2020-01-10 19:13:45 +01:00
|
|
|
|
2015-02-12 23:43:52 +01:00
|
|
|
if ((VT.isFloatingPoint() && NVT.isFloatingPoint()) ||
|
|
|
|
(VT.isVector() && VT.getVectorElementType().isFloatingPoint() &&
|
|
|
|
NVT.isVector() && NVT.getVectorElementType().isFloatingPoint()))
|
2020-01-11 20:36:50 +01:00
|
|
|
Res = DAG.getNode(ISD::FP_ROUND, dl, VT, Res, DAG.getIntPtrConstant(0, dl));
|
2014-08-27 18:16:04 +02:00
|
|
|
else
|
2020-01-11 20:36:50 +01:00
|
|
|
Res = DAG.getNode(ISD::BITCAST, dl, VT, Res);
|
2020-01-10 19:13:45 +01:00
|
|
|
|
|
|
|
Results.push_back(Res);
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
void VectorLegalizer::PromoteINT_TO_FP(SDNode *Node,
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2012-06-28 23:03:44 +02:00
|
|
|
// INT_TO_FP operations may require the input operand be promoted even
|
|
|
|
// when the type is otherwise legal.
|
2020-01-11 20:36:50 +01:00
|
|
|
bool IsStrict = Node->isStrictFPOpcode();
|
|
|
|
MVT VT = Node->getOperand(IsStrict ? 1 : 0).getSimpleValueType();
|
|
|
|
MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
|
2018-01-01 20:21:35 +01:00
|
|
|
assert(NVT.getVectorNumElements() == VT.getVectorNumElements() &&
|
|
|
|
"Vectors have different number of elements!");
|
2012-06-28 23:03:44 +02:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDLoc dl(Node);
|
|
|
|
SmallVector<SDValue, 4> Operands(Node->getNumOperands());
|
2012-06-28 23:03:44 +02:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
unsigned Opc = (Node->getOpcode() == ISD::UINT_TO_FP ||
|
|
|
|
Node->getOpcode() == ISD::STRICT_UINT_TO_FP)
|
2019-12-24 02:44:22 +01:00
|
|
|
? ISD::ZERO_EXTEND
|
|
|
|
: ISD::SIGN_EXTEND;
|
2020-01-11 20:36:50 +01:00
|
|
|
for (unsigned j = 0; j != Node->getNumOperands(); ++j) {
|
|
|
|
if (Node->getOperand(j).getValueType().isVector())
|
|
|
|
Operands[j] = DAG.getNode(Opc, dl, NVT, Node->getOperand(j));
|
2012-06-28 23:03:44 +02:00
|
|
|
else
|
2020-01-11 20:36:50 +01:00
|
|
|
Operands[j] = Node->getOperand(j);
|
2012-06-28 23:03:44 +02:00
|
|
|
}
|
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
if (IsStrict) {
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Res = DAG.getNode(Node->getOpcode(), dl,
|
|
|
|
{Node->getValueType(0), MVT::Other}, Operands);
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Res);
|
|
|
|
Results.push_back(Res.getValue(1));
|
|
|
|
return;
|
|
|
|
}
|
2019-12-24 02:44:22 +01:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Res =
|
|
|
|
DAG.getNode(Node->getOpcode(), dl, Node->getValueType(0), Operands);
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Res);
|
2012-06-28 23:03:44 +02:00
|
|
|
}
|
|
|
|
|
2014-03-17 18:06:14 +01:00
|
|
|
// For FP_TO_INT we promote the result type to a vector type with wider
|
|
|
|
// elements and then truncate the result. This is different from the default
|
|
|
|
// PromoteVector which uses bitcast to promote thus assumning that the
|
|
|
|
// promoted vector type has the same overall size.
|
2020-01-11 20:36:50 +01:00
|
|
|
void VectorLegalizer::PromoteFP_TO_INT(SDNode *Node,
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2020-01-11 20:36:50 +01:00
|
|
|
MVT VT = Node->getSimpleValueType(0);
|
|
|
|
MVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT);
|
|
|
|
bool IsStrict = Node->isStrictFPOpcode();
|
2018-01-01 20:21:35 +01:00
|
|
|
assert(NVT.getVectorNumElements() == VT.getVectorNumElements() &&
|
|
|
|
"Vectors have different number of elements!");
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
unsigned NewOpc = Node->getOpcode();
|
2018-01-01 20:21:35 +01:00
|
|
|
// Change FP_TO_UINT to FP_TO_SINT if possible.
|
|
|
|
// TODO: Should we only do this if FP_TO_UINT itself isn't legal?
|
|
|
|
if (NewOpc == ISD::FP_TO_UINT &&
|
|
|
|
TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NVT))
|
|
|
|
NewOpc = ISD::FP_TO_SINT;
|
2014-03-17 18:06:14 +01:00
|
|
|
|
2019-12-19 07:43:45 +01:00
|
|
|
if (NewOpc == ISD::STRICT_FP_TO_UINT &&
|
|
|
|
TLI.isOperationLegalOrCustom(ISD::STRICT_FP_TO_SINT, NVT))
|
|
|
|
NewOpc = ISD::STRICT_FP_TO_SINT;
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDLoc dl(Node);
|
2019-12-19 07:43:45 +01:00
|
|
|
SDValue Promoted, Chain;
|
|
|
|
if (IsStrict) {
|
|
|
|
Promoted = DAG.getNode(NewOpc, dl, {NVT, MVT::Other},
|
2020-01-11 20:36:50 +01:00
|
|
|
{Node->getOperand(0), Node->getOperand(1)});
|
2019-12-19 07:43:45 +01:00
|
|
|
Chain = Promoted.getValue(1);
|
|
|
|
} else
|
2020-01-11 20:36:50 +01:00
|
|
|
Promoted = DAG.getNode(NewOpc, dl, NVT, Node->getOperand(0));
|
2017-11-29 23:15:43 +01:00
|
|
|
|
|
|
|
// Assert that the converted value fits in the original type. If it doesn't
|
|
|
|
// (eg: because the value being converted is too big), then the result of the
|
|
|
|
// original operation was undefined anyway, so the assert is still correct.
|
2020-01-11 20:36:50 +01:00
|
|
|
if (Node->getOpcode() == ISD::FP_TO_UINT ||
|
|
|
|
Node->getOpcode() == ISD::STRICT_FP_TO_UINT)
|
2019-12-19 07:43:45 +01:00
|
|
|
NewOpc = ISD::AssertZext;
|
|
|
|
else
|
|
|
|
NewOpc = ISD::AssertSext;
|
|
|
|
|
|
|
|
Promoted = DAG.getNode(NewOpc, dl, NVT, Promoted,
|
2017-11-29 23:15:43 +01:00
|
|
|
DAG.getValueType(VT.getScalarType()));
|
2019-12-19 07:43:45 +01:00
|
|
|
Promoted = DAG.getNode(ISD::TRUNCATE, dl, VT, Promoted);
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Promoted);
|
2019-12-19 07:43:45 +01:00
|
|
|
if (IsStrict)
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Chain);
|
2014-03-17 18:06:14 +01:00
|
|
|
}
|
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
std::pair<SDValue, SDValue> VectorLegalizer::ExpandLoad(SDNode *N) {
|
|
|
|
LoadSDNode *LD = cast<LoadSDNode>(N);
|
2011-10-15 09:41:10 +02:00
|
|
|
|
2016-03-30 23:15:10 +02:00
|
|
|
EVT SrcVT = LD->getMemoryVT();
|
|
|
|
EVT SrcEltVT = SrcVT.getScalarType();
|
2011-10-15 09:41:10 +02:00
|
|
|
unsigned NumElem = SrcVT.getVectorNumElements();
|
|
|
|
|
2016-03-30 23:15:10 +02:00
|
|
|
SDValue NewChain;
|
|
|
|
SDValue Value;
|
2013-02-20 19:04:21 +01:00
|
|
|
if (SrcVT.getVectorNumElements() > 1 && !SrcEltVT.isByteSized()) {
|
2020-01-10 19:13:45 +01:00
|
|
|
SDLoc dl(N);
|
2016-03-30 23:15:10 +02:00
|
|
|
|
|
|
|
SmallVector<SDValue, 8> Vals;
|
|
|
|
SmallVector<SDValue, 8> LoadChains;
|
|
|
|
|
|
|
|
EVT DstEltVT = LD->getValueType(0).getScalarType();
|
|
|
|
SDValue Chain = LD->getChain();
|
|
|
|
SDValue BasePTR = LD->getBasePtr();
|
|
|
|
ISD::LoadExtType ExtType = LD->getExtensionType();
|
|
|
|
|
2013-02-20 19:04:21 +01:00
|
|
|
// When elements in a vector is not byte-addressable, we cannot directly
|
|
|
|
// load each element by advancing pointer, which could only address bytes.
|
|
|
|
// Instead, we load all significant words, mask bits off, and concatenate
|
|
|
|
// them to form each element. Finally, they are extended to destination
|
|
|
|
// scalar type to build the destination vector.
|
2015-07-09 04:09:04 +02:00
|
|
|
EVT WideVT = TLI.getPointerTy(DAG.getDataLayout());
|
2013-02-20 19:04:21 +01:00
|
|
|
|
|
|
|
assert(WideVT.isRound() &&
|
|
|
|
"Could not handle the sophisticated case when the widest integer is"
|
|
|
|
" not power of 2.");
|
|
|
|
assert(WideVT.bitsGE(SrcEltVT) &&
|
|
|
|
"Type is not legalized?");
|
|
|
|
|
|
|
|
unsigned WideBytes = WideVT.getStoreSize();
|
|
|
|
unsigned Offset = 0;
|
|
|
|
unsigned RemainingBytes = SrcVT.getStoreSize();
|
|
|
|
SmallVector<SDValue, 8> LoadVals;
|
|
|
|
while (RemainingBytes > 0) {
|
|
|
|
SDValue ScalarLoad;
|
|
|
|
unsigned LoadBytes = WideBytes;
|
|
|
|
|
|
|
|
if (RemainingBytes >= LoadBytes) {
|
[SelectionDAG] Get rid of bool parameters in SelectionDAG::getLoad, getStore, and friends.
Summary:
Instead, we take a single flags arg (a bitset).
Also add a default 0 alignment, and change the order of arguments so the
alignment comes before the flags.
This greatly simplifies many callsites, and fixes a bug in
AMDGPUISelLowering, wherein the order of the args to getLoad was
inverted. It also greatly simplifies the process of adding another flag
to getLoad.
Reviewers: chandlerc, tstellarAMD
Subscribers: jholewinski, arsenm, jyknight, dsanders, nemanjai, llvm-commits
Differential Revision: http://reviews.llvm.org/D22249
llvm-svn: 275592
2016-07-15 20:27:10 +02:00
|
|
|
ScalarLoad =
|
|
|
|
DAG.getLoad(WideVT, dl, Chain, BasePTR,
|
|
|
|
LD->getPointerInfo().getWithOffset(Offset),
|
|
|
|
MinAlign(LD->getAlignment(), Offset),
|
|
|
|
LD->getMemOperand()->getFlags(), LD->getAAInfo());
|
2013-02-20 19:04:21 +01:00
|
|
|
} else {
|
|
|
|
EVT LoadVT = WideVT;
|
|
|
|
while (RemainingBytes < LoadBytes) {
|
|
|
|
LoadBytes >>= 1; // Reduce the load size by half.
|
|
|
|
LoadVT = EVT::getIntegerVT(*DAG.getContext(), LoadBytes << 3);
|
|
|
|
}
|
[SelectionDAG] Get rid of bool parameters in SelectionDAG::getLoad, getStore, and friends.
Summary:
Instead, we take a single flags arg (a bitset).
Also add a default 0 alignment, and change the order of arguments so the
alignment comes before the flags.
This greatly simplifies many callsites, and fixes a bug in
AMDGPUISelLowering, wherein the order of the args to getLoad was
inverted. It also greatly simplifies the process of adding another flag
to getLoad.
Reviewers: chandlerc, tstellarAMD
Subscribers: jholewinski, arsenm, jyknight, dsanders, nemanjai, llvm-commits
Differential Revision: http://reviews.llvm.org/D22249
llvm-svn: 275592
2016-07-15 20:27:10 +02:00
|
|
|
ScalarLoad =
|
|
|
|
DAG.getExtLoad(ISD::EXTLOAD, dl, WideVT, Chain, BasePTR,
|
|
|
|
LD->getPointerInfo().getWithOffset(Offset), LoadVT,
|
|
|
|
MinAlign(LD->getAlignment(), Offset),
|
|
|
|
LD->getMemOperand()->getFlags(), LD->getAAInfo());
|
2013-02-20 19:04:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
RemainingBytes -= LoadBytes;
|
|
|
|
Offset += LoadBytes;
|
2017-11-29 02:25:12 +01:00
|
|
|
|
|
|
|
BasePTR = DAG.getObjectPtrOffset(dl, BasePTR, LoadBytes);
|
2013-02-20 19:04:21 +01:00
|
|
|
|
|
|
|
LoadVals.push_back(ScalarLoad.getValue(0));
|
|
|
|
LoadChains.push_back(ScalarLoad.getValue(1));
|
|
|
|
}
|
2011-10-15 09:41:10 +02:00
|
|
|
|
2013-02-20 19:04:21 +01:00
|
|
|
unsigned BitOffset = 0;
|
|
|
|
unsigned WideIdx = 0;
|
|
|
|
unsigned WideBits = WideVT.getSizeInBits();
|
|
|
|
|
2019-02-22 08:03:25 +01:00
|
|
|
// Extract bits, pack and extend/trunc them into destination type.
|
|
|
|
unsigned SrcEltBits = SrcEltVT.getSizeInBits();
|
|
|
|
SDValue SrcEltBitMask = DAG.getConstant(
|
|
|
|
APInt::getLowBitsSet(WideBits, SrcEltBits), dl, WideVT);
|
|
|
|
|
2013-02-20 19:04:21 +01:00
|
|
|
for (unsigned Idx = 0; Idx != NumElem; ++Idx) {
|
2019-02-22 07:18:33 +01:00
|
|
|
assert(BitOffset < WideBits && "Unexpected offset!");
|
2013-02-20 19:04:21 +01:00
|
|
|
|
2019-02-22 07:18:33 +01:00
|
|
|
SDValue ShAmt = DAG.getConstant(
|
|
|
|
BitOffset, dl, TLI.getShiftAmountTy(WideVT, DAG.getDataLayout()));
|
|
|
|
SDValue Lo = DAG.getNode(ISD::SRL, dl, WideVT, LoadVals[WideIdx], ShAmt);
|
2013-02-20 19:04:21 +01:00
|
|
|
|
|
|
|
BitOffset += SrcEltBits;
|
|
|
|
if (BitOffset >= WideBits) {
|
|
|
|
WideIdx++;
|
2015-02-04 19:54:01 +01:00
|
|
|
BitOffset -= WideBits;
|
|
|
|
if (BitOffset > 0) {
|
2015-07-09 04:09:20 +02:00
|
|
|
ShAmt = DAG.getConstant(
|
|
|
|
SrcEltBits - BitOffset, dl,
|
|
|
|
TLI.getShiftAmountTy(WideVT, DAG.getDataLayout()));
|
2019-02-22 07:18:33 +01:00
|
|
|
SDValue Hi =
|
|
|
|
DAG.getNode(ISD::SHL, dl, WideVT, LoadVals[WideIdx], ShAmt);
|
|
|
|
Lo = DAG.getNode(ISD::OR, dl, WideVT, Lo, Hi);
|
2013-02-20 19:04:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-22 08:03:25 +01:00
|
|
|
Lo = DAG.getNode(ISD::AND, dl, WideVT, Lo, SrcEltBitMask);
|
|
|
|
|
2013-02-20 19:04:21 +01:00
|
|
|
switch (ExtType) {
|
|
|
|
default: llvm_unreachable("Unknown extended-load op!");
|
|
|
|
case ISD::EXTLOAD:
|
|
|
|
Lo = DAG.getAnyExtOrTrunc(Lo, dl, DstEltVT);
|
|
|
|
break;
|
|
|
|
case ISD::ZEXTLOAD:
|
|
|
|
Lo = DAG.getZExtOrTrunc(Lo, dl, DstEltVT);
|
|
|
|
break;
|
|
|
|
case ISD::SEXTLOAD:
|
2015-07-09 04:09:20 +02:00
|
|
|
ShAmt =
|
|
|
|
DAG.getConstant(WideBits - SrcEltBits, dl,
|
|
|
|
TLI.getShiftAmountTy(WideVT, DAG.getDataLayout()));
|
2013-02-20 19:04:21 +01:00
|
|
|
Lo = DAG.getNode(ISD::SHL, dl, WideVT, Lo, ShAmt);
|
|
|
|
Lo = DAG.getNode(ISD::SRA, dl, WideVT, Lo, ShAmt);
|
|
|
|
Lo = DAG.getSExtOrTrunc(Lo, dl, DstEltVT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Vals.push_back(Lo);
|
|
|
|
}
|
|
|
|
|
2016-03-30 23:15:10 +02:00
|
|
|
NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, LoadChains);
|
2020-01-10 19:13:45 +01:00
|
|
|
Value = DAG.getBuildVector(N->getValueType(0), dl, Vals);
|
2016-03-30 23:15:10 +02:00
|
|
|
} else {
|
2019-12-31 04:07:36 +01:00
|
|
|
std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
|
2011-10-15 09:41:10 +02:00
|
|
|
}
|
2011-10-19 00:32:43 +02:00
|
|
|
|
2020-01-03 20:52:18 +01:00
|
|
|
return std::make_pair(Value, NewChain);
|
2011-10-15 09:41:10 +02:00
|
|
|
}
|
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
SDValue VectorLegalizer::ExpandStore(SDNode *N) {
|
|
|
|
StoreSDNode *ST = cast<StoreSDNode>(N);
|
2016-03-30 23:15:18 +02:00
|
|
|
SDValue TF = TLI.scalarizeVectorStore(ST, DAG);
|
2011-10-15 09:41:10 +02:00
|
|
|
return TF;
|
|
|
|
}
|
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
|
2020-01-11 21:12:53 +01:00
|
|
|
SDValue Tmp;
|
2020-01-11 20:36:50 +01:00
|
|
|
switch (Node->getOpcode()) {
|
2020-01-12 01:04:28 +01:00
|
|
|
case ISD::MERGE_VALUES:
|
|
|
|
for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
|
|
|
|
Results.push_back(Node->getOperand(i));
|
|
|
|
return;
|
2014-07-02 08:23:34 +02:00
|
|
|
case ISD::SIGN_EXTEND_INREG:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(ExpandSEXTINREG(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-10 14:32:32 +02:00
|
|
|
case ISD::ANY_EXTEND_VECTOR_INREG:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(ExpandANY_EXTEND_VECTOR_INREG(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-10 14:32:32 +02:00
|
|
|
case ISD::SIGN_EXTEND_VECTOR_INREG:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(ExpandSIGN_EXTEND_VECTOR_INREG(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-09 12:58:18 +02:00
|
|
|
case ISD::ZERO_EXTEND_VECTOR_INREG:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(ExpandZERO_EXTEND_VECTOR_INREG(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-02 08:23:34 +02:00
|
|
|
case ISD::BSWAP:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(ExpandBSWAP(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-02 08:23:34 +02:00
|
|
|
case ISD::VSELECT:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(ExpandVSELECT(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-02 08:23:34 +02:00
|
|
|
case ISD::SELECT:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(ExpandSELECT(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2018-10-28 14:07:25 +01:00
|
|
|
case ISD::FP_TO_UINT:
|
2020-01-11 20:36:50 +01:00
|
|
|
ExpandFP_TO_UINT(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-02 08:23:34 +02:00
|
|
|
case ISD::UINT_TO_FP:
|
2020-01-11 20:36:50 +01:00
|
|
|
ExpandUINT_TO_FLOAT(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-02 08:23:34 +02:00
|
|
|
case ISD::FNEG:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(ExpandFNEG(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2017-02-15 23:02:42 +01:00
|
|
|
case ISD::FSUB:
|
2020-01-11 21:12:53 +01:00
|
|
|
ExpandFSUB(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-02 08:23:34 +02:00
|
|
|
case ISD::SETCC:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(UnrollVSETCC(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2019-01-12 10:59:32 +01:00
|
|
|
case ISD::ABS:
|
2020-01-11 21:12:53 +01:00
|
|
|
if (TLI.expandABS(Node, Tmp, DAG)) {
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Tmp);
|
2020-01-11 21:12:53 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ISD::BITREVERSE:
|
|
|
|
ExpandBITREVERSE(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2018-11-01 19:22:11 +01:00
|
|
|
case ISD::CTPOP:
|
2020-01-11 21:12:53 +01:00
|
|
|
if (TLI.expandCTPOP(Node, Tmp, DAG)) {
|
|
|
|
Results.push_back(Tmp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2016-11-08 15:10:28 +01:00
|
|
|
case ISD::CTLZ:
|
2015-12-27 22:33:47 +01:00
|
|
|
case ISD::CTLZ_ZERO_UNDEF:
|
2020-01-11 21:12:53 +01:00
|
|
|
if (TLI.expandCTLZ(Node, Tmp, DAG)) {
|
|
|
|
Results.push_back(Tmp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2018-12-05 12:12:12 +01:00
|
|
|
case ISD::CTTZ:
|
|
|
|
case ISD::CTTZ_ZERO_UNDEF:
|
2020-01-11 21:12:53 +01:00
|
|
|
if (TLI.expandCTTZ(Node, Tmp, DAG)) {
|
|
|
|
Results.push_back(Tmp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2018-12-05 12:12:12 +01:00
|
|
|
case ISD::FSHL:
|
|
|
|
case ISD::FSHR:
|
2020-01-11 21:12:53 +01:00
|
|
|
if (TLI.expandFunnelShift(Node, Tmp, DAG)) {
|
|
|
|
Results.push_back(Tmp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2018-12-13 12:20:48 +01:00
|
|
|
case ISD::ROTL:
|
|
|
|
case ISD::ROTR:
|
2020-01-11 21:12:53 +01:00
|
|
|
if (TLI.expandROT(Node, Tmp, DAG)) {
|
|
|
|
Results.push_back(Tmp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2018-12-05 12:12:12 +01:00
|
|
|
case ISD::FMINNUM:
|
|
|
|
case ISD::FMAXNUM:
|
2020-01-11 21:12:53 +01:00
|
|
|
if (SDValue Expanded = TLI.expandFMINNUM_FMAXNUM(Node, DAG)) {
|
|
|
|
Results.push_back(Expanded);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2019-05-20 18:09:22 +02:00
|
|
|
case ISD::UADDO:
|
|
|
|
case ISD::USUBO:
|
2020-01-11 20:36:50 +01:00
|
|
|
ExpandUADDSUBO(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2019-05-20 18:09:22 +02:00
|
|
|
case ISD::SADDO:
|
|
|
|
case ISD::SSUBO:
|
2020-01-11 20:36:50 +01:00
|
|
|
ExpandSADDSUBO(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2019-02-20 21:41:44 +01:00
|
|
|
case ISD::UMULO:
|
|
|
|
case ISD::SMULO:
|
2020-01-11 20:36:50 +01:00
|
|
|
ExpandMULO(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2019-01-15 19:43:41 +01:00
|
|
|
case ISD::USUBSAT:
|
|
|
|
case ISD::SSUBSAT:
|
|
|
|
case ISD::UADDSAT:
|
|
|
|
case ISD::SADDSAT:
|
2020-01-11 21:12:53 +01:00
|
|
|
if (SDValue Expanded = TLI.expandAddSubSat(Node, DAG)) {
|
|
|
|
Results.push_back(Expanded);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2019-01-31 20:15:37 +01:00
|
|
|
case ISD::SMULFIX:
|
2019-02-04 18:18:11 +01:00
|
|
|
case ISD::UMULFIX:
|
2020-01-11 21:12:53 +01:00
|
|
|
if (SDValue Expanded = TLI.expandFixedPointMul(Node, DAG)) {
|
|
|
|
Results.push_back(Expanded);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2019-08-11 21:27:06 +02:00
|
|
|
case ISD::SMULFIXSAT:
|
[Intrinsic] Add the llvm.umul.fix.sat intrinsic
Summary:
Add an intrinsic that takes 2 unsigned integers with
the scale of them provided as the third argument and
performs fixed point multiplication on them. The
result is saturated and clamped between the largest and
smallest representable values of the first 2 operands.
This is a part of implementing fixed point arithmetic
in clang where some of the more complex operations
will be implemented as intrinsics.
Patch by: leonardchan, bjope
Reviewers: RKSimon, craig.topper, bevinh, leonardchan, lebedev.ri, spatel
Reviewed By: leonardchan
Subscribers: ychen, wuzish, nemanjai, MaskRay, jsji, jdoerfert, Ka-Ka, hiraditya, rjmccall, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57836
llvm-svn: 371308
2019-09-07 14:16:14 +02:00
|
|
|
case ISD::UMULFIXSAT:
|
|
|
|
// FIXME: We do not expand SMULFIXSAT/UMULFIXSAT here yet, not sure exactly
|
|
|
|
// why. Maybe it results in worse codegen compared to the unroll for some
|
|
|
|
// targets? This should probably be investigated. And if we still prefer to
|
|
|
|
// unroll an explanation could be helpful.
|
2020-01-11 21:12:53 +01:00
|
|
|
break;
|
2020-01-08 15:05:03 +01:00
|
|
|
case ISD::SDIVFIX:
|
|
|
|
case ISD::UDIVFIX:
|
2019-12-16 15:25:52 +01:00
|
|
|
ExpandFixedPointDiv(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2019-12-16 15:25:52 +01:00
|
|
|
case ISD::SDIVFIXSAT:
|
|
|
|
case ISD::UDIVFIXSAT:
|
|
|
|
break;
|
2020-01-17 03:32:30 +01:00
|
|
|
#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \
|
2019-11-05 14:42:16 +01:00
|
|
|
case ISD::STRICT_##DAGN:
|
|
|
|
#include "llvm/IR/ConstrainedOps.def"
|
2020-01-11 20:36:50 +01:00
|
|
|
ExpandStrictFPOp(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
[SDAG][AArch64] Legalize VECREDUCE
Fixes https://bugs.llvm.org/show_bug.cgi?id=36796.
Implement basic legalizations (PromoteIntRes, PromoteIntOp,
ExpandIntRes, ScalarizeVecOp, WidenVecOp) for VECREDUCE opcodes.
There are more legalizations missing (esp float legalizations),
but there's no way to test them right now, so I'm not adding them.
This also includes a few more changes to make this work somewhat
reasonably:
* Add support for expanding VECREDUCE in SDAG. Usually
experimental.vector.reduce is expanded prior to codegen, but if the
target does have native vector reduce, it may of course still be
necessary to expand due to legalization issues. This uses a shuffle
reduction if possible, followed by a naive scalar reduction.
* Allow the result type of integer VECREDUCE to be larger than the
vector element type. For example we need to be able to reduce a v8i8
into an (nominally) i32 result type on AArch64.
* Use the vector operand type rather than the scalar result type to
determine the action, so we can control exactly which vector types are
supported. Also change the legalize vector op code to handle
operations that only have vector operands, but no vector results, as
is the case for VECREDUCE.
* Default VECREDUCE to Expand. On AArch64 (only target using VECREDUCE),
explicitly specify for which vector types the reductions are supported.
This does not handle anything related to VECREDUCE_STRICT_*.
Differential Revision: https://reviews.llvm.org/D58015
llvm-svn: 355860
2019-03-11 21:22:13 +01:00
|
|
|
case ISD::VECREDUCE_ADD:
|
|
|
|
case ISD::VECREDUCE_MUL:
|
|
|
|
case ISD::VECREDUCE_AND:
|
|
|
|
case ISD::VECREDUCE_OR:
|
|
|
|
case ISD::VECREDUCE_XOR:
|
|
|
|
case ISD::VECREDUCE_SMAX:
|
|
|
|
case ISD::VECREDUCE_SMIN:
|
|
|
|
case ISD::VECREDUCE_UMAX:
|
|
|
|
case ISD::VECREDUCE_UMIN:
|
|
|
|
case ISD::VECREDUCE_FADD:
|
|
|
|
case ISD::VECREDUCE_FMUL:
|
|
|
|
case ISD::VECREDUCE_FMAX:
|
|
|
|
case ISD::VECREDUCE_FMIN:
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(TLI.expandVecReduce(Node, DAG));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2014-07-02 08:23:34 +02:00
|
|
|
}
|
2020-01-11 21:12:53 +01:00
|
|
|
|
|
|
|
Results.push_back(DAG.UnrollVectorOp(Node));
|
2014-07-02 08:23:34 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue VectorLegalizer::ExpandSELECT(SDNode *Node) {
|
2012-08-30 21:17:29 +02:00
|
|
|
// Lower a select instruction where the condition is a scalar and the
|
|
|
|
// operands are vectors. Lower this select to VSELECT and implement it
|
2013-07-08 02:37:03 +02:00
|
|
|
// using XOR AND OR. The selector bit is broadcasted.
|
2020-01-11 20:36:50 +01:00
|
|
|
EVT VT = Node->getValueType(0);
|
|
|
|
SDLoc DL(Node);
|
2012-08-30 21:17:29 +02:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Mask = Node->getOperand(0);
|
|
|
|
SDValue Op1 = Node->getOperand(1);
|
|
|
|
SDValue Op2 = Node->getOperand(2);
|
2012-08-30 21:17:29 +02:00
|
|
|
|
|
|
|
assert(VT.isVector() && !Mask.getValueType().isVector()
|
|
|
|
&& Op1.getValueType() == Op2.getValueType() && "Invalid type");
|
|
|
|
|
|
|
|
// If we can't even use the basic vector operations of
|
|
|
|
// AND,OR,XOR, we will have to scalarize the op.
|
|
|
|
// Notice that the operation may be 'promoted' which means that it is
|
|
|
|
// 'bitcasted' to another type which is handled.
|
|
|
|
// Also, we need to be able to construct a splat vector using BUILD_VECTOR.
|
|
|
|
if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
|
|
|
|
TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
|
|
|
|
TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand ||
|
|
|
|
TLI.getOperationAction(ISD::BUILD_VECTOR, VT) == TargetLowering::Expand)
|
2020-01-11 20:36:50 +01:00
|
|
|
return DAG.UnrollVectorOp(Node);
|
2012-08-30 21:17:29 +02:00
|
|
|
|
|
|
|
// Generate a mask operand.
|
2013-09-10 02:41:56 +02:00
|
|
|
EVT MaskTy = VT.changeVectorElementTypeToInteger();
|
2012-08-30 21:17:29 +02:00
|
|
|
|
|
|
|
// What is the size of each element in the vector mask.
|
|
|
|
EVT BitTy = MaskTy.getScalarType();
|
|
|
|
|
2013-06-15 00:04:37 +02:00
|
|
|
Mask = DAG.getSelect(DL, BitTy, Mask,
|
2015-04-28 16:05:47 +02:00
|
|
|
DAG.getConstant(APInt::getAllOnesValue(BitTy.getSizeInBits()), DL,
|
|
|
|
BitTy),
|
|
|
|
DAG.getConstant(0, DL, BitTy));
|
2012-08-30 21:17:29 +02:00
|
|
|
|
|
|
|
// Broadcast the mask so that the entire vector is all-one or all zero.
|
2017-01-30 19:20:42 +01:00
|
|
|
Mask = DAG.getSplatBuildVector(MaskTy, DL, Mask);
|
2012-08-30 21:17:29 +02:00
|
|
|
|
|
|
|
// Bitcast the operands to be the same type as the mask.
|
|
|
|
// This is needed when we select between FP types because
|
|
|
|
// the mask is a vector of integers.
|
|
|
|
Op1 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op1);
|
|
|
|
Op2 = DAG.getNode(ISD::BITCAST, DL, MaskTy, Op2);
|
|
|
|
|
|
|
|
SDValue AllOnes = DAG.getConstant(
|
2015-04-28 16:05:47 +02:00
|
|
|
APInt::getAllOnesValue(BitTy.getSizeInBits()), DL, MaskTy);
|
2012-08-30 21:17:29 +02:00
|
|
|
SDValue NotMask = DAG.getNode(ISD::XOR, DL, MaskTy, Mask, AllOnes);
|
|
|
|
|
|
|
|
Op1 = DAG.getNode(ISD::AND, DL, MaskTy, Op1, Mask);
|
|
|
|
Op2 = DAG.getNode(ISD::AND, DL, MaskTy, Op2, NotMask);
|
|
|
|
SDValue Val = DAG.getNode(ISD::OR, DL, MaskTy, Op1, Op2);
|
2020-01-11 20:36:50 +01:00
|
|
|
return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
|
2012-08-30 21:17:29 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue VectorLegalizer::ExpandSEXTINREG(SDNode *Node) {
|
|
|
|
EVT VT = Node->getValueType(0);
|
2013-01-11 23:57:48 +01:00
|
|
|
|
2013-01-12 20:06:44 +01:00
|
|
|
// Make sure that the SRA and SHL instructions are available.
|
2013-01-11 23:57:48 +01:00
|
|
|
if (TLI.getOperationAction(ISD::SRA, VT) == TargetLowering::Expand ||
|
2013-01-12 20:06:44 +01:00
|
|
|
TLI.getOperationAction(ISD::SHL, VT) == TargetLowering::Expand)
|
2020-01-11 20:36:50 +01:00
|
|
|
return DAG.UnrollVectorOp(Node);
|
2013-01-11 23:57:48 +01:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDLoc DL(Node);
|
|
|
|
EVT OrigTy = cast<VTSDNode>(Node->getOperand(1))->getVT();
|
2013-01-11 23:57:48 +01:00
|
|
|
|
2016-09-14 17:21:00 +02:00
|
|
|
unsigned BW = VT.getScalarSizeInBits();
|
|
|
|
unsigned OrigBW = OrigTy.getScalarSizeInBits();
|
2015-04-28 16:05:47 +02:00
|
|
|
SDValue ShiftSz = DAG.getConstant(BW - OrigBW, DL, VT);
|
2013-01-11 23:57:48 +01:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Op = DAG.getNode(ISD::SHL, DL, VT, Node->getOperand(0), ShiftSz);
|
2013-01-11 23:57:48 +01:00
|
|
|
return DAG.getNode(ISD::SRA, DL, VT, Op, ShiftSz);
|
|
|
|
}
|
|
|
|
|
2014-07-10 14:32:32 +02:00
|
|
|
// Generically expand a vector anyext in register to a shuffle of the relevant
|
|
|
|
// lanes into the appropriate locations, with other lanes left undef.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue VectorLegalizer::ExpandANY_EXTEND_VECTOR_INREG(SDNode *Node) {
|
|
|
|
SDLoc DL(Node);
|
|
|
|
EVT VT = Node->getValueType(0);
|
2014-07-10 14:32:32 +02:00
|
|
|
int NumElements = VT.getVectorNumElements();
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Src = Node->getOperand(0);
|
2014-07-10 14:32:32 +02:00
|
|
|
EVT SrcVT = Src.getValueType();
|
|
|
|
int NumSrcElements = SrcVT.getVectorNumElements();
|
|
|
|
|
2019-06-25 13:31:37 +02:00
|
|
|
// *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
|
|
|
|
// into a larger vector type.
|
|
|
|
if (SrcVT.bitsLE(VT)) {
|
|
|
|
assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
|
|
|
|
"ANY_EXTEND_VECTOR_INREG vector size mismatch");
|
|
|
|
NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
|
|
|
|
SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
|
|
|
|
NumSrcElements);
|
2020-01-15 08:06:57 +01:00
|
|
|
Src = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, SrcVT, DAG.getUNDEF(SrcVT),
|
|
|
|
Src, DAG.getVectorIdxConstant(0, DL));
|
2019-06-25 13:31:37 +02:00
|
|
|
}
|
|
|
|
|
2014-07-10 14:32:32 +02:00
|
|
|
// Build a base mask of undef shuffles.
|
|
|
|
SmallVector<int, 16> ShuffleMask;
|
|
|
|
ShuffleMask.resize(NumSrcElements, -1);
|
|
|
|
|
|
|
|
// Place the extended lanes into the correct locations.
|
|
|
|
int ExtLaneScale = NumSrcElements / NumElements;
|
2015-07-07 21:07:19 +02:00
|
|
|
int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
|
2014-07-10 14:32:32 +02:00
|
|
|
for (int i = 0; i < NumElements; ++i)
|
|
|
|
ShuffleMask[i * ExtLaneScale + EndianOffset] = i;
|
|
|
|
|
|
|
|
return DAG.getNode(
|
|
|
|
ISD::BITCAST, DL, VT,
|
|
|
|
DAG.getVectorShuffle(SrcVT, DL, Src, DAG.getUNDEF(SrcVT), ShuffleMask));
|
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue VectorLegalizer::ExpandSIGN_EXTEND_VECTOR_INREG(SDNode *Node) {
|
|
|
|
SDLoc DL(Node);
|
|
|
|
EVT VT = Node->getValueType(0);
|
|
|
|
SDValue Src = Node->getOperand(0);
|
2014-07-10 14:32:32 +02:00
|
|
|
EVT SrcVT = Src.getValueType();
|
|
|
|
|
|
|
|
// First build an any-extend node which can be legalized above when we
|
|
|
|
// recurse through it.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Op = DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, Src);
|
2014-07-10 14:32:32 +02:00
|
|
|
|
|
|
|
// Now we need sign extend. Do this by shifting the elements. Even if these
|
|
|
|
// aren't legal operations, they have a better chance of being legalized
|
|
|
|
// without full scalarization than the sign extension does.
|
2016-09-14 18:37:15 +02:00
|
|
|
unsigned EltWidth = VT.getScalarSizeInBits();
|
|
|
|
unsigned SrcEltWidth = SrcVT.getScalarSizeInBits();
|
2015-04-28 16:05:47 +02:00
|
|
|
SDValue ShiftAmount = DAG.getConstant(EltWidth - SrcEltWidth, DL, VT);
|
2014-07-10 14:32:32 +02:00
|
|
|
return DAG.getNode(ISD::SRA, DL, VT,
|
|
|
|
DAG.getNode(ISD::SHL, DL, VT, Op, ShiftAmount),
|
|
|
|
ShiftAmount);
|
|
|
|
}
|
|
|
|
|
2014-07-09 12:58:18 +02:00
|
|
|
// Generically expand a vector zext in register to a shuffle of the relevant
|
|
|
|
// lanes into the appropriate locations, a blend of zero into the high bits,
|
|
|
|
// and a bitcast to the wider element type.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue VectorLegalizer::ExpandZERO_EXTEND_VECTOR_INREG(SDNode *Node) {
|
|
|
|
SDLoc DL(Node);
|
|
|
|
EVT VT = Node->getValueType(0);
|
2014-07-09 12:58:18 +02:00
|
|
|
int NumElements = VT.getVectorNumElements();
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Src = Node->getOperand(0);
|
2014-07-09 12:58:18 +02:00
|
|
|
EVT SrcVT = Src.getValueType();
|
|
|
|
int NumSrcElements = SrcVT.getVectorNumElements();
|
|
|
|
|
2019-06-25 13:31:37 +02:00
|
|
|
// *_EXTEND_VECTOR_INREG SrcVT can be smaller than VT - so insert the vector
|
|
|
|
// into a larger vector type.
|
|
|
|
if (SrcVT.bitsLE(VT)) {
|
|
|
|
assert((VT.getSizeInBits() % SrcVT.getScalarSizeInBits()) == 0 &&
|
|
|
|
"ZERO_EXTEND_VECTOR_INREG vector size mismatch");
|
|
|
|
NumSrcElements = VT.getSizeInBits() / SrcVT.getScalarSizeInBits();
|
|
|
|
SrcVT = EVT::getVectorVT(*DAG.getContext(), SrcVT.getScalarType(),
|
|
|
|
NumSrcElements);
|
2020-01-15 08:06:57 +01:00
|
|
|
Src = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, SrcVT, DAG.getUNDEF(SrcVT),
|
|
|
|
Src, DAG.getVectorIdxConstant(0, DL));
|
2019-06-25 13:31:37 +02:00
|
|
|
}
|
|
|
|
|
2014-07-09 12:58:18 +02:00
|
|
|
// Build up a zero vector to blend into this one.
|
2016-03-10 21:40:26 +01:00
|
|
|
SDValue Zero = DAG.getConstant(0, DL, SrcVT);
|
2014-07-09 12:58:18 +02:00
|
|
|
|
|
|
|
// Shuffle the incoming lanes into the correct position, and pull all other
|
|
|
|
// lanes from the zero vector.
|
|
|
|
SmallVector<int, 16> ShuffleMask;
|
|
|
|
ShuffleMask.reserve(NumSrcElements);
|
|
|
|
for (int i = 0; i < NumSrcElements; ++i)
|
|
|
|
ShuffleMask.push_back(i);
|
|
|
|
|
|
|
|
int ExtLaneScale = NumSrcElements / NumElements;
|
2015-07-07 21:07:19 +02:00
|
|
|
int EndianOffset = DAG.getDataLayout().isBigEndian() ? ExtLaneScale - 1 : 0;
|
2014-07-09 12:58:18 +02:00
|
|
|
for (int i = 0; i < NumElements; ++i)
|
|
|
|
ShuffleMask[i * ExtLaneScale + EndianOffset] = NumSrcElements + i;
|
|
|
|
|
|
|
|
return DAG.getNode(ISD::BITCAST, DL, VT,
|
|
|
|
DAG.getVectorShuffle(SrcVT, DL, Zero, Src, ShuffleMask));
|
|
|
|
}
|
|
|
|
|
2016-05-12 15:09:49 +02:00
|
|
|
static void createBSWAPShuffleMask(EVT VT, SmallVectorImpl<int> &ShuffleMask) {
|
2014-05-19 15:12:38 +02:00
|
|
|
int ScalarSizeInBytes = VT.getScalarSizeInBits() / 8;
|
|
|
|
for (int I = 0, E = VT.getVectorNumElements(); I != E; ++I)
|
|
|
|
for (int J = ScalarSizeInBytes - 1; J >= 0; --J)
|
|
|
|
ShuffleMask.push_back((I * ScalarSizeInBytes) + J);
|
2016-05-12 15:09:49 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue VectorLegalizer::ExpandBSWAP(SDNode *Node) {
|
|
|
|
EVT VT = Node->getValueType(0);
|
2014-05-19 15:12:38 +02:00
|
|
|
|
2016-05-12 15:09:49 +02:00
|
|
|
// Generate a byte wise shuffle mask for the BSWAP.
|
|
|
|
SmallVector<int, 16> ShuffleMask;
|
|
|
|
createBSWAPShuffleMask(VT, ShuffleMask);
|
2014-05-19 15:12:38 +02:00
|
|
|
EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, ShuffleMask.size());
|
|
|
|
|
|
|
|
// Only emit a shuffle if the mask is legal.
|
|
|
|
if (!TLI.isShuffleMaskLegal(ShuffleMask, ByteVT))
|
2020-01-11 20:36:50 +01:00
|
|
|
return DAG.UnrollVectorOp(Node);
|
2014-05-19 15:12:38 +02:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDLoc DL(Node);
|
|
|
|
SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
|
2016-07-01 08:54:47 +02:00
|
|
|
Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT), ShuffleMask);
|
2014-05-19 15:12:38 +02:00
|
|
|
return DAG.getNode(ISD::BITCAST, DL, VT, Op);
|
|
|
|
}
|
|
|
|
|
2020-01-11 21:12:53 +01:00
|
|
|
void VectorLegalizer::ExpandBITREVERSE(SDNode *Node,
|
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2020-01-11 20:36:50 +01:00
|
|
|
EVT VT = Node->getValueType(0);
|
2015-12-14 18:25:38 +01:00
|
|
|
|
|
|
|
// If we have the scalar operation, it's probably cheaper to unroll it.
|
2020-01-11 21:12:53 +01:00
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::BITREVERSE, VT.getScalarType())) {
|
|
|
|
SDValue Tmp = DAG.UnrollVectorOp(Node);
|
|
|
|
Results.push_back(Tmp);
|
|
|
|
return;
|
|
|
|
}
|
2015-12-14 18:25:38 +01:00
|
|
|
|
2016-05-12 15:09:49 +02:00
|
|
|
// If the vector element width is a whole number of bytes, test if its legal
|
|
|
|
// to BSWAP shuffle the bytes and then perform the BITREVERSE on the byte
|
|
|
|
// vector. This greatly reduces the number of bit shifts necessary.
|
|
|
|
unsigned ScalarSizeInBits = VT.getScalarSizeInBits();
|
|
|
|
if (ScalarSizeInBits > 8 && (ScalarSizeInBits % 8) == 0) {
|
|
|
|
SmallVector<int, 16> BSWAPMask;
|
|
|
|
createBSWAPShuffleMask(VT, BSWAPMask);
|
|
|
|
|
|
|
|
EVT ByteVT = EVT::getVectorVT(*DAG.getContext(), MVT::i8, BSWAPMask.size());
|
|
|
|
if (TLI.isShuffleMaskLegal(BSWAPMask, ByteVT) &&
|
|
|
|
(TLI.isOperationLegalOrCustom(ISD::BITREVERSE, ByteVT) ||
|
|
|
|
(TLI.isOperationLegalOrCustom(ISD::SHL, ByteVT) &&
|
|
|
|
TLI.isOperationLegalOrCustom(ISD::SRL, ByteVT) &&
|
|
|
|
TLI.isOperationLegalOrCustomOrPromote(ISD::AND, ByteVT) &&
|
|
|
|
TLI.isOperationLegalOrCustomOrPromote(ISD::OR, ByteVT)))) {
|
2020-01-11 20:36:50 +01:00
|
|
|
SDLoc DL(Node);
|
|
|
|
SDValue Op = DAG.getNode(ISD::BITCAST, DL, ByteVT, Node->getOperand(0));
|
2016-05-12 15:09:49 +02:00
|
|
|
Op = DAG.getVectorShuffle(ByteVT, DL, Op, DAG.getUNDEF(ByteVT),
|
2016-07-01 08:54:47 +02:00
|
|
|
BSWAPMask);
|
2016-05-12 15:09:49 +02:00
|
|
|
Op = DAG.getNode(ISD::BITREVERSE, DL, ByteVT, Op);
|
2020-01-11 21:12:53 +01:00
|
|
|
Op = DAG.getNode(ISD::BITCAST, DL, VT, Op);
|
|
|
|
Results.push_back(Op);
|
|
|
|
return;
|
2016-05-12 15:09:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-14 18:25:38 +01:00
|
|
|
// If we have the appropriate vector bit operations, it is better to use them
|
|
|
|
// than unrolling and expanding each component.
|
2020-01-11 21:12:53 +01:00
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::SHL, VT) &&
|
|
|
|
TLI.isOperationLegalOrCustom(ISD::SRL, VT) &&
|
|
|
|
TLI.isOperationLegalOrCustomOrPromote(ISD::AND, VT) &&
|
|
|
|
TLI.isOperationLegalOrCustomOrPromote(ISD::OR, VT))
|
|
|
|
// Let LegalizeDAG handle this later.
|
|
|
|
return;
|
2015-12-14 18:25:38 +01:00
|
|
|
|
2020-01-11 21:12:53 +01:00
|
|
|
// Otherwise unroll.
|
|
|
|
SDValue Tmp = DAG.UnrollVectorOp(Node);
|
|
|
|
Results.push_back(Tmp);
|
2015-12-14 18:25:38 +01:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue VectorLegalizer::ExpandVSELECT(SDNode *Node) {
|
2011-09-13 21:17:42 +02:00
|
|
|
// Implement VSELECT in terms of XOR, AND, OR
|
|
|
|
// on platforms which do not support blend natively.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDLoc DL(Node);
|
2011-09-13 21:17:42 +02:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Mask = Node->getOperand(0);
|
|
|
|
SDValue Op1 = Node->getOperand(1);
|
|
|
|
SDValue Op2 = Node->getOperand(2);
|
2011-09-13 21:17:42 +02:00
|
|
|
|
2013-05-07 22:24:18 +02:00
|
|
|
EVT VT = Mask.getValueType();
|
|
|
|
|
2011-09-13 21:17:42 +02:00
|
|
|
// If we can't even use the basic vector operations of
|
|
|
|
// AND,OR,XOR, we will have to scalarize the op.
|
2011-10-19 22:43:16 +02:00
|
|
|
// Notice that the operation may be 'promoted' which means that it is
|
|
|
|
// 'bitcasted' to another type which is handled.
|
2012-09-02 00:27:48 +02:00
|
|
|
// This operation also isn't safe with AND, OR, XOR when the boolean
|
|
|
|
// type is 0/1 as we need an all ones vector constant to mask with.
|
|
|
|
// FIXME: Sign extend 1 to all ones if thats legal on the target.
|
2011-10-19 22:43:16 +02:00
|
|
|
if (TLI.getOperationAction(ISD::AND, VT) == TargetLowering::Expand ||
|
|
|
|
TLI.getOperationAction(ISD::XOR, VT) == TargetLowering::Expand ||
|
2014-07-10 12:18:12 +02:00
|
|
|
TLI.getOperationAction(ISD::OR, VT) == TargetLowering::Expand ||
|
|
|
|
TLI.getBooleanContents(Op1.getValueType()) !=
|
|
|
|
TargetLowering::ZeroOrNegativeOneBooleanContent)
|
2020-01-11 20:36:50 +01:00
|
|
|
return DAG.UnrollVectorOp(Node);
|
2011-03-19 14:09:10 +01:00
|
|
|
|
2013-05-07 22:24:18 +02:00
|
|
|
// If the mask and the type are different sizes, unroll the vector op. This
|
|
|
|
// can occur when getSetCCResultType returns something that is different in
|
|
|
|
// size from the operand types. For example, v4i8 = select v4i32, v4i8, v4i8.
|
2016-09-14 18:05:51 +02:00
|
|
|
if (VT.getSizeInBits() != Op1.getValueSizeInBits())
|
2020-01-11 20:36:50 +01:00
|
|
|
return DAG.UnrollVectorOp(Node);
|
2013-05-07 22:24:18 +02:00
|
|
|
|
2011-09-13 21:17:42 +02:00
|
|
|
// Bitcast the operands to be the same type as the mask.
|
|
|
|
// This is needed when we select between FP types because
|
|
|
|
// the mask is a vector of integers.
|
|
|
|
Op1 = DAG.getNode(ISD::BITCAST, DL, VT, Op1);
|
|
|
|
Op2 = DAG.getNode(ISD::BITCAST, DL, VT, Op2);
|
2011-03-19 14:09:10 +01:00
|
|
|
|
2011-09-13 21:17:42 +02:00
|
|
|
SDValue AllOnes = DAG.getConstant(
|
2016-09-14 17:21:00 +02:00
|
|
|
APInt::getAllOnesValue(VT.getScalarSizeInBits()), DL, VT);
|
2011-09-13 21:17:42 +02:00
|
|
|
SDValue NotMask = DAG.getNode(ISD::XOR, DL, VT, Mask, AllOnes);
|
|
|
|
|
|
|
|
Op1 = DAG.getNode(ISD::AND, DL, VT, Op1, Mask);
|
|
|
|
Op2 = DAG.getNode(ISD::AND, DL, VT, Op2, NotMask);
|
2012-04-15 17:08:09 +02:00
|
|
|
SDValue Val = DAG.getNode(ISD::OR, DL, VT, Op1, Op2);
|
2020-01-11 20:36:50 +01:00
|
|
|
return DAG.getNode(ISD::BITCAST, DL, Node->getValueType(0), Val);
|
2011-09-13 21:17:42 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
void VectorLegalizer::ExpandFP_TO_UINT(SDNode *Node,
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2018-10-28 14:07:25 +01:00
|
|
|
// Attempt to expand using TargetLowering.
|
2019-08-28 18:33:36 +02:00
|
|
|
SDValue Result, Chain;
|
2020-01-11 20:36:50 +01:00
|
|
|
if (TLI.expandFP_TO_UINT(Node, Result, Chain, DAG)) {
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Result);
|
2020-01-11 20:36:50 +01:00
|
|
|
if (Node->isStrictFPOpcode())
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Chain);
|
|
|
|
return;
|
2019-08-28 18:33:36 +02:00
|
|
|
}
|
2018-10-28 14:07:25 +01:00
|
|
|
|
|
|
|
// Otherwise go ahead and unroll.
|
2020-01-11 20:36:50 +01:00
|
|
|
if (Node->isStrictFPOpcode()) {
|
|
|
|
UnrollStrictFPOp(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(DAG.UnrollVectorOp(Node));
|
2018-10-28 14:07:25 +01:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
void VectorLegalizer::ExpandUINT_TO_FLOAT(SDNode *Node,
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2020-01-11 20:36:50 +01:00
|
|
|
bool IsStrict = Node->isStrictFPOpcode();
|
2019-10-16 21:24:47 +02:00
|
|
|
unsigned OpNo = IsStrict ? 1 : 0;
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Src = Node->getOperand(OpNo);
|
2019-10-16 21:24:47 +02:00
|
|
|
EVT VT = Src.getValueType();
|
2020-01-11 20:36:50 +01:00
|
|
|
SDLoc DL(Node);
|
2011-03-19 14:09:10 +01:00
|
|
|
|
2018-10-25 13:15:57 +02:00
|
|
|
// Attempt to expand using TargetLowering.
|
|
|
|
SDValue Result;
|
2019-10-16 21:24:47 +02:00
|
|
|
SDValue Chain;
|
2020-01-11 20:36:50 +01:00
|
|
|
if (TLI.expandUINT_TO_FP(Node, Result, Chain, DAG)) {
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Result);
|
2019-10-16 21:24:47 +02:00
|
|
|
if (IsStrict)
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Chain);
|
|
|
|
return;
|
2019-10-16 21:24:47 +02:00
|
|
|
}
|
2018-10-25 13:15:57 +02:00
|
|
|
|
2011-03-19 14:09:10 +01:00
|
|
|
// Make sure that the SINT_TO_FP and SRL instructions are available.
|
2019-10-16 21:24:47 +02:00
|
|
|
if (((!IsStrict && TLI.getOperationAction(ISD::SINT_TO_FP, VT) ==
|
|
|
|
TargetLowering::Expand) ||
|
|
|
|
(IsStrict && TLI.getOperationAction(ISD::STRICT_SINT_TO_FP, VT) ==
|
|
|
|
TargetLowering::Expand)) ||
|
2020-01-05 02:03:33 +01:00
|
|
|
TLI.getOperationAction(ISD::SRL, VT) == TargetLowering::Expand) {
|
2020-01-10 19:13:45 +01:00
|
|
|
if (IsStrict) {
|
2020-01-11 20:36:50 +01:00
|
|
|
UnrollStrictFPOp(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(DAG.UnrollVectorOp(Node));
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
2020-01-05 02:03:33 +01:00
|
|
|
}
|
2011-03-19 14:09:10 +01:00
|
|
|
|
2016-11-21 19:24:44 +01:00
|
|
|
unsigned BW = VT.getScalarSizeInBits();
|
|
|
|
assert((BW == 64 || BW == 32) &&
|
|
|
|
"Elements in vector-UINT_TO_FP must be 32 or 64 bits wide");
|
2011-03-19 14:09:10 +01:00
|
|
|
|
2016-11-21 19:24:44 +01:00
|
|
|
SDValue HalfWord = DAG.getConstant(BW / 2, DL, VT);
|
2011-03-19 14:09:10 +01:00
|
|
|
|
|
|
|
// Constants to clear the upper part of the word.
|
|
|
|
// Notice that we can also use SHL+SHR, but using a constant is slightly
|
|
|
|
// faster on x86.
|
2016-11-21 19:24:44 +01:00
|
|
|
uint64_t HWMask = (BW == 64) ? 0x00000000FFFFFFFF : 0x0000FFFF;
|
2015-04-28 16:05:47 +02:00
|
|
|
SDValue HalfWordMask = DAG.getConstant(HWMask, DL, VT);
|
2011-03-19 14:09:10 +01:00
|
|
|
|
|
|
|
// Two to the power of half-word-size.
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue TWOHW =
|
|
|
|
DAG.getConstantFP(1ULL << (BW / 2), DL, Node->getValueType(0));
|
2011-03-19 14:09:10 +01:00
|
|
|
|
|
|
|
// Clear upper part of LO, lower HI
|
2019-10-16 21:24:47 +02:00
|
|
|
SDValue HI = DAG.getNode(ISD::SRL, DL, VT, Src, HalfWord);
|
|
|
|
SDValue LO = DAG.getNode(ISD::AND, DL, VT, Src, HalfWordMask);
|
|
|
|
|
|
|
|
if (IsStrict) {
|
|
|
|
// Convert hi and lo to floats
|
|
|
|
// Convert the hi part back to the upper values
|
|
|
|
// TODO: Can any fast-math-flags be set on these nodes?
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue fHI = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL,
|
|
|
|
{Node->getValueType(0), MVT::Other},
|
|
|
|
{Node->getOperand(0), HI});
|
|
|
|
fHI = DAG.getNode(ISD::STRICT_FMUL, DL, {Node->getValueType(0), MVT::Other},
|
2020-01-12 02:43:22 +01:00
|
|
|
{fHI.getValue(1), fHI, TWOHW});
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue fLO = DAG.getNode(ISD::STRICT_SINT_TO_FP, DL,
|
|
|
|
{Node->getValueType(0), MVT::Other},
|
2020-01-12 02:43:22 +01:00
|
|
|
{Node->getOperand(0), LO});
|
|
|
|
|
|
|
|
SDValue TF = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, fHI.getValue(1),
|
|
|
|
fLO.getValue(1));
|
2019-10-16 21:24:47 +02:00
|
|
|
|
|
|
|
// Add the two halves
|
|
|
|
SDValue Result =
|
2020-01-11 20:36:50 +01:00
|
|
|
DAG.getNode(ISD::STRICT_FADD, DL, {Node->getValueType(0), MVT::Other},
|
2020-01-12 02:43:22 +01:00
|
|
|
{TF, fHI, fLO});
|
2019-10-16 21:24:47 +02:00
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Result);
|
|
|
|
Results.push_back(Result.getValue(1));
|
|
|
|
return;
|
2019-10-16 21:24:47 +02:00
|
|
|
}
|
2011-03-19 14:09:10 +01:00
|
|
|
|
|
|
|
// Convert hi and lo to floats
|
|
|
|
// Convert the hi part back to the upper values
|
2015-09-16 18:31:21 +02:00
|
|
|
// TODO: Can any fast-math-flags be set on these nodes?
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue fHI = DAG.getNode(ISD::SINT_TO_FP, DL, Node->getValueType(0), HI);
|
|
|
|
fHI = DAG.getNode(ISD::FMUL, DL, Node->getValueType(0), fHI, TWOHW);
|
|
|
|
SDValue fLO = DAG.getNode(ISD::SINT_TO_FP, DL, Node->getValueType(0), LO);
|
2011-03-19 14:09:10 +01:00
|
|
|
|
|
|
|
// Add the two halves
|
2020-01-11 20:36:50 +01:00
|
|
|
Results.push_back(
|
|
|
|
DAG.getNode(ISD::FADD, DL, Node->getValueType(0), fHI, fLO));
|
2011-03-19 14:09:10 +01:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue VectorLegalizer::ExpandFNEG(SDNode *Node) {
|
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::FSUB, Node->getValueType(0))) {
|
|
|
|
SDLoc DL(Node);
|
|
|
|
SDValue Zero = DAG.getConstantFP(-0.0, DL, Node->getValueType(0));
|
2015-09-16 18:31:21 +02:00
|
|
|
// TODO: If FNEG had fast-math-flags, they'd get propagated to this FSUB.
|
2020-01-11 20:36:50 +01:00
|
|
|
return DAG.getNode(ISD::FSUB, DL, Node->getValueType(0), Zero,
|
|
|
|
Node->getOperand(0));
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
2020-01-11 20:36:50 +01:00
|
|
|
return DAG.UnrollVectorOp(Node);
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 21:12:53 +01:00
|
|
|
void VectorLegalizer::ExpandFSUB(SDNode *Node,
|
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2017-02-15 23:02:42 +01:00
|
|
|
// For floating-point values, (a-b) is the same as a+(-b). If FNEG is legal,
|
|
|
|
// we can defer this to operation legalization where it will be lowered as
|
|
|
|
// a+(-b).
|
2020-01-11 20:36:50 +01:00
|
|
|
EVT VT = Node->getValueType(0);
|
2017-02-15 23:02:42 +01:00
|
|
|
if (TLI.isOperationLegalOrCustom(ISD::FNEG, VT) &&
|
|
|
|
TLI.isOperationLegalOrCustom(ISD::FADD, VT))
|
2020-01-11 21:12:53 +01:00
|
|
|
return; // Defer to LegalizeDAG
|
2017-02-15 23:02:42 +01:00
|
|
|
|
2020-01-11 21:12:53 +01:00
|
|
|
SDValue Tmp = DAG.UnrollVectorOp(Node);
|
|
|
|
Results.push_back(Tmp);
|
2018-10-22 18:27:27 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
void VectorLegalizer::ExpandUADDSUBO(SDNode *Node,
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2019-05-20 18:09:22 +02:00
|
|
|
SDValue Result, Overflow;
|
2020-01-11 20:36:50 +01:00
|
|
|
TLI.expandUADDSUBO(Node, Result, Overflow, DAG);
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Result);
|
|
|
|
Results.push_back(Overflow);
|
2019-05-20 18:09:22 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
void VectorLegalizer::ExpandSADDSUBO(SDNode *Node,
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2019-05-20 18:09:22 +02:00
|
|
|
SDValue Result, Overflow;
|
2020-01-11 20:36:50 +01:00
|
|
|
TLI.expandSADDSUBO(Node, Result, Overflow, DAG);
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Result);
|
|
|
|
Results.push_back(Overflow);
|
2019-05-20 18:09:22 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
void VectorLegalizer::ExpandMULO(SDNode *Node,
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2019-02-20 21:41:44 +01:00
|
|
|
SDValue Result, Overflow;
|
2020-01-11 20:36:50 +01:00
|
|
|
if (!TLI.expandMULO(Node, Result, Overflow, DAG))
|
|
|
|
std::tie(Result, Overflow) = DAG.UnrollVectorOverflowOp(Node);
|
2019-02-20 21:41:44 +01:00
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Result);
|
|
|
|
Results.push_back(Overflow);
|
2019-02-20 21:41:44 +01:00
|
|
|
}
|
|
|
|
|
2019-12-16 15:25:52 +01:00
|
|
|
void VectorLegalizer::ExpandFixedPointDiv(SDNode *Node,
|
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2020-01-11 20:36:50 +01:00
|
|
|
SDNode *N = Node;
|
2020-01-08 15:05:03 +01:00
|
|
|
if (SDValue Expanded = TLI.expandFixedPointDiv(N->getOpcode(), SDLoc(N),
|
|
|
|
N->getOperand(0), N->getOperand(1), N->getConstantOperandVal(2), DAG))
|
2019-12-16 15:25:52 +01:00
|
|
|
Results.push_back(Expanded);
|
2020-01-08 15:05:03 +01:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
void VectorLegalizer::ExpandStrictFPOp(SDNode *Node,
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2020-01-11 20:36:50 +01:00
|
|
|
if (Node->getOpcode() == ISD::STRICT_UINT_TO_FP) {
|
|
|
|
ExpandUINT_TO_FLOAT(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
|
|
|
}
|
2020-01-11 20:36:50 +01:00
|
|
|
if (Node->getOpcode() == ISD::STRICT_FP_TO_UINT) {
|
|
|
|
ExpandFP_TO_UINT(Node, Results);
|
2020-01-10 19:13:45 +01:00
|
|
|
return;
|
|
|
|
}
|
2020-01-05 02:03:33 +01:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
UnrollStrictFPOp(Node, Results);
|
2020-01-05 02:03:33 +01:00
|
|
|
}
|
2019-10-16 21:24:47 +02:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
void VectorLegalizer::UnrollStrictFPOp(SDNode *Node,
|
2020-01-10 19:13:45 +01:00
|
|
|
SmallVectorImpl<SDValue> &Results) {
|
2020-01-11 20:36:50 +01:00
|
|
|
EVT VT = Node->getValueType(0);
|
2018-06-13 16:32:12 +02:00
|
|
|
EVT EltVT = VT.getVectorElementType();
|
|
|
|
unsigned NumElems = VT.getVectorNumElements();
|
2020-01-11 20:36:50 +01:00
|
|
|
unsigned NumOpers = Node->getNumOperands();
|
2018-06-13 16:32:12 +02:00
|
|
|
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
[FPEnv] Constrained FCmp intrinsics
This adds support for constrained floating-point comparison intrinsics.
Specifically, we add:
declare <ty2>
@llvm.experimental.constrained.fcmp(<type> <op1>, <type> <op2>,
metadata <condition code>,
metadata <exception behavior>)
declare <ty2>
@llvm.experimental.constrained.fcmps(<type> <op1>, <type> <op2>,
metadata <condition code>,
metadata <exception behavior>)
The first variant implements an IEEE "quiet" comparison (i.e. we only
get an invalid FP exception if either argument is a SNaN), while the
second variant implements an IEEE "signaling" comparison (i.e. we get
an invalid FP exception if either argument is any NaN).
The condition code is implemented as a metadata string. The same set
of predicates as for the fcmp instruction is supported (except for the
"true" and "false" predicates).
These new intrinsics are mapped by SelectionDAG codegen onto two new
ISD opcodes, ISD::STRICT_FSETCC and ISD::STRICT_FSETCCS, again
representing quiet vs. signaling comparison operations. Otherwise
those nodes look like SETCC nodes, with an additional chain argument
and result as usual for strict FP nodes. The patch includes support
for the common legalization operations for those nodes.
The patch also includes full SystemZ back-end support for the new
ISD nodes, mapping them to all available SystemZ instruction to
fully implement strict semantics (scalar and vector).
Differential Revision: https://reviews.llvm.org/D69281
2019-12-06 11:30:04 +01:00
|
|
|
|
|
|
|
EVT TmpEltVT = EltVT;
|
2020-01-11 20:36:50 +01:00
|
|
|
if (Node->getOpcode() == ISD::STRICT_FSETCC ||
|
|
|
|
Node->getOpcode() == ISD::STRICT_FSETCCS)
|
[FPEnv] Constrained FCmp intrinsics
This adds support for constrained floating-point comparison intrinsics.
Specifically, we add:
declare <ty2>
@llvm.experimental.constrained.fcmp(<type> <op1>, <type> <op2>,
metadata <condition code>,
metadata <exception behavior>)
declare <ty2>
@llvm.experimental.constrained.fcmps(<type> <op1>, <type> <op2>,
metadata <condition code>,
metadata <exception behavior>)
The first variant implements an IEEE "quiet" comparison (i.e. we only
get an invalid FP exception if either argument is a SNaN), while the
second variant implements an IEEE "signaling" comparison (i.e. we get
an invalid FP exception if either argument is any NaN).
The condition code is implemented as a metadata string. The same set
of predicates as for the fcmp instruction is supported (except for the
"true" and "false" predicates).
These new intrinsics are mapped by SelectionDAG codegen onto two new
ISD opcodes, ISD::STRICT_FSETCC and ISD::STRICT_FSETCCS, again
representing quiet vs. signaling comparison operations. Otherwise
those nodes look like SETCC nodes, with an additional chain argument
and result as usual for strict FP nodes. The patch includes support
for the common legalization operations for those nodes.
The patch also includes full SystemZ back-end support for the new
ISD nodes, mapping them to all available SystemZ instruction to
fully implement strict semantics (scalar and vector).
Differential Revision: https://reviews.llvm.org/D69281
2019-12-06 11:30:04 +01:00
|
|
|
TmpEltVT = TLI.getSetCCResultType(DAG.getDataLayout(),
|
|
|
|
*DAG.getContext(), TmpEltVT);
|
|
|
|
|
|
|
|
EVT ValueVTs[] = {TmpEltVT, MVT::Other};
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Chain = Node->getOperand(0);
|
|
|
|
SDLoc dl(Node);
|
2018-06-13 16:32:12 +02:00
|
|
|
|
2018-06-15 22:57:55 +02:00
|
|
|
SmallVector<SDValue, 32> OpValues;
|
|
|
|
SmallVector<SDValue, 32> OpChains;
|
2018-06-13 16:32:12 +02:00
|
|
|
for (unsigned i = 0; i < NumElems; ++i) {
|
|
|
|
SmallVector<SDValue, 4> Opers;
|
2020-01-15 08:06:57 +01:00
|
|
|
SDValue Idx = DAG.getVectorIdxConstant(i, dl);
|
2018-06-13 16:32:12 +02:00
|
|
|
|
|
|
|
// The Chain is the first operand.
|
|
|
|
Opers.push_back(Chain);
|
|
|
|
|
2018-07-30 21:41:25 +02:00
|
|
|
// Now process the remaining operands.
|
2018-06-13 16:32:12 +02:00
|
|
|
for (unsigned j = 1; j < NumOpers; ++j) {
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue Oper = Node->getOperand(j);
|
2018-06-15 22:57:55 +02:00
|
|
|
EVT OperVT = Oper.getValueType();
|
|
|
|
|
|
|
|
if (OperVT.isVector())
|
2018-07-30 21:41:25 +02:00
|
|
|
Oper = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl,
|
2019-05-13 15:23:30 +02:00
|
|
|
OperVT.getVectorElementType(), Oper, Idx);
|
2018-06-15 22:57:55 +02:00
|
|
|
|
2018-06-13 16:32:12 +02:00
|
|
|
Opers.push_back(Oper);
|
|
|
|
}
|
2018-07-30 21:41:25 +02:00
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue ScalarOp = DAG.getNode(Node->getOpcode(), dl, ValueVTs, Opers);
|
[FPEnv] Constrained FCmp intrinsics
This adds support for constrained floating-point comparison intrinsics.
Specifically, we add:
declare <ty2>
@llvm.experimental.constrained.fcmp(<type> <op1>, <type> <op2>,
metadata <condition code>,
metadata <exception behavior>)
declare <ty2>
@llvm.experimental.constrained.fcmps(<type> <op1>, <type> <op2>,
metadata <condition code>,
metadata <exception behavior>)
The first variant implements an IEEE "quiet" comparison (i.e. we only
get an invalid FP exception if either argument is a SNaN), while the
second variant implements an IEEE "signaling" comparison (i.e. we get
an invalid FP exception if either argument is any NaN).
The condition code is implemented as a metadata string. The same set
of predicates as for the fcmp instruction is supported (except for the
"true" and "false" predicates).
These new intrinsics are mapped by SelectionDAG codegen onto two new
ISD opcodes, ISD::STRICT_FSETCC and ISD::STRICT_FSETCCS, again
representing quiet vs. signaling comparison operations. Otherwise
those nodes look like SETCC nodes, with an additional chain argument
and result as usual for strict FP nodes. The patch includes support
for the common legalization operations for those nodes.
The patch also includes full SystemZ back-end support for the new
ISD nodes, mapping them to all available SystemZ instruction to
fully implement strict semantics (scalar and vector).
Differential Revision: https://reviews.llvm.org/D69281
2019-12-06 11:30:04 +01:00
|
|
|
SDValue ScalarResult = ScalarOp.getValue(0);
|
|
|
|
SDValue ScalarChain = ScalarOp.getValue(1);
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
if (Node->getOpcode() == ISD::STRICT_FSETCC ||
|
|
|
|
Node->getOpcode() == ISD::STRICT_FSETCCS)
|
[FPEnv] Constrained FCmp intrinsics
This adds support for constrained floating-point comparison intrinsics.
Specifically, we add:
declare <ty2>
@llvm.experimental.constrained.fcmp(<type> <op1>, <type> <op2>,
metadata <condition code>,
metadata <exception behavior>)
declare <ty2>
@llvm.experimental.constrained.fcmps(<type> <op1>, <type> <op2>,
metadata <condition code>,
metadata <exception behavior>)
The first variant implements an IEEE "quiet" comparison (i.e. we only
get an invalid FP exception if either argument is a SNaN), while the
second variant implements an IEEE "signaling" comparison (i.e. we get
an invalid FP exception if either argument is any NaN).
The condition code is implemented as a metadata string. The same set
of predicates as for the fcmp instruction is supported (except for the
"true" and "false" predicates).
These new intrinsics are mapped by SelectionDAG codegen onto two new
ISD opcodes, ISD::STRICT_FSETCC and ISD::STRICT_FSETCCS, again
representing quiet vs. signaling comparison operations. Otherwise
those nodes look like SETCC nodes, with an additional chain argument
and result as usual for strict FP nodes. The patch includes support
for the common legalization operations for those nodes.
The patch also includes full SystemZ back-end support for the new
ISD nodes, mapping them to all available SystemZ instruction to
fully implement strict semantics (scalar and vector).
Differential Revision: https://reviews.llvm.org/D69281
2019-12-06 11:30:04 +01:00
|
|
|
ScalarResult = DAG.getSelect(dl, EltVT, ScalarResult,
|
|
|
|
DAG.getConstant(APInt::getAllOnesValue
|
|
|
|
(EltVT.getSizeInBits()), dl, EltVT),
|
|
|
|
DAG.getConstant(0, dl, EltVT));
|
|
|
|
|
|
|
|
OpValues.push_back(ScalarResult);
|
|
|
|
OpChains.push_back(ScalarChain);
|
2018-06-13 16:32:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue Result = DAG.getBuildVector(VT, dl, OpValues);
|
|
|
|
SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
|
|
|
|
|
2020-01-10 19:13:45 +01:00
|
|
|
Results.push_back(Result);
|
|
|
|
Results.push_back(NewChain);
|
2018-06-13 16:32:12 +02:00
|
|
|
}
|
|
|
|
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue VectorLegalizer::UnrollVSETCC(SDNode *Node) {
|
|
|
|
EVT VT = Node->getValueType(0);
|
2009-05-23 14:35:30 +02:00
|
|
|
unsigned NumElems = VT.getVectorNumElements();
|
2009-08-11 00:56:29 +02:00
|
|
|
EVT EltVT = VT.getVectorElementType();
|
2020-01-11 20:36:50 +01:00
|
|
|
SDValue LHS = Node->getOperand(0);
|
|
|
|
SDValue RHS = Node->getOperand(1);
|
|
|
|
SDValue CC = Node->getOperand(2);
|
2009-08-11 00:56:29 +02:00
|
|
|
EVT TmpEltVT = LHS.getValueType().getVectorElementType();
|
2020-01-11 20:36:50 +01:00
|
|
|
SDLoc dl(Node);
|
2009-05-23 14:35:30 +02:00
|
|
|
SmallVector<SDValue, 8> Ops(NumElems);
|
|
|
|
for (unsigned i = 0; i < NumElems; ++i) {
|
2020-01-15 08:06:57 +01:00
|
|
|
SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
|
|
|
|
DAG.getVectorIdxConstant(i, dl));
|
|
|
|
SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
|
|
|
|
DAG.getVectorIdxConstant(i, dl));
|
2013-05-18 02:21:46 +02:00
|
|
|
Ops[i] = DAG.getNode(ISD::SETCC, dl,
|
2015-07-09 04:09:04 +02:00
|
|
|
TLI.getSetCCResultType(DAG.getDataLayout(),
|
|
|
|
*DAG.getContext(), TmpEltVT),
|
2009-05-23 14:35:30 +02:00
|
|
|
LHSElem, RHSElem, CC);
|
2013-06-15 00:04:37 +02:00
|
|
|
Ops[i] = DAG.getSelect(dl, EltVT, Ops[i],
|
|
|
|
DAG.getConstant(APInt::getAllOnesValue
|
2015-04-28 16:05:47 +02:00
|
|
|
(EltVT.getSizeInBits()), dl, EltVT),
|
|
|
|
DAG.getConstant(0, dl, EltVT));
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
2017-01-30 19:20:42 +01:00
|
|
|
return DAG.getBuildVector(VT, dl, Ops);
|
2009-05-23 14:35:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SelectionDAG::LegalizeVectors() {
|
|
|
|
return VectorLegalizer(*this).Run();
|
|
|
|
}
|