diff options
author | Bob Wilson <bob.wilson@apple.com> | 2010-06-15 19:05:35 +0000 |
---|---|---|
committer | Bob Wilson <bob.wilson@apple.com> | 2010-06-15 19:05:35 +0000 |
commit | 827b2106fe39c4195f5f5393b6bab70cc297657d (patch) | |
tree | eb0a2a262d57159658346a714c1688f3e1c007d3 | |
parent | 2ebb4f81f7979838bc5eb00ef997d30b00442a02 (diff) | |
download | external_llvm-827b2106fe39c4195f5f5393b6bab70cc297657d.zip external_llvm-827b2106fe39c4195f5f5393b6bab70cc297657d.tar.gz external_llvm-827b2106fe39c4195f5f5393b6bab70cc297657d.tar.bz2 |
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
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 19 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.h | 3 | ||||
-rw-r--r-- | 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 5fb3856..725d42c 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<BuildVectorSDNode>(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<int> &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 d9f47d9..787272c 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 6ae755e..cc2fddd 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<build_vector, [{ - return ARM::getNEONModImm(N, 1, *CurDAG); + return ARM::getNEONModImm(N, 1, true, *CurDAG); }]>; 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<build_vector, [{ - return ARM::getNEONModImm(N, 2, *CurDAG); + return ARM::getNEONModImm(N, 2, true, *CurDAG); }]>; 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<build_vector, [{ - return ARM::getNEONModImm(N, 4, *CurDAG); + return ARM::getNEONModImm(N, 4, true, *CurDAG); }]>; 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<build_vector, [{ - return ARM::getNEONModImm(N, 8, *CurDAG); + return ARM::getNEONModImm(N, 8, true, *CurDAG); }]>; 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 |