From 07e915913b6b3d4e6e210f6dbc8e7e0e8ea594c4 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Fri, 28 Jun 2024 07:16:07 +0100 Subject: [PATCH] i386: Handle sign_extend like zero_extend in *concatditi3_[346] This patch generalizes some of the patterns in i386.md that recognize double word concatenation, so they handle sign_extend the same way that they handle zero_extend in appropriate contexts. As a motivating example consider the following function: __int128 foo(long long x, unsigned long long y) { return ((__int128)x<<64) | y; } when compiled with -O2, x86_64 currently generates: foo: movq %rdi, %rdx xorl %eax, %eax xorl %edi, %edi orq %rsi, %rax orq %rdi, %rdx ret with this patch we now generate (the same as if x is unsigned): foo: movq %rsi, %rax movq %rdi, %rdx ret Treating both extensions the same way using any_extend is valid as the top (extended) bits are "unused" after the shift by 64 (or more). In theory, the RTL optimizers might consider canonicalizing the form of extension used in these cases, but zero_extend is faster on some machine, whereas sign extension is supported via addressing modes on others, so handling both in the machine description is probably best. 2024-06-28 Roger Sayle gcc/ChangeLog * config/i386/i386.md (*concat3_3): Change zero_extend to any_extend in first operand to left shift by mode precision. (*concat3_4): Likewise. (*concat3_6): Likewise. gcc/testsuite/ChangeLog * gcc.target/i386/concatditi-1.c: New test case. --- gcc/config/i386/i386.md | 6 +++--- gcc/testsuite/gcc.target/i386/concatditi-1.c | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/concatditi-1.c diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index fd48e7644695..b6ccb1e798d2 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -13446,7 +13446,7 @@ [(set (match_operand: 0 "nonimmediate_operand" "=ro,r,r,&r,x") (any_or_plus: (ashift: - (zero_extend: + (any_extend: (match_operand:DWIH 1 "nonimmediate_operand" "r,m,r,m,x")) (match_operand:QI 2 "const_int_operand")) (zero_extend: @@ -13473,7 +13473,7 @@ (zero_extend: (match_operand:DWIH 1 "nonimmediate_operand" "r,m,r,m")) (ashift: - (zero_extend: + (any_extend: (match_operand:DWIH 2 "nonimmediate_operand" "r,r,m,m")) (match_operand:QI 3 "const_int_operand"))))] "INTVAL (operands[3]) == * BITS_PER_UNIT" @@ -13520,7 +13520,7 @@ [(set (match_operand: 0 "nonimmediate_operand" "=r,o,o,r") (any_or_plus: (ashift: - (zero_extend: + (any_extend: (match_operand:DWIH 1 "nonimmediate_operand" "r,r,r,m")) (match_operand:QI 2 "const_int_operand")) (match_operand: 3 "const_scalar_int_operand" "n,n,Wd,n")))] diff --git a/gcc/testsuite/gcc.target/i386/concatditi-1.c b/gcc/testsuite/gcc.target/i386/concatditi-1.c new file mode 100644 index 000000000000..25c2a95586b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/concatditi-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2" } */ + +__int128 foo(long long x, unsigned long long y) +{ + return ((__int128)x<<64) | y; +} + +/* { dg-final { scan-assembler-not "xorl" } } */ +/* { dg-final { scan-assembler-not "orq" } } */ -- 2.47.2