aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/pru/pru.md
diff options
context:
space:
mode:
authorDimitar Dimitrov <dimitar@dinux.eu>2023-11-19 12:20:08 +0200
committerDimitar Dimitrov <dimitar@dinux.eu>2024-05-07 10:17:27 +0300
commit47b757cf31fffb2ae5fdb93f9f031890080504a8 (patch)
treeec44b2c0228b6ff7b84c529d92dc1d985c1705f2 /gcc/config/pru/pru.md
parentca7d6d729183685279a0d9dcd39aed11021f1dfa (diff)
downloadgcc-47b757cf31fffb2ae5fdb93f9f031890080504a8.zip
gcc-47b757cf31fffb2ae5fdb93f9f031890080504a8.tar.gz
gcc-47b757cf31fffb2ae5fdb93f9f031890080504a8.tar.bz2
pru: Optimize the extzv and insv patterns
Optimize the generated code for the bit-field extract and insert patterns: - Use bit-set and bit-clear instructions for 1-bit fields. - Expand to SImode operations instead of relying on the default expansion to word (QI) mode. gcc/ChangeLog: * config/pru/pru.md (extzv<mode>): Make it an expand pattern, handle efficiently zero-positioned bit-fields. (insv<mode>): New expand pattern. gcc/testsuite/ChangeLog: * gcc.target/pru/ashiftrt.c: Minor update due to new (but equivalent) generated code sequence. * gcc.target/pru/extzv-1.c: New test. * gcc.target/pru/extzv-2.c: New test. * gcc.target/pru/extzv-3.c: New test. * gcc.target/pru/insv-1.c: New test. * gcc.target/pru/insv-2.c: New test. * gcc.target/pru/insv-3.c: New test. * gcc.target/pru/insv-4.c: New test. Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
Diffstat (limited to 'gcc/config/pru/pru.md')
-rw-r--r--gcc/config/pru/pru.md104
1 files changed, 95 insertions, 9 deletions
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
index 0123952..2ceea2e 100644
--- a/gcc/config/pru/pru.md
+++ b/gcc/config/pru/pru.md
@@ -486,22 +486,108 @@
})
;; Bit extraction
-;; We define it solely to allow combine to choose SImode
+;; One reason to define it is to allow combine to choose SImode
;; for word mode when trying to match our cbranch_qbbx_* insn.
;;
;; Check how combine.cc:make_extraction() uses
;; get_best_reg_extraction_insn() to select the op size.
-(define_insn "extzv<mode>"
- [(set (match_operand:QISI 0 "register_operand" "=r")
+(define_expand "extzv<mode>"
+ [(set (match_operand:QISI 0 "register_operand")
(zero_extract:QISI
- (match_operand:QISI 1 "register_operand" "r")
- (match_operand:QISI 2 "const_int_operand" "i")
- (match_operand:QISI 3 "const_int_operand" "i")))]
+ (match_operand:QISI 1 "register_operand")
+ (match_operand:QISI 2 "const_int_operand")
+ (match_operand:QISI 3 "const_int_operand")))]
""
- "lsl\\t%0, %1, (%S0 * 8 - %2 - %3)\;lsr\\t%0, %0, (%S0 * 8 - %2)"
- [(set_attr "type" "complex")
- (set_attr "length" "8")])
+{
+ const int nbits = INTVAL (operands[2]);
+ const int bitpos = INTVAL (operands[3]);
+ const int trailing_bits = GET_MODE_BITSIZE (<MODE>mode) - nbits - bitpos;
+
+ if (bitpos == 0 && nbits <= 7)
+ {
+ emit_insn (gen_and<mode>3 (operands[0],
+ operands[1],
+ gen_int_mode ((HOST_WIDE_INT_1U << nbits) - 1,
+ <MODE>mode)));
+ DONE;
+ }
+
+ rtx src = operands[1];
+ if (trailing_bits != 0)
+ {
+ emit_insn (gen_ashl<mode>3 (operands[0],
+ operands[1],
+ GEN_INT (trailing_bits)));
+ src = operands[0];
+ }
+ emit_insn (gen_lshr<mode>3 (operands[0],
+ src,
+ GEN_INT (trailing_bits + bitpos)));
+ DONE;
+})
+
+;; Bit-field insert.
+(define_expand "insv<mode>"
+ [(set (zero_extract:QISI
+ (match_operand:QISI 0 "register_operand")
+ (match_operand:QISI 1 "const_int_operand")
+ (match_operand:QISI 2 "const_int_operand"))
+ (match_operand:QISI 3 "reg_or_ubyte_operand"))]
+ ""
+{
+ const int nbits = INTVAL (operands[1]);
+ const int bitpos = INTVAL (operands[2]);
+ if (nbits == 1)
+ {
+ rtx j;
+ rtx src = gen_reg_rtx (<MODE>mode);
+ rtx dst = operands[0];
+
+ emit_move_insn (src, operands[3]);
+
+ emit_insn (gen_and<mode>3 (dst,
+ dst,
+ gen_int_mode (~(HOST_WIDE_INT_1U << bitpos),
+ <MODE>mode)));
+
+ rtx_code_label *skip_set_label = gen_label_rtx ();
+ j = emit_jump_insn (gen_cbranch_qbbx_eq<mode><mode><mode>4 (
+ src,
+ GEN_INT (0),
+ skip_set_label));
+ JUMP_LABEL (j) = skip_set_label;
+ LABEL_NUSES (skip_set_label)++;
+
+ emit_insn (gen_ior<mode>3 (dst,
+ dst,
+ gen_int_mode (HOST_WIDE_INT_1U << bitpos,
+ <MODE>mode)));
+ emit_label (skip_set_label);
+
+ DONE;
+ }
+
+ /* Explicitly expand in order to avoid using word_mode for PRU, and instead
+ use SI and HI modes as applicable. */
+ rtx dst = operands[0];
+ rtx src = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_and<mode>3 (src,
+ force_reg (<MODE>mode, operands[3]),
+ gen_int_mode ((HOST_WIDE_INT_1U << nbits) - 1,
+ <MODE>mode)));
+ if (bitpos > 0)
+ emit_insn (gen_ashl<mode>3 (src, src, gen_int_mode (bitpos, <MODE>mode)));
+
+ HOST_WIDE_INT vmask = ~(((HOST_WIDE_INT_1U << nbits) - 1) << bitpos);
+ emit_insn (gen_and<mode>3 (dst,
+ dst,
+ gen_int_mode (vmask, <MODE>mode)));
+
+ emit_insn (gen_ior<mode>3 (dst, dst, src));
+
+ DONE;
+})
;; Arithmetic Operations