Narrow right shifts need to encode their immediates differently from a normal
authorBill Wendling <isanbard@gmail.com>
Tue, 1 Mar 2011 01:00:59 +0000 (01:00 +0000)
committerBill Wendling <isanbard@gmail.com>
Tue, 1 Mar 2011 01:00:59 +0000 (01:00 +0000)
shift.

   16-bit: imm6<5:3> = '001', 8 - <imm> is encded in imm6<2:0>
   32-bit: imm6<5:4> = '01',16 - <imm> is encded in imm6<3:0>
   64-bit: imm6<5> = '1', 32 - <imm> is encded in imm6<4:0>

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126723 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMInstrFormats.td
lib/Target/ARM/ARMInstrNEON.td
lib/Target/ARM/ARMMCCodeEmitter.cpp
test/CodeGen/ARM/neon_shift.ll [new file with mode: 0644]
test/MC/ARM/neon-shift-encoding.s
utils/TableGen/EDEmitter.cpp

index 9bbf6a030687bff11c425fad6666d10945d5f80d..51d771ec9f2dec81f5ff1c04f5cff1248ae3f064 100644 (file)
@@ -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.
index 359ac45cee1dc942920b048150cdcecf8447bcce..cf8c4724c59d6cd637ff954de5c9a69876d0a50f 100644 (file)
@@ -221,6 +221,22 @@ def neg_zero : Operand<i32> {
   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 - <imm> is encded in imm6<2:0>
+//   32-bit: imm6<5:4> = '01',16 - <imm> is encded in imm6<3:0>
+//   64-bit: imm6<5> = '1', 32 - <imm> is encded in imm6<4:0>
+def nsr16_imm : Operand<i32> {
+  let EncoderMethod = "getNarrowShiftRight16Imm";
+}
+def nsr32_imm : Operand<i32> {
+  let EncoderMethod = "getNarrowShiftRight32Imm";
+}
+def nsr64_imm : Operand<i32> {
+  let EncoderMethod = "getNarrowShiftRight64Imm";
+}
+
 //===----------------------------------------------------------------------===//
 // ARM Instruction templates.
 //
index dc3d63e26ef5e2865e32c5aa4e2b0bd18fe3aaf2..5be6df5025a8899a0ec0e6da3015c1dbcd89f58c 100644 (file)
@@ -2315,9 +2315,9 @@ class N2VLSh<bit op24, bit op23, bits<4> op11_8, bit op7, bit op6, bit op4,
 // Narrow shift by immediate.
 class N2VNSh<bit op24, bit op23, bits<4> 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<op24, op23, op11_8, op7, op6, op4,
-           (outs DPR:$Vd), (ins QPR:$Vm, i32imm:$SIMM), N2RegVShRFrm, itin,
+           (outs DPR:$Vd), (ins QPR:$Vm, ImmTy:$SIMM), N2RegVShRFrm, itin,
            OpcodeStr, Dt, "$Vd, $Vm, $SIMM", "",
            [(set DPR:$Vd, (ResTy (OpNode (OpTy QPR:$Vm),
                                           (i32 imm:$SIMM))))]>;
@@ -3153,15 +3153,18 @@ multiclass N2VNSh_HSD<bit op24, bit op23, bits<4> op11_8, bit op7, bit op6,
                       bit op4, InstrItinClass itin, string OpcodeStr, string Dt,
                       SDNode OpNode> {
   def v8i8 : N2VNSh<op24, op23, op11_8, op7, op6, op4, itin,
-                    OpcodeStr, !strconcat(Dt, "16"), v8i8, v8i16, OpNode> {
+                    OpcodeStr, !strconcat(Dt, "16"),
+                    v8i8, v8i16, nsr16_imm, OpNode> {
     let Inst{21-19} = 0b001; // imm6 = 001xxx
   }
   def v4i16 : N2VNSh<op24, op23, op11_8, op7, op6, op4, itin,
-                     OpcodeStr, !strconcat(Dt, "32"), v4i16, v4i32, OpNode> {
+                     OpcodeStr, !strconcat(Dt, "32"),
+                     v4i16, v4i32, nsr32_imm, OpNode> {
     let Inst{21-20} = 0b01;  // imm6 = 01xxxx
   }
   def v2i32 : N2VNSh<op24, op23, op11_8, op7, op6, op4, itin,
-                     OpcodeStr, !strconcat(Dt, "64"), v2i32, v2i64, OpNode> {
+                     OpcodeStr, !strconcat(Dt, "64"),
+                     v2i32, v2i64, nsr64_imm, OpNode> {
     let Inst{21} = 0b1;      // imm6 = 1xxxxx
   }
 }
index 6d7b48587d19570ef839d8d4eb7a1d6851815dd5..48884a1d7182dc77fe26619997f1a3bf1e813098 100644 (file)
@@ -278,6 +278,13 @@ public:
   unsigned getAddrMode6OffsetOpValue(const MCInst &MI, unsigned Op,
                                      SmallVectorImpl<MCFixup> &Fixups) const;
 
+  unsigned getNarrowShiftRight16Imm(const MCInst &MI, unsigned Op,
+                                    SmallVectorImpl<MCFixup> &Fixups) const;
+  unsigned getNarrowShiftRight32Imm(const MCInst &MI, unsigned Op,
+                                    SmallVectorImpl<MCFixup> &Fixups) const;
+  unsigned getNarrowShiftRight64Imm(const MCInst &MI, unsigned Op,
+                                    SmallVectorImpl<MCFixup> &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<MCFixup> &Fixups) const {
+  return 8 - MI.getOperand(Op).getImm();
+}
+
+unsigned ARMMCCodeEmitter::
+getNarrowShiftRight32Imm(const MCInst &MI, unsigned Op,
+                         SmallVectorImpl<MCFixup> &Fixups) const {
+  return 16 - MI.getOperand(Op).getImm();
+}
+
+unsigned ARMMCCodeEmitter::
+getNarrowShiftRight64Imm(const MCInst &MI, unsigned Op,
+                         SmallVectorImpl<MCFixup> &Fixups) const {
+  return 32 - MI.getOperand(Op).getImm();
+}
+
 void ARMMCCodeEmitter::
 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
                   SmallVectorImpl<MCFixup> &Fixups) const {
diff --git a/test/CodeGen/ARM/neon_shift.ll b/test/CodeGen/ARM/neon_shift.ll
new file mode 100644 (file)
index 0000000..340f220
--- /dev/null
@@ -0,0 +1,11 @@
+; RUN: llc < %s -march=arm -mattr=+neon | FileCheck %s
+
+; <rdar://problem/9055897>
+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> <i32 -13, i32 -13, i32 -13, i32 -13>)
+  ret <4 x i16> %x
+}
+
+declare <4 x i16> @llvm.arm.neon.vqrshiftns.v4i16(<4 x i32>, <4 x i32>) nounwind readnone
index 4b4fa0876ccdac888f2f662fad396bca302409e8..1985a6a647dcba25be03be8a2f92932096464d1b 100644 (file)
        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
index 020a4a312d7b3fef1412ebb20a90cf995980461f..b3deb84f66738c8cecdf8d6aa1e722b7663af99c 100644 (file)
@@ -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");           // ?