aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorJeff Law <jlaw@ventanamicro.com>2024-05-29 07:41:55 -0600
committerJeff Law <jlaw@ventanamicro.com>2024-05-29 07:48:45 -0600
commit3ae02dcb108df426838bbbcc73d7d01855bc1196 (patch)
tree2ed14986b1c815aa633644d0a6b31e47241f7b9c /gcc/config
parentff41abdca0ab9993b6170b9b1f46b3a40921f1b0 (diff)
downloadgcc-3ae02dcb108df426838bbbcc73d7d01855bc1196.zip
gcc-3ae02dcb108df426838bbbcc73d7d01855bc1196.tar.gz
gcc-3ae02dcb108df426838bbbcc73d7d01855bc1196.tar.bz2
[to-be-committed] [RISC-V] Use pack to handle repeating constants
This patch utilizes zbkb to improve the code we generate for 64bit constants when the high half is a duplicate of the low half. Basically we generate the low half and use a pack instruction with that same register repeated. ie pack dest,src,src That gives us a maximum sequence of 3 instructions and sometimes it will be just 2 instructions (say if the low 32bits can be constructed with a single addi or lui). As with shadd, I'm abusing an RTL opcode. This time it's CONCAT. It's reasonably close to what we're doing. Obviously it's just how we identify the desire to generate a pack in the array of opcodes. We don't actually emit a CONCAT. Note that we don't care about the potential sign extension from bit 31. pack will only look at bits 0..31 of each input (for rv64). So we go ahead and sign extend before synthesizing the low part as that allows us to handle more cases trivially. I had my testsuite generator chew on random cases of a repeating constant without any surprises. I don't see much point in including all those in the testcase (after all there's 2**32 of them). I've got a set of 10 I'm including. Nothing particularly interesting in them. An enterprising developer that needs this improved without zbkb could probably do so with a bit of work. First increase the cost by 1 unit. Second avoid cases where bit 31 is set and restrict it to cases when we can still create pseudos. On the codegen side, when encountering the CONCAT, generate the appropriate shift of "X" into a temporary register, then IOR the temporary with "X" into the new destination. Anyway, I've tested this in my tester (though it doesn't turn on zbkb, yet). I'll let the CI system chew on it overnight, but like mine, I don't think it lights up zbkb. So it's unlikely to spit out anything interesting. gcc/ * config/riscv/crypto.md (riscv_xpack_<X:mode>_<HX:mode>_2): Remove '*' allow it to be used via the gen_* interface. * config/riscv/riscv.cc (riscv_build_integer): Identify when Zbkb can be used to profitably synthesize repeating constants. (riscv_move_integer): Codegen changes to generate those Zbkb sequences. gcc/testsuite/ * gcc.target/riscv/synthesis-9.c: New test.
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/riscv/crypto.md2
-rw-r--r--gcc/config/riscv/riscv.cc23
2 files changed, 24 insertions, 1 deletions
diff --git a/gcc/config/riscv/crypto.md b/gcc/config/riscv/crypto.md
index b632312..b9cac78 100644
--- a/gcc/config/riscv/crypto.md
+++ b/gcc/config/riscv/crypto.md
@@ -107,7 +107,7 @@
;; This is slightly more complex than the other pack patterns
;; that fully expose the RTL as it needs to self-adjust to
;; rv32 and rv64. But it's not that hard.
-(define_insn "*riscv_xpack_<X:mode>_2"
+(define_insn "riscv_xpack_<X:mode>_<HX:mode>_2"
[(set (match_operand:X 0 "register_operand" "=r")
(ior:X (ashift:X (match_operand:X 1 "register_operand" "r")
(match_operand 2 "immediate_operand" "n"))
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a99211d..91fefac 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1123,6 +1123,22 @@ riscv_build_integer (struct riscv_integer_op *codes, HOST_WIDE_INT value,
}
}
+ /* With pack we can generate a 64 bit constant with the same high
+ and low 32 bits triviall. */
+ if (cost > 3 && TARGET_64BIT && TARGET_ZBKB)
+ {
+ unsigned HOST_WIDE_INT loval = value & 0xffffffff;
+ unsigned HOST_WIDE_INT hival = value & ~loval;
+ if (hival >> 32 == loval)
+ {
+ cost = 1 + riscv_build_integer_1 (codes, sext_hwi (loval, 32), mode);
+ codes[cost - 1].code = CONCAT;
+ codes[cost - 1].value = 0;
+ codes[cost - 1].use_uw = false;
+ }
+
+ }
+
return cost;
}
@@ -2679,6 +2695,13 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value,
rtx t = can_create_pseudo_p () ? gen_reg_rtx (mode) : temp;
x = riscv_emit_set (t, x);
}
+ else if (codes[i].code == CONCAT)
+ {
+ rtx t = can_create_pseudo_p () ? gen_reg_rtx (mode) : temp;
+ rtx t2 = gen_lowpart (SImode, x);
+ emit_insn (gen_riscv_xpack_di_si_2 (t, x, GEN_INT (32), t2));
+ x = t;
+ }
else
x = gen_rtx_fmt_ee (codes[i].code, mode,
x, GEN_INT (codes[i].value));