[gcc(refs/users/meissner/heads/work010)] PowerPC: Rework C min/max & cmove functions.
Michael Meissner
meissner@gcc.gnu.org
Sat Aug 15 01:28:38 GMT 2020
https://gcc.gnu.org/g:af2ba4669cb3b0a64677e5a661857d6a92e8f8ec
commit af2ba4669cb3b0a64677e5a661857d6a92e8f8ec
Author: Michael Meissner <meissner@gcc.gnu.org>
Date: Fri Aug 14 21:27:57 2020 -0400
PowerPC: Rework C min/max & cmove functions.
gcc/
2020-08-14 Michael Meissner <meissner@linux.ibm.com>
* config/rs6000/rs6000-protos.h (have_compare_and_set_mask): New
declaration.
* config/rs6000/rs6000.c (rs6000_emit_p9_fp_minmax): Rename to
maybe_emit_fp_c_minmax.
(maybe_emit_fp_c_minmax): Rename rs6000_emit_p9_fp_minmax. Return
bool instead of int.
(rs6000_emit_p9_fp_cmove): Rename to maybe_emit_fp_cmove.
(maybe_emit_fp_cmove): Rename rs6000_emit_p9_fp_cmove. Return
bool instead of int.
(have_compare_and_set_mask): New function.
(rs6000_emit_cmove): Rework support of ISA 3.0 functions to
generate "C" minimum, "C" maximum, and conditional move
instructions for scalar floating point.
Diff:
---
gcc/config/rs6000/rs6000-protos.h | 1 +
gcc/config/rs6000/rs6000.c | 77 +++++++++++++++++++++++++++------------
2 files changed, 54 insertions(+), 24 deletions(-)
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 02e4d71922f..3ba04fa487b 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -119,6 +119,7 @@ extern char * output_cbranch (rtx, const char *, int, rtx_insn *);
extern const char * output_probe_stack_range (rtx, rtx, rtx);
extern void rs6000_emit_dot_insn (rtx dst, rtx src, int dot, rtx ccreg);
extern bool rs6000_emit_set_const (rtx, rtx);
+extern bool have_compare_and_set_mask (machine_mode);
extern bool rs6000_emit_cmove (rtx, rtx, rtx, rtx);
extern bool rs6000_emit_int_cmove (rtx, rtx, rtx, rtx);
extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index f1cc1a64b9c..8952904b29c 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -15032,13 +15032,17 @@ rs6000_emit_vector_cond_expr (rtx dest, rtx op_true, rtx op_false,
return 1;
}
-/* ISA 3.0 (power9) minmax subcase to emit a XSMAXCDP or XSMINCDP instruction
- for SF/DF scalars. Move TRUE_COND to DEST if OP of the operands of the last
- comparison is nonzero/true, FALSE_COND if it is zero/false. Return 0 if the
- hardware has no such operation. */
+/* Possibly emit the C variant of the minimum or maximum instruction for
+ floating point scalars (xsmincdp, xsmaxcdp, etc.).
-static int
-rs6000_emit_p9_fp_minmax (rtx dest, rtx op, rtx true_cond, rtx false_cond)
+ Move TRUE_COND to DEST if OP of the operands of the last comparison is
+ nonzero/true, FALSE_COND if it is zero/false.
+
+ Return false if we can't generate the appropriate minimum or maximum, and
+ true if we can did the minimum or maximum. */
+
+static bool
+maybe_emit_fp_c_minmax (rtx dest, rtx op, rtx true_cond, rtx false_cond)
{
enum rtx_code code = GET_CODE (op);
rtx op0 = XEXP (op, 0);
@@ -15048,14 +15052,14 @@ rs6000_emit_p9_fp_minmax (rtx dest, rtx op, rtx true_cond, rtx false_cond)
bool max_p = false;
if (result_mode != compare_mode)
- return 0;
+ return false;
if (code == GE || code == GT)
max_p = true;
else if (code == LE || code == LT)
max_p = false;
else
- return 0;
+ return false;
if (rtx_equal_p (op0, true_cond) && rtx_equal_p (op1, false_cond))
;
@@ -15068,19 +15072,23 @@ rs6000_emit_p9_fp_minmax (rtx dest, rtx op, rtx true_cond, rtx false_cond)
max_p = !max_p;
else
- return 0;
+ return false;
rs6000_emit_minmax (dest, max_p ? SMAX : SMIN, op0, op1);
- return 1;
+ return true;
}
-/* ISA 3.0 (power9) conditional move subcase to emit XSCMP{EQ,GE,GT,NE}DP and
- XXSEL instructions for SF/DF scalars. Move TRUE_COND to DEST if OP of the
- operands of the last comparison is nonzero/true, FALSE_COND if it is
- zero/false. Return 0 if the hardware has no such operation. */
+/* Possibly emit a floating point conditional move by generating a compare that
+ sets a mask instruction and a XXSEL select instruction.
-static int
-rs6000_emit_p9_fp_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
+ Move TRUE_COND to DEST if OP of the operands of the last comparison is
+ nonzero/true, FALSE_COND if it is zero/false.
+
+ Return false if the operation cannot be generated, and true if we could
+ generate the instruction. */
+
+static bool
+maybe_emit_fp_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
{
enum rtx_code code = GET_CODE (op);
rtx op0 = XEXP (op, 0);
@@ -15108,7 +15116,7 @@ rs6000_emit_p9_fp_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
break;
default:
- return 0;
+ return false;
}
/* Generate: [(parallel [(set (dest)
@@ -15128,7 +15136,28 @@ rs6000_emit_p9_fp_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
emit_insn (gen_rtx_PARALLEL (VOIDmode,
gen_rtvec (2, cmove_rtx, clobber_rtx)));
- return 1;
+ return true;
+}
+
+/* Helper function to return true if the target has instructions to do a
+ compare and set mask instruction that can be used with XXSEL to implement a
+ conditional move. It is also assumed that such a target also supports the
+ "C" minimum and maximum instructions. */
+
+bool
+have_compare_and_set_mask (machine_mode mode)
+{
+ switch (mode)
+ {
+ case SFmode:
+ case DFmode:
+ return TARGET_P9_MINMAX;
+
+ default:
+ break;
+ }
+
+ return false;
}
/* Emit a conditional move: move TRUE_COND to DEST if OP of the
@@ -15157,15 +15186,15 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
if (GET_MODE (false_cond) != result_mode)
return false;
- /* See if we can use the ISA 3.0 (power9) min/max/compare functions. */
- if (TARGET_P9_MINMAX
- && (compare_mode == SFmode || compare_mode == DFmode)
- && (result_mode == SFmode || result_mode == DFmode))
+ /* See if we can use the "C" minimum, "C" maximum, and compare and set mask
+ instructions. */
+ if (have_compare_and_set_mask (compare_mode)
+ && have_compare_and_set_mask (result_mode))
{
- if (rs6000_emit_p9_fp_minmax (dest, op, true_cond, false_cond))
+ if (maybe_emit_fp_c_minmax (dest, op, true_cond, false_cond))
return true;
- if (rs6000_emit_p9_fp_cmove (dest, op, true_cond, false_cond))
+ if (maybe_emit_fp_cmove (dest, op, true_cond, false_cond))
return true;
}
More information about the Gcc-cvs
mailing list