summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp')
-rw-r--r--gnu/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp127
1 files changed, 74 insertions, 53 deletions
diff --git a/gnu/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/gnu/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
index 9355dbe77f9..6a141818bb6 100644
--- a/gnu/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
+++ b/gnu/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
@@ -1,4 +1,4 @@
-//===-- LegalizeVectorOps.cpp - Implement SelectionDAG::LegalizeVectors ---===//
+//===- LegalizeVectorOps.cpp - Implement SelectionDAG::LegalizeVectors ----===//
//
// The LLVM Compiler Infrastructure
//
@@ -27,15 +27,36 @@
//
//===----------------------------------------------------------------------===//
+#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"
+#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/SelectionDAG.h"
-#include "llvm/Target/TargetLowering.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <utility>
+
using namespace llvm;
+#define DEBUG_TYPE "legalizevectorops"
+
namespace {
+
class VectorLegalizer {
SelectionDAG& DAG;
const TargetLowering &TLI;
- bool Changed; // Keep track of whether anything changed
+ bool Changed = false; // Keep track of whether anything changed
/// 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
@@ -118,22 +139,25 @@ class VectorLegalizer {
/// \brief Implements [SU]INT_TO_FP vector promotion.
///
- /// This is a [zs]ext of the input operand to the next size up.
+ /// This is a [zs]ext of the input operand to a larger integer type.
SDValue PromoteINT_TO_FP(SDValue Op);
/// \brief Implements FP_TO_[SU]INT vector promotion of the result type.
///
- /// It is promoted to the next size up integer type. The result is then
+ /// It is promoted to a larger integer type. The result is then
/// truncated back to the original type.
- SDValue PromoteFP_TO_INT(SDValue Op, bool isSigned);
+ SDValue PromoteFP_TO_INT(SDValue Op);
public:
+ VectorLegalizer(SelectionDAG& dag) :
+ DAG(dag), TLI(dag.getTargetLoweringInfo()) {}
+
/// \brief Begin legalizer the vector operations in the DAG.
bool Run();
- VectorLegalizer(SelectionDAG& dag) :
- DAG(dag), TLI(dag.getTargetLoweringInfo()), Changed(false) {}
};
+} // end anonymous namespace
+
bool VectorLegalizer::Run() {
// Before we start legalizing vector nodes, check if there are any vectors.
bool HasVectors = false;
@@ -204,7 +228,8 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
if (Op.getOpcode() == ISD::LOAD) {
LoadSDNode *LD = cast<LoadSDNode>(Op.getNode());
ISD::LoadExtType ExtType = LD->getExtensionType();
- if (LD->getMemoryVT().isVector() && ExtType != ISD::NON_EXTLOAD)
+ if (LD->getMemoryVT().isVector() && ExtType != ISD::NON_EXTLOAD) {
+ DEBUG(dbgs() << "\nLegalizing extending vector load: "; Node->dump(&DAG));
switch (TLI.getLoadExtAction(LD->getExtensionType(), LD->getValueType(0),
LD->getMemoryVT())) {
default: llvm_unreachable("This action is not supported yet!");
@@ -230,11 +255,14 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
Changed = true;
return LegalizeOp(ExpandLoad(Op));
}
+ }
} else if (Op.getOpcode() == ISD::STORE) {
StoreSDNode *ST = cast<StoreSDNode>(Op.getNode());
EVT StVT = ST->getMemoryVT();
MVT ValVT = ST->getValue().getSimpleValueType();
- if (StVT.isVector() && ST->isTruncatingStore())
+ if (StVT.isVector() && ST->isTruncatingStore()) {
+ DEBUG(dbgs() << "\nLegalizing truncating vector store: ";
+ Node->dump(&DAG));
switch (TLI.getTruncStoreAction(ValVT, StVT)) {
default: llvm_unreachable("This action is not supported yet!");
case TargetLowering::Legal:
@@ -248,6 +276,7 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
Changed = true;
return LegalizeOp(ExpandStore(Op));
}
+ }
} else if (Op.getOpcode() == ISD::MSCATTER || Op.getOpcode() == ISD::MSTORE)
HasVectorValue = true;
@@ -354,6 +383,8 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
break;
}
+ DEBUG(dbgs() << "\nLegalizing vector op: "; Node->dump(&DAG));
+
switch (TLI.getOperationAction(Node->getOpcode(), QueryType)) {
default: llvm_unreachable("This action is not supported yet!");
case TargetLowering::Promote:
@@ -361,12 +392,16 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
Changed = true;
break;
case TargetLowering::Legal:
+ DEBUG(dbgs() << "Legal node: nothing to do\n");
break;
case TargetLowering::Custom: {
+ DEBUG(dbgs() << "Trying custom legalization\n");
if (SDValue Tmp1 = TLI.LowerOperation(Op, DAG)) {
+ DEBUG(dbgs() << "Successfully custom legalized node\n");
Result = Tmp1;
break;
}
+ DEBUG(dbgs() << "Could not custom legalize node\n");
LLVM_FALLTHROUGH;
}
case TargetLowering::Expand:
@@ -396,7 +431,7 @@ SDValue VectorLegalizer::Promote(SDValue Op) {
case ISD::FP_TO_UINT:
case ISD::FP_TO_SINT:
// Promote the operation by extending the operand.
- return PromoteFP_TO_INT(Op, Op->getOpcode() == ISD::FP_TO_SINT);
+ return PromoteFP_TO_INT(Op);
}
// There are currently two cases of vector promotion:
@@ -437,20 +472,11 @@ SDValue VectorLegalizer::Promote(SDValue Op) {
SDValue VectorLegalizer::PromoteINT_TO_FP(SDValue Op) {
// INT_TO_FP operations may require the input operand be promoted even
// when the type is otherwise legal.
- EVT VT = Op.getOperand(0).getValueType();
- assert(Op.getNode()->getNumValues() == 1 &&
- "Can't promote a vector with multiple results!");
-
- // Normal getTypeToPromoteTo() doesn't work here, as that will promote
- // by widening the vector w/ the same element width and twice the number
- // of elements. We want the other way around, the same number of elements,
- // each twice the width.
- //
- // Increase the bitwidth of the element to the next pow-of-two
- // (which is greater than 8 bits).
+ MVT VT = Op.getOperand(0).getSimpleValueType();
+ MVT NVT = TLI.getTypeToPromoteTo(Op.getOpcode(), VT);
+ assert(NVT.getVectorNumElements() == VT.getVectorNumElements() &&
+ "Vectors have different number of elements!");
- EVT NVT = VT.widenIntegerVectorElementType(*DAG.getContext());
- assert(NVT.isSimple() && "Promoting to a non-simple vector type!");
SDLoc dl(Op);
SmallVector<SDValue, 4> Operands(Op.getNumOperands());
@@ -470,32 +496,32 @@ SDValue VectorLegalizer::PromoteINT_TO_FP(SDValue Op) {
// 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.
-SDValue VectorLegalizer::PromoteFP_TO_INT(SDValue Op, bool isSigned) {
- assert(Op.getNode()->getNumValues() == 1 &&
- "Can't promote a vector with multiple results!");
- EVT VT = Op.getValueType();
+SDValue VectorLegalizer::PromoteFP_TO_INT(SDValue Op) {
+ MVT VT = Op.getSimpleValueType();
+ MVT NVT = TLI.getTypeToPromoteTo(Op.getOpcode(), VT);
+ assert(NVT.getVectorNumElements() == VT.getVectorNumElements() &&
+ "Vectors have different number of elements!");
- EVT NewVT;
- unsigned NewOpc;
- while (1) {
- NewVT = VT.widenIntegerVectorElementType(*DAG.getContext());
- assert(NewVT.isSimple() && "Promoting to a non-simple vector type!");
- if (TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NewVT)) {
- NewOpc = ISD::FP_TO_SINT;
- break;
- }
- if (!isSigned && TLI.isOperationLegalOrCustom(ISD::FP_TO_UINT, NewVT)) {
- NewOpc = ISD::FP_TO_UINT;
- break;
- }
- }
+ unsigned NewOpc = Op->getOpcode();
+ // 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;
- SDLoc loc(Op);
- SDValue promoted = DAG.getNode(NewOpc, SDLoc(Op), NewVT, Op.getOperand(0));
- return DAG.getNode(ISD::TRUNCATE, SDLoc(Op), VT, promoted);
+ SDLoc dl(Op);
+ SDValue Promoted = DAG.getNode(NewOpc, dl, NVT, Op.getOperand(0));
+
+ // 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.
+ Promoted = DAG.getNode(Op->getOpcode() == ISD::FP_TO_UINT ? ISD::AssertZext
+ : ISD::AssertSext,
+ dl, NVT, Promoted,
+ DAG.getValueType(VT.getScalarType()));
+ return DAG.getNode(ISD::TRUNCATE, dl, VT, Promoted);
}
-
SDValue VectorLegalizer::ExpandLoad(SDValue Op) {
LoadSDNode *LD = cast<LoadSDNode>(Op.getNode());
@@ -503,7 +529,6 @@ SDValue VectorLegalizer::ExpandLoad(SDValue Op) {
EVT SrcEltVT = SrcVT.getScalarType();
unsigned NumElem = SrcVT.getVectorNumElements();
-
SDValue NewChain;
SDValue Value;
if (SrcVT.getVectorNumElements() > 1 && !SrcEltVT.isByteSized()) {
@@ -534,7 +559,6 @@ SDValue VectorLegalizer::ExpandLoad(SDValue Op) {
unsigned Offset = 0;
unsigned RemainingBytes = SrcVT.getStoreSize();
SmallVector<SDValue, 8> LoadVals;
-
while (RemainingBytes > 0) {
SDValue ScalarLoad;
unsigned LoadBytes = WideBytes;
@@ -560,9 +584,8 @@ SDValue VectorLegalizer::ExpandLoad(SDValue Op) {
RemainingBytes -= LoadBytes;
Offset += LoadBytes;
- BasePTR = DAG.getNode(ISD::ADD, dl, BasePTR.getValueType(), BasePTR,
- DAG.getConstant(LoadBytes, dl,
- BasePTR.getValueType()));
+
+ BasePTR = DAG.getObjectPtrOffset(dl, BasePTR, LoadBytes);
LoadVals.push_back(ScalarLoad.getValue(0));
LoadChains.push_back(ScalarLoad.getValue(1));
@@ -1117,8 +1140,6 @@ SDValue VectorLegalizer::UnrollVSETCC(SDValue Op) {
return DAG.getBuildVector(VT, dl, Ops);
}
-}
-
bool SelectionDAG::LegalizeVectors() {
return VectorLegalizer(*this).Run();
}