diff --git a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp index 9bbf6a030687..51d771ec9f2d 100644 --- a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp @@ -312,6 +312,13 @@ namespace { unsigned getRegisterListOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getNarrowShiftRight16Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getNarrowShiftRight32Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getNarrowShiftRight64Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + /// getMovi32Value - Return binary encoding of operand for movw/movt. If the /// machine operand requires relocation, record the relocation and return /// zero. diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 359ac45cee1d..cf8c4724c59d 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -221,6 +221,22 @@ def neg_zero : Operand { let PrintMethod = "printNegZeroOperand"; } +// Narrow Shift Right Immediate - A narrow shift right immediate is encoded +// differently from other shift immediates. The imm6 field is encoded like so: +// +// 16-bit: imm6<5:3> = '001', 8 - is encded in imm6<2:0> +// 32-bit: imm6<5:4> = '01',16 - is encded in imm6<3:0> +// 64-bit: imm6<5> = '1', 32 - is encded in imm6<4:0> +def nsr16_imm : Operand { + let EncoderMethod = "getNarrowShiftRight16Imm"; +} +def nsr32_imm : Operand { + let EncoderMethod = "getNarrowShiftRight32Imm"; +} +def nsr64_imm : Operand { + let EncoderMethod = "getNarrowShiftRight64Imm"; +} + //===----------------------------------------------------------------------===// // ARM Instruction templates. // diff --git a/llvm/lib/Target/ARM/ARMInstrNEON.td b/llvm/lib/Target/ARM/ARMInstrNEON.td index dc3d63e26ef5..5be6df5025a8 100644 --- a/llvm/lib/Target/ARM/ARMInstrNEON.td +++ b/llvm/lib/Target/ARM/ARMInstrNEON.td @@ -2315,9 +2315,9 @@ class N2VLSh op11_8, bit op7, bit op6, bit op4, // Narrow shift by immediate. class N2VNSh op11_8, bit op7, bit op6, bit op4, InstrItinClass itin, string OpcodeStr, string Dt, - ValueType ResTy, ValueType OpTy, SDNode OpNode> + ValueType ResTy, ValueType OpTy, Operand ImmTy, SDNode OpNode> : N2VImm; @@ -3153,15 +3153,18 @@ multiclass N2VNSh_HSD op11_8, bit op7, bit op6, bit op4, InstrItinClass itin, string OpcodeStr, string Dt, SDNode OpNode> { def v8i8 : N2VNSh { + OpcodeStr, !strconcat(Dt, "16"), + v8i8, v8i16, nsr16_imm, OpNode> { let Inst{21-19} = 0b001; // imm6 = 001xxx } def v4i16 : N2VNSh { + OpcodeStr, !strconcat(Dt, "32"), + v4i16, v4i32, nsr32_imm, OpNode> { let Inst{21-20} = 0b01; // imm6 = 01xxxx } def v2i32 : N2VNSh { + OpcodeStr, !strconcat(Dt, "64"), + v2i32, v2i64, nsr64_imm, OpNode> { let Inst{21} = 0b1; // imm6 = 1xxxxx } } diff --git a/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp index 6d7b48587d19..48884a1d7182 100644 --- a/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -278,6 +278,13 @@ public: unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups) const; + unsigned getNarrowShiftRight16Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; + unsigned getNarrowShiftRight32Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; + unsigned getNarrowShiftRight64Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; + unsigned NEONThumb2DataIPostEncoder(const MCInst &MI, unsigned EncodedValue) const; unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI, @@ -1201,6 +1208,24 @@ getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op, return MO.getReg(); } +unsigned ARMMCCodeEmitter:: +getNarrowShiftRight16Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const { + return 8 - MI.getOperand(Op).getImm(); +} + +unsigned ARMMCCodeEmitter:: +getNarrowShiftRight32Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const { + return 16 - MI.getOperand(Op).getImm(); +} + +unsigned ARMMCCodeEmitter:: +getNarrowShiftRight64Imm(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const { + return 32 - MI.getOperand(Op).getImm(); +} + void ARMMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups) const { diff --git a/llvm/test/CodeGen/ARM/neon_shift.ll b/llvm/test/CodeGen/ARM/neon_shift.ll new file mode 100644 index 000000000000..340f220fb362 --- /dev/null +++ b/llvm/test/CodeGen/ARM/neon_shift.ll @@ -0,0 +1,11 @@ +; RUN: llc < %s -march=arm -mattr=+neon | FileCheck %s + +; +define <4 x i16> @t1(<4 x i32> %a) nounwind { +entry: +; CHECK: vqrshrn.s32 d{{[0-9]+}}, q{{[0-9]*}}, #13 + %x = tail call <4 x i16> @llvm.arm.neon.vqrshiftns.v4i16(<4 x i32> %a, <4 x i32> ) + ret <4 x i16> %x +} + +declare <4 x i16> @llvm.arm.neon.vqrshiftns.v4i16(<4 x i32>, <4 x i32>) nounwind readnone diff --git a/llvm/test/MC/ARM/neon-shift-encoding.s b/llvm/test/MC/ARM/neon-shift-encoding.s index 4b4fa0876ccd..1985a6a647dc 100644 --- a/llvm/test/MC/ARM/neon-shift-encoding.s +++ b/llvm/test/MC/ARM/neon-shift-encoding.s @@ -158,3 +158,5 @@ vrshrn.i32 d16, q8, #16 @ CHECK: vrshrn.i64 d16, q8, #32 @ encoding: [0x70,0x08,0xe0,0xf2] vrshrn.i64 d16, q8, #32 +@ CHECK: vqrshrn.s32 d16, q8, #13 @ encoding: [0x70,0x09,0xd3,0xf2] + vqrshrn.s32 d16, q8, #13 diff --git a/llvm/utils/TableGen/EDEmitter.cpp b/llvm/utils/TableGen/EDEmitter.cpp index 020a4a312d7b..b3deb84f6673 100644 --- a/llvm/utils/TableGen/EDEmitter.cpp +++ b/llvm/utils/TableGen/EDEmitter.cpp @@ -598,6 +598,9 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("t2adrlabel"); IMM("shift_imm"); IMM("neon_vcvt_imm32"); + IMM("nsr16_imm"); + IMM("nsr32_imm"); + IMM("nsr64_imm"); MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ?