If SImode reg is continuous left shifted twice, combine related
instruction to one.
extsv_ashlsi3 combines the mov and shift operations into sign_extrace
and shift, cause optimization template of slli.d + and + add.w =>
and + alsl.w fail to match.
Add new template to match this optimization.
(set (reg:DI 91)
(ashift:DI (sign_extract:DI (reg:DI 96 [ x ])
(const_int 31 [0x1f])
(const_int 0 [0]))
(const_int 1 [0x1])))
(insn 9 7 10 2 (set (reg:DI 93)
(const_int 7710 [0x1e1e])) "main.c":10:29 153 {*movdi_64bit}
(nil))
(insn 10 9 11 2 (set (reg:DI 92)
(ior:DI (reg:DI 91)
(reg:DI 93))) "main.c":10:29 98 {*iordi3})
->
(set (reg:DI 95)
(sign_extend:DI (plus:SI (subreg:SI (ior:DI (subreg:DI (ashift:SI
(subreg:SI (reg:DI 96 [ x ]) 0)
(const_int 1 [0x1])) 0)
(const_int 7710 [0x1e1e])) 0)
(subreg:SI (reg:DI 97 [ y ]) 0))))
gcc/ChangeLog:
* config/loongarch/loongarch.md: New template.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/slli-1.c: New test.
Change-Id: I10138f7eaaf6f6ebaa2a6db1c8a89ece3d2d17e5
---
gcc/config/loongarch/loongarch.md | 66 +++++++++++++++++++++
gcc/testsuite/gcc.target/loongarch/slli-1.c | 10 ++++
2 files changed, 76 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/loongarch/slli-1.c
diff --git a/gcc/config/loongarch/loongarch.md
b/gcc/config/loongarch/loongarch.md
index e23c973c38b..47b9445aa95 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -3127,6 +3127,19 @@ (define_insn "sign_extend_ashift<GPR:mode><SHORT:mode>"
[(set_attr "type" "shift")
(set_attr "mode" "<GPR:MODE>")])
+(define_insn "extsv_ashlsi3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ashift:DI
+ (sign_extract:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_uimm5_operand")
+ (const_int 0))
+ (match_operand:SI 3 "const_uimm5_operand")))]
+ "TARGET_64BIT
+ &&(INTVAL (operands[2]) + INTVAL (operands[3])) == 0x20"
+ "slli.w\t%0,%1,%3"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
(define_insn "*rotr<mode>3"
[(set (match_operand:GPR 0 "register_operand" "=r,r")
(rotatert:GPR (match_operand:GPR 1 "register_operand" "r,r")
@@ -3293,6 +3306,59 @@ (define_insn_and_split "<optab>_alsl_reversesi_extended"
}
})
+(define_insn_and_split "<optab>_alsl_reversesi_1_extended"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (sign_extend:DI
+ (plus:SI
+ (subreg:SI
+ (any_bitwise:DI
+ (subreg:DI
+ (ashift:SI
+ (subreg:SI
+ (match_operand:DI 1 "register_operand" "r0")
+ 0)
+ (match_operand:SI 2 "const_immalsl_operand" ""))
+ 0)
+ (match_operand:DI 3 "const_int_operand" "i"))
+ 0)
+ (match_operand:SI 4 "register_operand" "r"))))]
+ "TARGET_64BIT
+ && loongarch_reassoc_shift_bitwise (<is_and>, operands[2], operands[3],
+ SImode)"
+ "#"
+ "&& reload_completed"
+ [; r0 = r1 [&|^] r3 is emitted in PREPARATION-STATEMENTS because we
+ ; need to handle a special case, see below.
+ (set (match_dup 0)
+ (sign_extend:DI
+ (plus:SI (ashift:SI (subreg:SI (match_dup 0) 0) (match_dup 2))
+ (match_dup 4))))]
+ {
+ operands[3] = loongarch_reassoc_shift_bitwise (<is_and>,
+ operands[2],
+ operands[3],
+ SImode);
+
+ if (ins_zero_bitmask_operand (operands[3], SImode))
+ {
+ gcc_checking_assert (<is_and>);
+ emit_move_insn (operands[0], operands[1]);
+ operands[1] = operands[0];
+ }
+
+ if (operands[3] != CONSTM1_RTX (SImode))
+ emit_insn (gen_<optab>di3 (operands[0], operands[1], operands[3]));
+ else
+ {
+ /* Hmm would we really reach here? If we reach here we'd have
+ a miss-optimization in the generic code (as it should have
+ optimized this to alslsi3_extend_subreg). But let's be safe
+ than sorry. */
+ gcc_checking_assert (<is_and>);
+ emit_move_insn (operands[0], operands[1]);
+ }
+ })
+
;; Reverse the order of bytes of operand 1 and store the result in operand 0.
diff --git a/gcc/testsuite/gcc.target/loongarch/slli-1.c
b/gcc/testsuite/gcc.target/loongarch/slli-1.c
new file mode 100644
index 00000000000..891d6457b12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/slli-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+foo (int x)
+{
+ return (x << 2) * 8;
+}
+
+/* { dg-final { scan-assembler-times "slli\.\[dw\]" 1} } */
--
2.20.1