From 827b2106fe39c4195f5f5393b6bab70cc297657d Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Tue, 15 Jun 2010 19:05:35 +0000 Subject: [PATCH] Add basic support for NEON modified immediates besides VMOV. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@106030 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 19 +++++++++++++++---- lib/Target/ARM/ARMISelLowering.h | 3 ++- lib/Target/ARM/ARMInstrNEON.td | 16 ++++++++-------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 5fb3856625c..725d42c06b8 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -2766,10 +2766,18 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) { /// bits7-0=Immediate. static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, - bool DoEncode) { + bool isVMOV, bool DoEncode) { unsigned Op, Cmode, Imm; EVT VT; + // SplatBitSize is set to the smallest size that splats the vector, so a + // zero vector will always have SplatBitSize == 8. However, NEON modified + // immediate instructions others than VMOV do not support the 8-bit encoding + // of a zero vector, and the default encoding of zero is supposed to be the + // 32-bit version. + if (SplatBits == 0) + SplatBitSize = 32; + Op = 0; switch (SplatBitSize) { case 8: @@ -2855,6 +2863,8 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, case 64: { // NEON has a 64-bit VMOV splat where each byte is either 0 or 0xff. + if (!isVMOV) + return SDValue(); uint64_t BitMask = 0xff; uint64_t Val = 0; unsigned ImmMask = 1; @@ -2892,7 +2902,8 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, /// with a "modified immediate" operand (e.g., VMOV) of the specified element /// size, return the encoded value for that immediate. The ByteSize field /// indicates the number of bytes of each element [1248]. -SDValue ARM::getNEONModImm(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) { +SDValue ARM::getNEONModImm(SDNode *N, unsigned ByteSize, bool isVMOV, + SelectionDAG &DAG) { BuildVectorSDNode *BVN = dyn_cast(N); APInt SplatBits, SplatUndef; unsigned SplatBitSize; @@ -2905,7 +2916,7 @@ SDValue ARM::getNEONModImm(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) { return SDValue(); return isNEONModifiedImm(SplatBits.getZExtValue(), SplatUndef.getZExtValue(), - SplatBitSize, DAG, true); + SplatBitSize, DAG, isVMOV, true); } static bool isVEXTMask(const SmallVectorImpl &M, EVT VT, @@ -3148,7 +3159,7 @@ static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) { // Check if an immediate VMOV works. SDValue Val = isNEONModifiedImm(SplatBits.getZExtValue(), SplatUndef.getZExtValue(), - SplatBitSize, DAG, false); + SplatBitSize, DAG, true, false); if (Val.getNode()) return BuildSplat(Val, VT, DAG, dl); } diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index d9f47d9a815..787272c1eb5 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -154,7 +154,8 @@ namespace llvm { /// instruction with a "modified immediate" operand (e.g., VMOV) of the /// specified element size, return the encoded value for that immediate. /// The ByteSize field indicates the number of bytes of each element [1248]. - SDValue getNEONModImm(SDNode *N, unsigned ByteSize, SelectionDAG &DAG); + SDValue getNEONModImm(SDNode *N, unsigned ByteSize, bool isVMOV, + SelectionDAG &DAG); /// getVFPf32Imm / getVFPf64Imm - If the given fp immediate can be /// materialized with a VMOV.f32 / VMOV.f64 (i.e. fconsts / fconstd) diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 6ae755eb685..cc2fddd154b 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -2820,34 +2820,34 @@ def VMOVQQQQ : PseudoInst<(outs QQQQPR:$dst), (ins QQQQPR:$src), // VMOV_get_imm8 xform function: convert build_vector to VMOV.i8 imm. def VMOV_get_imm8 : SDNodeXForm; def vmovImm8 : PatLeaf<(build_vector), [{ - return ARM::getNEONModImm(N, 1, *CurDAG).getNode() != 0; + return ARM::getNEONModImm(N, 1, true, *CurDAG).getNode() != 0; }], VMOV_get_imm8>; // VMOV_get_imm16 xform function: convert build_vector to VMOV.i16 imm. def VMOV_get_imm16 : SDNodeXForm; def vmovImm16 : PatLeaf<(build_vector), [{ - return ARM::getNEONModImm(N, 2, *CurDAG).getNode() != 0; + return ARM::getNEONModImm(N, 2, true, *CurDAG).getNode() != 0; }], VMOV_get_imm16>; // VMOV_get_imm32 xform function: convert build_vector to VMOV.i32 imm. def VMOV_get_imm32 : SDNodeXForm; def vmovImm32 : PatLeaf<(build_vector), [{ - return ARM::getNEONModImm(N, 4, *CurDAG).getNode() != 0; + return ARM::getNEONModImm(N, 4, true, *CurDAG).getNode() != 0; }], VMOV_get_imm32>; // VMOV_get_imm64 xform function: convert build_vector to VMOV.i64 imm. def VMOV_get_imm64 : SDNodeXForm; def vmovImm64 : PatLeaf<(build_vector), [{ - return ARM::getNEONModImm(N, 8, *CurDAG).getNode() != 0; + return ARM::getNEONModImm(N, 8, true, *CurDAG).getNode() != 0; }], VMOV_get_imm64>; // Note: Some of the cmode bits in the following VMOV instructions need to