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<DstOp> DstOps,
ArrayRef<SrcOp> SrcOps,
Optional<unsigned> Flags = None);
/// *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)
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
//------------------------------------------------------------------------------
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");
# 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
#
EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
}
+
+TEST_F(GISelMITest, BuildMinMax) {
+ if (!TM)
+ return;
+
+ LLT S64 = LLT::scalar(64);
+ SmallVector<unsigned, 4> 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;
+}