[llvm] r207080 - Fix for PR18921, "vmov" part.

Stepan Dyatkovskiy stpworld at narod.ru
Wed Apr 23 23:03:01 PDT 2014


Author: dyatkovskiy
Date: Thu Apr 24 01:03:01 2014
New Revision: 207080

URL: http://llvm.org/viewvc/llvm-project?rev=207080&view=rev
Log:
Fix for PR18921, "vmov" part.
Added support for bytes replication feature, so it could be GAS compatible.

E.g. instructions below:
"vmov.i32 d0, 0xffffffff"
"vmvn.i32 d0, 0xabababab"
"vmov.i32 d0, 0xabababab"
"vmov.i16 d0, 0xabab"
are incorrect, but we could deal with such cases.

For first one we should emit:
"vmov.i8 d0, 0xff"
For second one ("vmvn"):
"vmov.i8 d0, 0x54"
For last two instructions it should emit:
"vmov.i8 d0, 0xab"

P.S.: In ARMAsmParser.cpp I have also fixed few nearby style issues in old code.
Just for keeping method bodies in harmony with themselves.


Added:
    llvm/trunk/test/MC/ARM/vmov-vmvn-byte-replicate.s
    llvm/trunk/test/MC/ARM/vmov-vmvn-illegal-cases.s
    llvm/trunk/test/MC/ARM/vorr-vbic-illegal-cases.s
Modified:
    llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Modified: llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrNEON.td?rev=207080&r1=207079&r2=207080&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrNEON.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrNEON.td Thu Apr 24 01:03:01 2014
@@ -39,6 +39,49 @@ def nImmVMOVI32 : Operand<i32> {
   let PrintMethod = "printNEONModImmOperand";
   let ParserMatchClass = nImmVMOVI32AsmOperand;
 }
+
+def nImmVMOVI16AsmOperandByteReplicate :
+  AsmOperandClass {
+  let Name = "NEONi16vmovByteReplicate";
+  let PredicateMethod = "isNEONi16ByteReplicate";
+  let RenderMethod = "addNEONvmovByteReplicateOperands";
+}
+def nImmVMOVI32AsmOperandByteReplicate :
+  AsmOperandClass {
+  let Name = "NEONi32vmovByteReplicate";
+  let PredicateMethod = "isNEONi32ByteReplicate";
+  let RenderMethod = "addNEONvmovByteReplicateOperands";
+}
+def nImmVMVNI16AsmOperandByteReplicate :
+  AsmOperandClass {
+  let Name = "NEONi16invByteReplicate";
+  let PredicateMethod = "isNEONi16ByteReplicate";
+  let RenderMethod = "addNEONinvByteReplicateOperands";
+}
+def nImmVMVNI32AsmOperandByteReplicate :
+  AsmOperandClass {
+  let Name = "NEONi32invByteReplicate";
+  let PredicateMethod = "isNEONi32ByteReplicate";
+  let RenderMethod = "addNEONinvByteReplicateOperands";
+}
+
+def nImmVMOVI16ByteReplicate : Operand<i32> {
+  let PrintMethod = "printNEONModImmOperand";
+  let ParserMatchClass = nImmVMOVI16AsmOperandByteReplicate;
+}
+def nImmVMOVI32ByteReplicate : Operand<i32> {
+  let PrintMethod = "printNEONModImmOperand";
+  let ParserMatchClass = nImmVMOVI32AsmOperandByteReplicate;
+}
+def nImmVMVNI16ByteReplicate : Operand<i32> {
+  let PrintMethod = "printNEONModImmOperand";
+  let ParserMatchClass = nImmVMVNI16AsmOperandByteReplicate;
+}
+def nImmVMVNI32ByteReplicate : Operand<i32> {
+  let PrintMethod = "printNEONModImmOperand";
+  let ParserMatchClass = nImmVMVNI32AsmOperandByteReplicate;
+}
+
 def nImmVMOVI32NegAsmOperand : AsmOperandClass { let Name = "NEONi32vmovNeg"; }
 def nImmVMOVI32Neg : Operand<i32> {
   let PrintMethod = "printNEONModImmOperand";
@@ -5301,6 +5344,35 @@ def VMOVv4f32 : N1ModImm<1, 0b000, 0b111
                          [(set QPR:$Vd, (v4f32 (NEONvmovFPImm timm:$SIMM)))]>;
 } // isReMaterializable
 
