diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -def SVE8BitLslImm : ComplexPattern; def SVELShiftImm64 : ComplexPattern", []>; // Contiguous loads - node definitions diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -167,8 +167,8 @@ def SVEAddSubImmOperand64 : SVEShiftedImmOperand<64, "AddSub", "isSVEAddSubImm">; class imm8_opt_lsl - : Operand, ImmLeaf { + AsmOperandClass OpndClass> + : Operand { let EncoderMethod = "getImm8OptLsl"; let DecoderMethod = "DecodeImm8OptLsl<" # ElementWidth # ">"; let PrintMethod = "printImm8OptLsl<" # printType # ">"; @@ -176,31 +176,15 @@ let MIOperandInfo = (ops i32imm, i32imm); } -def cpy_imm8_opt_lsl_i8 : imm8_opt_lsl<8, "int8_t", SVECpyImmOperand8, [{ - return AArch64_AM::isSVECpyImm(Imm); -}]>; -def cpy_imm8_opt_lsl_i16 : imm8_opt_lsl<16, "int16_t", SVECpyImmOperand16, [{ - return AArch64_AM::isSVECpyImm(Imm); -}]>; -def cpy_imm8_opt_lsl_i32 : imm8_opt_lsl<32, "int32_t", SVECpyImmOperand32, [{ - return AArch64_AM::isSVECpyImm(Imm); -}]>; -def cpy_imm8_opt_lsl_i64 : imm8_opt_lsl<64, "int64_t", SVECpyImmOperand64, [{ - return AArch64_AM::isSVECpyImm(Imm); -}]>; - -def addsub_imm8_opt_lsl_i8 : imm8_opt_lsl<8, "uint8_t", SVEAddSubImmOperand8, [{ - return AArch64_AM::isSVEAddSubImm(Imm); -}]>; -def addsub_imm8_opt_lsl_i16 : imm8_opt_lsl<16, "uint16_t", SVEAddSubImmOperand16, [{ - return AArch64_AM::isSVEAddSubImm(Imm); -}]>; -def addsub_imm8_opt_lsl_i32 : imm8_opt_lsl<32, "uint32_t", SVEAddSubImmOperand32, [{ - return AArch64_AM::isSVEAddSubImm(Imm); -}]>; -def addsub_imm8_opt_lsl_i64 : imm8_opt_lsl<64, "uint64_t", SVEAddSubImmOperand64, [{ - return AArch64_AM::isSVEAddSubImm(Imm); -}]>; +def cpy_imm8_opt_lsl_i8 : imm8_opt_lsl<8, "int8_t", SVECpyImmOperand8>; +def cpy_imm8_opt_lsl_i16 : imm8_opt_lsl<16, "int16_t", SVECpyImmOperand16>; +def cpy_imm8_opt_lsl_i32 : imm8_opt_lsl<32, "int32_t", SVECpyImmOperand32>; +def cpy_imm8_opt_lsl_i64 : imm8_opt_lsl<64, "int64_t", SVECpyImmOperand64>; + +def addsub_imm8_opt_lsl_i8 : imm8_opt_lsl<8, "uint8_t", SVEAddSubImmOperand8>; +def addsub_imm8_opt_lsl_i16 : imm8_opt_lsl<16, "uint16_t", SVEAddSubImmOperand16>; +def addsub_imm8_opt_lsl_i32 : imm8_opt_lsl<32, "uint32_t", SVEAddSubImmOperand32>; +def addsub_imm8_opt_lsl_i64 : imm8_opt_lsl<64, "uint64_t", SVEAddSubImmOperand64>; def SVEAddSubImm8Pat : ComplexPattern", []>; def SVEAddSubImm16Pat : ComplexPattern", []>; @@ -212,6 +196,8 @@ def SVELogicalImm32Pat : ComplexPattern", []>; def SVELogicalImm64Pat : ComplexPattern", []>; +def SVE8BitLslImm : ComplexPattern; + def SVEArithUImmPat : ComplexPattern; def SVEArithSImmPat : ComplexPattern; @@ -4079,8 +4065,9 @@ multiclass sve_int_dup_imm_pred_zero_inst< bits<2> sz8_64, string asm, ZPRRegOp zprty, ValueType intty, - ValueType predty, imm8_opt_lsl cpyimm> { - def NAME : sve_int_dup_imm_pred; + ValueType predty, ValueType scalarty, imm8_opt_lsl cpyimm> { + def NAME : sve_int_dup_imm_pred; def : InstAlias<"mov $Zd, $Pg/z, $imm", (!cast(NAME) zprty:$Zd, PPRAny:$Pg, cpyimm:$imm), 1>; def : Pat<(intty (zext (predty PPRAny:$Ps1))), @@ -4089,13 +4076,22 @@ (!cast(NAME) PPRAny:$Ps1, -1, 0)>; def : Pat<(intty (anyext (predty PPRAny:$Ps1))), (!cast(NAME) PPRAny:$Ps1, 1, 0)>; + def : Pat<(intty + (vselect predty:$Pg, + (intty (AArch64dup (scalarty (SVE8BitLslImm i32:$imm, i32:$shift)))), + (intty (AArch64dup (scalarty 0))))), + (!cast(NAME) $Pg, i32:$imm, i32:$shift)>; } multiclass sve_int_dup_imm_pred_zero { - defm _B : sve_int_dup_imm_pred_zero_inst<0b00, asm, ZPR8, nxv16i8, nxv16i1, cpy_imm8_opt_lsl_i8>; - defm _H : sve_int_dup_imm_pred_zero_inst<0b01, asm, ZPR16, nxv8i16, nxv8i1, cpy_imm8_opt_lsl_i16>; - defm _S : sve_int_dup_imm_pred_zero_inst<0b10, asm, ZPR32, nxv4i32, nxv4i1, cpy_imm8_opt_lsl_i32>; - defm _D : sve_int_dup_imm_pred_zero_inst<0b11, asm, ZPR64, nxv2i64, nxv2i1, cpy_imm8_opt_lsl_i64>; + defm _B : sve_int_dup_imm_pred_zero_inst<0b00, asm, ZPR8, nxv16i8, nxv16i1, + i32, cpy_imm8_opt_lsl_i8>; + defm _H : sve_int_dup_imm_pred_zero_inst<0b01, asm, ZPR16, nxv8i16, nxv8i1, + i32, cpy_imm8_opt_lsl_i16>; + defm _S : sve_int_dup_imm_pred_zero_inst<0b10, asm, ZPR32, nxv4i32, nxv4i1, + i32, cpy_imm8_opt_lsl_i32>; + defm _D : sve_int_dup_imm_pred_zero_inst<0b11, asm, ZPR64, nxv2i64, nxv2i1, + i64, cpy_imm8_opt_lsl_i64>; } //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/AArch64/sve-vselect-imm.ll b/llvm/test/CodeGen/AArch64/sve-vselect-imm.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve-vselect-imm.ll @@ -0,0 +1,192 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64--linux-gnu -mattr=+sve < %s | FileCheck %s + +define @sel_8_positive( %p) { +; CHECK-LABEL: sel_8_positive: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.b, p0/z, #3 // =0x3 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i8 3, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_16_positive( %p) { +; CHECK-LABEL: sel_16_positive: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.h, p0/z, #3 // =0x3 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i16 3, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_32_positive( %p) { +; CHECK-LABEL: sel_32_positive: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.s, p0/z, #3 // =0x3 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i32 3, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_64_positive( %p) { +; CHECK-LABEL: sel_64_positive: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.d, p0/z, #3 // =0x3 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i64 3, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_8_negative( %p) { +; CHECK-LABEL: sel_8_negative: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.b, p0/z, #-128 // =0xffffffffffffff80 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i8 -128, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_16_negative( %p) { +; CHECK-LABEL: sel_16_negative: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.h, p0/z, #-128 // =0xffffffffffffff80 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i16 -128, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_32_negative( %p) { +; CHECK-LABEL: sel_32_negative: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.s, p0/z, #-128 // =0xffffffffffffff80 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i32 -128, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_64_negative( %p) { +; CHECK-LABEL: sel_64_negative: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.d, p0/z, #-128 // =0xffffffffffffff80 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i64 -128, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_16_shifted( %p) { +; CHECK-LABEL: sel_16_shifted: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.h, p0/z, #512 // =0x200 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i16 512, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_32_shifted( %p) { +; CHECK-LABEL: sel_32_shifted: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.s, p0/z, #512 // =0x200 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i32 512, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_64_shifted( %p) { +; CHECK-LABEL: sel_64_shifted: +; CHECK: // %bb.0: +; CHECK-NEXT: mov z0.d, p0/z, #512 // =0x200 +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i64 512, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +; TODO: We could actually use something like "sel z0.b, p0/z, #-128" if the +; odd bits of the predicate are zero. +define @sel_16_illegal_wrong_extension( %p) { +; CHECK-LABEL: sel_16_illegal: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #128 +; CHECK-NEXT: mov z0.h, w8 +; CHECK-NEXT: mov z1.h, #0 // =0x0 +; CHECK-NEXT: sel z0.h, p0, z0.h, z1.h +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i16 128, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_32_illegal_wrong_extension( %p) { +; CHECK-LABEL: sel_32_illegal: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #128 +; CHECK-NEXT: mov z0.s, w8 +; CHECK-NEXT: mov z1.s, #0 // =0x0 +; CHECK-NEXT: sel z0.s, p0, z0.s, z1.s +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i32 128, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_64_illegal_wrong_extension( %p) { +; CHECK-LABEL: sel_64_illegal: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #128 +; CHECK-NEXT: mov z0.d, x8 +; CHECK-NEXT: mov z1.d, #0 // =0x0 +; CHECK-NEXT: sel z0.d, p0, z0.d, z1.d +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i64 128, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_16_illegal_shifted( %p) { +; CHECK-LABEL: sel_16_illegal_shifted: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #513 +; CHECK-NEXT: mov z0.h, w8 +; CHECK-NEXT: mov z1.h, #0 // =0x0 +; CHECK-NEXT: sel z0.h, p0, z0.h, z1.h +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i16 513, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_32_illegal_shifted( %p) { +; CHECK-LABEL: sel_32_illegal_shifted: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #513 +; CHECK-NEXT: mov z0.s, w8 +; CHECK-NEXT: mov z1.s, #0 // =0x0 +; CHECK-NEXT: sel z0.s, p0, z0.s, z1.s +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i32 513, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +} + +define @sel_64_illegal_shifted( %p) { +; CHECK-LABEL: sel_64_illegal_shifted: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #513 +; CHECK-NEXT: mov z0.d, x8 +; CHECK-NEXT: mov z1.d, #0 // =0x0 +; CHECK-NEXT: sel z0.d, p0, z0.d, z1.d +; CHECK-NEXT: ret +%vec = shufflevector insertelement ( undef, i64 513, i32 0), zeroinitializer, zeroinitializer +%sel = select %p, %vec, zeroinitializer +ret %sel +}