summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/ARMInstrNEON.td
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARM/ARMInstrNEON.td')
-rw-r--r--llvm/lib/Target/ARM/ARMInstrNEON.td131
1 files changed, 68 insertions, 63 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrNEON.td b/llvm/lib/Target/ARM/ARMInstrNEON.td
index cd67dded585..ca56835f984 100644
--- a/llvm/lib/Target/ARM/ARMInstrNEON.td
+++ b/llvm/lib/Target/ARM/ARMInstrNEON.td
@@ -48,46 +48,28 @@ def nImmVMOVI32 : Operand<i32> {
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;
+class nImmVMOVIAsmOperandReplicate<ValueType From, ValueType To>
+ : AsmOperandClass {
+ let Name = "NEONi" # To.Size # "vmovi" # From.Size # "Replicate";
+ let PredicateMethod = "isNEONmovReplicate<" # From.Size # ", " # To.Size # ">";
+ let RenderMethod = "addNEONvmovi" # From.Size # "ReplicateOperands";
}
-def nImmVMOVI32ByteReplicate : Operand<i32> {
- let PrintMethod = "printNEONModImmOperand";
- let ParserMatchClass = nImmVMOVI32AsmOperandByteReplicate;
+
+class nImmVINVIAsmOperandReplicate<ValueType From, ValueType To>
+ : AsmOperandClass {
+ let Name = "NEONi" # To.Size # "invi" # From.Size # "Replicate";
+ let PredicateMethod = "isNEONinvReplicate<" # From.Size # ", " # To.Size # ">";
+ let RenderMethod = "addNEONinvi" # From.Size # "ReplicateOperands";
}
-def nImmVMVNI16ByteReplicate : Operand<i32> {
+
+class nImmVMOVIReplicate<ValueType From, ValueType To> : Operand<i32> {
let PrintMethod = "printNEONModImmOperand";
- let ParserMatchClass = nImmVMVNI16AsmOperandByteReplicate;
+ let ParserMatchClass = nImmVMOVIAsmOperandReplicate<From, To>;
}
-def nImmVMVNI32ByteReplicate : Operand<i32> {
+
+class nImmVINVIReplicate<ValueType From, ValueType To> : Operand<i32> {
let PrintMethod = "printNEONModImmOperand";
- let ParserMatchClass = nImmVMVNI32AsmOperandByteReplicate;
+ let ParserMatchClass = nImmVINVIAsmOperandReplicate<From, To>;
}
def nImmVMOVI32NegAsmOperand : AsmOperandClass { let Name = "NEONi32vmovNeg"; }
@@ -5933,34 +5915,57 @@ def VMOVv4f32 : N1ModImm<1, 0b000, 0b1111, 0, 1, 0, 1, (outs QPR:$Vd),
} // isReMaterializable, isAsCheapAsAMove
// 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)>;
+multiclass NEONImmReplicateI8InstAlias<ValueType To> {
+ // 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}.i" # To.Size # " $Vd, $Vm",
+ (VMOVv8i8 DPR:$Vd, nImmVMOVIReplicate<i8, To>:$Vm, pred:$p)>;
+ def : NEONInstAlias<"vmov${p}.i" # To.Size # " $Vd, $Vm",
+ (VMOVv16i8 QPR:$Vd, nImmVMOVIReplicate<i8, To>:$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}.i" # To.Size # " $Vd, $Vm",
+ (VMOVv8i8 DPR:$Vd, nImmVINVIReplicate<i8, To>:$Vm, pred:$p)>;
+ def : NEONInstAlias<"vmvn${p}.i" # To.Size # " $Vd, $Vm",
+ (VMOVv16i8 QPR:$Vd, nImmVINVIReplicate<i8, To>:$Vm, pred:$p)>;
+}
+
+defm : NEONImmReplicateI8InstAlias<i16>;
+defm : NEONImmReplicateI8InstAlias<i32>;
+defm : NEONImmReplicateI8InstAlias<i64>;
+
+// Similar to above for types other than i8, e.g.:
+// "vmov.i32 d0, #0xab00ab00" -> "vmov.i16 d0, #0xab00"
+// "vmvn.i64 q0, #0xab000000ab000000" -> "vmvn.i32 q0, #0xab000000"
+// In this case we do not canonicalize VMVN to VMOV
+multiclass NEONImmReplicateInstAlias<ValueType From, NeonI V8, NeonI V16,
+ NeonI NV8, NeonI NV16, ValueType To> {
+ def : NEONInstAlias<"vmov${p}.i" # To.Size # " $Vd, $Vm",
+ (V8 DPR:$Vd, nImmVMOVIReplicate<From, To>:$Vm, pred:$p)>;
+ def : NEONInstAlias<"vmov${p}.i" # To.Size # " $Vd, $Vm",
+ (V16 QPR:$Vd, nImmVMOVIReplicate<From, To>:$Vm, pred:$p)>;
+ def : NEONInstAlias<"vmvn${p}.i" # To.Size # " $Vd, $Vm",
+ (NV8 DPR:$Vd, nImmVMOVIReplicate<From, To>:$Vm, pred:$p)>;
+ def : NEONInstAlias<"vmvn${p}.i" # To.Size # " $Vd, $Vm",
+ (NV16 QPR:$Vd, nImmVMOVIReplicate<From, To>:$Vm, pred:$p)>;
+}
+
+defm : NEONImmReplicateInstAlias<i16, VMOVv4i16, VMOVv8i16,
+ VMVNv4i16, VMVNv8i16, i32>;
+defm : NEONImmReplicateInstAlias<i16, VMOVv4i16, VMOVv8i16,
+ VMVNv4i16, VMVNv8i16, i64>;
+defm : NEONImmReplicateInstAlias<i32, VMOVv2i32, VMOVv4i32,
+ VMVNv2i32, VMVNv4i32, i64>;
+// TODO: add "VMOV <-> VMVN" conversion for cases like
+// "vmov.i32 d0, #0xffaaffaa" -> "vmvn.i16 d0, #0x55"
+// "vmvn.i32 d0, #0xaaffaaff" -> "vmov.i16 d0, #0xff00"
// 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
OpenPOWER on IntegriCloud