-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[AArch64] Define constructive EXT_ZZI pseudo instruction #152552
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-backend-aarch64 Author: Gaëtan Bossu (gbossu) ChangesIt will get expanded into MOVPRFX_ZZ and EXT_ZZI by the AArch64ExpandPseudo pass. Note this patch only defines the pseudo, it isn't used in any ISel pattern yet. This is a chained PR Full diff: https://github.com/llvm/llvm-project/pull/152552.diff 13 Files Affected:
diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
index 201bfe0a443d6..45f9c8fdec567 100644
--- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
@@ -528,6 +528,10 @@ bool AArch64ExpandPseudo::expand_DestructiveOp(
UseRev = true;
}
break;
+ case AArch64::DestructiveRegRegImmUnpred:
+ // EXT_ZZZI Zd, Zs1, Zs2, Imm ==> EXT_ZZI Zds1, Zs2, Imm
+ std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3);
+ break;
default:
llvm_unreachable("Unsupported Destructive Operand type");
}
@@ -538,6 +542,7 @@ bool AArch64ExpandPseudo::expand_DestructiveOp(
bool DOPRegIsUnique = false;
switch (DType) {
case AArch64::DestructiveBinary:
+ case AArch64::DestructiveRegRegImmUnpred:
DOPRegIsUnique = DstReg != MI.getOperand(SrcIdx).getReg();
break;
case AArch64::DestructiveBinaryComm:
@@ -639,10 +644,20 @@ bool AArch64ExpandPseudo::expand_DestructiveOp(
.addImm(0);
}
} else if (DstReg != MI.getOperand(DOPIdx).getReg()) {
- assert(DOPRegIsUnique && "The destructive operand should be unique");
- PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MovPrfx))
- .addReg(DstReg, RegState::Define)
- .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState);
+ if (DOPRegIsUnique) {
+ PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MovPrfx))
+ .addReg(DstReg, RegState::Define)
+ .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState);
+ } else {
+ // MOVPRFX requires unique operands: Just build a COPY (Using ORR directly
+ // as we are past PostRAPseudo expansion).
+ assert(DType == AArch64::DestructiveRegRegImmUnpred &&
+ "Unexpected destructive operation type");
+ PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORR_ZZZ))
+ .addReg(DstReg, RegState::Define)
+ .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
+ .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState);
+ }
DOPIdx = 0;
DOPRegState = 0;
}
@@ -674,6 +689,11 @@ bool AArch64ExpandPseudo::expand_DestructiveOp(
.add(MI.getOperand(SrcIdx))
.add(MI.getOperand(Src2Idx));
break;
+ case AArch64::DestructiveRegRegImmUnpred:
+ DOP.addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
+ .add(MI.getOperand(SrcIdx))
+ .add(MI.getOperand(Src2Idx));
+ break;
}
if (PRFX) {
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index d068a12c7f7d5..35f1151f90068 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -36,7 +36,8 @@ def DestructiveBinary : DestructiveInstTypeEnum<5>;
def DestructiveBinaryComm : DestructiveInstTypeEnum<6>;
def DestructiveBinaryCommWithRev : DestructiveInstTypeEnum<7>;
def DestructiveTernaryCommWithRev : DestructiveInstTypeEnum<8>;
-def DestructiveUnaryPassthru : DestructiveInstTypeEnum<9>;
+def DestructiveRegRegImmUnpred : DestructiveInstTypeEnum<9>;
+def DestructiveUnaryPassthru : DestructiveInstTypeEnum<10>;
class FalseLanesEnum<bits<2> val> {
bits<2> Value = val;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 7c255da333e4b..9df1d80101dfe 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -820,7 +820,8 @@ enum DestructiveInstType {
DestructiveBinaryComm = TSFLAG_DESTRUCTIVE_INST_TYPE(0x6),
DestructiveBinaryCommWithRev = TSFLAG_DESTRUCTIVE_INST_TYPE(0x7),
DestructiveTernaryCommWithRev = TSFLAG_DESTRUCTIVE_INST_TYPE(0x8),
- DestructiveUnaryPassthru = TSFLAG_DESTRUCTIVE_INST_TYPE(0x9),
+ DestructiveRegRegImmUnpred = TSFLAG_DESTRUCTIVE_INST_TYPE(0x9),
+ DestructiveUnaryPassthru = TSFLAG_DESTRUCTIVE_INST_TYPE(0xa),
};
enum FalseLaneType {
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 0c4b4f4c3ed88..85e647af6684c 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -1021,7 +1021,9 @@ let Predicates = [HasNonStreamingSVE_or_SME2p2] in {
let Predicates = [HasSVE_or_SME] in {
defm INSR_ZR : sve_int_perm_insrs<"insr", AArch64insr>;
defm INSR_ZV : sve_int_perm_insrv<"insr", AArch64insr>;
- defm EXT_ZZI : sve_int_perm_extract_i<"ext", AArch64ext>;
+ defm EXT_ZZI : sve_int_perm_extract_i<"ext", AArch64ext, "EXT_ZZZI">;
+
+ def EXT_ZZZI : UnpredRegRegImmPseudo<"EXT_ZZZI", ZPR8, imm0_255>;
defm RBIT_ZPmZ : sve_int_perm_rev_rbit<"rbit", AArch64rbit_mt>;
defm REVB_ZPmZ : sve_int_perm_rev_revb<"revb", AArch64revb_mt>;
diff --git a/llvm/lib/Target/AArch64/AArch64SchedA320.td b/llvm/lib/Target/AArch64/AArch64SchedA320.td
index 89ed13389daf0..7f44a35ec37fc 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedA320.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedA320.td
@@ -847,7 +847,7 @@ def : InstRW<[CortexA320Write<3, CortexA320UnitVALU>], (instregex "^[SU]XTB_ZPmZ
"^[SU]XTW_ZPmZ_[D]")>;
// Extract
-def : InstRW<[CortexA320Write<3, CortexA320UnitVALU>], (instrs EXT_ZZI, EXT_ZZI_B)>;
+def : InstRW<[CortexA320Write<3, CortexA320UnitVALU>], (instrs EXT_ZZI, EXT_ZZZI, EXT_ZZI_B)>;
// Extract narrow saturating
def : InstRW<[CortexA320Write<4, CortexA320UnitVALU>], (instregex "^[SU]QXTN[BT]_ZZ_[BHS]",
diff --git a/llvm/lib/Target/AArch64/AArch64SchedA510.td b/llvm/lib/Target/AArch64/AArch64SchedA510.td
index 9456878946151..4126d876ca45a 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedA510.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedA510.td
@@ -825,7 +825,7 @@ def : InstRW<[CortexA510Write<3, CortexA510UnitVALU>], (instregex "^[SU]XTB_ZPmZ
"^[SU]XTW_ZPmZ_[D]")>;
// Extract
-def : InstRW<[CortexA510Write<3, CortexA510UnitVALU>], (instrs EXT_ZZI, EXT_ZZI_B)>;
+def : InstRW<[CortexA510Write<3, CortexA510UnitVALU>], (instrs EXT_ZZI, EXT_ZZZI, EXT_ZZI_B)>;
// Extract narrow saturating
def : InstRW<[CortexA510Write<4, CortexA510UnitVALU>], (instregex "^[SU]QXTN[BT]_ZZ_[BHS]",
diff --git a/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td b/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td
index 91a707910a7f3..82a50daae7e19 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td
@@ -1785,7 +1785,7 @@ def : InstRW<[N2Write_2c_1V1], (instregex "^[SU]XTB_ZPmZ_[HSD]",
"^[SU]XTW_ZPmZ_[D]")>;
// Extract
-def : InstRW<[N2Write_2c_1V], (instrs EXT_ZZI, EXT_ZZI_B)>;
+def : InstRW<[N2Write_2c_1V], (instrs EXT_ZZI, EXT_ZZZI, EXT_ZZI_B)>;
// Extract narrow saturating
def : InstRW<[N2Write_4c_1V1], (instregex "^[SU]QXTN[BT]_ZZ_[BHS]$",
diff --git a/llvm/lib/Target/AArch64/AArch64SchedNeoverseN3.td b/llvm/lib/Target/AArch64/AArch64SchedNeoverseN3.td
index ecfb1249cfc49..1dbd7135d7870 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedNeoverseN3.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedNeoverseN3.td
@@ -1757,7 +1757,7 @@ def : InstRW<[N3Write_2c_1V], (instregex "^[SU]XTB_ZPmZ_[HSD]",
"^[SU]XTW_ZPmZ_[D]")>;
// Extract
-def : InstRW<[N3Write_2c_1V], (instrs EXT_ZZI, EXT_ZZI_B)>;
+def : InstRW<[N3Write_2c_1V], (instrs EXT_ZZI, EXT_ZZZI, EXT_ZZI_B)>;
// Extract narrow saturating
def : InstRW<[N3Write_4c_1V1], (instregex "^[SU]QXTN[BT]_ZZ_[BHS]$",
diff --git a/llvm/lib/Target/AArch64/AArch64SchedNeoverseV1.td b/llvm/lib/Target/AArch64/AArch64SchedNeoverseV1.td
index 368665467859f..e885c42f66bfb 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedNeoverseV1.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedNeoverseV1.td
@@ -1575,7 +1575,7 @@ def : InstRW<[V1Write_2c_1V1], (instregex "^[SU]XTB_ZPmZ_[HSD]",
"^[SU]XTW_ZPmZ_[D]")>;
// Extract
-def : InstRW<[V1Write_2c_1V01], (instrs EXT_ZZI)>;
+def : InstRW<[V1Write_2c_1V01], (instrs EXT_ZZI, EXT_ZZZI)>;
// Extract/insert operation, SIMD and FP scalar form
def : InstRW<[V1Write_3c_1V1], (instregex "^LAST[AB]_VPZ_[BHSD]$",
diff --git a/llvm/lib/Target/AArch64/AArch64SchedNeoverseV2.td b/llvm/lib/Target/AArch64/AArch64SchedNeoverseV2.td
index b2c3da03b4b84..678e10b35513d 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedNeoverseV2.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedNeoverseV2.td
@@ -2272,7 +2272,7 @@ def : InstRW<[V2Write_2c_1V13], (instregex "^[SU]XTB_ZPmZ_[HSD]",
"^[SU]XTW_ZPmZ_[D]")>;
// Extract
-def : InstRW<[V2Write_2c_1V], (instrs EXT_ZZI, EXT_ZZI_B)>;
+def : InstRW<[V2Write_2c_1V], (instrs EXT_ZZI, EXT_ZZZI, EXT_ZZI_B)>;
// Extract narrow saturating
def : InstRW<[V2Write_4c_1V13], (instregex "^[SU]QXTN[BT]_ZZ_[BHS]",
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index a0320f919e8c5..4392e36e6819c 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -809,6 +809,11 @@ let hasNoSchedulingInfo = 1 in {
Pseudo<(outs zprty:$Zd), (ins PPR3bAny:$Pg, zprty:$Zs1, zprty:$Zs2, zprty:$Zs3), []> {
let FalseLanes = flags;
}
+
+ class UnpredRegRegImmPseudo<string name, ZPRRegOp zprty, Operand immty>
+ : SVEPseudo2Instr<name, 0>,
+ Pseudo<(outs zprty:$Zd), (ins zprty:$Zs1, zprty:$Zs2, immty:$imm), []> {
+ }
}
//
@@ -1885,13 +1890,14 @@ class sve_int_perm_extract_i<string asm>
let Inst{4-0} = Zdn;
let Constraints = "$Zdn = $_Zdn";
- let DestructiveInstType = DestructiveOther;
+ let DestructiveInstType = DestructiveRegRegImmUnpred;
let ElementSize = ElementSizeNone;
let hasSideEffects = 0;
}
-multiclass sve_int_perm_extract_i<string asm, SDPatternOperator op> {
- def NAME : sve_int_perm_extract_i<asm>;
+multiclass sve_int_perm_extract_i<string asm, SDPatternOperator op, string pseudoInstrName> {
+ def NAME : sve_int_perm_extract_i<asm>,
+ SVEPseudo2Instr<pseudoInstrName, 1>;
def : SVE_3_Op_Imm_Pat<nxv16i8, op, nxv16i8, nxv16i8, i32, imm0_255,
!cast<Instruction>(NAME)>;
diff --git a/llvm/test/CodeGen/AArch64/expand-constructive-zpzz.mir b/llvm/test/CodeGen/AArch64/expand-constructive-zpzz.mir
new file mode 100644
index 0000000000000..5e1c211ccb9a2
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/expand-constructive-zpzz.mir
@@ -0,0 +1,95 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=aarch64 -mattr=+sve -run-pass=aarch64-expand-pseudo -verify-machineinstrs %s -o - | FileCheck %s
+
+# Test the expansion of constructive binary operations into their
+# destructive counterparts.
+
+
+# BIC_ZPmZ_B
+
+---
+name: test_bic_zpzz_unique_regs
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_bic_zpzz_unique_regs
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit killed $p0, implicit $z0, implicit killed $z1 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZPzZ_B $p0, $z0
+ ; CHECK-NEXT: $z2 = BIC_ZPmZ_B killed $p0, internal killed $z2, killed $z1
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = BIC_ZPZZ_B_ZERO killed $p0, killed $z0, killed $z1
+ RET_ReallyLR implicit killed $z2
+...
+
+---
+name: test_bic_zpzz_not_unique_regs
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_bic_zpzz_not_unique_regs
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit killed $p0, implicit $z0 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZPzZ_B $p0, $z0
+ ; CHECK-NEXT: $z2 = LSL_ZPmI_B killed $p0, internal $z2, 0
+ ; CHECK-NEXT: $z2 = BIC_ZPmZ_B killed $p0, internal killed $z2, internal killed $z2
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = BIC_ZPZZ_B_ZERO killed $p0, killed $z0, killed $z2
+ RET_ReallyLR implicit killed $z2
+...
+
+---
+name: test_bic_zpzz_implicit_ops
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_bic_zpzz_implicit_ops
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit killed $p0, implicit $z0, implicit killed $q0, implicit killed $q1, implicit killed $z1 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZPzZ_B $p0, $z0, implicit killed $q0, implicit killed $q1
+ ; CHECK-NEXT: $z2 = BIC_ZPmZ_B killed $p0, internal killed $z2, killed $z1, implicit-def $q2
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2, implicit killed $q2
+ $z2 = BIC_ZPZZ_B_ZERO killed $p0, killed $z0, killed $z1, implicit-def $q2, implicit killed $q0, implicit killed $q1
+ RET_ReallyLR implicit killed $z2, implicit killed $q2
+...
+
+---
+name: test_bic_zpzz_undef
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_bic_zpzz_undef
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit $p0, implicit undef $z0, implicit undef $z1 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZPzZ_B $p0, undef $z0
+ ; CHECK-NEXT: $z2 = BIC_ZPmZ_B undef $p0, internal killed $z2, undef $z1
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = BIC_ZPZZ_B_ZERO undef $p0, undef $z0, undef $z1
+ RET_ReallyLR implicit killed $z2
+...
+
+# ADD_ZPmZ_B
+
+---
+name: test_add_zpzz_unique_regs
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_add_zpzz_unique_regs
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit killed $p0, implicit $z0, implicit killed $z1 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZPzZ_B $p0, $z0
+ ; CHECK-NEXT: $z2 = ADD_ZPmZ_B killed $p0, internal killed $z2, killed $z1
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = ADD_ZPZZ_B_ZERO killed $p0, killed $z0, killed $z1
+ RET_ReallyLR implicit killed $z2
+...
+
+---
+name: test_add_zpzz_not_unique_regs
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_add_zpzz_not_unique_regs
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit killed $p0, implicit $z2, implicit killed $z0 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZPzZ_B $p0, $z2
+ ; CHECK-NEXT: $z2 = ADD_ZPmZ_B killed $p0, internal killed $z2, killed $z0
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = ADD_ZPZZ_B_ZERO killed $p0, killed $z0, killed $z2
+ RET_ReallyLR implicit killed $z2
+...
diff --git a/llvm/test/CodeGen/AArch64/expand-constructive-zzzi.mir b/llvm/test/CodeGen/AArch64/expand-constructive-zzzi.mir
new file mode 100644
index 0000000000000..70fa117a5b463
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/expand-constructive-zzzi.mir
@@ -0,0 +1,91 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=aarch64 -mattr=+sve -run-pass=aarch64-expand-pseudo -verify-machineinstrs %s -o - | FileCheck %s
+
+# Test the expansion of constructive ternary operations into their
+# destructive counterparts.
+
+
+# EXT_ZZZI
+
+---
+name: test_ext_zzzi_unique
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_ext_zzzi_unique
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit $z0, implicit killed $z1 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZZ $z0
+ ; CHECK-NEXT: $z2 = EXT_ZZI internal killed $z2, killed $z1, 1
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = EXT_ZZZI killed $z0, killed $z1, 1
+ RET_ReallyLR implicit killed $z2
+...
+
+# Here the destination register is the same as the second operand,
+# we cannot use movprfx.
+---
+name: test_ext_zzzi_not_unique
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_ext_zzzi_not_unique
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit $z0 {
+ ; CHECK-NEXT: $z2 = ORR_ZZZ $z0, $z0
+ ; CHECK-NEXT: $z2 = EXT_ZZI internal killed $z2, internal killed $z2, 1
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = EXT_ZZZI killed $z0, killed $z2, 1
+ RET_ReallyLR implicit killed $z2
+...
+
+---
+name: test_ext_zzzi_same_inputs
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_ext_zzzi_same_inputs
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit killed $z0 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZZ $z0
+ ; CHECK-NEXT: $z2 = EXT_ZZI internal killed $z2, killed $z0, 1
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = EXT_ZZZI killed $z0, killed $z0, 1
+ RET_ReallyLR implicit killed $z2
+...
+
+---
+name: test_ext_zzzi_already_destructive
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_ext_zzzi_already_destructive
+ ; CHECK: $z2 = EXT_ZZI killed $z2, killed $z1, 1
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = EXT_ZZZI killed $z2, killed $z1, 1
+ RET_ReallyLR implicit killed $z2
+...
+
+---
+name: test_ext_zzzi_unique_implicit_ops
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_ext_zzzi_unique_implicit_ops
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit $z0, implicit killed $q0, implicit killed $q1, implicit killed $z1 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZZ $z0, implicit killed $q0, implicit killed $q1
+ ; CHECK-NEXT: $z2 = EXT_ZZI internal killed $z2, killed $z1, 1, implicit-def $q2
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $q2
+ $z2 = EXT_ZZZI killed $z0, killed $z1, 1, implicit-def $q2, implicit killed $q0, implicit killed $q1
+ RET_ReallyLR implicit killed $q2
+...
+
+---
+name: test_ext_zzzi_undef
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: test_ext_zzzi_undef
+ ; CHECK: BUNDLE implicit-def $z2, implicit-def $q2, implicit-def $d2, implicit-def $s2, implicit-def $h2, implicit-def $b2, implicit-def $b2_hi, implicit-def $h2_hi, implicit-def $s2_hi, implicit-def $d2_hi, implicit-def $q2_hi, implicit undef $z0, implicit undef $z1 {
+ ; CHECK-NEXT: $z2 = MOVPRFX_ZZ undef $z0
+ ; CHECK-NEXT: $z2 = EXT_ZZI internal killed $z2, undef $z1, 1
+ ; CHECK-NEXT: }
+ ; CHECK-NEXT: RET undef $lr, implicit killed $z2
+ $z2 = EXT_ZZZI undef $z0, undef $z1, 1
+ RET_ReallyLR implicit killed $z2
+...
|
You can test this locally with the following command:git-clang-format --diff HEAD~1 HEAD --extensions cpp,h -- llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp llvm/lib/Target/AArch64/AArch64InstrInfo.hView the diff from clang-format here.diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index b903cd90c..c65f59cba 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -810,18 +810,18 @@ enum ElementSizeType {
};
enum DestructiveInstType {
- DestructiveInstTypeMask = TSFLAG_DESTRUCTIVE_INST_TYPE(0xf),
- NotDestructive = TSFLAG_DESTRUCTIVE_INST_TYPE(0x0),
- DestructiveOther = TSFLAG_DESTRUCTIVE_INST_TYPE(0x1),
- DestructiveUnary = TSFLAG_DESTRUCTIVE_INST_TYPE(0x2),
- DestructiveBinaryImm = TSFLAG_DESTRUCTIVE_INST_TYPE(0x3),
- DestructiveBinaryShImmUnpred = TSFLAG_DESTRUCTIVE_INST_TYPE(0x4),
- DestructiveBinary = TSFLAG_DESTRUCTIVE_INST_TYPE(0x5),
- DestructiveBinaryComm = TSFLAG_DESTRUCTIVE_INST_TYPE(0x6),
- DestructiveBinaryCommWithRev = TSFLAG_DESTRUCTIVE_INST_TYPE(0x7),
+ DestructiveInstTypeMask = TSFLAG_DESTRUCTIVE_INST_TYPE(0xf),
+ NotDestructive = TSFLAG_DESTRUCTIVE_INST_TYPE(0x0),
+ DestructiveOther = TSFLAG_DESTRUCTIVE_INST_TYPE(0x1),
+ DestructiveUnary = TSFLAG_DESTRUCTIVE_INST_TYPE(0x2),
+ DestructiveBinaryImm = TSFLAG_DESTRUCTIVE_INST_TYPE(0x3),
+ DestructiveBinaryShImmUnpred = TSFLAG_DESTRUCTIVE_INST_TYPE(0x4),
+ DestructiveBinary = TSFLAG_DESTRUCTIVE_INST_TYPE(0x5),
+ DestructiveBinaryComm = TSFLAG_DESTRUCTIVE_INST_TYPE(0x6),
+ DestructiveBinaryCommWithRev = TSFLAG_DESTRUCTIVE_INST_TYPE(0x7),
DestructiveTernaryCommWithRev = TSFLAG_DESTRUCTIVE_INST_TYPE(0x8),
- Destructive2xRegImmUnpred = TSFLAG_DESTRUCTIVE_INST_TYPE(0x9),
- DestructiveUnaryPassthru = TSFLAG_DESTRUCTIVE_INST_TYPE(0xa),
+ Destructive2xRegImmUnpred = TSFLAG_DESTRUCTIVE_INST_TYPE(0x9),
+ DestructiveUnaryPassthru = TSFLAG_DESTRUCTIVE_INST_TYPE(0xa),
};
enum FalseLaneType {
|
| # RUN: llc -mtriple=aarch64 -mattr=+sve -run-pass=aarch64-expand-pseudo -verify-machineinstrs %s -o - | FileCheck %s | ||
|
|
||
| # Test the expansion of constructive binary operations into their | ||
| # destructive counterparts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note these aren't new instructions, but there are no MIR test for those "constructive pseudos", only end-to-end .ll tests. So I thought I would add a couple test cases for existing instructions to show the current behaviour, especially around implicit operands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed that test file as it was unrelated.
I'll probably create an NFC PR later where I document all the different types of "destructive instructions" and add tests for them, because I have done that locally for my own understanding anyway.
SamTebbs33
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
1d4c1a8 to
1ccb570
Compare
It will get expanded into MOVPRFX_ZZ and EXT_ZZI by the AArch64ExpandPseudo pass. This instruction takes a single Z register as input, as opposed to the existing destructive EXT_ZZI instruction. Note this patch only defines the pseudo, it isn't used in any ISel pattern yet. It will later be used for vector.extract.
- More consistent .td - Clearer comment in AArch64ExpandPseudoInsts.cpp
7a7bbc3 to
3293d18
Compare
|
Rebased and updated CHECK lines |
It will get expanded into MOVPRFX_ZZ and EXT_ZZI by the AArch64ExpandPseudo pass. This instruction takes a single Z register as input, as opposed to the existing destructive EXT_ZZI instruction.
Note this patch only defines the pseudo, it isn't used in any ISel pattern yet. It will later be used for vector.extract.
This is a chained PR: #152552 - #152553 - #152554