summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>2018-04-20 19:38:37 +0000
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>2018-04-20 19:38:37 +0000
commit41a24b7b139a63225c03b8dd8c25c335d611dec3 (patch)
tree92d22188d7ce5008e3612fdf687680a7f3b1cf40 /llvm/lib
parentaadbabc070427fd3eaa85bb406d3d1db4ea2bac7 (diff)
downloadbcm5719-llvm-41a24b7b139a63225c03b8dd8c25c335d611dec3.tar.gz
bcm5719-llvm-41a24b7b139a63225c03b8dd8c25c335d611dec3.zip
[Hexagon] Improve HVX instruction selection (bitcast, vsplat)
There was some unfortunate interaction between VSPLAT and BITCAST related to the selection of constant vectors (coming from selecting shuffles). Introduce VSPLATW that always splats a 32-bit word, and can have arbitrary result type (to avoid BITCASTs of VSPLAT). Clean up the previous selection of BITCAST/VSPLAT. llvm-svn: 330471
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp17
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h1
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp42
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLowering.cpp1
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLowering.h4
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp4
-rw-r--r--llvm/lib/Target/Hexagon/HexagonPatternsHVX.td93
-rw-r--r--llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.cpp2
8 files changed, 93 insertions, 71 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index b2e9cc620d1..3f3585ca31a 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -758,22 +758,6 @@ void HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
ReplaceNode(N, R);
}
-
-void HexagonDAGToDAGISel::SelectBitcast(SDNode *N) {
- EVT SVT = N->getOperand(0).getValueType();
- EVT DVT = N->getValueType(0);
- if (!SVT.isVector() || !DVT.isVector() ||
- SVT.getVectorElementType() == MVT::i1 ||
- DVT.getVectorElementType() == MVT::i1 ||
- SVT.getSizeInBits() != DVT.getSizeInBits()) {
- SelectCode(N);
- return;
- }
-
- ReplaceUses(SDValue(N, 0), N->getOperand(0));
- CurDAG->RemoveDeadNode(N);
-}
-
void HexagonDAGToDAGISel::SelectVAlign(SDNode *N) {
MVT ResTy = N->getValueType(0).getSimpleVT();
if (HST->isHVXVectorType(ResTy, true))
@@ -882,7 +866,6 @@ void HexagonDAGToDAGISel::Select(SDNode *N) {
case ISD::Constant: return SelectConstant(N);
case ISD::ConstantFP: return SelectConstantFP(N);
case ISD::FrameIndex: return SelectFrameIndex(N);
- case ISD::BITCAST: return SelectBitcast(N);
case ISD::SHL: return SelectSHL(N);
case ISD::LOAD: return SelectLoad(N);
case ISD::STORE: return SelectStore(N);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
index b9f9d90b1f9..1c3379bf015 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
@@ -102,7 +102,6 @@ public:
void SelectIntrinsicWOChain(SDNode *N);
void SelectConstant(SDNode *N);
void SelectConstantFP(SDNode *N);
- void SelectBitcast(SDNode *N);
void SelectV65Gather(SDNode *N);
void SelectV65GatherPred(SDNode *N);
void SelectHVXDualOutput(SDNode *N);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
index 7eddf55a48e..a5c911d15dc 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
@@ -919,36 +919,40 @@ static bool isPermutation(ArrayRef<int> Mask) {
}
bool HvxSelector::selectVectorConstants(SDNode *N) {
- // Constant vectors are generated as loads from constant pools or
- // as VSPLATs of a constant value.
- // Since they are generated during the selection process, the main
- // selection algorithm is not aware of them. Select them directly
- // here.
+ // Constant vectors are generated as loads from constant pools or as
+ // splats of a constant value. Since they are generated during the
+ // selection process, the main selection algorithm is not aware of them.
+ // Select them directly here.
SmallVector<SDNode*,4> Nodes;
SetVector<SDNode*> WorkQ;
+ // The one-use test for VSPLATW's operand may fail due to dead nodes
+ // left over in the DAG.
+ DAG.RemoveDeadNodes();
+
// The DAG can change (due to CSE) during selection, so cache all the
// unselected nodes first to avoid traversing a mutating DAG.
auto IsNodeToSelect = [] (SDNode *N) {
if (N->isMachineOpcode())
return false;
- unsigned Opc = N->getOpcode();
- if (Opc == HexagonISD::VSPLAT || Opc == HexagonISD::VZERO)
- return true;
- if (Opc == ISD::BITCAST) {
- // Only select bitcasts of VSPLATs.
- if (N->getOperand(0).getOpcode() == HexagonISD::VSPLAT)
+ switch (N->getOpcode()) {
+ case HexagonISD::VZERO:
+ case HexagonISD::VSPLATW:
return true;
+ case ISD::LOAD: {
+ SDValue Addr = cast<LoadSDNode>(N)->getBasePtr();
+ unsigned AddrOpc = Addr.getOpcode();
+ if (AddrOpc == HexagonISD::AT_PCREL || AddrOpc == HexagonISD::CP)
+ if (Addr.getOperand(0).getOpcode() == ISD::TargetConstantPool)
+ return true;
+ }
+ break;
}
- if (Opc == ISD::LOAD) {
- SDValue Addr = cast<LoadSDNode>(N)->getBasePtr();
- unsigned AddrOpc = Addr.getOpcode();
- if (AddrOpc == HexagonISD::AT_PCREL || AddrOpc == HexagonISD::CP)
- if (Addr.getOperand(0).getOpcode() == ISD::TargetConstantPool)
- return true;
- }
- return false;
+ // Make sure to select the operand of VSPLATW.
+ bool IsSplatOp = N->hasOneUse() &&
+ N->use_begin()->getOpcode() == HexagonISD::VSPLATW;
+ return IsSplatOp;
};
WorkQ.insert(N);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
index 40740f1e156..be036b3ddb3 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp
@@ -1731,6 +1731,7 @@ const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
case HexagonISD::VROR: return "HexagonISD::VROR";
case HexagonISD::READCYCLE: return "HexagonISD::READCYCLE";
case HexagonISD::VZERO: return "HexagonISD::VZERO";
+ case HexagonISD::VSPLATW: return "HexagonISD::VSPLATW";
case HexagonISD::D2P: return "HexagonISD::D2P";
case HexagonISD::P2D: return "HexagonISD::P2D";
case HexagonISD::V2Q: return "HexagonISD::V2Q";
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
index adbb066171e..5ed26101d58 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h
@@ -51,7 +51,8 @@ namespace HexagonISD {
CP, // Constant pool.
COMBINE,
- VSPLAT,
+ VSPLAT, // Generic splat, selection depends on argument/return
+ // types.
VASL,
VASR,
VLSR,
@@ -77,6 +78,7 @@ namespace HexagonISD {
QTRUE,
QFALSE,
VZERO,
+ VSPLATW, // HVX splat of a 32-bit word with an arbitrary result type.
TYPECAST, // No-op that's used to convert between different legal
// types in a register.
VALIGN, // Align two vectors (in Op0, Op1) to one that would have
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
index 4aad920f2bc..281cfcf9f89 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
@@ -367,9 +367,7 @@ HexagonTargetLowering::buildHvxVectorReg(ArrayRef<SDValue> Values,
auto *IdxN = dyn_cast<ConstantSDNode>(SplatV.getNode());
if (IdxN && IdxN->isNullValue())
return getZero(dl, VecTy, DAG);
- MVT WordTy = MVT::getVectorVT(MVT::i32, HwLen/4);
- SDValue SV = DAG.getNode(HexagonISD::VSPLAT, dl, WordTy, SplatV);
- return DAG.getBitcast(VecTy, SV);
+ return DAG.getNode(HexagonISD::VSPLATW, dl, VecTy, SplatV);
}
// Delay recognizing constant vectors until here, so that we can generate
diff --git a/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td b/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td
index 6217df504f1..9c313abee8b 100644
--- a/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td
+++ b/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td
@@ -9,7 +9,10 @@ def HexagonVEXTRACTW : SDNode<"HexagonISD::VEXTRACTW", SDTHexagonVEXTRACTW>;
def SDTHexagonVINSERTW0: SDTypeProfile<1, 2,
[SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisVT<2, i32>]>;
-def HexagonVINSERTW0 : SDNode<"HexagonISD::VINSERTW0", SDTHexagonVINSERTW0>;
+def HexagonVINSERTW0: SDNode<"HexagonISD::VINSERTW0", SDTHexagonVINSERTW0>;
+
+def SDTHexagonVSPLATW: SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVT<1, i32>]>;
+def HexagonVSPLATW: SDNode<"HexagonISD::VSPLATW", SDTHexagonVSPLATW>;
def HwLen2: SDNodeXForm<imm, [{
const auto &ST = static_cast<const HexagonSubtarget&>(CurDAG->getSubtarget());
@@ -157,6 +160,26 @@ let Predicates = [UseHVX] in {
defm: HvxSt_pat<V6_vS32Ub_ai, unalignedstore, IsVecOff, HVI32>;
}
+// Bitcasts between same-size vector types are no-ops, except for the
+// actual type change.
+class Bitcast<ValueType ResTy, ValueType InpTy, RegisterClass RC>
+ : Pat<(ResTy (bitconvert (InpTy RC:$Val))), (ResTy RC:$Val)>;
+
+let Predicates = [UseHVX] in {
+ def: Bitcast<VecI8, VecI16, HvxVR>;
+ def: Bitcast<VecI8, VecI32, HvxVR>;
+ def: Bitcast<VecI16, VecI8, HvxVR>;
+ def: Bitcast<VecI16, VecI32, HvxVR>;
+ def: Bitcast<VecI32, VecI8, HvxVR>;
+ def: Bitcast<VecI32, VecI16, HvxVR>;
+
+ def: Bitcast<VecPI8, VecPI16, HvxWR>;
+ def: Bitcast<VecPI8, VecPI32, HvxWR>;
+ def: Bitcast<VecPI16, VecPI8, HvxWR>;
+ def: Bitcast<VecPI16, VecPI32, HvxWR>;
+ def: Bitcast<VecPI32, VecPI8, HvxWR>;
+ def: Bitcast<VecPI32, VecPI16, HvxWR>;
+}
let Predicates = [UseHVX] in {
def: Pat<(VecI8 vzero), (V6_vd0)>;
@@ -190,38 +213,44 @@ let Predicates = [UseHVX] in {
(V6_vinsertwr HvxVR:$Vu, I32:$Rt)>;
def: Pat<(HexagonVINSERTW0 HVI32:$Vu, I32:$Rt),
(V6_vinsertwr HvxVR:$Vu, I32:$Rt)>;
+}
+
+def Vsplatib: OutPatFrag<(ops node:$V), (V6_lvsplatw (ToI32 (SplatB $V)))>;
+def Vsplatih: OutPatFrag<(ops node:$V), (V6_lvsplatw (ToI32 (SplatH $V)))>;
+def Vsplatiw: OutPatFrag<(ops node:$V), (V6_lvsplatw (ToI32 $V))>;
+def Vsplatrb: OutPatFrag<(ops node:$Rs), (V6_lvsplatw (S2_vsplatrb $Rs))>;
+def Vsplatrh: OutPatFrag<(ops node:$Rs),
+ (V6_lvsplatw (A2_combine_ll $Rs, $Rs))>;
+def Vsplatrw: OutPatFrag<(ops node:$Rs), (V6_lvsplatw $Rs)>;
+
+def Rep: OutPatFrag<(ops node:$N), (Combinev $N, $N)>;
+
+let Predicates = [UseHVX] in {
let AddedComplexity = 10 in {
- def: Pat<(VecI8 (HexagonVSPLAT u8_0ImmPred:$V)),
- (V6_lvsplatw (ToI32 (SplatB $V)))>;
- def: Pat<(VecI16 (HexagonVSPLAT u16_0ImmPred:$V)),
- (V6_lvsplatw (ToI32 (SplatH $V)))>;
- def: Pat<(VecI32 (HexagonVSPLAT anyimm:$V)),
- (V6_lvsplatw (ToI32 $V))>;
- def: Pat<(VecPI8 (HexagonVSPLAT u8_0ImmPred:$V)),
- (Combinev (V6_lvsplatw (ToI32 (SplatB $V))),
- (V6_lvsplatw (ToI32 (SplatB $V))))>;
- def: Pat<(VecPI16 (HexagonVSPLAT u16_0ImmPred:$V)),
- (Combinev (V6_lvsplatw (ToI32 (SplatH $V))),
- (V6_lvsplatw (ToI32 (SplatH $V))))>;
- def: Pat<(VecPI32 (HexagonVSPLAT anyimm:$V)),
- (Combinev (V6_lvsplatw (ToI32 $V)), (V6_lvsplatw (ToI32 $V)))>;
+ def: Pat<(VecI8 (HexagonVSPLAT u8_0ImmPred:$V)), (Vsplatib $V)>;
+ def: Pat<(VecI16 (HexagonVSPLAT u16_0ImmPred:$V)), (Vsplatih $V)>;
+ def: Pat<(VecI32 (HexagonVSPLAT anyimm:$V)), (Vsplatiw $V)>;
+ def: Pat<(VecPI8 (HexagonVSPLAT u8_0ImmPred:$V)), (Rep (Vsplatib $V))>;
+ def: Pat<(VecPI16 (HexagonVSPLAT u16_0ImmPred:$V)), (Rep (Vsplatih $V))>;
+ def: Pat<(VecPI32 (HexagonVSPLAT anyimm:$V)), (Rep (Vsplatiw $V))>;
}
- def: Pat<(VecI8 (HexagonVSPLAT I32:$Rs)),
- (V6_lvsplatw (S2_vsplatrb I32:$Rs))>;
- def: Pat<(VecI16 (HexagonVSPLAT I32:$Rs)),
- (V6_lvsplatw (A2_combine_ll I32:$Rs, I32:$Rs))>;
- def: Pat<(VecI32 (HexagonVSPLAT I32:$Rs)),
- (V6_lvsplatw I32:$Rs)>;
- def: Pat<(VecPI8 (HexagonVSPLAT I32:$Rs)),
- (Combinev (V6_lvsplatw (S2_vsplatrb I32:$Rs)),
- (V6_lvsplatw (S2_vsplatrb I32:$Rs)))>;
- def: Pat<(VecPI16 (HexagonVSPLAT I32:$Rs)),
- (Combinev (V6_lvsplatw (A2_combine_ll I32:$Rs, I32:$Rs)),
- (V6_lvsplatw (A2_combine_ll I32:$Rs, I32:$Rs)))>;
- def: Pat<(VecPI32 (HexagonVSPLAT I32:$Rs)),
- (Combinev (V6_lvsplatw I32:$Rs), (V6_lvsplatw I32:$Rs))>;
+ def: Pat<(VecI8 (HexagonVSPLAT I32:$Rs)), (Vsplatrb $Rs)>;
+ def: Pat<(VecI16 (HexagonVSPLAT I32:$Rs)), (Vsplatrh $Rs)>;
+ def: Pat<(VecI32 (HexagonVSPLAT I32:$Rs)), (Vsplatrw $Rs)>;
+ def: Pat<(VecPI8 (HexagonVSPLAT I32:$Rs)), (Rep (Vsplatrb $Rs))>;
+ def: Pat<(VecPI16 (HexagonVSPLAT I32:$Rs)), (Rep (Vsplatrh $Rs))>;
+ def: Pat<(VecPI32 (HexagonVSPLAT I32:$Rs)), (Rep (Vsplatrw $Rs))>;
+
+ def: Pat<(VecI8 (HexagonVSPLATW I32:$Rs)), (V6_lvsplatw I32:$Rs)>;
+ def: Pat<(VecI16 (HexagonVSPLATW I32:$Rs)), (V6_lvsplatw I32:$Rs)>;
+ def: Pat<(VecI32 (HexagonVSPLATW I32:$Rs)), (V6_lvsplatw I32:$Rs)>;
+ def: Pat<(VecPI8 (HexagonVSPLATW I32:$Rs)), (Rep (V6_lvsplatw I32:$Rs))>;
+ def: Pat<(VecPI16 (HexagonVSPLATW I32:$Rs)), (Rep (V6_lvsplatw I32:$Rs))>;
+ def: Pat<(VecPI32 (HexagonVSPLATW I32:$Rs)), (Rep (V6_lvsplatw I32:$Rs))>;
+}
+let Predicates = [UseHVX] in {
def: Pat<(add HVI8:$Vs, HVI8:$Vt), (V6_vaddb HvxVR:$Vs, HvxVR:$Vt)>;
def: Pat<(add HVI16:$Vs, HVI16:$Vt), (V6_vaddh HvxVR:$Vs, HvxVR:$Vt)>;
def: Pat<(add HVI32:$Vs, HVI32:$Vt), (V6_vaddw HvxVR:$Vs, HvxVR:$Vt)>;
@@ -237,8 +266,14 @@ let Predicates = [UseHVX] in {
def: Pat<(sub HWI32:$Vs, HWI32:$Vt), (V6_vsubw_dv HvxWR:$Vs, HvxWR:$Vt)>;
def: Pat<(and HVI8:$Vs, HVI8:$Vt), (V6_vand HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(and HVI16:$Vs, HVI16:$Vt), (V6_vand HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(and HVI32:$Vs, HVI32:$Vt), (V6_vand HvxVR:$Vs, HvxVR:$Vt)>;
def: Pat<(or HVI8:$Vs, HVI8:$Vt), (V6_vor HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(or HVI16:$Vs, HVI16:$Vt), (V6_vor HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(or HVI32:$Vs, HVI32:$Vt), (V6_vor HvxVR:$Vs, HvxVR:$Vt)>;
def: Pat<(xor HVI8:$Vs, HVI8:$Vt), (V6_vxor HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(xor HVI16:$Vs, HVI16:$Vt), (V6_vxor HvxVR:$Vs, HvxVR:$Vt)>;
+ def: Pat<(xor HVI32:$Vs, HVI32:$Vt), (V6_vxor HvxVR:$Vs, HvxVR:$Vt)>;
def: Pat<(vselect HQ8:$Qu, HVI8:$Vs, HVI8:$Vt),
(V6_vmux HvxQR:$Qu, HvxVR:$Vs, HvxVR:$Vt)>;
diff --git a/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.cpp b/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.cpp
index bca856ae9cb..ded0adb97a3 100644
--- a/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.cpp
@@ -28,7 +28,7 @@ using namespace llvm;
#define DEBUG_TYPE "hexagontti"
-static cl::opt<bool> HexagonAutoHVX("hexagon-autohvx", cl::init(false),
+static cl::opt<bool> HexagonAutoHVX("hexagon-autohvx", cl::init(true),
cl::Hidden, cl::desc("Enable loop vectorizer for HVX"));
static cl::opt<bool> EmitLookupTables("hexagon-emit-lookup-tables",
OpenPOWER on IntegriCloud