Skip to content

Commit 5b64f0a

Browse files
author
Thorsten Schütt
committed
[GlobalIsel] Add G_SCMP and G_UCMP instructions
#83227
1 parent 6192f45 commit 5b64f0a

File tree

8 files changed

+125
-0
lines changed

8 files changed

+125
-0
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,26 @@ G_ICMP
348348
Perform integer comparison producing non-zero (true) or zero (false). It's
349349
target specific whether a true value is 1, ~0U, or some other non-zero value.
350350

351+
G_SCMP
352+
^^^^^^
353+
354+
Perform signed 3-way integer comparison producing -1 (smaller), 0 (equal), or 1 (larger).
355+
356+
.. code-block:: none
357+
358+
%5:_(s32) = G_SCMP %6, %2
359+
360+
361+
G_UCMP
362+
^^^^^^
363+
364+
Perform unsigned 3-way integer comparison producing -1 (smaller), 0 (equal), or 1 (larger).
365+
366+
.. code-block:: none
367+
368+
%7:_(s32) = G_UCMP %2, %6
369+
370+
351371
G_SELECT
352372
^^^^^^^^
353373

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,34 @@ class MachineIRBuilder {
12731273
const SrcOp &Op0, const SrcOp &Op1,
12741274
std::optional<unsigned> Flags = std::nullopt);
12751275

1276+
/// Build and insert a \p Res = G_SCMP \p Op0, \p Op1
1277+
///
1278+
/// \pre setBasicBlock or setMI must have been called.
1279+
1280+
/// \pre \p Res must be a generic virtual register with scalar or
1281+
/// vector type. Typically this starts as s2 or <N x s2>.
1282+
/// \pre \p Op0 and Op1 must be generic virtual registers with the
1283+
/// same number of elements as \p Res. If \p Res is a scalar,
1284+
/// \p Op0 must be a scalar.
1285+
///
1286+
/// \return a MachineInstrBuilder for the newly created instruction.
1287+
MachineInstrBuilder buildSCmp(const DstOp &Res, const SrcOp &Op0,
1288+
const SrcOp &Op1);
1289+
1290+
/// Build and insert a \p Res = G_UCMP \p Op0, \p Op1
1291+
///
1292+
/// \pre setBasicBlock or setMI must have been called.
1293+
1294+
/// \pre \p Res must be a generic virtual register with scalar or
1295+
/// vector type. Typically this starts as s2 or <N x s2>.
1296+
/// \pre \p Op0 and Op1 must be generic virtual registers with the
1297+
/// same number of elements as \p Res. If \p Res is a scalar,
1298+
/// \p Op0 must be a scalar.
1299+
///
1300+
/// \return a MachineInstrBuilder for the newly created instruction.
1301+
MachineInstrBuilder buildUCmp(const DstOp &Res, const SrcOp &Op0,
1302+
const SrcOp &Op1);
1303+
12761304
/// Build and insert a \p Res = G_IS_FPCLASS \p Src, \p Mask
12771305
MachineInstrBuilder buildIsFPClass(const DstOp &Res, const SrcOp &Src,
12781306
unsigned Mask) {

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,12 @@ HANDLE_TARGET_OPCODE(G_ICMP)
503503
/// Generic floating-point comparison, also applicable to vectors.
504504
HANDLE_TARGET_OPCODE(G_FCMP)
505505

506+
/// Generic signed 3-way comparison.
507+
HANDLE_TARGET_OPCODE(G_SCMP)
508+
509+
/// Generic unsigned 3-way comparison.
510+
HANDLE_TARGET_OPCODE(G_UCMP)
511+
506512
/// Generic select.
507513
HANDLE_TARGET_OPCODE(G_SELECT)
508514

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,20 @@ def G_FCMP : GenericInstruction {
430430
let hasSideEffects = false;
431431
}
432432

433+
// Generic signed three-way comparison.
434+
def G_SCMP : GenericInstruction {
435+
let OutOperandList = (outs type0:$dst);
436+
let InOperandList = (ins type1:$src1, type1:$src2);
437+
let hasSideEffects = false;
438+
}
439+
440+
// Generic unsigned three-way comparison.
441+
def G_UCMP : GenericInstruction {
442+
let OutOperandList = (outs type0:$dst);
443+
let InOperandList = (ins type1:$src1, type1:$src2);
444+
let hasSideEffects = false;
445+
}
446+
433447
// Generic select
434448
def G_SELECT : GenericInstruction {
435449
let OutOperandList = (outs type0:$dst);

llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,18 @@ MachineInstrBuilder MachineIRBuilder::buildFCmp(CmpInst::Predicate Pred,
911911
return buildInstr(TargetOpcode::G_FCMP, Res, {Pred, Op0, Op1}, Flags);
912912
}
913913

914+
MachineInstrBuilder MachineIRBuilder::buildSCmp(const DstOp &Res,
915+
const SrcOp &Op0,
916+
const SrcOp &Op1) {
917+
return buildInstr(TargetOpcode::G_SCMP, Res, {Op0, Op1});
918+
}
919+
920+
MachineInstrBuilder MachineIRBuilder::buildUCmp(const DstOp &Res,
921+
const SrcOp &Op0,
922+
const SrcOp &Op1) {
923+
return buildInstr(TargetOpcode::G_UCMP, Res, {Op0, Op1});
924+
}
925+
914926
MachineInstrBuilder
915927
MachineIRBuilder::buildSelect(const DstOp &Res, const SrcOp &Tst,
916928
const SrcOp &Op0, const SrcOp &Op1,

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,26 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
15441544

15451545
break;
15461546
}
1547+
case TargetOpcode::G_SCMP:
1548+
case TargetOpcode::G_UCMP: {
1549+
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
1550+
LLT SrcTy = MRI->getType(MI->getOperand(1).getReg());
1551+
LLT SrcTy2 = MRI->getType(MI->getOperand(2).getReg());
1552+
1553+
if ((DstTy.isVector() != SrcTy.isVector()) ||
1554+
(DstTy.isVector() &&
1555+
DstTy.getElementCount() != SrcTy.getElementCount())) {
1556+
report("Generic vector scmp/ucmp must preserve number of lanes", MI);
1557+
break;
1558+
}
1559+
1560+
if (SrcTy != SrcTy2) {
1561+
report("Generic scmp/ucmp must have same input types", MI);
1562+
break;
1563+
}
1564+
1565+
break;
1566+
}
15471567
case TargetOpcode::G_EXTRACT: {
15481568
const MachineOperand &SrcOp = MI->getOperand(1);
15491569
if (!SrcOp.isReg()) {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,12 @@
351351
# DEBUG-NEXT: G_FCMP (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
352352
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
353353
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
354+
# DEBUG-NEXT: G_SCMP (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
355+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
356+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
357+
# DEBUG-NEXT: G_UCMP (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
358+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
359+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
354360
# DEBUG-NEXT: G_SELECT (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
355361
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
356362
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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: test_uscmp
6+
body: |
7+
bb.0:
8+
9+
%3:_(<2 x s32>) = G_IMPLICIT_DEF
10+
%4:_(<2 x s32>) = G_IMPLICIT_DEF
11+
; CHECK: Generic vector scmp/ucmp must preserve number of lanes
12+
%5:_(s1) = G_UCMP %3, %4
13+
14+
%12:_(s32) = G_CONSTANT i32 0
15+
%13:_(s64) = G_CONSTANT i64 2
16+
; CHECK: Generic scmp/ucmp must have same input types
17+
%14:_(s1) = G_SCMP %12, %13
18+
19+
...

0 commit comments

Comments
 (0)