aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRoger Sayle <roger@nextmovesoftware.com>2020-08-25 18:57:55 +0100
committerRoger Sayle <roger@nextmovesoftware.com>2020-08-25 18:57:55 +0100
commitf410cd248566febad02edacee3ec5f13ae3fc990 (patch)
treeae6c1dd6d21651d41528c6a8f6ff91f391162319 /gcc
parent3d5ed337cb354c2f85a9caf60377bad887b18d53 (diff)
downloadgcc-f410cd248566febad02edacee3ec5f13ae3fc990.zip
gcc-f410cd248566febad02edacee3ec5f13ae3fc990.tar.gz
gcc-f410cd248566febad02edacee3ec5f13ae3fc990.tar.bz2
hppa: Improve expansion of ashldi3 when !TARGET_64BIT
This patch improves the code generated on PA-RISC for DImode (double word) left shifts by small constants (1-31). This target has a very cool shd instruction that can be recognized by combine for simple shifts, but relying on combine is fragile for more complicated functions. This patch tweaks pa.md's ashldi3 expander, to form the optimal two instruction shd/zdep sequence at RTL expansion time. As an example of the benefits of this approach, the simple function unsigned long long u9(unsigned long long x) { return x*9; } currently generates 9 instructions and with this patch now requires only 7. 2020-08-25 Roger Sayle <roger@nextmovesoftware.com> * config/pa/pa.md (ashldi3): Additionally, on !TARGET_64BIT generate a two instruction shd/zdep sequence when shifting registers by suitable constants. (shd_internal): New define_expand to provide gen_shd_internal.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/pa/pa.md34
1 files changed, 33 insertions, 1 deletions
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index 6350c68..713ff17 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -6416,9 +6416,32 @@
[(set (match_operand:DI 0 "register_operand" "")
(ashift:DI (match_operand:DI 1 "lhs_lshift_operand" "")
(match_operand:DI 2 "arith32_operand" "")))]
- "TARGET_64BIT"
+ ""
"
{
+ if (!TARGET_64BIT)
+ {
+ if (REG_P (operands[0]) && GET_CODE (operands[2]) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT shift = UINTVAL (operands[2]);
+ if (shift >= 1 && shift <= 31)
+ {
+ rtx dst = operands[0];
+ rtx src = force_reg (DImode, operands[1]);
+ emit_insn (gen_shd_internal (gen_highpart (SImode, dst),
+ gen_lowpart (SImode, src),
+ GEN_INT (32-shift),
+ gen_highpart (SImode, src),
+ GEN_INT (shift)));
+ emit_insn (gen_ashlsi3 (gen_lowpart (SImode, dst),
+ gen_lowpart (SImode, src),
+ GEN_INT (shift)));
+ DONE;
+ }
+ }
+ /* Fallback to using optabs.c's expand_doubleword_shift. */
+ FAIL;
+ }
if (GET_CODE (operands[2]) != CONST_INT)
{
rtx temp = gen_reg_rtx (DImode);
@@ -6705,6 +6728,15 @@
[(set_attr "type" "shift")
(set_attr "length" "4")])
+(define_expand "shd_internal"
+ [(set (match_operand:SI 0 "register_operand")
+ (ior:SI
+ (lshiftrt:SI (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "const_int_operand"))
+ (ashift:SI (match_operand:SI 3 "register_operand")
+ (match_operand:SI 4 "const_int_operand"))))]
+ "")
+
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")