+// Add support for bytes replication feature, so it could be GAS compatible.
+// E.g. instructions below:
+// "vmov.i32 d0, 0xffffffff"
+// "vmov.i32 d0, 0xabababab"
+// "vmov.i16 d0, 0xabab"
+// are incorrect, but we could deal with such cases.
+// For last two instructions, for example, it should emit:
+// "vmov.i8 d0, 0xab"
+def : NEONInstAlias<"vmov${p}.i16 $Vd, $Vm",
+                    (VMOVv8i8 DPR:$Vd, nImmVMOVI16ByteReplicate:$Vm, pred:$p)>;
+def : NEONInstAlias<"vmov${p}.i32 $Vd, $Vm",
+                    (VMOVv8i8 DPR:$Vd, nImmVMOVI32ByteReplicate:$Vm, pred:$p)>;
+def : NEONInstAlias<"vmov${p}.i16 $Vd, $Vm",
+                    (VMOVv16i8 QPR:$Vd, nImmVMOVI16ByteReplicate:$Vm, pred:$p)>;
+def : NEONInstAlias<"vmov${p}.i32 $Vd, $Vm",
+                    (VMOVv16i8 QPR:$Vd, nImmVMOVI32ByteReplicate:$Vm, pred:$p)>;
+
+// Also add same support for VMVN instructions. So instruction:
+// "vmvn.i32 d0, 0xabababab"
+// actually means:
+// "vmov.i8 d0, 0x54"
+def : NEONInstAlias<"vmvn${p}.i16 $Vd, $Vm",
+                    (VMOVv8i8 DPR:$Vd, nImmVMVNI16ByteReplicate:$Vm, pred:$p)>;
+def : NEONInstAlias<"vmvn${p}.i32 $Vd, $Vm",
+                    (VMOVv8i8 DPR:$Vd, nImmVMVNI32ByteReplicate:$Vm, pred:$p)>;
+def : NEONInstAlias<"vmvn${p}.i16 $Vd, $Vm",
+                    (VMOVv16i8 QPR:$Vd, nImmVMVNI16ByteReplicate:$Vm, pred:$p)>;
+def : NEONInstAlias<"vmvn${p}.i32 $Vd, $Vm",
+                    (VMOVv16i8 QPR:$Vd, nImmVMVNI32ByteReplicate:$Vm, pred:$p)>;
 
 // On some CPUs the two instructions "vmov.i32 dD, #0" and "vmov.i32 qD, #0"
 // require zero cycles to execute so they should be used wherever possible for

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=207080&r1=207079&r2=207080&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Thu Apr 24 01:03:01 2014
@@ -1610,7 +1610,10 @@ public:
   }
 
   bool isNEONi16splat() const {
-    if (!isImm()) return false;
+    if (isNEONByteReplicate(2))
+      return false; // Leave that for bytes replication and forbid by default.
+    if (!isImm())
+      return false;
     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
     // Must be a constant.
     if (!CE) return false;
@@ -1620,7 +1623,10 @@ public:
   }
 
   bool isNEONi32splat() const {
-    if (!isImm()) return false;
+    if (isNEONByteReplicate(4))
+      return false; // Leave that for bytes replication and forbid by default.
+    if (!isImm())
+      return false;
     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
     // Must be a constant.
     if (!CE) return false;
@@ -1632,11 +1638,36 @@ public:
       (Value >= 0x01000000 && Value <= 0xff000000);
   }
 
