Skip to content

Commit 9f929ff

Browse files
author
Thorsten Schütt
committed
[GlobalISel] Add G_ABDS and G_ABDU instructions
Fixes #118085 The DAG has the same instructions: the signed and unsigned absulute difference of it's input. For AArch64, they map to uabd and sabd for Neon and SVE. The SVE instructions will require custom patterns. /// i.e trunc(abs(sext(Op0) - sext(Op1))) becomes abds(Op0, Op1) /// or trunc(abs(zext(Op0) - zext(Op1))) becomes abdu(Op0, Op1) For GlobalISel, we are going to write the combines in MIR patterns. see: llvm/test/CodeGen/AArch64/abd-combine.ll
1 parent fe04290 commit 9f929ff

File tree

8 files changed

+141
-0
lines changed

8 files changed

+141
-0
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,13 @@ undefined.
474474
%2:_(s33) = G_CTLZ_ZERO_UNDEF %1
475475
%2:_(s33) = G_CTTZ_ZERO_UNDEF %1
476476
477+
Compute the absolute difference (signed and unsigned), e.g. abs(x-y).
478+
479+
.. code-block:: none
480+
481+
%0:_(s33) = G_ABDS %2, %3
482+
%1:_(s33) = G_ABDU %4, %5
483+
477484
Floating Point Operations
478485
-------------------------
479486

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,6 +1767,34 @@ class MachineIRBuilder {
17671767
return buildInstr(TargetOpcode::G_MUL, {Dst}, {Src0, Src1}, Flags);
17681768
}
17691769

