1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[Hexagon] Handle widening of truncation's operand with legal result

Failing example: v8i8 = truncate v8i32. v8i8 is legal, but v8i32 was
widened to HVX. Make sure that v8i8 does not get altered (even if it's
changed to another legal type).
This commit is contained in:
Krzysztof Parzyszek 2020-09-08 14:20:41 -05:00
parent 94da56feaf
commit 77adca5920
3 changed files with 84 additions and 19 deletions

View File

@ -487,6 +487,7 @@ private:
findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT)
const override;
bool shouldWidenToHvx(MVT Ty, SelectionDAG &DAG) const;
bool isHvxOperation(SDNode *N, SelectionDAG &DAG) const;
SDValue LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const;
void LowerHvxOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results,

View File

@ -1939,16 +1939,36 @@ HexagonTargetLowering::WidenHvxTruncate(SDValue Op, SelectionDAG &DAG) const {
SDValue Op0 = Op.getOperand(0);
MVT ResTy = ty(Op);
MVT OpTy = ty(Op0);
// .-res, op-> Scalar Illegal HVX
// Scalar ok extract(widen) -
// Illegal - widen widen
// HVX - - ok
if (Subtarget.isHVXVectorType(OpTy))
return DAG.getNode(HexagonISD::VPACKL, dl, getWideTy(ResTy), Op0);
assert(!isTypeLegal(OpTy) && "HVX-widening a truncate of scalar?");
MVT WideOpTy = getWideTy(OpTy);
SmallVector<SDValue, 4> Concats = {Op0};
for (int i = 0, e = getFactor(OpTy) - 1; i != e; ++i)
Concats.push_back(DAG.getUNDEF(OpTy));
SDValue Cat = DAG.getNode(ISD::CONCAT_VECTORS, dl, WideOpTy, Concats);
return DAG.getNode(HexagonISD::VPACKL, dl, getWideTy(ResTy), Cat);
SDValue V = DAG.getNode(HexagonISD::VPACKL, dl, getWideTy(ResTy), Cat);
// If the original result wasn't legal and was supposed to be widened,
// we're done.
if (shouldWidenToHvx(ResTy, DAG))
return V;
// The original result type wasn't meant to be widened to HVX, so
// leave it as it is. Standard legalization should be able to deal
// with it (since now it's a result of a target-idendependent ISD
// node).
assert(ResTy.isVector());
return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, ResTy,
{V, getZero(dl, MVT::i32, DAG)});
}
SDValue
@ -2029,11 +2049,15 @@ HexagonTargetLowering::LowerHvxOperationWrapper(SDNode *N,
SDValue Op(N, 0);
switch (Opc) {
case ISD::TRUNCATE: {
assert(shouldWidenToHvx(ty(Op.getOperand(0)), DAG) && "Not widening?");
SDValue T = WidenHvxTruncate(Op, DAG);
Results.push_back(T);
break;
}
case ISD::STORE: {
assert(
getPreferredHvxVectorAction(ty(cast<StoreSDNode>(N)->getValue())) ==
TargetLoweringBase::TypeWidenVector &&
"Not widening?");
assert(shouldWidenToHvx(ty(cast<StoreSDNode>(N)->getValue()), DAG) &&
"Not widening?");
SDValue Store = WidenHvxStore(SDValue(N, 0), DAG);
Results.push_back(Store);
break;
@ -2061,12 +2085,12 @@ HexagonTargetLowering::ReplaceHvxNodeResults(SDNode *N,
unsigned Opc = N->getOpcode();
SDValue Op(N, 0);
switch (Opc) {
case ISD::TRUNCATE:
if (!Subtarget.isHVXVectorType(ty(Op), false)) {
SDValue T = WidenHvxTruncate(Op, DAG);
Results.push_back(T);
}
case ISD::TRUNCATE: {
assert(shouldWidenToHvx(ty(Op), DAG) && "Not widening?");
SDValue T = WidenHvxTruncate(Op, DAG);
Results.push_back(T);
break;
}
case ISD::BITCAST:
if (isHvxBoolTy(ty(N->getOperand(0)))) {
SDValue Op(N, 0);
@ -2103,8 +2127,22 @@ HexagonTargetLowering::PerformHvxDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
return SDValue();
}
bool
HexagonTargetLowering::shouldWidenToHvx(MVT Ty, SelectionDAG &DAG) const {
assert(!Subtarget.isHVXVectorType(Ty, true));
auto Action = getPreferredHvxVectorAction(Ty);
if (Action == TargetLoweringBase::TypeWidenVector) {
EVT WideTy = getTypeToTransformTo(*DAG.getContext(), Ty);
assert(WideTy.isSimple());
return Subtarget.isHVXVectorType(WideTy.getSimpleVT(), true);
}
return false;
}
bool
HexagonTargetLowering::isHvxOperation(SDNode *N, SelectionDAG &DAG) const {
if (!Subtarget.useHVXOps())
return false;
// If the type of any result, or any operand type are HVX vector types,
// this is an HVX operation.
auto IsHvxTy = [this](EVT Ty) {
@ -2122,15 +2160,7 @@ HexagonTargetLowering::isHvxOperation(SDNode *N, SelectionDAG &DAG) const {
if (!Op.getValueType().isSimple())
return false;
MVT ValTy = ty(Op);
if (ValTy.isVector()) {
auto Action = getPreferredVectorAction(ValTy);
if (Action == TargetLoweringBase::TypeWidenVector) {
EVT WideTy = getTypeToTransformTo(*DAG.getContext(), ValTy);
assert(WideTy.isSimple());
return Subtarget.isHVXVectorType(WideTy.getSimpleVT(), true);
}
}
return false;
return ValTy.isVector() && shouldWidenToHvx(ValTy, DAG);
};
for (int i = 0, e = N->getNumValues(); i != e; ++i) {

View File

@ -0,0 +1,34 @@
; RUN: llc -march=hexagon -hexagon-hvx-widen=32 < %s | FileCheck %s
; Truncating a type-to-be-widenened to a legal type (v8i8).
; Check that this compiles successfully.
; CHECK-LABEL: f0:
; CHECK: dealloc_return
target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
target triple = "hexagon"
define dllexport void @f0(i8* %a0) local_unnamed_addr #0 {
b0:
%v0 = load i8, i8* undef, align 1
%v1 = zext i8 %v0 to i16
%v2 = add i16 0, %v1
%v3 = icmp sgt i16 %v2, 1
%v4 = select i1 %v3, i16 %v2, i16 1
%v5 = udiv i16 -32768, %v4
%v6 = zext i16 %v5 to i32
%v7 = insertelement <8 x i32> undef, i32 %v6, i32 0
%v8 = shufflevector <8 x i32> %v7, <8 x i32> undef, <8 x i32> zeroinitializer
%v9 = load <8 x i16>, <8 x i16>* undef, align 2
%v10 = sext <8 x i16> %v9 to <8 x i32>
%v11 = mul nsw <8 x i32> %v8, %v10
%v12 = add nsw <8 x i32> %v11, <i32 16384, i32 16384, i32 16384, i32 16384, i32 16384, i32 16384, i32 16384, i32 16384>
%v13 = lshr <8 x i32> %v12, <i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15, i32 15>
%v14 = trunc <8 x i32> %v13 to <8 x i8>
%v15 = getelementptr inbounds i8, i8* %a0, i32 undef
%v16 = bitcast i8* %v15 to <8 x i8>*
store <8 x i8> %v14, <8 x i8>* %v16, align 1
ret void
}
attributes #0 = { "target-features"="+hvx,+hvx-length128b" }