0011-committed-RISC-V-Handle-more-cases-in-riscv_expand_c.patch 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. From 4c7b0ec59a1a3ab92d8b3221f4e3c23c29719a0a Mon Sep 17 00:00:00 2001
  2. From: Raphael Zinsly <rzinsly@ventanamicro.com>
  3. Date: Mon, 7 Aug 2023 10:26:24 -0400
  4. Subject: [PATCH 11/30] [committed] [RISC-V] Handle more cases in
  5. riscv_expand_conditional_move
  6. As I've mentioned in the main zicond thread, Ventana has had patches
  7. that support more cases by first emitting a suitable scc instruction
  8. essentially as a canonicalization step of the condition for zicond.
  9. For example if we have
  10. (set (target) (if_then_else (op (reg1) (reg2))
  11. (true_value)
  12. (false_value)))
  13. The two register comparison isn't handled by zicond directly. But we
  14. can generate something like this instead
  15. (set (temp) (op (reg1) (reg2)))
  16. (set (target) (if_then_else (op (temp) (const_int 0))
  17. (true_value)
  18. (false_value)
  19. Then let the remaining code from Xiao handle the true_value/false_value
  20. to make sure it's zicond compatible.
  21. This is primarily Raphael's work. My involvement has been mostly to
  22. move it from its original location (in the .md file) into the expander
  23. function and fix minor problems with the FP case.
  24. gcc/
  25. * config/riscv/riscv.cc (riscv_expand_int_scc): Add invert_ptr
  26. as an argument and pass it to riscv_emit_int_order_test.
  27. (riscv_expand_conditional_move): Handle cases where the condition
  28. is not EQ/NE or the second argument to the conditional is not
  29. (const_int 0).
  30. * config/riscv/riscv-protos.h (riscv_expand_int_scc): Update prototype.
  31. Co-authored-by: Jeff Law <jlaw@ventanamicro.com>
  32. ---
  33. gcc/config/riscv/riscv-protos.h | 2 +-
  34. gcc/config/riscv/riscv.cc | 44 ++++++++++++++++++++++++++++++---
  35. 2 files changed, 42 insertions(+), 4 deletions(-)
  36. diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
  37. index 02b33e02020..8dd35f4262a 100644
  38. --- a/gcc/config/riscv/riscv-protos.h
  39. +++ b/gcc/config/riscv/riscv-protos.h
  40. @@ -56,7 +56,7 @@ extern const char *riscv_output_move (rtx, rtx);
  41. extern const char *riscv_output_return ();
  42. #ifdef RTX_CODE
  43. -extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
  44. +extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0);
  45. extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx);
  46. extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx);
  47. #endif
  48. diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
  49. index f16fb17beb5..9b9fff496a3 100644
  50. --- a/gcc/config/riscv/riscv.cc
  51. +++ b/gcc/config/riscv/riscv.cc
  52. @@ -3335,7 +3335,7 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
  53. /* CODE-compare OP0 and OP1. Store the result in TARGET. */
  54. void
  55. -riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1)
  56. +riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1, bool *invert_ptr)
  57. {
  58. riscv_extend_comparands (code, &op0, &op1);
  59. op0 = force_reg (word_mode, op0);
  60. @@ -3346,7 +3346,7 @@ riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1)
  61. riscv_emit_binary (code, target, zie, const0_rtx);
  62. }
  63. else
  64. - riscv_emit_int_order_test (code, 0, target, op0, op1);
  65. + riscv_emit_int_order_test (code, invert_ptr, target, op0, op1);
  66. }
  67. /* Like riscv_expand_int_scc, but for floating-point comparisons. */
  68. @@ -3444,7 +3444,6 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
  69. return true;
  70. }
  71. else if (TARGET_ZICOND
  72. - && (code == EQ || code == NE)
  73. && GET_MODE_CLASS (mode) == MODE_INT)
  74. {
  75. /* The comparison must be comparing WORD_MODE objects. We must
  76. @@ -3454,6 +3453,45 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
  77. if (GET_MODE (op0) != word_mode || GET_MODE (op1) != word_mode)
  78. return false;
  79. + /* Canonicalize the comparison. It must be an equality comparison
  80. + against 0. If it isn't, then emit an SCC instruction so that
  81. + we can then use an equality comparison against zero. */
  82. + if (!equality_operator (op, VOIDmode) || op1 != CONST0_RTX (mode))
  83. + {
  84. + enum rtx_code new_code = NE;
  85. + bool *invert_ptr = 0;
  86. + bool invert = false;
  87. +
  88. + if (code == LE || code == GE)
  89. + invert_ptr = &invert;
  90. +
  91. + /* Emit an scc like instruction into a temporary
  92. + so that we can use an EQ/NE comparison. */
  93. + rtx tmp = gen_reg_rtx (mode);
  94. +
  95. + /* We can support both FP and integer conditional moves. */
  96. + if (INTEGRAL_MODE_P (GET_MODE (XEXP (op, 0))))
  97. + riscv_expand_int_scc (tmp, code, op0, op1, invert_ptr);
  98. + else if (FLOAT_MODE_P (GET_MODE (XEXP (op, 0)))
  99. + && fp_scc_comparison (op, GET_MODE (op)))
  100. + riscv_expand_float_scc (tmp, code, op0, op1);
  101. + else
  102. + return false;
  103. +
  104. + /* If riscv_expand_int_scc inverts the condition, then it will
  105. + flip the value of INVERT. We need to know where so that
  106. + we can adjust it for our needs. */
  107. + if (invert)
  108. + new_code = EQ;
  109. +
  110. + op = gen_rtx_fmt_ee (new_code, mode, tmp, const0_rtx);
  111. +
  112. + /* We've generated a new comparison. Update the local variables. */
  113. + code = GET_CODE (op);
  114. + op0 = XEXP (op, 0);
  115. + op1 = XEXP (op, 1);
  116. + }
  117. +
  118. /* 0, reg or 0, imm */
  119. if (cons == CONST0_RTX (mode)
  120. && (REG_P (alt)
  121. --
  122. 2.25.1