1770+
/// Build and insert \p Res = G_ABDS \p Op0, \p Op1
1771+
///
1772+
/// G_ABDS return the signed absolute difference of \p Op0 and \p Op1.
1773+
///
1774+
/// \pre setBasicBlock or setMI must have been called.
1775+
/// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
1776+
/// with the same (scalar or vector) type).
1777+
///
1778+
/// \return a MachineInstrBuilder for the newly created instruction.
1779+
MachineInstrBuilder buildAbds(const DstOp &Dst, const SrcOp &Src0,
1780+
const SrcOp &Src1) {
1781+
return buildInstr(TargetOpcode::G_ABDS, {Dst}, {Src0, Src1});
1782+
}
1783+
1784+
/// Build and insert \p Res = G_ABDU \p Op0, \p Op1
1785+
///
1786+
/// G_ABDS return the unsigned absolute difference of \p Op0 and \p Op1.
1787+
///
1788+
/// \pre setBasicBlock or setMI must have been called.
1789+
/// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
1790+
/// with the same (scalar or vector) type).
1791+
///
1792+
/// \return a MachineInstrBuilder for the newly created instruction.
1793+
MachineInstrBuilder buildAbdu(const DstOp &Dst, const SrcOp &Src0,
1794+
const SrcOp &Src1) {
1795+
return buildInstr(TargetOpcode::G_ABDU, {Dst}, {Src0, Src1});
1796+
}
1797+
17701798
MachineInstrBuilder buildUMulH(const DstOp &Dst, const SrcOp &Src0,
17711799
const SrcOp &Src1,
17721800
std::optional<unsigned> Flags = std::nullopt) {

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ HANDLE_TARGET_OPCODE(G_OR)
289289
/// Generic bitwise exclusive-or instruction.
290290
HANDLE_TARGET_OPCODE(G_XOR)
291291

292+
/// Generic absolute difference signed instruction.
293+
HANDLE_TARGET_OPCODE(G_ABDS)
294+
295+
/// Generic absolute difference unsigned instruction.
296+
HANDLE_TARGET_OPCODE(G_ABDU)
297+
292298

293299
HANDLE_TARGET_OPCODE(G_IMPLICIT_DEF)
294300

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,20 @@ def G_ASHR : GenericInstruction {
386386
let hasSideEffects = false;
387387
}
388388

389+
// Generic absolute difference signed.
390+
def G_ABDS : GenericInstruction {
391+
let OutOperandList = (outs type0:$dst);
392+
let InOperandList = (ins type0:$src1, type0:$src2);
393+
let hasSideEffects = false;
394+
}
395+
396+
// Generic absolute difference unsigned.
397+
def G_ABDU : GenericInstruction {
398+
let OutOperandList = (outs type0:$dst);
399+
let InOperandList = (ins type0:$src1, type0:$src2);
400+
let hasSideEffects = false;
401+
}
402+
389403
/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
390404
/// fshl(X,Y,Z): (X << (Z % bitwidth)) | (Y >> (bitwidth - (Z % bitwidth)))
391405
def G_FSHL : GenericInstruction {

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,41 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
15851585

15861586
break;
15871587
}
1588+
case TargetOpcode::G_ABDS:
1589+
case TargetOpcode::G_ABDU: {
1590+
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
1591+
LLT SrcTy = MRI->getType(MI->getOperand(1).getReg());
1592+
LLT SrcTy2 = MRI->getType(MI->getOperand(2).getReg());
1593+
1594+
if (SrcTy.isPointerOrPointerVector() || SrcTy2.isPointerOrPointerVector()) {
1595+
report("Generic abds/abdu does not support pointers as operands", MI);
1596+
break;
1597+
}
1598+
1599+
if (DstTy.isPointerOrPointerVector()) {
1600+
report("Generic abds/abdu does not support pointers as a result", MI);
1601+
break;
1602+
}
1603+
1604+
if ((DstTy.isVector() != SrcTy.isVector()) ||
1605+
(DstTy.isVector() &&
1606+
DstTy.getElementCount() != SrcTy.getElementCount())) {
1607+
report("Generic vector abds/abdu must preserve number of lanes", MI);
1608+
break;
1609+
}
1610+
1611+
if (SrcTy != SrcTy2) {
1612+
report("Generic abds/abdu must have same input types", MI);
1613+
break;
1614+
}
1615+
1616+
if (DstTy != SrcTy) {
1617+
report("Generic abds/abdu must have same input and output types", MI);
1618+
break;
1619+
}
1620+
1621+
break;
1622+
}
15881623
case TargetOpcode::G_SCMP:
15891624
case TargetOpcode::G_UCMP: {
15901625
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());

llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@
7070
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
7171
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
7272
#
73+
# DEBUG-NEXT: G_ABDS (opcode 65): 1 type index, 0 imm indices
74+
# DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
75+
# DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
76+
#
77+
# DEBUG-NEXT:G_ABDU (opcode 66): 1 type index, 0 imm indices
78+
# DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
79+
# DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
80+
#
7381
# DEBUG-NEXT: G_IMPLICIT_DEF (opcode {{[0-9]+}}): 1 type index, 0 imm indices
7482
# DEBUG-NEXT: .. the first uncovered type index: {{[0-9]+}}, OK
7583
# DEBUG-NEXT: .. the first uncovered imm index: {{[0-9]+}}, OK

llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@
7373
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
7474
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
7575
#
76+
# DEBUG-NEXT: G_ABDS (opcode 65): 1 type index, 0 imm indices
77+
# DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
78+
# DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
79+
#
80+
# DEBUG-NEXT:G_ABDU (opcode 66): 1 type index, 0 imm indices
81+
# DEBUG-NEXT:.. type index coverage check SKIPPED: no rules defined
82+
# DEBUG-NEXT:.. imm index coverage check SKIPPED: no rules defined
83+
#
7684
# DEBUG-NEXT: G_IMPLICIT_DEF (opcode {{[0-9]+}}): 1 type index, 0 imm indices
7785
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
7886
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# RUN: not --crash llc -verify-machineinstrs -mtriple=arm64 -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
2+
# REQUIRES: aarch64-registered-target
3+
4+
---
5+
name: g_abd_su
6+
body: |
7+
bb.0:
8+
9+
%2:_(p0) = G_IMPLICIT_DEF
10+
%3:_(p0) = G_IMPLICIT_DEF
11+
; CHECK: Generic abds/abdu does not support pointers as operands
12+
%4:_(s1) = G_ABDS %2, %3
13+
14+
%12:_(s64) = G_IMPLICIT_DEF
15+
%13:_(s64) = G_IMPLICIT_DEF
16+
; CHECK: Generic abds/abdu does not support pointers as a result
17+
%14:_(p0) = G_ABDS %12, %13
18+
19+
%23:_(<2 x s32>) = G_IMPLICIT_DEF
20+
%24:_(<2 x s32>) = G_IMPLICIT_DEF
21+
; CHECK: Generic vector abds/abdu must preserve number of lanes
22+
%5:_(s1) = G_ABDU %23, %24
23+
24+
%15:_(s32) = G_CONSTANT i32 0
25+
%16:_(s64) = G_CONSTANT i64 2
26+
; CHECK: Generic abds/abdu must have same input types
27+
%17:_(s1) = G_ABDU %15, %16
28+
29+
%18:_(s64) = G_CONSTANT i64 0
30+
%19:_(s64) = G_CONSTANT i64 2
31+
; CHECK: Generic abds/abdu must have same input and output types
32+
%20:_(s1) = G_ABDU %18, %19
33+
34+
...
35+

0 commit comments

Comments
 (0)