Provide correct encodings for NEON vcvt, which has its own special immediate encoding
authorOwen Anderson <resistor@mac.com>
Wed, 27 Oct 2010 22:49:00 +0000 (22:49 +0000)
committerOwen Anderson <resistor@mac.com>
Wed, 27 Oct 2010 22:49:00 +0000 (22:49 +0000)
for specifying fractional bits for fixed point conversions.

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

lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrNEON.td
lib/Target/ARM/ARMMCCodeEmitter.cpp
test/MC/ARM/neon-convert-encoding.ll [new file with mode: 0644]
utils/TableGen/EDEmitter.cpp

index c103fab9a7336ad3723422f8ddc2220220191a09..1fb99fe5b0dd7c67ebf862c9785d1e573ee3d4db 100644 (file)
@@ -194,6 +194,8 @@ namespace {
         Binary |= (Reg << 13);
         return Binary;
       }
+    unsigned getNEONVcvtImm32(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
index ac7c165d4cfb8a9246817e30caeec87f2edbb805..7e8f4fff0fdd6e8301a52e1991cfdfc2225fe6c4 100644 (file)
@@ -299,6 +299,10 @@ def pclabel : Operand<i32> {
   let PrintMethod = "printPCLabel";
 }
 
+def neon_vcvt_imm32 : Operand<i32> {
+  string EncoderMethod = "getNEONVcvtImm32";
+}
+
 // rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24.
 def rot_imm : Operand<i32>, PatLeaf<(i32 imm), [{
   int32_t v = (int32_t)N->getZExtValue();
index a746049a30cc07b5798a50ecd7ea00e395fcb8d8..5208c2502ca367faf98ef7ef6c73c570e00f941d 100644 (file)
@@ -1764,16 +1764,16 @@ class N2VCvtD<bit op24, bit op23, bits<4> op11_8, bit op7, bit op4,
               string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy,
               Intrinsic IntOp>
   : N2VImm<op24, op23, op11_8, op7, 0, op4,
-           (outs DPR:$dst), (ins DPR:$src, i32imm:$SIMM), NVCVTFrm,
-           IIC_VUNAD, OpcodeStr, Dt, "$dst, $src, $SIMM", "",
-           [(set DPR:$dst, (ResTy (IntOp (OpTy DPR:$src), (i32 imm:$SIMM))))]>;
+           (outs DPR:$Vd), (ins DPR:$Vm, neon_vcvt_imm32:$SIMM), NVCVTFrm,
+           IIC_VUNAD, OpcodeStr, Dt, "$Vd, $Vm, $SIMM", "",
+           [(set DPR:$Vd, (ResTy (IntOp (OpTy DPR:$Vm), (i32 imm:$SIMM))))]>;
 class N2VCvtQ<bit op24, bit op23, bits<4> op11_8, bit op7, bit op4,
               string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy,
               Intrinsic IntOp>
   : N2VImm<op24, op23, op11_8, op7, 1, op4,
-           (outs QPR:$dst), (ins QPR:$src, i32imm:$SIMM), NVCVTFrm,
-           IIC_VUNAQ, OpcodeStr, Dt, "$dst, $src, $SIMM", "",
-           [(set QPR:$dst, (ResTy (IntOp (OpTy QPR:$src), (i32 imm:$SIMM))))]>;
+           (outs QPR:$Vd), (ins QPR:$Vm, neon_vcvt_imm32:$SIMM), NVCVTFrm,
+           IIC_VUNAQ, OpcodeStr, Dt, "$Vd, $Vm, $SIMM", "",
+           [(set QPR:$Vd, (ResTy (IntOp (OpTy QPR:$Vm), (i32 imm:$SIMM))))]>;
 
 //===----------------------------------------------------------------------===//
 // Multiclasses
index 13a80bdffde2cea611a8300f0f2eee1ce6c3c156..1259672b9b9b5f4819eb7c7abc84f363cad32b55 100644 (file)
@@ -91,6 +91,10 @@ public:
   unsigned getImmMinusOneOpValue(const MCInst &MI, unsigned Op) const {
     return MI.getOperand(Op).getImm() - 1;
   }
+  
+  unsigned getNEONVcvtImm32(const MCInst &MI, unsigned Op) const {
+    return 64 - MI.getOperand(Op).getImm();
+  }
 
   unsigned getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op) const;
 
diff --git a/test/MC/ARM/neon-convert-encoding.ll b/test/MC/ARM/neon-convert-encoding.ll
new file mode 100644 (file)
index 0000000..69e5409
--- /dev/null
@@ -0,0 +1,122 @@
+; RUN: llc -show-mc-encoding -march=arm -mcpu=cortex-a8 -mattr=+neon < %s | FileCheck %s
+
+define <2 x i32> @vcvt_f32tos32(<2 x float>* %A) nounwind {
+       %tmp1 = load <2 x float>* %A
+; CHECK: vcvt.s32.f32  d16, d16        @ encoding: [0x20,0x07,0xfb,0xf3]
+       %tmp2 = fptosi <2 x float> %tmp1 to <2 x i32>
+       ret <2 x i32> %tmp2
+}
+
+define <2 x i32> @vcvt_f32tou32(<2 x float>* %A) nounwind {
+       %tmp1 = load <2 x float>* %A
+; CHECK: vcvt.u32.f32  d16, d16        @ encoding: [0xa0,0x07,0xfb,0xf3]
+       %tmp2 = fptoui <2 x float> %tmp1 to <2 x i32>
+       ret <2 x i32> %tmp2
+}
+
+define <2 x float> @vcvt_s32tof32(<2 x i32>* %A) nounwind {
+       %tmp1 = load <2 x i32>* %A
+; CHECK: vcvt.f32.s32  d16, d16        @ encoding: [0x20,0x06,0xfb,0xf3]
+       %tmp2 = sitofp <2 x i32> %tmp1 to <2 x float>
+       ret <2 x float> %tmp2
+}
+
+define <2 x float> @vcvt_u32tof32(<2 x i32>* %A) nounwind {
+       %tmp1 = load <2 x i32>* %A
+; CHECK: vcvt.f32.u32  d16, d16        @ encoding: [0xa0,0x06,0xfb,0xf3]
+       %tmp2 = uitofp <2 x i32> %tmp1 to <2 x float>
+       ret <2 x float> %tmp2
+}
+
+define <4 x i32> @vcvtQ_f32tos32(<4 x float>* %A) nounwind {
+       %tmp1 = load <4 x float>* %A
+; CHECK: vcvt.s32.f32  q8, q8          @ encoding: [0x60,0x07,0xfb,0xf3]
+       %tmp2 = fptosi <4 x float> %tmp1 to <4 x i32>
+       ret <4 x i32> %tmp2
+}
+
+define <4 x i32> @vcvtQ_f32tou32(<4 x float>* %A) nounwind {
+       %tmp1 = load <4 x float>* %A
+; CHECK: vcvt.u32.f32  q8, q8          @ encoding: [0xe0,0x07,0xfb,0xf3]
+       %tmp2 = fptoui <4 x float> %tmp1 to <4 x i32>
+       ret <4 x i32> %tmp2
+}
+
+define <4 x float> @vcvtQ_s32tof32(<4 x i32>* %A) nounwind {
+       %tmp1 = load <4 x i32>* %A
+; CHECK: vcvt.f32.s32  q8, q8          @ encoding: [0x60,0x06,0xfb,0xf3]
+       %tmp2 = sitofp <4 x i32> %tmp1 to <4 x float>
+       ret <4 x float> %tmp2
+}
+
+define <4 x float> @vcvtQ_u32tof32(<4 x i32>* %A) nounwind {
+       %tmp1 = load <4 x i32>* %A
+; CHECK: vcvt.f32.u32  q8, q8          @ encoding: [0xe0,0x06,0xfb,0xf3]
+       %tmp2 = uitofp <4 x i32> %tmp1 to <4 x float>
+       ret <4 x float> %tmp2
+}
+
+define <2 x i32> @vcvt_n_f32tos32(<2 x float>* %A) nounwind {
+       %tmp1 = load <2 x float>* %A
+; CHECK: vcvt.s32.f32  d16, d16, #1    @ encoding: [0x30,0x0f,0xff,0xf2
+       %tmp2 = call <2 x i32> @llvm.arm.neon.vcvtfp2fxs.v2i32.v2f32(<2 x float> %tmp1, i32 1)
+       ret <2 x i32> %tmp2
+}
+
+define <2 x i32> @vcvt_n_f32tou32(<2 x float>* %A) nounwind {
+       %tmp1 = load <2 x float>* %A
+; CHECK: vcvt.u32.f32  d16, d16, #1    @ encoding: [0x30,0x0f,0xff,0xf3]
+       %tmp2 = call <2 x i32> @llvm.arm.neon.vcvtfp2fxu.v2i32.v2f32(<2 x float> %tmp1, i32 1)
+       ret <2 x i32> %tmp2
+}
+
+define <2 x float> @vcvt_n_s32tof32(<2 x i32>* %A) nounwind {
+       %tmp1 = load <2 x i32>* %A
+; CHECK: vcvt.f32.s32  d16, d16, #1    @ encoding: [0x30,0x0e,0xff,0xf2]
+       %tmp2 = call <2 x float> @llvm.arm.neon.vcvtfxs2fp.v2f32.v2i32(<2 x i32> %tmp1, i32 1)
+       ret <2 x float> %tmp2
+}
+
+define <2 x float> @vcvt_n_u32tof32(<2 x i32>* %A) nounwind {
+       %tmp1 = load <2 x i32>* %A
+; CHECK: vcvt.f32.u32  d16, d16, #1    @ encoding: [0x30,0x0e,0xff,0xf3]
+       %tmp2 = call <2 x float> @llvm.arm.neon.vcvtfxu2fp.v2f32.v2i32(<2 x i32> %tmp1, i32 1)
+       ret <2 x float> %tmp2
+}
+
+declare <2 x i32> @llvm.arm.neon.vcvtfp2fxs.v2i32.v2f32(<2 x float>, i32) nounwind readnone
+declare <2 x i32> @llvm.arm.neon.vcvtfp2fxu.v2i32.v2f32(<2 x float>, i32) nounwind readnone
+declare <2 x float> @llvm.arm.neon.vcvtfxs2fp.v2f32.v2i32(<2 x i32>, i32) nounwind readnone
+declare <2 x float> @llvm.arm.neon.vcvtfxu2fp.v2f32.v2i32(<2 x i32>, i32) nounwind readnone
+
+define <4 x i32> @vcvtQ_n_f32tos32(<4 x float>* %A) nounwind {
+       %tmp1 = load <4 x float>* %A
+; CHECK: vcvt.s32.f32  q8, q8, #1      @ encoding: [0x70,0x0f,0xff,0xf2]
+       %tmp2 = call <4 x i32> @llvm.arm.neon.vcvtfp2fxs.v4i32.v4f32(<4 x float> %tmp1, i32 1)
+       ret <4 x i32> %tmp2
+}
+
+define <4 x i32> @vcvtQ_n_f32tou32(<4 x float>* %A) nounwind {
+       %tmp1 = load <4 x float>* %A
+       %tmp2 = call <4 x i32> @llvm.arm.neon.vcvtfp2fxu.v4i32.v4f32(<4 x float> %tmp1, i32 1)
+       ret <4 x i32> %tmp2
+}
+
+define <4 x float> @vcvtQ_n_s32tof32(<4 x i32>* %A) nounwind {
+       %tmp1 = load <4 x i32>* %A
+; CHECK: vcvt.u32.f32  q8, q8, #1      @ encoding: [0x70,0x0f,0xff,0xf3]
+       %tmp2 = call <4 x float> @llvm.arm.neon.vcvtfxs2fp.v4f32.v4i32(<4 x i32> %tmp1, i32 1)
+       ret <4 x float> %tmp2
+}
+
+define <4 x float> @vcvtQ_n_u32tof32(<4 x i32>* %A) nounwind {
+       %tmp1 = load <4 x i32>* %A
+; CHECK: vcvt.f32.u32  q8, q8, #1      @ encoding: [0x70,0x0e,0xff,0xf3]
+       %tmp2 = call <4 x float> @llvm.arm.neon.vcvtfxu2fp.v4f32.v4i32(<4 x i32> %tmp1, i32 1)
+       ret <4 x float> %tmp2
+}
+
+declare <4 x i32> @llvm.arm.neon.vcvtfp2fxs.v4i32.v4f32(<4 x float>, i32) nounwind readnone
+declare <4 x i32> @llvm.arm.neon.vcvtfp2fxu.v4i32.v4f32(<4 x float>, i32) nounwind readnone
+declare <4 x float> @llvm.arm.neon.vcvtfxs2fp.v4f32.v4i32(<4 x i32>, i32) nounwind readnone
+declare <4 x float> @llvm.arm.neon.vcvtfxu2fp.v4f32.v4i32(<4 x i32>, i32) nounwind readnone
index a18443685a42190801f9d501c80e182a7fc4dfaa..b216a74b2e4706b29d0170ce9ba08591ad6c522c 100644 (file)
@@ -582,6 +582,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
   IMM("t_imm_s4");
   IMM("pclabel");
   IMM("shift_imm");
+  IMM("neon_vcvt_imm32");
 
   MISC("brtarget", "kOperandTypeARMBranchTarget");                // ?
   MISC("so_reg", "kOperandTypeARMSoReg");                         // R, R, I