From 33b1ce984e7dc873b19de61ae5836e279e8a28e2 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Fri, 17 May 2019 18:36:31 +0000 Subject: [PATCH] GlobalISel: Define integer min/max instructions Doesn't attempt to emit them for anything yet, but some legalizations I want to port use them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@361061 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../CodeGen/GlobalISel/MachineIRBuilder.h | 24 ++++++++++++++ include/llvm/Support/TargetOpcodes.def | 12 +++++++ include/llvm/Target/GenericOpcodes.td | 32 +++++++++++++++++++ lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 6 +++- .../GlobalISel/legalizer-info-validation.mir | 12 +++++++ .../GlobalISel/MachineIRBuilderTest.cpp | 25 +++++++++++++++ 6 files changed, 110 insertions(+), 1 deletion(-) diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 10c3dc77e13..1b1d7017c4b 100644 --- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1335,6 +1335,30 @@ public: return buildInstr(TargetOpcode::G_FPTOSI, {Dst}, {Src0}); } + /// Build and insert \p Res = G_SMIN \p Op0, \p Op1 + MachineInstrBuilder buildSMin(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_SMIN, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_SMAX \p Op0, \p Op1 + MachineInstrBuilder buildSMax(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_SMAX, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_UMIN \p Op0, \p Op1 + MachineInstrBuilder buildUMin(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_UMIN, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_UMAX \p Op0, \p Op1 + MachineInstrBuilder buildUMax(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_UMAX, {Dst}, {Src0, Src1}); + } + virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef DstOps, ArrayRef SrcOps, Optional Flags = None); diff --git a/include/llvm/Support/TargetOpcodes.def b/include/llvm/Support/TargetOpcodes.def index 4b64756dd92..479c5acb9fd 100644 --- a/include/llvm/Support/TargetOpcodes.def +++ b/include/llvm/Support/TargetOpcodes.def @@ -497,6 +497,18 @@ HANDLE_TARGET_OPCODE(G_GEP) /// *down* to the given alignment. HANDLE_TARGET_OPCODE(G_PTR_MASK) +/// Generic signed integer minimum. +HANDLE_TARGET_OPCODE(G_SMIN) + +/// Generic signed integer maximum. +HANDLE_TARGET_OPCODE(G_SMAX) + +/// Generic unsigned integer maximum. +HANDLE_TARGET_OPCODE(G_UMIN) + +/// Generic unsigned integer maximum. +HANDLE_TARGET_OPCODE(G_UMAX) + /// Generic BRANCH instruction. This is an unconditional branch. HANDLE_TARGET_OPCODE(G_BR) diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td index 07669d2492f..75f3b5fe746 100644 --- a/include/llvm/Target/GenericOpcodes.td +++ b/include/llvm/Target/GenericOpcodes.td @@ -308,6 +308,38 @@ def G_PTR_MASK : GenericInstruction { let hasSideEffects = 0; } +// Generic signed integer minimum. +def G_SMIN : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic signed integer maximum. +def G_SMAX : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic unsigned integer minimum. +def G_UMIN : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic unsigned integer maximum. +def G_UMAX : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + //------------------------------------------------------------------------------ // Overflow ops //------------------------------------------------------------------------------ diff --git a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 524031659bb..d58a4629815 100644 --- a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -901,7 +901,11 @@ MachineInstrBuilder MachineIRBuilder::buildInstr(unsigned Opc, case TargetOpcode::G_UDIV: case TargetOpcode::G_SDIV: case TargetOpcode::G_UREM: - case TargetOpcode::G_SREM: { + case TargetOpcode::G_SREM: + case TargetOpcode::G_SMIN: + case TargetOpcode::G_SMAX: + case TargetOpcode::G_UMIN: + case TargetOpcode::G_UMAX: { // All these are binary ops. assert(DstOps.size() == 1 && "Invalid Dst"); assert(SrcOps.size() == 2 && "Invalid Srcs"); diff --git a/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index 088b0c00c08..660aec3ecbe 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -306,6 +306,18 @@ # DEBUG-NEXT: G_PTR_MASK (opcode {{[0-9]+}}): 1 type index # DEBUG: .. the first uncovered type index: 1, OK # +# DEBUG: G_SMIN (opcode {{[0-9]+}}): 1 type index +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# +# DEBUG: G_SMAX (opcode {{[0-9]+}}): 1 type index +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# +# DEBUG: G_UMIN (opcode {{[0-9]+}}): 1 type index +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# +# DEBUG: G_UMAX (opcode {{[0-9]+}}): 1 type index +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# # DEBUG-NEXT: G_BR (opcode {{[0-9]+}}): 0 type indices # DEBUG: .. type index coverage check SKIPPED: no rules defined # diff --git a/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp b/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp index 04f72708b5f..a61cb56718b 100644 --- a/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp +++ b/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp @@ -253,3 +253,28 @@ TEST_F(GISelMITest, BuildCasts) { EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; } + +TEST_F(GISelMITest, BuildMinMax) { + if (!TM) + return; + + LLT S64 = LLT::scalar(64); + SmallVector Copies; + collectCopies(Copies, MF); + + B.buildSMin(S64, Copies[0], Copies[1]); + B.buildSMax(S64, Copies[0], Copies[1]); + B.buildUMin(S64, Copies[0], Copies[1]); + B.buildUMax(S64, Copies[0], Copies[1]); + + auto CheckStr = R"( + ; CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 + ; CHECK: [[SMIN0:%[0-9]+]]:_(s64) = G_SMIN [[COPY0]]:_, [[COPY1]]:_ + ; CHECK: [[SMAX0:%[0-9]+]]:_(s64) = G_SMAX [[COPY0]]:_, [[COPY1]]:_ + ; CHECK: [[UMIN0:%[0-9]+]]:_(s64) = G_UMIN [[COPY0]]:_, [[COPY1]]:_ + ; CHECK: [[UMAX0:%[0-9]+]]:_(s64) = G_UMAX [[COPY0]]:_, [[COPY1]]:_ + )"; + + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} -- 2.50.1