Skip to content

Commit 4c27279

Browse files
authored
[GlobalISel] Add Saturated Truncate Instructions (#147526)
Introduces saturated truncate instructions to Global ISel: G_TRUNC_SSAT_S, G_TRUNC_SSAT_U, G_TRUNC_USAT_U. These were previously introduced to SDAG to reduce redundant code. The patch only initially introduces the instruction, a later patch will follow to add combines and legalization for each instruction.
1 parent cd9236d commit 4c27279

File tree

10 files changed

+191
-68
lines changed

10 files changed

+191
-68
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,33 @@ G_EXTRACT for scalar types, but acts elementwise on vectors.
148148
149149
%1:_(s16) = G_TRUNC %0:_(s32)
150150
151+
G_TRUNC_SSAT_S
152+
^^^^^^^^^^^^^^
153+
154+
Truncate a signed input to a signed result with saturation.
155+
156+
.. code-block:: none
157+
158+
%1:_(s16) = G_TRUNC_SSAT_S %0:_(s32)
159+
160+
G_TRUNC_SSAT_U
161+
^^^^^^^^^^^^^^
162+
163+
Truncate a signed input to an unsigned result with saturation.
164+
165+
.. code-block:: none
166+
167+
%1:_(s16) = G_TRUNC_SSAT_U %0:_(s32)
168+
169+
G_TRUNC_USAT_U
170+
^^^^^^^^^^^^^^
171+
172+
Truncate a unsigned input to an unsigned result with saturation.
173+
174+
.. code-block:: none
175+
176+
%1:_(s16) = G_TRUNC_USAT_U %0:_(s32)
177+
151178
Type Conversions
152179
----------------
153180

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

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ class LLVM_ABI MachineIRBuilder {
763763

764764
/// Build and insert \p Res = G_SEXT \p Op, \p Res = G_TRUNC \p Op, or
765765
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
766-
/// ///
766+
///
767767
/// \pre setBasicBlock or setMI must have been called.
768768
/// \pre \p Res must be a generic virtual register with scalar or vector type.
769769
/// \pre \p Op must be a generic virtual register with scalar or vector type.
@@ -773,7 +773,7 @@ class LLVM_ABI MachineIRBuilder {
773773

774774
/// Build and insert \p Res = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or
775775
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
776-
/// ///
776+
///
777777
/// \pre setBasicBlock or setMI must have been called.
778778
/// \pre \p Res must be a generic virtual register with scalar or vector type.
779779
/// \pre \p Op must be a generic virtual register with scalar or vector type.
@@ -783,7 +783,7 @@ class LLVM_ABI MachineIRBuilder {
783783

784784
// Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_TRUNC \p Op, or
785785
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
786-
/// ///
786+
///
787787
/// \pre setBasicBlock or setMI must have been called.
788788
/// \pre \p Res must be a generic virtual register with scalar or vector type.
789789
/// \pre \p Op must be a generic virtual register with scalar or vector type.
@@ -794,7 +794,7 @@ class LLVM_ABI MachineIRBuilder {
794794
/// Build and insert \p Res = \p ExtOpc, \p Res = G_TRUNC \p
795795
/// Op, or \p Res = COPY \p Op depending on the differing sizes of \p Res and
796796
/// \p Op.
797-
/// ///
797+
///
798798
/// \pre setBasicBlock or setMI must have been called.
799799
/// \pre \p Res must be a generic virtual register with scalar or vector type.
800800
/// \pre \p Op must be a generic virtual register with scalar or vector type.
@@ -809,6 +809,48 @@ class LLVM_ABI MachineIRBuilder {
809809
MachineInstrBuilder buildZExtInReg(const DstOp &Res, const SrcOp &Op,
810810
int64_t ImmOp);
811811

812+
/// Build and insert \p Res = \p G_TRUNC_SSAT_S \p Op
813+
///
814+
/// G_TRUNC_SSAT_S truncates the signed input, \p Op, to a signed result with
815+
/// saturation.
816+
///
817+
/// \pre setBasicBlock or setMI must have been called.
818+
/// \pre \p Res must be a generic virtual register with scalar or vector type.
819+
/// \pre \p Op must be a generic virtual register with scalar or vector type.
820+
///
821+
/// \return The newly created instruction.
822+
MachineInstrBuilder buildTruncSSatS(const DstOp &Res, const SrcOp &Op) {
823+
return buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {Res}, {Op});
824+
}
825+
826+
/// Build and insert \p Res = \p G_TRUNC_SSAT_U \p Op
827+
///
828+
/// G_TRUNC_SSAT_U truncates the signed input, \p Op, to an unsigned result
829+
/// with saturation.
830+
///
831+
/// \pre setBasicBlock or setMI must have been called.
832+
/// \pre \p Res must be a generic virtual register with scalar or vector type.
833+
/// \pre \p Op must be a generic virtual register with scalar or vector type.
834+
///
835+
/// \return The newly created instruction.
836+
MachineInstrBuilder buildTruncSSatU(const DstOp &Res, const SrcOp &Op) {
837+
return buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {Res}, {Op});
838+
}
839+
840+
/// Build and insert \p Res = \p G_TRUNC_USAT_U \p Op
841+
///
842+
/// G_TRUNC_USAT_U truncates the unsigned input, \p Op, to an unsigned result
843+
/// with saturation.
844+
///
845+
/// \pre setBasicBlock or setMI must have been called.
846+
/// \pre \p Res must be a generic virtual register with scalar or vector type.
847+
/// \pre \p Op must be a generic virtual register with scalar or vector type.
848+
///
849+
/// \return The newly created instruction.
850+
MachineInstrBuilder buildTruncUSatU(const DstOp &Res, const SrcOp &Op) {
851+
return buildInstr(TargetOpcode::G_TRUNC_USAT_U, {Res}, {Op});
852+
}
853+
812854
/// Build and insert an appropriate cast between two registers of equal size.
813855
MachineInstrBuilder buildCast(const DstOp &Dst, const SrcOp &Src);
814856

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,15 @@ HANDLE_TARGET_OPCODE(G_ANYEXT)
475475
/// elements of the vector.
476476
HANDLE_TARGET_OPCODE(G_TRUNC)
477477

478+
/// Generic instruction to truncate a signed operand to a signed result with saturation.
479+
HANDLE_TARGET_OPCODE(G_TRUNC_SSAT_S)
480+
481+
/// Generic instruction to truncate a signed operand to an unsigned result with saturation.
482+
HANDLE_TARGET_OPCODE(G_TRUNC_SSAT_U)
483+
484+
/// Generic instruction to truncate a unsigned operand to an unsigned result with saturation.
485+
HANDLE_TARGET_OPCODE(G_TRUNC_USAT_U)
486+
478487
/// Generic integer constant.
479488
HANDLE_TARGET_OPCODE(G_CONSTANT)
480489

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,27 @@ def G_TRUNC : GenericInstruction {
8686
let hasSideEffects = false;
8787
}
8888

89+
// Truncate the signed operand to a signed result with saturation.
90+
def G_TRUNC_SSAT_S : GenericInstruction {
91+
let OutOperandList = (outs type0:$dst);
92+
let InOperandList = (ins type1:$src);
93+
let hasSideEffects = false;
94+
}
95+
96+
// Truncate the signed operand to an unsigned result with saturation.
97+
def G_TRUNC_SSAT_U : GenericInstruction {
98+
let OutOperandList = (outs type0:$dst);
99+
let InOperandList = (ins type1:$src);
100+
let hasSideEffects = false;
101+
}
102+
103+
// Truncate the unsigned operand to an unsigned result with saturation.
104+
def G_TRUNC_USAT_U : GenericInstruction {
105+
let OutOperandList = (outs type0:$dst);
106+
let InOperandList = (ins type1:$src);
107+
let hasSideEffects = false;
108+
}
109+
89110
def G_IMPLICIT_DEF : GenericInstruction {
90111
let OutOperandList = (outs type0:$dst);
91112
let InOperandList = (ins);

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,9 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
14241424
case TargetOpcode::G_ZEXT:
14251425
case TargetOpcode::G_ANYEXT:
14261426
case TargetOpcode::G_TRUNC:
1427+
case TargetOpcode::G_TRUNC_SSAT_S:
1428+
case TargetOpcode::G_TRUNC_SSAT_U:
1429+
case TargetOpcode::G_TRUNC_USAT_U:
14271430
case TargetOpcode::G_FPEXT:
14281431
case TargetOpcode::G_FPTRUNC: {
14291432
// Number of operands and presense of types is already checked (and
@@ -1450,6 +1453,9 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
14501453
report("Generic extend has destination type no larger than source", MI);
14511454
break;
14521455
case TargetOpcode::G_TRUNC:
1456+
case TargetOpcode::G_TRUNC_SSAT_S:
1457+
case TargetOpcode::G_TRUNC_SSAT_U:
1458+
case TargetOpcode::G_TRUNC_USAT_U:
14531459
case TargetOpcode::G_FPTRUNC:
14541460
if (DstSize >= SrcSize)
14551461
report("Generic truncate has destination type no smaller than source",

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,15 @@
319319
# DEBUG-NEXT: G_TRUNC (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
320320
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
321321
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
322+
# DEBUG-NEXT: G_TRUNC_SSAT_S (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
323+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
324+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
325+
# DEBUG-NEXT: G_TRUNC_SSAT_U (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
326+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
327+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
328+
# DEBUG-NEXT: G_TRUNC_USAT_U (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
329+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
330+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
322331
# DEBUG-NEXT: G_CONSTANT (opcode {{[0-9]+}}): 1 type index, 0 imm indices
323332
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
324333
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,15 @@
315315
# DEBUG-NEXT: G_TRUNC (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
316316
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
317317
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
318+
# DEBUG-NEXT: G_TRUNC_SSAT_S (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
319+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
320+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
321+
# DEBUG-NEXT: G_TRUNC_SSAT_U (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
322+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
323+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
324+
# DEBUG-NEXT: G_TRUNC_USAT_U (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
325+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
326+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
318327
# DEBUG-NEXT: G_CONSTANT (opcode {{[0-9]+}}): 1 type index, 0 imm indices
319328
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
320329
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK

llvm/test/MC/ELF/mc-dump.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# CHECK-NEXT:0 Data Size:0 []
1313
# CHECK-NEXT: Symbol @0 _start
1414
# CHECK-NEXT:0 Org Offset:3 Value:0
15-
# CHECK-NEXT:3 Relaxable Size:2 <MCInst #1996 <MCOperand Expr:.Ltmp0>>
15+
# CHECK-NEXT:3 Relaxable Size:2 <MCInst #1999 <MCOperand Expr:.Ltmp0>>
1616
# CHECK-NEXT: Fixup @1 Value:.Ltmp0 Kind:4001
1717
# CHECK-NEXT:5 Data Size:16 [48,8b,04,25,00,00,00,00,48,8b,04,25,00,00,00,00]
1818
# CHECK-NEXT: Fixup @4 Value:f0@<variant 11> Kind:4017

0 commit comments

Comments
 (0)