@@ -150,6 +150,12 @@ (define_mode_attr slot12_offset [(SI "-52") (DI "-104")])
;; to use the same template.
(define_code_iterator any_extend [sign_extend zero_extend])
+;; These code iterators allow unsigned and signed extraction to be generated
+;; from the same template.
+(define_code_iterator any_extract [sign_extract zero_extract])
+(define_code_attr extract_sidi_shift [(sign_extract "sraiw")
+ (zero_extract "srliw")])
+
;; This code iterator allows the two right shift instructions to be
;; generated from the same template.
(define_code_iterator any_shiftrt [ashiftrt lshiftrt])
@@ -2765,16 +2765,17 @@ (define_insn "*lshrsi3_zero_extend_1"
[(set_attr "type" "shift")
(set_attr "mode" "SI")])
-;; Canonical form for a zero-extend of a logical right shift.
-(define_insn "*lshrsi3_zero_extend_2"
+;; Canonical form for a sign/zero-extend of a logical right shift.
+;; Special case: extract MSB bits of lower 32-bit word
+(define_insn "*lshrsi3_extend_2"
[(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extract:DI (match_operand:DI 1 "register_operand" " r")
+ (any_extract:DI (match_operand:DI 1 "register_operand" " r")
(match_operand 2 "const_int_operand")
(match_operand 3 "const_int_operand")))]
"(TARGET_64BIT && (INTVAL (operands[3]) > 0)
&& (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
{
- return "srliw\t%0,%1,%3";
+ return "<extract_sidi_shift>\t%0,%1,%3";
}
[(set_attr "type" "shift")
(set_attr "mode" "SI")])
@@ -9,6 +9,20 @@ foo1 (int i)
}
/* { dg-final { scan-assembler "sraiw\ta\[0-9\],a\[0-9\],31" } } */
+signed char
+sub2 (long i)
+{
+ return i >> 24;
+}
+/* { dg-final { scan-assembler "sraiw\ta\[0-9\],a\[0-9\],24" } } */
+
+signed short
+sub3 (long i)
+{
+ return i >> 16;
+}
+/* { dg-final { scan-assembler "sraiw\ta\[0-9\],a\[0-9\],16" } } */
+
/* { dg-final { scan-assembler-not "srai\t" } } */
/* { dg-final { scan-assembler-not "srli\t" } } */
/* { dg-final { scan-assembler-not "srliw\t" } } */
The pattern lshrsi3_zero_extend_2 extracts the MSB bits of the lower 32-bit word and zero-extends it back to DImode. This is realized using srliw, which operates on 32-bit registers. The same optimziation can be applied to sign-extensions when emitting a sraiw instead of the srliw. Given these two optimizations are so similar, this patch simply converts the existing one to also cover the sign-extension case as well. gcc/ChangeLog: * config/riscv/iterators.md (sraiw): New code iterator 'any_extract'. New code attribute 'extract_sidi_shift'. * config/riscv/riscv.md (*lshrsi3_zero_extend_2): Rename to... (*lshrsi3_extend_2):...this and add support for sign-extensions. gcc/testsuite/ChangeLog: * gcc.target/riscv/sign-extend-1.c: Test sraiw 24 and sraiw 16. Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu> --- gcc/config/riscv/iterators.md | 6 ++++++ gcc/config/riscv/riscv.md | 9 +++++---- gcc/testsuite/gcc.target/riscv/sign-extend-1.c | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-)