Skip to content

Commit 148fdc5

Browse files
author
Thorsten Schütt
authored
[GlobalISel] Add G_ABDS and G_ABDU instructions (#118122)
The DAG has the same instructions: the signed and unsigned absolute difference of it's input. For AArch64, they map to uabd and sabd for Neon and SVE. The Neon and SVE instructions will require custom patterns. They are pseudo opcodes and are not imported by the IRTranslator. We need combines to create them. PowerPC, ARM, and AArch64 have native instructions. /// 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 - [ ] combine into abd - [ ] legalize and add td patterns
1 parent 041e5c9 commit 148fdc5

File tree

9 files changed

+132
-1
lines changed

9 files changed

+132
-1
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_ABDU 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: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,22 @@ 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+
let isCommutable = true;
395+
}
396+
397+
// Generic absolute difference unsigned.
398+
def G_ABDU : GenericInstruction {
399+
let OutOperandList = (outs type0:$dst);
400+
let InOperandList = (ins type0:$src1, type0:$src2);
401+
let hasSideEffects = false;
402+
let isCommutable = true;
403+
}
404+
389405
/// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
390406
/// fshl(X,Y,Z): (X << (Z % bitwidth)) | (Y >> (bitwidth - (Z % bitwidth)))
391407
def G_FSHL : GenericInstruction {

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,31 @@ 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 ((DstTy.isVector() != SrcTy.isVector()) ||
1595+
(DstTy.isVector() &&
1596+
DstTy.getElementCount() != SrcTy.getElementCount())) {
1597+
report("Generic vector abds/abdu must preserve number of lanes", MI);
1598+
break;
1599+
}
1600+
1601+
if (SrcTy != SrcTy2) {
1602+
report("Generic abds/abdu must have same input types", MI);
1603+
break;
1604+
}
1605+
1606+
if (DstTy != SrcTy) {
1607+
report("Generic abds/abdu must have same input and output types", MI);
1608+
break;
1609+
}
1610+
1611+
break;
1612+
}
15881613
case TargetOpcode::G_SCMP:
15891614
case TargetOpcode::G_UCMP: {
15901615
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: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
%4:_(s1) = G_ABDS %2, %3
12+
13+
%12:_(s64) = G_IMPLICIT_DEF
14+
%13:_(s64) = G_IMPLICIT_DEF
15+
%14:_(p0) = G_ABDS %12, %13
16+
17+
%23:_(<2 x s32>) = G_IMPLICIT_DEF
18+
%24:_(<2 x s32>) = G_IMPLICIT_DEF
19+
; CHECK: Generic vector abds/abdu must preserve number of lanes
20+
%5:_(s1) = G_ABDU %23, %24
21+
22+
%15:_(s32) = G_CONSTANT i32 0
23+
%16:_(s64) = G_CONSTANT i64 2
24+
; CHECK: Generic abds/abdu must have same input types
25+
%17:_(s1) = G_ABDU %15, %16
26+
27+
%18:_(s64) = G_CONSTANT i64 0
28+
%19:_(s64) = G_CONSTANT i64 2
29+
; CHECK: Generic abds/abdu must have same input and output types
30+
%20:_(s1) = G_ABDU %18, %19
31+
32+
...
33+

llvm/test/TableGen/GlobalISelEmitter.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ def : Pat<(frag GPR32:$src1, complex:$src2, complex:$src3),
513513
// R00O-NEXT: GIM_Reject,
514514
// R00O: // Label [[DEFAULT_NUM]]: @[[DEFAULT]]
515515
// R00O-NEXT: GIM_Reject,
516-
// R00O-NEXT: }; // Size: 1832 bytes
516+
// R00O-NEXT: }; // Size: 1840 bytes
517517

518518
def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4),
519519
[(set GPR32:$dst,

0 commit comments

Comments
 (0)