+  bool isNEONByteReplicate(unsigned NumBytes) const {
+    if (!isImm())
+      return false;
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    // Must be a constant.
+    if (!CE)
+      return false;
+    int64_t Value = CE->getValue();
+    if (!Value)
+      return false; // Don't bother with zero.
+
+    unsigned char B = Value & 0xff;
+    for (unsigned i = 1; i < NumBytes; ++i) {
+      Value >>= 8;
+      if ((Value & 0xff) != B)
+        return false;
+    }
+    return true;
+  }
+  bool isNEONi16ByteReplicate() const { return isNEONByteReplicate(2); }
+  bool isNEONi32ByteReplicate() const { return isNEONByteReplicate(4); }
   bool isNEONi32vmov() const {
-    if (!isImm()) return false;
+    if (isNEONByteReplicate(4))
+      return false; // Let it to be classified as byte-replicate case.
+    if (!isImm())
+      return false;
     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
     // Must be a constant.
-    if (!CE) return false;
+    if (!CE)
+      return false;
     int64_t Value = CE->getValue();
     // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
     // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
@@ -2384,6 +2415,19 @@ public:
     Inst.addOperand(MCOperand::CreateImm(Value));
   }
 
+  void addNEONinvByteReplicateOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    // The immediate encodes the type of constant as well as the value.
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    unsigned Value = CE->getValue();
+    assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
+            Inst.getOpcode() == ARM::VMOVv16i8) &&
+           "All vmvn instructions that wants to replicate non-zero byte "
+           "always must be replaced with VMOVv8i8 or VMOVv16i8.");
+    unsigned B = ((~Value) & 0xff);
+    B |= 0xe00; // cmode = 0b1110
+    Inst.addOperand(MCOperand::CreateImm(B));
+  }
   void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     // The immediate encodes the type of constant as well as the value.
@@ -2398,6 +2442,19 @@ public:
     Inst.addOperand(MCOperand::CreateImm(Value));
   }
 
+  void addNEONvmovByteReplicateOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    // The immediate encodes the type of constant as well as the value.
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    unsigned Value = CE->getValue();
+    assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
+            Inst.getOpcode() == ARM::VMOVv16i8) &&
+           "All instructions that wants to replicate non-zero byte "
+           "always must be replaced with VMOVv8i8 or VMOVv16i8.");
+    unsigned B = Value & 0xff;
+    B |= 0xe00; // cmode = 0b1110
+    Inst.addOperand(MCOperand::CreateImm(B));
+  }
   void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     // The immediate encodes the type of constant as well as the value.

Added: llvm/trunk/test/MC/ARM/vmov-vmvn-byte-replicate.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/vmov-vmvn-byte-replicate.s?rev=207080&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/vmov-vmvn-byte-replicate.s (added)
+++ llvm/trunk/test/MC/ARM/vmov-vmvn-byte-replicate.s Thu Apr 24 01:03:01 2014
@@ -0,0 +1,31 @@
+@ PR18921, "vmov" part.
+@ RUN: llvm-mc -triple=armv7-linux-gnueabi -show-encoding < %s | FileCheck %s
+.text
+
+@ CHECK: vmov.i8 d2, #0xff @ encoding: [0x1f,0x2e,0x87,0xf3]
+@ CHECK: vmov.i8 q2, #0xff @ encoding: [0x5f,0x4e,0x87,0xf3]
+@ CHECK: vmov.i8 d2, #0xab @ encoding: [0x1b,0x2e,0x82,0xf3]
+@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
+@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
+@ CHECK: vmov.i8 q2, #0xab @ encoding: [0x5b,0x4e,0x82,0xf3]
+
+@ CHECK: vmov.i8 d2, #0x0  @ encoding: [0x10,0x2e,0x80,0xf2]
+@ CHECK: vmov.i8 q2, #0x0  @ encoding: [0x50,0x4e,0x80,0xf2]
+@ CHECK: vmov.i8 d2, #0x54 @ encoding: [0x14,0x2e,0x85,0xf2]
+@ CHECK: vmov.i8 q2, #0x54 @ encoding: [0x54,0x4e,0x85,0xf2]
+@ CHECK: vmov.i8 d2, #0x54 @ encoding: [0x14,0x2e,0x85,0xf2]
+@ CHECK: vmov.i8 q2, #0x54 @ encoding: [0x54,0x4e,0x85,0xf2]
+
+        vmov.i32        d2, #0xffffffff
+        vmov.i32        q2, #0xffffffff
+        vmov.i32        d2, #0xabababab
+        vmov.i32        q2, #0xabababab
+        vmov.i16        q2, #0xabab
+        vmov.i16        q2, #0xabab
+
+        vmvn.i32        d2, #0xffffffff
+        vmvn.i32        q2, #0xffffffff
+        vmvn.i32        d2, #0xabababab
+        vmvn.i32        q2, #0xabababab
+        vmvn.i16        d2, #0xabab
+        vmvn.i16        q2, #0xabab

