[llvm] [GlobalISel] Combine into abd[su] and legalize abd[su] (PR #118865)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 5 13:59:05 PST 2024
Thorsten =?utf-8?q?Schütt?= <schuett at gmail.com>,
Thorsten =?utf-8?q?Schütt?= <schuett at gmail.com>,
Thorsten =?utf-8?q?Schütt?= <schuett at gmail.com>,
Thorsten =?utf-8?q?Schütt?= <schuett at gmail.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/118865 at github.com>
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Thorsten Schütt (tschuett)
<details>
<summary>Changes</summary>
PowerPC, AArch64, and ARM have instructions. The other targets lower them. We reverse those lowering as combines.
RISCV lowering:
// abds(lhs, rhs) -> sub(smax(lhs,rhs), smin(lhs,rhs))
// abdu(lhs, rhs) -> sub(umax(lhs,rhs), umin(lhs,rhs))
X86 lowering
// abds(lhs, rhs) -> select(slt(lhs,rhs),sub(rhs,lhs),sub(lhs,rhs))
// abdu(lhs, rhs) -> select(ult(lhs,rhs),sub(rhs,lhs),sub(lhs,rhs))
from SDAG:
// i.e trunc(abs(sext(Op0) - sext(Op1))) becomes abds(Op0, Op1)
// or trunc(abs(zext(Op0) - zext(Op1))) becomes abdu(Op0, Op1)
---
Patch is 49.57 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/118865.diff
11 Files Affected:
- (modified) llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h (+18)
- (modified) llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h (+29)
- (modified) llvm/include/llvm/Target/GlobalISel/Combine.td (+65-1)
- (modified) llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td (+2)
- (modified) llvm/lib/CodeGen/GlobalISel/CMakeLists.txt (+1)
- (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp (+46)
- (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp (+70)
- (added) llvm/lib/CodeGen/GlobalISel/CombinerHelperSelect.cpp (+73)
- (modified) llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp (+3)
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir (+7-6)
- (modified) llvm/test/CodeGen/AArch64/abd-combine.ll (+482-189)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 55c3b72c8e027f..ca8184b60bb6e3 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -942,6 +942,24 @@ class CombinerHelper {
// overflow sub
bool matchSuboCarryOut(const MachineInstr &MI, BuildFnTy &MatchInfo);
+ // trunc(abs(sext(x) - sext(y))) -> abds(x, y)
+ bool matchTruncAbds(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
+ // trunc(abs(zext(x) - zext(y))) -> abdu(x, y)
+ bool matchTruncAbdu(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
+ // select(slt(lhs,rhs),sub(rhs,lhs),sub(lhs,rhs)) -> abds(lhs, rhs)
+ bool matchSelectAbds(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
+ // select(ult(lhs,rhs),sub(rhs,lhs),sub(lhs,rhs)) -> abdu(lhs, rhs)
+ bool matchSelectAbdu(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
+ // sub(smax(lhs,rhs), smin(lhs,rhs)) -> abds(lhs, rhs)
+ bool matchSubAbds(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
+ // sub(umax(lhs,rhs), umin(lhs,rhs)) - abdu(lhs, rhs)
+ bool matchSubAbdu(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
private:
/// Checks for legality of an indexed variant of \p LdSt.
bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 9e5d4d34f24d2b..a99db10832c5a9 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -850,6 +850,16 @@ class GFreeze : public GenericMachineInstr {
}
};
+/// Represents an abs.
+class GAbs : public GenericMachineInstr {
+public:
+ Register getSourceReg() const { return getOperand(1).getReg(); }
+
+ static bool classof(const MachineInstr *MI) {
+ return MI->getOpcode() == TargetOpcode::G_ABS;
+ }
+};
+
/// Represents a cast operation.
/// It models the llvm::CastInst concept.
/// The exception is bitcast.
@@ -1022,6 +1032,25 @@ class GSplatVector : public GenericMachineInstr {
};
};
+/// Represents an integer max or min op.
+class GMMaxMinOp : public GenericMachineInstr {
+public:
+ Register getLHSReg() const { return getReg(1); }
+ Register getRHSReg() const { return getReg(2); }
+
+ static bool classof(const MachineInstr *MI) {
+ switch (MI->getOpcode()) {
+ case TargetOpcode::G_SMAX:
+ case TargetOpcode::G_SMIN:
+ case TargetOpcode::G_UMAX:
+ case TargetOpcode::G_UMIN:
+ return true;
+ default:
+ return false;
+ }
+ };
+};
+
} // namespace llvm
#endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index b0c63fc7c7b806..bd24bfb0587211 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1913,6 +1913,70 @@ def overflow_combines: GICombineGroup<[
match_subo_no_overflow
]>;
+def trunc_abds : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_SEXT $lhs, $x),
+ (G_SEXT $rhs, $y),
+ (G_SUB $sub, $lhs, $rhs),
+ (G_ABS $abs, $sub),
+ (G_TRUNC $root, $abs):$trunc,
+ [{ return Helper.matchTruncAbds(*${trunc}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${trunc}, ${matchinfo}); }])>;
+
+def trunc_abdu : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_ZEXT $lhs, $x),
+ (G_ZEXT $rhs, $y),
+ (G_SUB $sub, $lhs, $rhs),
+ (G_ABS $abs, $sub),
+ (G_TRUNC $root, $abs):$trunc,
+ [{ return Helper.matchTruncAbdu(*${trunc}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${trunc}, ${matchinfo}); }])>;
+
+def select_abds : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_SUB $lhs, $inputr, $inputl),
+ (G_SUB $rhs, $inputl, $inputr),
+ (G_ICMP $cond, $p, $inputl, $inputr),
+ (G_SELECT $root, $cond, $lhs, $rhs):$select,
+ [{ return ${p}.getPredicate() == CmpInst::ICMP_SLT && Helper.matchSelectAbds(*${select}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${select}, ${matchinfo}); }])>;
+
+def select_abdu : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_SUB $lhs, $inputr, $inputl),
+ (G_SUB $rhs, $inputl, $inputr),
+ (G_ICMP $cond, $p, $inputl, $inputr),
+ (G_SELECT $root, $cond, $lhs, $rhs):$select,
+ [{ return ${p}.getPredicate() == CmpInst::ICMP_ULT && Helper.matchSelectAbdu(*${select}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${select}, ${matchinfo}); }])>;
+
+def sub_abds : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_SMAX $smax, $inputl, $inputr),
+ (G_SMIN $smin, $inputl, $inputr),
+ (G_SUB $root, $smax, $smin):$sub,
+ [{ return Helper.matchSubAbds(*${sub}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${sub}, ${matchinfo}); }])>;
+
+def sub_abdu : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_UMAX $umax, $inputl, $inputr),
+ (G_UMIN $umin, $inputl, $inputr),
+ (G_SUB $root, $umax, $umin):$sub,
+ [{ return Helper.matchSubAbdu(*${sub}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${sub}, ${matchinfo}); }])>;
+
+def abd_su_combines: GICombineGroup<[
+ trunc_abds,
+ trunc_abdu,
+ select_abds,
+ select_abdu,
+ sub_abds,
+ sub_abdu
+]>;
+
+
// FIXME: These should use the custom predicate feature once it lands.
def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
undef_to_negative_one,
@@ -1979,7 +2043,7 @@ def shuffle_combines : GICombineGroup<[combine_shuffle_concat,
def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
vector_ops_combines, freeze_combines, cast_combines,
insert_vec_elt_combines, extract_vec_elt_combines, combines_for_extload,
- combine_extracted_vector_load,
+ combine_extracted_vector_load, abd_su_combines,
undef_combines, identity_combines, phi_combines,
simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands, shifts_too_big,
reassocs, ptr_add_immed_chain, cmp_combines,
diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index 2148f5be4c41aa..807d7195b811cb 100644
--- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
+++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -76,6 +76,8 @@ def : GINodeEquiv<G_XOR, xor>;
def : GINodeEquiv<G_SHL, shl>;
def : GINodeEquiv<G_LSHR, srl>;
def : GINodeEquiv<G_ASHR, sra>;
+def : GINodeEquiv<G_ABDS, abds>;
+def : GINodeEquiv<G_ABDU, abdu>;
def : GINodeEquiv<G_SADDSAT, saddsat>;
def : GINodeEquiv<G_UADDSAT, uaddsat>;
def : GINodeEquiv<G_SSUBSAT, ssubsat>;
diff --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt
index a45024d120be68..9d9aa7af1e3961 100644
--- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt
+++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt
@@ -9,6 +9,7 @@ add_llvm_component_library(LLVMGlobalISel
CombinerHelperArtifacts.cpp
CombinerHelperCasts.cpp
CombinerHelperCompares.cpp
+ CombinerHelperSelect.cpp
CombinerHelperVectorOps.cpp
GIMatchTableExecutor.cpp
GISelChangeObserver.cpp
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index d95fc8cfbcf558..79ce5e92d5dc38 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7865,3 +7865,49 @@ bool CombinerHelper::matchSuboCarryOut(const MachineInstr &MI,
return false;
}
+
+// sub(smax(lhs,rhs), smin(lhs,rhs)) -> abds(lhs, rhs)
+bool CombinerHelper::matchSubAbds(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ const GSub *Sub = cast<GSub>(&MI);
+ const GMMaxMinOp *LHS = cast<GMMaxMinOp>(MRI.getVRegDef(Sub->getLHSReg()));
+ const GMMaxMinOp *RHS = cast<GMMaxMinOp>(MRI.getVRegDef(Sub->getLHSReg()));
+
+ if (!MRI.hasOneNonDBGUse(LHS->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(RHS->getReg(0)))
+ return false;
+
+ Register Dst = Sub->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ABDS, {DstTy}}))
+ return false;
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildAbds(Dst, LHS->getLHSReg(), LHS->getRHSReg());
+ };
+ return true;
+}
+
+// sub(umax(lhs,rhs), umin(lhs,rhs)) -> abdu(lhs, rhs)
+bool CombinerHelper::matchSubAbdu(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ const GSub *Sub = cast<GSub>(&MI);
+ const GMMaxMinOp *LHS = cast<GMMaxMinOp>(MRI.getVRegDef(Sub->getLHSReg()));
+ const GMMaxMinOp *RHS = cast<GMMaxMinOp>(MRI.getVRegDef(Sub->getLHSReg()));
+
+ if (!MRI.hasOneNonDBGUse(LHS->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(RHS->getReg(0)))
+ return false;
+
+ Register Dst = Sub->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ABDU, {DstTy}}))
+ return false;
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildAbdu(Dst, LHS->getLHSReg(), LHS->getRHSReg());
+ };
+ return true;
+}
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp
index 30557e6a2304e6..16421ea088e9b5 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp
@@ -359,3 +359,73 @@ bool CombinerHelper::matchCastOfInteger(const MachineInstr &CastMI,
return false;
}
}
+
+// trunc(abs(sext(x) - sext(y))) -> abds(x, y)
+bool CombinerHelper::matchTruncAbds(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ const GTrunc *Trunc = cast<GTrunc>(&MI);
+ const GAbs *Abs = cast<GAbs>(MRI.getVRegDef(Trunc->getSrcReg()));
+ const GSub *Sub = cast<GSub>(MRI.getVRegDef(Abs->getSourceReg()));
+
+ Register Dst = Trunc->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ GSext *SextLHS = cast<GSext>(MRI.getVRegDef(Sub->getLHSReg()));
+ GSext *SextRHS = cast<GSext>(MRI.getVRegDef(Sub->getRHSReg()));
+
+ LLT SextLHSTy = MRI.getType(SextLHS->getSrcReg());
+ LLT SextRHSTy = MRI.getType(SextRHS->getSrcReg());
+
+ if (SextLHSTy != SextRHSTy || DstTy != SextLHSTy)
+ return false;
+
+ // one-use
+ if (!MRI.hasOneNonDBGUse(Abs->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(Sub->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(Sub->getLHSReg()) ||
+ !MRI.hasOneNonDBGUse(Sub->getRHSReg()))
+ return false;
+
+ if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ABDS, {DstTy}}))
+ return false;
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildAbds(Dst, SextLHS->getSrcReg(), SextLHS->getSrcReg());
+ };
+ return true;
+}
+
+// trunc(abs(zext(x) - zext(y))) -> abdu(x, y)
+bool CombinerHelper::matchTruncAbdu(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ const GTrunc *Trunc = cast<GTrunc>(&MI);
+ const GAbs *Abs = cast<GAbs>(MRI.getVRegDef(Trunc->getSrcReg()));
+ const GSub *Sub = cast<GSub>(MRI.getVRegDef(Abs->getSourceReg()));
+
+ Register Dst = Trunc->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ GZext *ZextLHS = cast<GZext>(MRI.getVRegDef(Sub->getLHSReg()));
+ GZext *ZextRHS = cast<GZext>(MRI.getVRegDef(Sub->getRHSReg()));
+
+ LLT ZextLHSTy = MRI.getType(ZextLHS->getSrcReg());
+ LLT ZextRHSTy = MRI.getType(ZextRHS->getSrcReg());
+
+ if (ZextLHSTy != ZextRHSTy || DstTy != ZextLHSTy)
+ return false;
+
+ // one-use
+ if (!MRI.hasOneNonDBGUse(Abs->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(Sub->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(Sub->getLHSReg()) ||
+ !MRI.hasOneNonDBGUse(Sub->getRHSReg()))
+ return false;
+
+ if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ABDU, {DstTy}}))
+ return false;
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildAbdu(Dst, ZextLHS->getSrcReg(), ZextLHS->getSrcReg());
+ };
+ return true;
+}
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelperSelect.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelperSelect.cpp
new file mode 100644
index 00000000000000..7ad7e8e1f45963
--- /dev/null
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelperSelect.cpp
@@ -0,0 +1,73 @@
+//===- CombinerHelperSelect.cpp--------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements CombinerHelper for G_SELECT.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
+#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
+#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
+#include "llvm/CodeGen/LowLevelTypeUtils.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/Support/Casting.h"
+
+#define DEBUG_TYPE "gi-combiner"
+
+using namespace llvm;
+
+// select(slt(lhs,rhs),sub(rhs,lhs),sub(lhs,rhs) -> abds(lhs, rhs)
+bool CombinerHelper::matchSelectAbds(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ const GSelect *Select = cast<GSelect>(&MI);
+ GSub *LHS = cast<GSub>(MRI.getVRegDef(Select->getTrueReg()));
+ GSub *RHS = cast<GSub>(MRI.getVRegDef(Select->getFalseReg()));
+
+ if (!MRI.hasOneNonDBGUse(Select->getCondReg()) ||
+ !MRI.hasOneNonDBGUse(LHS->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(RHS->getReg(0)))
+ return false;
+
+ Register Dst = Select->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ABDS, {DstTy}}))
+ return false;
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildAbds(Dst, RHS->getLHSReg(), RHS->getRHSReg());
+ };
+ return true;
+}
+
+// select(ult(lhs,rhs),sub(rhs,lhs),sub(lhs,rhs)) -> abdu(lhs, rhs)
+bool CombinerHelper::matchSelectAbdu(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ const GSelect *Select = cast<GSelect>(&MI);
+ GSub *LHS = cast<GSub>(MRI.getVRegDef(Select->getTrueReg()));
+ GSub *RHS = cast<GSub>(MRI.getVRegDef(Select->getFalseReg()));
+
+ if (!MRI.hasOneNonDBGUse(Select->getCondReg()) ||
+ !MRI.hasOneNonDBGUse(LHS->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(RHS->getReg(0)))
+ return false;
+
+ Register Dst = Select->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ABDU, {DstTy}}))
+ return false;
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildAbdu(Dst, RHS->getLHSReg(), RHS->getRHSReg());
+ };
+ return true;
+}
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 619a041c273cd8..7c980692f217b1 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -1344,6 +1344,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
getActionDefinitionsBuilder(G_SPLAT_VECTOR)
.legalFor(HasSVE, {{nxv4s32, s32}, {nxv2s64, s64}});
+ getActionDefinitionsBuilder({G_ABDS, G_ABDU})
+ .legalFor({{v8s8}, {v4s16}, {v2s32}, {v16s8}, {v8s16}, {v4s32}});
+
getLegacyLegalizerInfo().computeTables();
verify(*ST.getInstrInfo());
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 7c9c958b5a8189..da6c51a0be90a5 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -70,13 +70,14 @@
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
#
-# DEBUG-NEXT: G_ABDS (opcode 65): 1 type index, 0 imm indices
-# DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: G_ABDS (opcode {{[0-9]+}}): 1 type index, 0 imm indices
+# DEBUG-NEXT: .. the first uncovered type index: 1, OK
+# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
#
-# DEBUG-NEXT:G_ABDU (opcode 66): 1 type index, 0 imm indices
-# DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: G_ABDU (opcode {{[0-9]+}}): 1 type index, 0 imm indices
+# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
+# DEBUG-NEXT: .. the first uncovered type index: 1, OK
+# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
#
# DEBUG-NEXT: G_IMPLICIT_DEF (opcode {{[0-9]+}}): 1 type index, 0 imm indices
# DEBUG-NEXT: .. the first uncovered type index: {{[0-9]+}}, OK
diff --git a/llvm/test/CodeGen/AArch64/abd-combine.ll b/llvm/test/CodeGen/AArch64/abd-combine.ll
index e48680f4be98b6..9cf0f5273dd81f 100644
--- a/llvm/test/CodeGen/AArch64/abd-combine.ll
+++ b/llvm/test/CodeGen/AArch64/abd-combine.ll
@@ -1,11 +1,19 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=aarch64 | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+
+; CHECK-GI: warning: Instruction selection used fallback path for recursive
define <8 x i16> @abdu_base(<8 x i16> %src1, <8 x i16> %src2) {
-; CHECK-LABEL: abdu_base:
-; CHECK: // %bb.0:
-; CHECK-NEXT: uabd v0.8h, v0.8h, v1.8h
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: abdu_base:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: uabd v0.8h, v0.8h, v1.8h
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: abdu_base:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: uabd v0.8h, v0.8h, v0.8h
+; CHECK-GI-NEXT: ret
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
%zextsrc2 = zext <8 x i16> %src2 to <8 x i32>
%sub = sub <8 x i32> %zextsrc1, %zextsrc2
@@ -15,17 +23,29 @@ define <8 x i16> @abdu_base(<8 x i16> %src1, <8 x i16> %src2) {
}
define <8 x i16> @abdu_const(<8 x i16> %src1) {
-; CHECK-LABEL: abdu_const:
-; CHECK: // %bb.0:
-; CHECK-NEXT: movi v1.4s, #1
-; CHECK-NEXT: ushll2 v2.4s, v0.8h, #0
-; CHECK-NEXT: ushll v0.4s, v0.4h, #0
-; CHECK-NEXT: sub v0.4s, v0.4s, v1.4s
-; CHECK-NEXT: sub v1.4s, v2.4s, v1.4s
-; CHECK-NEXT: abs v1.4s, v1.4s
-; CHECK-NEXT: abs v0.4s, v0.4s
-; CHECK-NEXT: uzp1 v0.8h, v0.8h, v1.8h
-; CHECK-NEXT: ret
+; CHECK-SD-LABEL: abdu_const:
+; CHECK-SD: // %bb.0:
+; CHECK-SD-NEXT: movi v1.4s, #1
+; CHECK-SD-NEXT: ushll2 v2.4s, v0.8h, #0
+; CHECK-SD-NEXT: ushll v0.4s, v0.4h, #0
+; CHECK-SD-NEXT: sub v0.4s, v0.4s, v1.4s
+; CHECK-SD-NEXT: sub v1.4s, v2.4s, v1.4s
+; CHECK-SD-NEXT: abs v1.4s, v1.4s
+; CHECK-SD-NEXT: abs v0.4s, v0.4s
+; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: abdu_const:
+; CHECK-GI: // %bb.0:
+; CHECK-GI-NEXT: movi v1.4s, #1
+; CHECK-GI-NEXT: ushll v2.4s, v0.4h, #0
+; CHECK-GI-NEXT: ushll2 v0.4s, v0.8h, #0
+; CHECK-GI-NEXT: sub v2.4s, v2.4s, v1.4s
+; CHECK-GI-NEXT: sub v0.4s, v0.4s, v1.4s
+; CHECK-GI-NEXT: abs v1.4s, v2.4s
+; CHECK-GI-NEXT: abs v0.4s, v0.4s
+; CHECK-GI-NEXT: uzp1 v0.8h, v1.8h, v0.8h
+; CHECK-GI-NEXT: ret
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
%sub = sub <8 x i32> %zextsrc1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
%abs = call <8 x i32> @llvm.abs.v8i32(<8 x i32> %sub, i1 0)
@@ -34,15 +54,25 @@ define <8 x i16> @abdu_const(<8 x i16> %src1) {
}
define <8 x i16> @abdu_const_lhs(<8 x i16> %src1) {
-...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/118865
More information about the llvm-commits
mailing list