From ddb739e5ea6ccf6fa4f4e2a23e3da550868efaa1 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 6 Apr 2006 17:23:16 +0000 Subject: [PATCH] Compile the vpkuhum/vpkuwum intrinsics into vpkuhum/vpkuwum instead of into vperm with a perm mask lvx'd from the constant pool. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27448 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelLowering.cpp | 54 ++++++++++++++++++++++++++ lib/Target/PowerPC/PPCISelLowering.h | 8 ++++ lib/Target/PowerPC/PPCInstrAltivec.td | 15 ++++++- 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 8cf70529111..db9e390d0d7 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -267,6 +267,56 @@ static bool isFloatingPointZero(SDOperand Op) { return false; } +/// isConstantOrUndef - Op is either an undef node or a ConstantSDNode. Return +/// true if Op is undef or if it matches the specified value. +static bool isConstantOrUndef(SDOperand Op, unsigned Val) { + return Op.getOpcode() == ISD::UNDEF || + cast(Op)->getValue() == Val; +} + +/// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a +/// VPKUHUM instruction. +bool PPC::isVPKUHUMShuffleMask(SDNode *N) { + return isConstantOrUndef(N->getOperand( 0), 1) && + isConstantOrUndef(N->getOperand( 1), 3) && + isConstantOrUndef(N->getOperand( 2), 5) && + isConstantOrUndef(N->getOperand( 3), 7) && + isConstantOrUndef(N->getOperand( 4), 9) && + isConstantOrUndef(N->getOperand( 5), 11) && + isConstantOrUndef(N->getOperand( 6), 13) && + isConstantOrUndef(N->getOperand( 7), 15) && + isConstantOrUndef(N->getOperand( 8), 17) && + isConstantOrUndef(N->getOperand( 9), 19) && + isConstantOrUndef(N->getOperand(10), 21) && + isConstantOrUndef(N->getOperand(11), 23) && + isConstantOrUndef(N->getOperand(12), 25) && + isConstantOrUndef(N->getOperand(13), 27) && + isConstantOrUndef(N->getOperand(14), 29) && + isConstantOrUndef(N->getOperand(15), 31); +} + +/// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a +/// VPKUWUM instruction. +bool PPC::isVPKUWUMShuffleMask(SDNode *N) { + return isConstantOrUndef(N->getOperand( 0), 2) && + isConstantOrUndef(N->getOperand( 1), 3) && + isConstantOrUndef(N->getOperand( 2), 6) && + isConstantOrUndef(N->getOperand( 3), 7) && + isConstantOrUndef(N->getOperand( 4), 10) && + isConstantOrUndef(N->getOperand( 5), 11) && + isConstantOrUndef(N->getOperand( 6), 14) && + isConstantOrUndef(N->getOperand( 7), 15) && + isConstantOrUndef(N->getOperand( 8), 18) && + isConstantOrUndef(N->getOperand( 9), 19) && + isConstantOrUndef(N->getOperand(10), 22) && + isConstantOrUndef(N->getOperand(11), 23) && + isConstantOrUndef(N->getOperand(12), 26) && + isConstantOrUndef(N->getOperand(13), 27) && + isConstantOrUndef(N->getOperand(14), 30) && + isConstantOrUndef(N->getOperand(15), 31); +} + + /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a splat of a single element that is suitable for input to @@ -759,6 +809,10 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { PPC::isSplatShuffleMask(PermMask.Val, 4))) return Op; + if (PPC::isVPKUWUMShuffleMask(PermMask.Val) || + PPC::isVPKUHUMShuffleMask(PermMask.Val)) + return Op; + // TODO: Handle more cases, and also handle cases that are cheaper to do as // multiple such instructions than as a constant pool load/vperm pair. diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index 9e6efb9a7a2..4b59c2f5eb0 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -102,6 +102,14 @@ namespace llvm { /// Define some predicates that are used for node matching. namespace PPC { + /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a + /// VPKUHUM instruction. + bool isVPKUHUMShuffleMask(SDNode *N); + + /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a + /// VPKUWUM instruction. + bool isVPKUWUMShuffleMask(SDNode *N); + /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a splat of a single element that is suitable for input to /// VSPLTB/VSPLTH/VSPLTW. diff --git a/lib/Target/PowerPC/PPCInstrAltivec.td b/lib/Target/PowerPC/PPCInstrAltivec.td index 6cac3ec40d8..75cf82c301e 100644 --- a/lib/Target/PowerPC/PPCInstrAltivec.td +++ b/lib/Target/PowerPC/PPCInstrAltivec.td @@ -15,6 +15,15 @@ // Altivec transformation functions and pattern fragments. // +/// VPKUHUM_shuffle_mask/VPKUWUM_shuffle_mask - Return true if this is a valid +/// shuffle mask for the VPKUHUM or VPKUWUM instructions. +def VPKUHUM_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVPKUHUMShuffleMask(N); +}]>; +def VPKUWUM_shuffle_mask : PatLeaf<(build_vector), [{ + return PPC::isVPKUWUMShuffleMask(N); +}]>; + // VSPLT*_get_imm xform function: convert vector_shuffle mask to VSPLT* imm. def VSPLTB_get_imm : SDNodeXForm; def VPKSWUS : VX1_Int<334, "vpkswus", int_ppc_altivec_vpkswus>; def VPKUHUM : VXForm_1<14, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vpkuhum $vD, $vA, $vB", VecFP, - [/*TODO*/]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VPKUHUM_shuffle_mask))]>; def VPKUHUS : VX1_Int<142, "vpkuhus", int_ppc_altivec_vpkuhus>; def VPKUWUM : VXForm_1<78, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB), "vpkuwum $vD, $vA, $vB", VecFP, - [/*TODO*/]>; + [(set VRRC:$vD, (vector_shuffle (v16i8 VRRC:$vA), + VRRC:$vB, VPKUWUM_shuffle_mask))]>; def VPKUWUS : VX1_Int<206, "vpkuwus", int_ppc_altivec_vpkuwus>; // Vector Unpack.