Added: llvm/trunk/test/MC/ARM/vmov-vmvn-illegal-cases.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/vmov-vmvn-illegal-cases.s?rev=207080&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/vmov-vmvn-illegal-cases.s (added)
+++ llvm/trunk/test/MC/ARM/vmov-vmvn-illegal-cases.s Thu Apr 24 01:03:01 2014
@@ -0,0 +1,30 @@
+@ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s
+.text
+
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vmov.i32        d2, #0xffffffab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vmov.i32        q2, #0xffffffab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vmov.i16        q2, #0xffab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vmov.i16        q2, #0xffab
+
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vmvn.i32        d2, #0xffffffab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vmvn.i32        q2, #0xffffffab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vmvn.i16        q2, #0xffab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vmvn.i16        q2, #0xffab
+
+        vmov.i32        d2, #0xffffffab
+        vmov.i32        q2, #0xffffffab
+        vmov.i16        q2, #0xffab
+        vmov.i16        q2, #0xffab
+
+        vmvn.i32        d2, #0xffffffab
+        vmvn.i32        q2, #0xffffffab
+        vmvn.i16        q2, #0xffab
+        vmvn.i16        q2, #0xffab

Added: llvm/trunk/test/MC/ARM/vorr-vbic-illegal-cases.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/vorr-vbic-illegal-cases.s?rev=207080&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/vorr-vbic-illegal-cases.s (added)
+++ llvm/trunk/test/MC/ARM/vorr-vbic-illegal-cases.s Thu Apr 24 01:03:01 2014
@@ -0,0 +1,42 @@
+@ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s
+.text
+
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vorr.i32        d2, #0xffffffff
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vorr.i32        q2, #0xffffffff
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vorr.i32        d2, #0xabababab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vorr.i32        q2, #0xabababab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vorr.i16        q2, #0xabab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vorr.i16        q2, #0xabab
+
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i32        d2, #0xffffffff
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i32        q2, #0xffffffff
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i32        d2, #0xabababab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i32        q2, #0xabababab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i16        d2, #0xabab
+@ CHECK: error: invalid operand for instruction
+@ CHECK: vbic.i16        q2, #0xabab
+
+        vorr.i32        d2, #0xffffffff
+        vorr.i32        q2, #0xffffffff
+        vorr.i32        d2, #0xabababab
+        vorr.i32        q2, #0xabababab
+        vorr.i16        q2, #0xabab
+        vorr.i16        q2, #0xabab
+
+        vbic.i32        d2, #0xffffffff
+        vbic.i32        q2, #0xffffffff
+        vbic.i32        d2, #0xabababab
+        vbic.i32        q2, #0xabababab
+        vbic.i16        d2, #0xabab
+        vbic.i16        q2, #0xabab





More information about the llvm-commits mailing list