From 2baded3e3380be64fa1e17d0cd289fec331154d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= Date: Sun, 21 Jul 2024 19:32:33 +0200 Subject: [PATCH] [GlobalIsel][AArch64] Select G_SCMP and G_UCMP https://github.com/llvm/llvm-project/pull/91871 https://github.com/llvm/llvm-project/pull/98774 --- .../CodeGen/GlobalISel/GenericMachineInstrs.h | 19 +++ .../llvm/CodeGen/GlobalISel/LegalizerHelper.h | 1 + .../CodeGen/GlobalISel/LegalizerHelper.cpp | 33 +++++ .../AArch64/GISel/AArch64LegalizerInfo.cpp | 2 + .../GlobalISel/legalize-threeway-cmp.mir | 109 +++++++++++++++ llvm/test/CodeGen/AArch64/scmp.ll | 86 ++++++++---- llvm/test/CodeGen/AArch64/ucmp.ll | 132 +++++++++++++----- 7 files changed, 322 insertions(+), 60 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/legalize-threeway-cmp.mir diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h index d9f6f6540bdc8a..80897953156a0a 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h @@ -900,6 +900,25 @@ class GShl : public GenericMachineInstr { }; }; +/// Represents a threeway compare. +class GSUCmp : public GenericMachineInstr { +public: + Register getLHSReg() const { return getOperand(1).getReg(); } + Register getRHSReg() const { return getOperand(2).getReg(); } + + bool isSigned() const { return getOpcode() == TargetOpcode::G_SCMP; } + + static bool classof(const MachineInstr *MI) { + switch (MI->getOpcode()) { + case TargetOpcode::G_SCMP: + case TargetOpcode::G_UCMP: + return true; + default: + return false; + } + }; +}; + } // namespace llvm #endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index b17bc9aa2a44e5..cf1ca1dc34024b 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -402,6 +402,7 @@ class LegalizerHelper { LegalizeResult lowerISFPCLASS(MachineInstr &MI); + LegalizeResult lowerThreewayCompare(MachineInstr &MI); LegalizeResult lowerMinMax(MachineInstr &MI); LegalizeResult lowerFCopySign(MachineInstr &MI); LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI); diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 640a425ffa7357..9ed363f0e1551f 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -4006,6 +4006,9 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) { case G_UMIN: case G_UMAX: return lowerMinMax(MI); + case G_SCMP: + case G_UCMP: + return lowerThreewayCompare(MI); case G_FCOPYSIGN: return lowerFCopySign(MI); case G_FMINNUM: @@ -7269,6 +7272,36 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerMinMax(MachineInstr &MI) { return Legalized; } +LegalizerHelper::LegalizeResult +LegalizerHelper::lowerThreewayCompare(MachineInstr &MI) { + GSUCmp *Cmp = cast(&MI); + + Register Dst = Cmp->getReg(0); + LLT DstTy = MRI.getType(Dst); + LLT CmpTy = DstTy.changeElementSize(1); + + CmpInst::Predicate LTPredicate = Cmp->isSigned() + ? CmpInst::Predicate::ICMP_SLT + : CmpInst::Predicate::ICMP_ULT; + CmpInst::Predicate GTPredicate = Cmp->isSigned() + ? CmpInst::Predicate::ICMP_SGT + : CmpInst::Predicate::ICMP_UGT; + + auto One = MIRBuilder.buildConstant(DstTy, 1); + auto Zero = MIRBuilder.buildConstant(DstTy, 0); + auto MinusOne = MIRBuilder.buildConstant(DstTy, -1); + + auto IsLT = MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(), + Cmp->getRHSReg()); + auto IsGT = MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(), + Cmp->getRHSReg()); + auto SelectZeroOrOne = MIRBuilder.buildSelect(DstTy, IsGT, One, Zero); + MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne); + + MI.eraseFromParent(); + return Legalized; +} + LegalizerHelper::LegalizeResult LegalizerHelper::lowerFCopySign(MachineInstr &MI) { auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] = MI.getFirst3RegLLTs(); diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp index 3f8641945bcd7d..c1c51660ecf1c4 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -1288,6 +1288,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) getActionDefinitionsBuilder(G_PREFETCH).custom(); + getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower(); + getLegacyLegalizerInfo().computeTables(); verify(*ST.getInstrInfo()); } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-threeway-cmp.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-threeway-cmp.mir new file mode 100644 index 00000000000000..3a7b8067a2ba91 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-threeway-cmp.mir @@ -0,0 +1,109 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=aarch64 -run-pass=legalizer -global-isel-abort=1 -verify-machineinstrs %s -o - | FileCheck %s +--- +name: test_scmp +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_scmp + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY]](s64), [[COPY1]] + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(sgt), [[COPY]](s64), [[COPY1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP1]](s32), [[C]], [[C1]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[SELECT1:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s32), [[C2]], [[SELECT]] + ; CHECK-NEXT: $w0 = COPY [[SELECT1]](s32) + %0:_(s64) = COPY $x0 + %1:_(s64) = COPY $x0 + %4:_(s2) = G_SCMP %0(s64), %1 + %14:_(s32) = G_ANYEXT %4(s2) + $w0 = COPY %14(s32) + +... +--- +name: test_ucmp +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_ucmp + ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY]](s64), [[COPY1]] + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ugt), [[COPY]](s64), [[COPY1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP1]](s32), [[C]], [[C1]] + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[SELECT1:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s32), [[C2]], [[SELECT]] + ; CHECK-NEXT: $w0 = COPY [[SELECT1]](s32) + %0:_(s64) = COPY $x0 + %1:_(s64) = COPY $x0 + %4:_(s2) = G_UCMP %0(s64), %1 + %14:_(s32) = G_ANYEXT %4(s2) + $w0 = COPY %14(s32) + +... +--- +name: test_ucmp_vector +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_ucmp_vector + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2 + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32) + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY $w2 + ; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY $w3 + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s8) = G_CONSTANT i8 0 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 3 + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<4 x s32>) = G_ICMP intpred(ult), [[BUILD_VECTOR]](<4 x s32>), [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(<4 x s32>) = G_ICMP intpred(ugt), [[BUILD_VECTOR]](<4 x s32>), [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[ICMP1]](<4 x s32>) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR2]](<8 x s8>) + ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<4 x s16>), [[UV1:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT]](<8 x s16>) + ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(<4 x s16>) = G_XOR [[TRUNC]], [[UV]] + ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8) + ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR3]](<8 x s8>) + ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(<4 x s16>), [[UV3:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT1]](<8 x s16>) + ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[ICMP1]](<4 x s32>) + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(<4 x s16>) = G_AND [[UV2]], [[TRUNC1]] + ; CHECK-NEXT: [[BUILD_VECTOR4:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8) + ; CHECK-NEXT: [[ANYEXT2:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR4]](<8 x s8>) + ; CHECK-NEXT: [[UV4:%[0-9]+]]:_(<4 x s16>), [[UV5:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT2]](<8 x s16>) + ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(<4 x s16>) = G_AND [[UV4]], [[XOR]] + ; CHECK-NEXT: [[OR:%[0-9]+]]:_(<4 x s16>) = G_OR [[AND]], [[AND1]] + ; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[ICMP]](<4 x s32>) + ; CHECK-NEXT: [[BUILD_VECTOR5:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8) + ; CHECK-NEXT: [[ANYEXT3:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR5]](<8 x s8>) + ; CHECK-NEXT: [[UV6:%[0-9]+]]:_(<4 x s16>), [[UV7:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT3]](<8 x s16>) + ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(<4 x s16>) = G_XOR [[TRUNC2]], [[UV6]] + ; CHECK-NEXT: [[BUILD_VECTOR6:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8) + ; CHECK-NEXT: [[ANYEXT4:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR6]](<8 x s8>) + ; CHECK-NEXT: [[UV8:%[0-9]+]]:_(<4 x s16>), [[UV9:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT4]](<8 x s16>) + ; CHECK-NEXT: [[TRUNC3:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[ICMP]](<4 x s32>) + ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(<4 x s16>) = G_AND [[UV8]], [[TRUNC3]] + ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(<4 x s16>) = G_AND [[OR]], [[XOR1]] + ; CHECK-NEXT: [[OR1:%[0-9]+]]:_(<4 x s16>) = G_OR [[AND2]], [[AND3]] + ; CHECK-NEXT: [[ANYEXT5:%[0-9]+]]:_(<4 x s32>) = G_ANYEXT [[OR1]](<4 x s16>) + ; CHECK-NEXT: $q0 = COPY [[ANYEXT5]](<4 x s32>) + %0:_(s32) = COPY $w0 + %1:_(s32) = COPY $w1 + %2:_(s32) = COPY $w2 + %3:_(s32) = COPY $w3 + %4:_(<4 x s32>) = G_BUILD_VECTOR %0(s32), %1(s32), %2(s32), %3(s32) + %5:_(s32) = COPY $w0 + %6:_(s32) = COPY $w1 + %7:_(s32) = COPY $w2 + %8:_(s32) = COPY $w3 + %9:_(<4 x s32>) = G_BUILD_VECTOR %0(s32), %1(s32), %2(s32), %3(s32) + %10:_(<4 x s2>) = G_UCMP %4(<4 x s32>), %9 + %11:_(<4 x s32>) = G_ANYEXT %10(<4 x s2>) + $q0 = COPY %11(<4 x s32>) diff --git a/llvm/test/CodeGen/AArch64/scmp.ll b/llvm/test/CodeGen/AArch64/scmp.ll index a7abc5eadaff66..3137337e5e59f3 100644 --- a/llvm/test/CodeGen/AArch64/scmp.ll +++ b/llvm/test/CodeGen/AArch64/scmp.ll @@ -1,26 +1,45 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs < %s | FileCheck %s +; 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 define i8 @scmp.8.8(i8 %x, i8 %y) nounwind { -; CHECK-LABEL: scmp.8.8: -; CHECK: // %bb.0: -; CHECK-NEXT: sxtb w8, w0 -; CHECK-NEXT: cmp w8, w1, sxtb -; CHECK-NEXT: cset w8, gt -; CHECK-NEXT: csinv w0, w8, wzr, ge -; CHECK-NEXT: ret +; CHECK-SD-LABEL: scmp.8.8: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: sxtb w8, w0 +; CHECK-SD-NEXT: cmp w8, w1, sxtb +; CHECK-SD-NEXT: cset w8, gt +; CHECK-SD-NEXT: csinv w0, w8, wzr, ge +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: scmp.8.8: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: sxtb w8, w0 +; CHECK-GI-NEXT: sxtb w9, w1 +; CHECK-GI-NEXT: cmp w8, w9 +; CHECK-GI-NEXT: cset w8, gt +; CHECK-GI-NEXT: csinv w0, w8, wzr, ge +; CHECK-GI-NEXT: ret %1 = call i8 @llvm.scmp(i8 %x, i8 %y) ret i8 %1 } define i8 @scmp.8.16(i16 %x, i16 %y) nounwind { -; CHECK-LABEL: scmp.8.16: -; CHECK: // %bb.0: -; CHECK-NEXT: sxth w8, w0 -; CHECK-NEXT: cmp w8, w1, sxth -; CHECK-NEXT: cset w8, gt -; CHECK-NEXT: csinv w0, w8, wzr, ge -; CHECK-NEXT: ret +; CHECK-SD-LABEL: scmp.8.16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: sxth w8, w0 +; CHECK-SD-NEXT: cmp w8, w1, sxth +; CHECK-SD-NEXT: cset w8, gt +; CHECK-SD-NEXT: csinv w0, w8, wzr, ge +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: scmp.8.16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: sxth w8, w0 +; CHECK-GI-NEXT: sxth w9, w1 +; CHECK-GI-NEXT: cmp w8, w9 +; CHECK-GI-NEXT: cset w8, gt +; CHECK-GI-NEXT: csinv w0, w8, wzr, ge +; CHECK-GI-NEXT: ret %1 = call i8 @llvm.scmp(i16 %x, i16 %y) ret i8 %1 } @@ -48,15 +67,34 @@ define i8 @scmp.8.64(i64 %x, i64 %y) nounwind { } define i8 @scmp.8.128(i128 %x, i128 %y) nounwind { -; CHECK-LABEL: scmp.8.128: -; CHECK: // %bb.0: -; CHECK-NEXT: cmp x2, x0 -; CHECK-NEXT: sbcs xzr, x3, x1 -; CHECK-NEXT: cset w8, lt -; CHECK-NEXT: cmp x0, x2 -; CHECK-NEXT: sbcs xzr, x1, x3 -; CHECK-NEXT: csinv w0, w8, wzr, ge -; CHECK-NEXT: ret +; CHECK-SD-LABEL: scmp.8.128: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmp x2, x0 +; CHECK-SD-NEXT: sbcs xzr, x3, x1 +; CHECK-SD-NEXT: cset w8, lt +; CHECK-SD-NEXT: cmp x0, x2 +; CHECK-SD-NEXT: sbcs xzr, x1, x3 +; CHECK-SD-NEXT: csinv w0, w8, wzr, ge +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: scmp.8.128: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: cmp x1, x3 +; CHECK-GI-NEXT: cset w8, lt +; CHECK-GI-NEXT: cmp x0, x2 +; CHECK-GI-NEXT: cset w9, lo +; CHECK-GI-NEXT: cmp x1, x3 +; CHECK-GI-NEXT: csel w8, w9, w8, eq +; CHECK-GI-NEXT: cset w9, gt +; CHECK-GI-NEXT: cmp x0, x2 +; CHECK-GI-NEXT: cset w10, hi +; CHECK-GI-NEXT: cmp x1, x3 +; CHECK-GI-NEXT: csel w9, w10, w9, eq +; CHECK-GI-NEXT: tst w9, #0x1 +; CHECK-GI-NEXT: cset w9, ne +; CHECK-GI-NEXT: tst w8, #0x1 +; CHECK-GI-NEXT: csinv w0, w9, wzr, eq +; CHECK-GI-NEXT: ret %1 = call i8 @llvm.scmp(i128 %x, i128 %y) ret i8 %1 } diff --git a/llvm/test/CodeGen/AArch64/ucmp.ll b/llvm/test/CodeGen/AArch64/ucmp.ll index 351d440243b70d..ee5e4c497a5ff5 100644 --- a/llvm/test/CodeGen/AArch64/ucmp.ll +++ b/llvm/test/CodeGen/AArch64/ucmp.ll @@ -1,26 +1,45 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs < %s | FileCheck %s +; 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 define i8 @ucmp.8.8(i8 %x, i8 %y) nounwind { -; CHECK-LABEL: ucmp.8.8: -; CHECK: // %bb.0: -; CHECK-NEXT: and w8, w0, #0xff -; CHECK-NEXT: cmp w8, w1, uxtb -; CHECK-NEXT: cset w8, hi -; CHECK-NEXT: csinv w0, w8, wzr, hs -; CHECK-NEXT: ret +; CHECK-SD-LABEL: ucmp.8.8: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: and w8, w0, #0xff +; CHECK-SD-NEXT: cmp w8, w1, uxtb +; CHECK-SD-NEXT: cset w8, hi +; CHECK-SD-NEXT: csinv w0, w8, wzr, hs +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: ucmp.8.8: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: and w8, w0, #0xff +; CHECK-GI-NEXT: and w9, w1, #0xff +; CHECK-GI-NEXT: cmp w8, w9 +; CHECK-GI-NEXT: cset w8, hi +; CHECK-GI-NEXT: csinv w0, w8, wzr, hs +; CHECK-GI-NEXT: ret %1 = call i8 @llvm.ucmp(i8 %x, i8 %y) ret i8 %1 } define i8 @ucmp.8.16(i16 %x, i16 %y) nounwind { -; CHECK-LABEL: ucmp.8.16: -; CHECK: // %bb.0: -; CHECK-NEXT: and w8, w0, #0xffff -; CHECK-NEXT: cmp w8, w1, uxth -; CHECK-NEXT: cset w8, hi -; CHECK-NEXT: csinv w0, w8, wzr, hs -; CHECK-NEXT: ret +; CHECK-SD-LABEL: ucmp.8.16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: and w8, w0, #0xffff +; CHECK-SD-NEXT: cmp w8, w1, uxth +; CHECK-SD-NEXT: cset w8, hi +; CHECK-SD-NEXT: csinv w0, w8, wzr, hs +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: ucmp.8.16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: and w8, w0, #0xffff +; CHECK-GI-NEXT: and w9, w1, #0xffff +; CHECK-GI-NEXT: cmp w8, w9 +; CHECK-GI-NEXT: cset w8, hi +; CHECK-GI-NEXT: csinv w0, w8, wzr, hs +; CHECK-GI-NEXT: ret %1 = call i8 @llvm.ucmp(i16 %x, i16 %y) ret i8 %1 } @@ -48,15 +67,34 @@ define i8 @ucmp.8.64(i64 %x, i64 %y) nounwind { } define i8 @ucmp.8.128(i128 %x, i128 %y) nounwind { -; CHECK-LABEL: ucmp.8.128: -; CHECK: // %bb.0: -; CHECK-NEXT: cmp x2, x0 -; CHECK-NEXT: sbcs xzr, x3, x1 -; CHECK-NEXT: cset w8, lo -; CHECK-NEXT: cmp x0, x2 -; CHECK-NEXT: sbcs xzr, x1, x3 -; CHECK-NEXT: csinv w0, w8, wzr, hs -; CHECK-NEXT: ret +; CHECK-SD-LABEL: ucmp.8.128: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: cmp x2, x0 +; CHECK-SD-NEXT: sbcs xzr, x3, x1 +; CHECK-SD-NEXT: cset w8, lo +; CHECK-SD-NEXT: cmp x0, x2 +; CHECK-SD-NEXT: sbcs xzr, x1, x3 +; CHECK-SD-NEXT: csinv w0, w8, wzr, hs +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: ucmp.8.128: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: cmp x1, x3 +; CHECK-GI-NEXT: cset w8, lo +; CHECK-GI-NEXT: cmp x0, x2 +; CHECK-GI-NEXT: cset w9, lo +; CHECK-GI-NEXT: cmp x1, x3 +; CHECK-GI-NEXT: csel w8, w9, w8, eq +; CHECK-GI-NEXT: cset w9, hi +; CHECK-GI-NEXT: cmp x0, x2 +; CHECK-GI-NEXT: cset w10, hi +; CHECK-GI-NEXT: cmp x1, x3 +; CHECK-GI-NEXT: csel w9, w10, w9, eq +; CHECK-GI-NEXT: tst w9, #0x1 +; CHECK-GI-NEXT: cset w9, ne +; CHECK-GI-NEXT: tst w8, #0x1 +; CHECK-GI-NEXT: csinv w0, w9, wzr, eq +; CHECK-GI-NEXT: ret %1 = call i8 @llvm.ucmp(i128 %x, i128 %y) ret i8 %1 } @@ -95,18 +133,40 @@ define i64 @ucmp.64.64(i64 %x, i64 %y) nounwind { } define <1 x i64> @ucmp.1.64.65(<1 x i65> %x, <1 x i65> %y) { -; CHECK-LABEL: ucmp.1.64.65: -; CHECK: // %bb.0: -; CHECK-NEXT: and x8, x1, #0x1 -; CHECK-NEXT: and x9, x3, #0x1 -; CHECK-NEXT: cmp x2, x0 -; CHECK-NEXT: sbcs xzr, x9, x8 -; CHECK-NEXT: cset x10, lo -; CHECK-NEXT: cmp x0, x2 -; CHECK-NEXT: sbcs xzr, x8, x9 -; CHECK-NEXT: csinv x8, x10, xzr, hs -; CHECK-NEXT: fmov d0, x8 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: ucmp.1.64.65: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: and x8, x1, #0x1 +; CHECK-SD-NEXT: and x9, x3, #0x1 +; CHECK-SD-NEXT: cmp x2, x0 +; CHECK-SD-NEXT: sbcs xzr, x9, x8 +; CHECK-SD-NEXT: cset x10, lo +; CHECK-SD-NEXT: cmp x0, x2 +; CHECK-SD-NEXT: sbcs xzr, x8, x9 +; CHECK-SD-NEXT: csinv x8, x10, xzr, hs +; CHECK-SD-NEXT: fmov d0, x8 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: ucmp.1.64.65: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: and x8, x1, #0x1 +; CHECK-GI-NEXT: and x9, x3, #0x1 +; CHECK-GI-NEXT: cmp x8, x9 +; CHECK-GI-NEXT: cset w10, lo +; CHECK-GI-NEXT: cmp x0, x2 +; CHECK-GI-NEXT: cset w11, lo +; CHECK-GI-NEXT: cmp x8, x9 +; CHECK-GI-NEXT: csel w10, w11, w10, eq +; CHECK-GI-NEXT: cset w11, hi +; CHECK-GI-NEXT: cmp x0, x2 +; CHECK-GI-NEXT: cset w12, hi +; CHECK-GI-NEXT: cmp x8, x9 +; CHECK-GI-NEXT: csel w8, w12, w11, eq +; CHECK-GI-NEXT: tst w8, #0x1 +; CHECK-GI-NEXT: cset x8, ne +; CHECK-GI-NEXT: tst w10, #0x1 +; CHECK-GI-NEXT: csinv x8, x8, xzr, eq +; CHECK-GI-NEXT: fmov d0, x8 +; CHECK-GI-NEXT: ret %1 = call <1 x i64> @llvm.ucmp(<1 x i65> %x, <1 x i65> %y) ret <1 x i64> %1 }