diff options
| author | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2018-04-19 14:24:31 +0000 |
|---|---|---|
| committer | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2018-04-19 14:24:31 +0000 |
| commit | 23bcf06a15e5ade824fdd6d3290a2a011d721dcc (patch) | |
| tree | 5b10bb060bf5c579884c47b9da1fde3f7c232fd9 /llvm/lib | |
| parent | aeb6c48d2937df07fc3426a0e60d667dd14ab5d2 (diff) | |
| download | bcm5719-llvm-23bcf06a15e5ade824fdd6d3290a2a011d721dcc.tar.gz bcm5719-llvm-23bcf06a15e5ade824fdd6d3290a2a011d721dcc.zip | |
[Hexagon] Add/fix patterns for 32/64-bit vector compares and logical ops
llvm-svn: 330330
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelLowering.cpp | 95 | ||||
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonPatterns.td | 93 |
2 files changed, 89 insertions, 99 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index 91af9e228ea..40740f1e156 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -803,63 +803,62 @@ HexagonTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { MachinePointerInfo(SV)); } -static bool isSExtFree(SDValue N) { - // A sign-extend of a truncate of a sign-extend is free. - if (N.getOpcode() == ISD::TRUNCATE && - N.getOperand(0).getOpcode() == ISD::AssertSext) - return true; - // We have sign-extended loads. - if (N.getOpcode() == ISD::LOAD) - return true; - return false; -} - SDValue HexagonTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { - SDLoc dl(Op); + const SDLoc &dl(Op); SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); - SDValue Cmp = Op.getOperand(2); - ISD::CondCode CC = cast<CondCodeSDNode>(Cmp)->get(); - - EVT VT = Op.getValueType(); - EVT LHSVT = LHS.getValueType(); - EVT RHSVT = RHS.getValueType(); + ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); + MVT ResTy = ty(Op); + MVT OpTy = ty(LHS); - if (LHSVT == MVT::v2i16) { - assert(CC == ISD::SETEQ || CC == ISD::SETNE || - ISD::isSignedIntSetCC(CC) || ISD::isUnsignedIntSetCC(CC)); - unsigned ExtOpc = ISD::isSignedIntSetCC(CC) ? ISD::SIGN_EXTEND - : ISD::ZERO_EXTEND; - SDValue LX = DAG.getNode(ExtOpc, dl, MVT::v2i32, LHS); - SDValue RX = DAG.getNode(ExtOpc, dl, MVT::v2i32, RHS); - SDValue SC = DAG.getNode(ISD::SETCC, dl, MVT::v2i1, LX, RX, Cmp); - return SC; + if (OpTy == MVT::v2i16 || OpTy == MVT::v4i8) { + MVT ElemTy = OpTy.getVectorElementType(); + assert(ElemTy.isScalarInteger()); + MVT WideTy = MVT::getVectorVT(MVT::getIntegerVT(2*ElemTy.getSizeInBits()), + OpTy.getVectorNumElements()); + return DAG.getSetCC(dl, ResTy, + DAG.getSExtOrTrunc(LHS, SDLoc(LHS), WideTy), + DAG.getSExtOrTrunc(RHS, SDLoc(RHS), WideTy), CC); } // Treat all other vector types as legal. - if (VT.isVector()) + if (ResTy.isVector()) return Op; - // Equals and not equals should use sign-extend, not zero-extend, since - // we can represent small negative values in the compare instructions. + // Comparisons of short integers should use sign-extend, not zero-extend, + // since we can represent small negative values in the compare instructions. // The LLVM default is to use zero-extend arbitrarily in these cases. - if ((CC == ISD::SETEQ || CC == ISD::SETNE) && - (RHSVT == MVT::i8 || RHSVT == MVT::i16) && - (LHSVT == MVT::i8 || LHSVT == MVT::i16)) { - ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS); - if (C && C->getAPIntValue().isNegative()) { - LHS = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, LHS); - RHS = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, RHS); - return DAG.getNode(ISD::SETCC, dl, Op.getValueType(), - LHS, RHS, Op.getOperand(2)); - } - if (isSExtFree(LHS) || isSExtFree(RHS)) { - LHS = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, LHS); - RHS = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, RHS); - return DAG.getNode(ISD::SETCC, dl, Op.getValueType(), - LHS, RHS, Op.getOperand(2)); + auto isSExtFree = [this](SDValue N) { + switch (N.getOpcode()) { + case ISD::TRUNCATE: { + // A sign-extend of a truncate of a sign-extend is free. + SDValue Op = N.getOperand(0); + if (Op.getOpcode() != ISD::AssertSext) + return false; + MVT OrigTy = cast<VTSDNode>(Op.getOperand(1))->getVT().getSimpleVT(); + unsigned ThisBW = ty(N).getSizeInBits(); + unsigned OrigBW = OrigTy.getSizeInBits(); + // The type that was sign-extended to get the AssertSext must be + // narrower than the type of N (so that N has still the same value + // as the original). + return ThisBW >= OrigBW; + } + case ISD::LOAD: + // We have sign-extended loads. + return true; } + return false; + }; + + if (OpTy == MVT::i8 || OpTy == MVT::i16) { + ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS); + bool IsNegative = C && C->getAPIntValue().isNegative(); + if (IsNegative || isSExtFree(LHS) || isSExtFree(RHS)) + return DAG.getSetCC(dl, ResTy, + DAG.getSExtOrTrunc(LHS, SDLoc(LHS), MVT::i32), + DAG.getSExtOrTrunc(RHS, SDLoc(RHS), MVT::i32), CC); } + return SDValue(); } @@ -1306,8 +1305,10 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, setOperationAction(ISD::BlockAddress, MVT::i32, Custom); // Hexagon needs to optimize cases with negative constants. - setOperationAction(ISD::SETCC, MVT::i8, Custom); - setOperationAction(ISD::SETCC, MVT::i16, Custom); + setOperationAction(ISD::SETCC, MVT::i8, Custom); + setOperationAction(ISD::SETCC, MVT::i16, Custom); + setOperationAction(ISD::SETCC, MVT::v4i8, Custom); + setOperationAction(ISD::SETCC, MVT::v2i16, Custom); // VASTART needs to be custom lowered to use the VarArgsFrameIndex. setOperationAction(ISD::VASTART, MVT::Other, Custom); diff --git a/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td index 6806981ab58..91e03b561d8 100644 --- a/llvm/lib/Target/Hexagon/HexagonPatterns.td +++ b/llvm/lib/Target/Hexagon/HexagonPatterns.td @@ -616,27 +616,40 @@ def: Pat<(i1 (setle I32:$Rs, anyimm:$u5)), def: Pat<(i1 (setule I32:$Rs, anyimm:$u5)), (C2_not (C2_cmpgtui I32:$Rs, imm:$u5))>; -def: Pat<(i1 (setne I32:$Rs, I32:$Rt)), - (C2_not (C2_cmpeq I32:$Rs, I32:$Rt))>; -def: Pat<(i1 (setle I32:$Rs, I32:$Rt)), - (C2_not (C2_cmpgt I32:$Rs, I32:$Rt))>; -def: Pat<(i1 (setule I32:$Rs, I32:$Rt)), - (C2_not (C2_cmpgtu I32:$Rs, I32:$Rt))>; -def: Pat<(i1 (setge I32:$Rs, I32:$Rt)), - (C2_not (C2_cmpgt I32:$Rt, I32:$Rs))>; -def: Pat<(i1 (setuge I32:$Rs, I32:$Rt)), - (C2_not (C2_cmpgtu I32:$Rt, I32:$Rs))>; - -def: Pat<(i1 (setle I64:$Rs, I64:$Rt)), - (C2_not (C2_cmpgtp I64:$Rs, I64:$Rt))>; -def: Pat<(i1 (setne I64:$Rs, I64:$Rt)), - (C2_not (C2_cmpeqp I64:$Rs, I64:$Rt))>; -def: Pat<(i1 (setge I64:$Rs, I64:$Rt)), - (C2_not (C2_cmpgtp I64:$Rt, I64:$Rs))>; -def: Pat<(i1 (setuge I64:$Rs, I64:$Rt)), - (C2_not (C2_cmpgtup I64:$Rt, I64:$Rs))>; -def: Pat<(i1 (setule I64:$Rs, I64:$Rt)), - (C2_not (C2_cmpgtup I64:$Rs, I64:$Rt))>; +class OpmR_RR_pat<PatFrag Output, PatFrag Op, ValueType ResType, + PatFrag RsPred, PatFrag RtPred = RsPred> + : Pat<(ResType (Op RsPred:$Rs, RtPred:$Rt)), + (Output RsPred:$Rs, RtPred:$Rt)>; + +class Outn<InstHexagon MI> + : OutPatFrag<(ops node:$Rs, node:$Rt), + (C2_not (MI $Rs, $Rt))>; + +def: OpmR_RR_pat<Outn<C2_cmpeq>, setne, i1, I32>; +def: OpmR_RR_pat<Outn<C2_cmpgt>, setle, i1, I32>; +def: OpmR_RR_pat<Outn<C2_cmpgtu>, setule, i1, I32>; +def: OpmR_RR_pat<Outn<C2_cmpgt>, RevCmp<setge>, i1, I32>; +def: OpmR_RR_pat<Outn<C2_cmpgtu>, RevCmp<setuge>, i1, I32>; +def: OpmR_RR_pat<Outn<C2_cmpeqp>, setne, i1, I64>; +def: OpmR_RR_pat<Outn<C2_cmpgtp>, setle, i1, I64>; +def: OpmR_RR_pat<Outn<C2_cmpgtup>, setule, i1, I64>; +def: OpmR_RR_pat<Outn<C2_cmpgtp>, RevCmp<setge>, i1, I64>; +def: OpmR_RR_pat<Outn<C2_cmpgtup>, RevCmp<setuge>, i1, I64>; +def: OpmR_RR_pat<Outn<A2_vcmpbeq>, setne, v8i1, V8I8>; +def: OpmR_RR_pat<Outn<A4_vcmpbgt>, setle, v8i1, V8I8>; +def: OpmR_RR_pat<Outn<A2_vcmpbgtu>, setule, v8i1, V8I8>; +def: OpmR_RR_pat<Outn<A4_vcmpbgt>, RevCmp<setge>, v8i1, V8I8>; +def: OpmR_RR_pat<Outn<A2_vcmpbgtu>, RevCmp<setuge>, v8i1, V8I8>; +def: OpmR_RR_pat<Outn<A2_vcmpheq>, setne, v4i1, V4I16>; +def: OpmR_RR_pat<Outn<A2_vcmphgt>, setle, v4i1, V4I16>; +def: OpmR_RR_pat<Outn<A2_vcmphgtu>, setule, v4i1, V4I16>; +def: OpmR_RR_pat<Outn<A2_vcmphgt>, RevCmp<setge>, v4i1, V4I16>; +def: OpmR_RR_pat<Outn<A2_vcmphgtu>, RevCmp<setuge>, v4i1, V4I16>; +def: OpmR_RR_pat<Outn<A2_vcmpweq>, setne, v2i1, V2I32>; +def: OpmR_RR_pat<Outn<A2_vcmpwgt>, setle, v2i1, V2I32>; +def: OpmR_RR_pat<Outn<A2_vcmpwgtu>, setule, v2i1, V2I32>; +def: OpmR_RR_pat<Outn<A2_vcmpwgt>, RevCmp<setge>, v2i1, V2I32>; +def: OpmR_RR_pat<Outn<A2_vcmpwgtu>, RevCmp<setuge>, v2i1, V2I32>; let AddedComplexity = 100 in { def: Pat<(i1 (seteq (and (xor I32:$Rs, I32:$Rt), 255), 0)), @@ -703,34 +716,12 @@ def: Pat<(i1 (setne I1:$Ps, (i1 -1))), (C2_not I1:$Ps)>; def: Pat<(i1 (seteq I1:$Ps, I1:$Pt)), (C2_xor I1:$Ps, (C2_not I1:$Pt))>; def: Pat<(i1 (setne I1:$Ps, I1:$Pt)), (C2_xor I1:$Ps, I1:$Pt)>; -def: Pat<(v4i1 (seteq V4I8:$Rs, V4I8:$Rt)), - (A2_vcmpbeq (ToZext64 $Rs), (ToZext64 $Rt))>; -def: Pat<(v4i1 (setgt V4I8:$Rs, V4I8:$Rt)), - (A4_vcmpbgt (ToZext64 $Rs), (ToZext64 $Rt))>; -def: Pat<(v4i1 (setugt V4I8:$Rs, V4I8:$Rt)), - (A2_vcmpbgtu (ToZext64 $Rs), (ToZext64 $Rt))>; - -def: Pat<(v2i1 (seteq V2I16:$Rs, V2I16:$Rt)), - (A2_vcmpheq (ToZext64 $Rs), (ToZext64 $Rt))>; -def: Pat<(v2i1 (setgt V2I16:$Rs, V2I16:$Rt)), - (A2_vcmphgt (ToZext64 $Rs), (ToZext64 $Rt))>; -def: Pat<(v2i1 (setugt V2I16:$Rs, V2I16:$Rt)), - (A2_vcmphgtu (ToZext64 $Rs), (ToZext64 $Rt))>; - -def: Pat<(v2i1 (setne V2I32:$Rs, V2I32:$Rt)), - (C2_not (v2i1 (A2_vcmpbeq V2I32:$Rs, V2I32:$Rt)))>; - // Floating-point comparisons with checks for ordered/unordered status. class T3<InstHexagon MI1, InstHexagon MI2, InstHexagon MI3> : OutPatFrag<(ops node:$Rs, node:$Rt), (MI1 (MI2 $Rs, $Rt), (MI3 $Rs, $Rt))>; -class OpmR_RR_pat<PatFrag Output, PatFrag Op, ValueType ResType, - PatFrag RsPred, PatFrag RtPred = RsPred> - : Pat<(ResType (Op RsPred:$Rs, RtPred:$Rt)), - (Output RsPred:$Rs, RtPred:$Rt)>; - class Cmpuf<InstHexagon MI>: T3<C2_or, F2_sfcmpuo, MI>; class Cmpud<InstHexagon MI>: T3<C2_or, F2_dfcmpuo, MI>; @@ -753,10 +744,6 @@ let Predicates = [HasV5T] in { def: OpmR_RR_pat<Cmpudn<F2_dfcmpeq>, setune, i1, F64>; } -class Outn<InstHexagon MI> - : OutPatFrag<(ops node:$Rs, node:$Rt), - (C2_not (MI $Rs, $Rt))>; - let Predicates = [HasV5T] in { def: OpmR_RR_pat<Outn<F2_sfcmpeq>, setone, i1, F32>; def: OpmR_RR_pat<Outn<F2_sfcmpeq>, setne, i1, F32>; @@ -1221,18 +1208,20 @@ def: OpR_RR_pat<A2_vsubub, Sub, v8i8, V8I8>; def: OpR_RR_pat<A2_vsubh, Sub, v4i16, V4I16>; def: OpR_RR_pat<A2_vsubw, Sub, v2i32, V2I32>; +def: OpR_RR_pat<A2_and, And, v4i8, V4I8>; +def: OpR_RR_pat<A2_xor, Xor, v4i8, V4I8>; +def: OpR_RR_pat<A2_or, Or, v4i8, V4I8>; def: OpR_RR_pat<A2_and, And, v2i16, V2I16>; def: OpR_RR_pat<A2_xor, Xor, v2i16, V2I16>; def: OpR_RR_pat<A2_or, Or, v2i16, V2I16>; - def: OpR_RR_pat<A2_andp, And, v8i8, V8I8>; -def: OpR_RR_pat<A2_andp, And, v4i16, V4I16>; -def: OpR_RR_pat<A2_andp, And, v2i32, V2I32>; def: OpR_RR_pat<A2_orp, Or, v8i8, V8I8>; -def: OpR_RR_pat<A2_orp, Or, v4i16, V4I16>; -def: OpR_RR_pat<A2_orp, Or, v2i32, V2I32>; def: OpR_RR_pat<A2_xorp, Xor, v8i8, V8I8>; +def: OpR_RR_pat<A2_andp, And, v4i16, V4I16>; +def: OpR_RR_pat<A2_orp, Or, v4i16, V4I16>; def: OpR_RR_pat<A2_xorp, Xor, v4i16, V4I16>; +def: OpR_RR_pat<A2_andp, And, v2i32, V2I32>; +def: OpR_RR_pat<A2_orp, Or, v2i32, V2I32>; def: OpR_RR_pat<A2_xorp, Xor, v2i32, V2I32>; def: OpR_RR_pat<M2_mpyi, Mul, i32, I32>; |

