0022-Implement-instruction-patterns-for-ZBS-extension.patch 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. From d3bc6ead74d78d367c0d6cc53efc57c05d8133e9 Mon Sep 17 00:00:00 2001
  2. From: "yilun.xie" <yilun.xie@starfivetech.com>
  3. Date: Thu, 18 Nov 2021 16:08:45 +0800
  4. Subject: [PATCH 22/26] Implement instruction patterns for ZBS extension
  5. ---
  6. gcc/config/riscv/predicates.md | 22 +++++++++++
  7. gcc/config/riscv/riscv.c | 37 ++++++++++++++++++-
  8. gcc/config/riscv/riscv.h | 8 ++++
  9. gcc/testsuite/gcc.target/riscv/zba-slliuw.c | 4 +-
  10. gcc/testsuite/gcc.target/riscv/zbs-bclr.c | 20 ++++++++++
  11. gcc/testsuite/gcc.target/riscv/zbs-bext.c | 20 ++++++++++
  12. gcc/testsuite/gcc.target/riscv/zbs-binv.c | 20 ++++++++++
  13. gcc/testsuite/gcc.target/riscv/zbs-bset.c | 41 +++++++++++++++++++++
  14. 8 files changed, 168 insertions(+), 4 deletions(-)
  15. create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-bclr.c
  16. create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-bext.c
  17. create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-binv.c
  18. create mode 100644 gcc/testsuite/gcc.target/riscv/zbs-bset.c
  19. diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
  20. index 23211513554..7a079ebd175 100644
  21. --- a/gcc/config/riscv/predicates.md
  22. +++ b/gcc/config/riscv/predicates.md
  23. @@ -74,6 +74,11 @@
  24. if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
  25. return false;
  26. + /* Check whether the constant can be loaded in a single
  27. + instruction with zbs extensions. */
  28. + if (TARGET_64BIT && TARGET_ZBS && SINGLE_BIT_MASK_OPERAND (INTVAL (op)))
  29. + return false;
  30. +
  31. /* Otherwise check whether the constant can be loaded in a single
  32. instruction. */
  33. return !LUI_OPERAND (INTVAL (op)) && !SMALL_OPERAND (INTVAL (op));
  34. @@ -217,3 +222,20 @@
  35. {
  36. return riscv_gpr_save_operation_p (op);
  37. })
  38. +
  39. +;; Predicates for the ZBS extension.
  40. +(define_predicate "single_bit_mask_operand"
  41. + (and (match_code "const_int")
  42. + (match_test "pow2p_hwi (INTVAL (op))")))
  43. +
  44. +(define_predicate "not_single_bit_mask_operand"
  45. + (and (match_code "const_int")
  46. + (match_test "pow2p_hwi (~INTVAL (op))")))
  47. +
  48. +(define_predicate "const31_operand"
  49. + (and (match_code "const_int")
  50. + (match_test "INTVAL (op) == 31")))
  51. +
  52. +(define_predicate "const63_operand"
  53. + (and (match_code "const_int")
  54. + (match_test "INTVAL (op) == 63")))
  55. \ No newline at end of file
  56. diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
  57. index 9e45c1ff9be..0978666a366 100644
  58. --- a/gcc/config/riscv/riscv.c
  59. +++ b/gcc/config/riscv/riscv.c
  60. @@ -388,6 +388,14 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
  61. return 1;
  62. }
  63. + if (TARGET_ZBS && SINGLE_BIT_MASK_OPERAND (value))
  64. + {
  65. + /* Simply BSETI. */
  66. + codes[0].code = UNKNOWN;
  67. + codes[0].value = value;
  68. + return 1;
  69. + }
  70. +
  71. /* End with ADDI. When constructing HImode constants, do not generate any
  72. intermediate value that is not itself a valid HImode constant. The
  73. XORI case below will handle those remaining HImode constants. */
  74. @@ -2199,7 +2207,17 @@ riscv_output_move (rtx dest, rtx src)
  75. }
  76. if (src_code == CONST_INT)
  77. - return "li\t%0,%1";
  78. + {
  79. + if (SMALL_OPERAND (INTVAL (src)) || LUI_OPERAND (INTVAL (src)))
  80. + return "li\t%0,%1";
  81. +
  82. + if (TARGET_ZBS
  83. + && SINGLE_BIT_MASK_OPERAND (INTVAL (src)))
  84. + return "bseti\t%0,zero,%S1";
  85. +
  86. + /* Should never reach here. */
  87. + abort ();
  88. + }
  89. if (src_code == HIGH)
  90. return "lui\t%0,%h1";
  91. @@ -3543,7 +3561,9 @@ riscv_memmodel_needs_release_fence (enum memmodel model)
  92. 'A' Print the atomic operation suffix for memory model OP.
  93. 'F' Print a FENCE if the memory model requires a release.
  94. 'z' Print x0 if OP is zero, otherwise print OP normally.
  95. - 'i' Print i if the operand is not a register. */
  96. + 'i' Print i if the operand is not a register.
  97. + 'S' Print shift-index of single-bit mask OP.
  98. + 'T' Print shift-index of inverted single-bit mask OP. */
  99. static void
  100. riscv_print_operand (FILE *file, rtx op, int letter)
  101. @@ -3583,6 +3603,19 @@ riscv_print_operand (FILE *file, rtx op, int letter)
  102. fputs ("i", file);
  103. break;
  104. + case 'S':
  105. + {
  106. + rtx newop = GEN_INT (ctz_hwi (INTVAL (op)));
  107. + output_addr_const (file, newop);
  108. + break;
  109. + }
  110. + case 'T':
  111. + {
  112. + rtx newop = GEN_INT (ctz_hwi (~INTVAL (op)));
  113. + output_addr_const (file, newop);
  114. + break;
  115. + }
  116. +
  117. default:
  118. switch (code)
  119. {
  120. diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
  121. index d17096e1dfa..ff6729aedac 100644
  122. --- a/gcc/config/riscv/riscv.h
  123. +++ b/gcc/config/riscv/riscv.h
  124. @@ -521,6 +521,14 @@ enum reg_class
  125. (((VALUE) | ((1UL<<31) - IMM_REACH)) == ((1UL<<31) - IMM_REACH) \
  126. || ((VALUE) | ((1UL<<31) - IMM_REACH)) + IMM_REACH == 0)
  127. +/* If this is a single bit mask, then we can load it with bseti. But this
  128. + is not useful for any of the low 31 bits because we can use addi or lui
  129. + to load them. It is wrong for loading SImode 0x80000000 on rv64 because it
  130. + needs to be sign-extended. So we restrict this to the upper 32-bits
  131. + only. */
  132. +#define SINGLE_BIT_MASK_OPERAND(VALUE) \
  133. + (pow2p_hwi (VALUE) && (ctz_hwi (VALUE) >= 32))
  134. +
  135. /* Stack layout; function entry, exit and calling. */
  136. #define STACK_GROWS_DOWNWARD 1
  137. diff --git a/gcc/testsuite/gcc.target/riscv/zba-slliuw.c b/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
  138. index 55ebc1c81ce..2c86e446272 100644
  139. --- a/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
  140. +++ b/gcc/testsuite/gcc.target/riscv/zba-slliuw.c
  141. @@ -1,5 +1,5 @@
  142. /* { dg-do compile } */
  143. -/* { dg-options "-march=rv64gc_zba -mabi=lp64 -O2" } */
  144. +/* { dg-options "-march=rv64gc_zba_zbs -mabi=lp64 -O2" } */
  145. long
  146. foo (long i)
  147. @@ -8,4 +8,4 @@ foo (long i)
  148. }
  149. /* XXX: This pattern need combine improvement or intermediate instruction
  150. * from zbs. */
  151. -/* { dg-final { scan-assembler-not "slli.uw" } } */
  152. \ No newline at end of file
  153. +/* { dg-final { scan-assembler "slli.uw" } } */
  154. \ No newline at end of file
  155. diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bclr.c b/gcc/testsuite/gcc.target/riscv/zbs-bclr.c
  156. new file mode 100644
  157. index 00000000000..fdf75b039b9
  158. --- /dev/null
  159. +++ b/gcc/testsuite/gcc.target/riscv/zbs-bclr.c
  160. @@ -0,0 +1,20 @@
  161. +/* { dg-do compile } */
  162. +/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
  163. +
  164. +/* bclr */
  165. +long
  166. +foo0 (long i, long j)
  167. +{
  168. + return i & ~(1L << j);
  169. +}
  170. +
  171. +/* bclri */
  172. +long
  173. +foo1 (long i)
  174. +{
  175. + return i & ~(1L << 20);
  176. +}
  177. +
  178. +/* { dg-final { scan-assembler-times "bclr\t" 1 } } */
  179. +/* { dg-final { scan-assembler-times "bclri\t" 1 } } */
  180. +/* { dg-final { scan-assembler-not "andi" } } */
  181. \ No newline at end of file
  182. diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bext.c b/gcc/testsuite/gcc.target/riscv/zbs-bext.c
  183. new file mode 100644
  184. index 00000000000..766a7c4423a
  185. --- /dev/null
  186. +++ b/gcc/testsuite/gcc.target/riscv/zbs-bext.c
  187. @@ -0,0 +1,20 @@
  188. +/* { dg-do compile } */
  189. +/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
  190. +
  191. +/* bext */
  192. +long
  193. +foo0 (long i, long j)
  194. +{
  195. + return 1L & (i >> j);
  196. +}
  197. +
  198. +/* bexti */
  199. +long
  200. +foo1 (long i)
  201. +{
  202. + return 1L & (i >> 20);
  203. +}
  204. +
  205. +/* { dg-final { scan-assembler-times "bexti\t" 1 } } */
  206. +/* { dg-final { scan-assembler-times "bext\t" 1 } } */
  207. +/* { dg-final { scan-assembler-not "andi" } } */
  208. \ No newline at end of file
  209. diff --git a/gcc/testsuite/gcc.target/riscv/zbs-binv.c b/gcc/testsuite/gcc.target/riscv/zbs-binv.c
  210. new file mode 100644
  211. index 00000000000..d90a6301103
  212. --- /dev/null
  213. +++ b/gcc/testsuite/gcc.target/riscv/zbs-binv.c
  214. @@ -0,0 +1,20 @@
  215. +/* { dg-do compile } */
  216. +/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
  217. +
  218. +/* binv */
  219. +long
  220. +foo0 (long i, long j)
  221. +{
  222. + return i ^ (1L << j);
  223. +}
  224. +
  225. +/* binvi */
  226. +long
  227. +foo1 (long i)
  228. +{
  229. + return i ^ (1L << 20);
  230. +}
  231. +
  232. +/* { dg-final { scan-assembler-times "binv\t" 1 } } */
  233. +/* { dg-final { scan-assembler-times "binvi\t" 1 } } */
  234. +/* { dg-final { scan-assembler-not "andi" } } */
  235. \ No newline at end of file
  236. diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bset.c b/gcc/testsuite/gcc.target/riscv/zbs-bset.c
  237. new file mode 100644
  238. index 00000000000..c3107270153
  239. --- /dev/null
  240. +++ b/gcc/testsuite/gcc.target/riscv/zbs-bset.c
  241. @@ -0,0 +1,41 @@
  242. +/* { dg-do compile } */
  243. +/* { dg-options "-march=rv64gc_zbs -mabi=lp64 -O2" } */
  244. +
  245. +/* bset */
  246. +long
  247. +sub0 (long i, long j)
  248. +{
  249. + return i | (1L << j);
  250. +}
  251. +
  252. +/* bset_mask */
  253. +long
  254. +sub1 (long i, long j)
  255. +{
  256. + return i | (1L << (j & 0x3f));
  257. +}
  258. +
  259. +/* bset_1 */
  260. +long
  261. +sub2 (long i)
  262. +{
  263. + return 1L << i;
  264. +}
  265. +
  266. +/* bset_1_mask */
  267. +long
  268. +sub3 (long i)
  269. +{
  270. + return 1L << (i & 0x3f);
  271. +}
  272. +
  273. +/* bseti */
  274. +long
  275. +sub4 (long i)
  276. +{
  277. + return i | (1L << 20);
  278. +}
  279. +
  280. +/* { dg-final { scan-assembler-times "bset\t" 4 } } */
  281. +/* { dg-final { scan-assembler-times "bseti\t" 1 } } */
  282. +/* { dg-final { scan-assembler-not "andi" } } */
  283. \ No newline at end of file
  284. --
  285. 2.33.1