Adjust the cost for non-zero array element access and vector integer
conversion without SSE4.1. For
extern char *var1;
extern int var2;
void
func (void)
{
var2 = var1[1] + var1[0];
}
we generate
movq var1(%rip), %rdx
movsbl 1(%rdx), %eax
movsbl (%rdx), %edx
addl %edx, %eax
movl %eax, var2(%rip)
instead of
movq var1(%rip), %rax
pxor %xmm1, %xmm1
pinsrw $0, (%rax), %xmm0
pcmpgtb %xmm0, %xmm1
punpcklbw %xmm1, %xmm0
movdqa %xmm0, %xmm1
psraw $15, %xmm1
punpcklwd %xmm1, %xmm0
movd %xmm0, %edx
pshufd $0xe5, %xmm0, %xmm2
movd %xmm2, %eax
addl %edx, %eax
movl %eax, var2(%rip)
with -O2 -march=x86-64. With SSE4.1 enabled, we generate
movq var1(%rip), %rax
pinsrw $0, (%rax), %xmm0
pmovsxbd %xmm0, %xmm0
movd %xmm0, %edx
pextrd $1, %xmm0, %eax
addl %edx, %eax
movl %eax, var2(%rip)
Also update gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c and
gcc.target/i386/pr125026.c as adjusting the cost for non-zero array
element access increases scalar cost so that costmodel-pr69297.c can
be fully vectorized and we generate
movd %eax, %xmm1
pshufd $0xe0, %xmm1, %xmm0
movq %xmm0, 24(%rsp)
instead of
movl %eax, 24(%rsp)
movl %eax, 28(%rsp)
for pr125026.c.
gcc/
PR target/126802
* config/i386/i386.cc (ix86_vector_costs::add_stmt_cost): Adjust
the cost for non-zero array element access and vector integer
conversion without SSE4.1.
testsuite/
PR target/126802
* gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c: Updated.
* gcc.target/i386/pr125026.c: Likewise.
* gcc.target/i386/pr126802-1a.c: New test.
* gcc.target/i386/pr126802-1b.c: Likewise.
* gcc.target/i386/pr126802-1c.c: Likewise.
* gcc.target/i386/pr126802-2a.c: Likewise.
* gcc.target/i386/pr126802-2b.c: Likewise.
* gcc.target/i386/pr126802-2c.c: Likewise.
* gcc.target/i386/pr126802-3a.c: Likewise.
* gcc.target/i386/pr126802-3b.c: Likewise.
* gcc.target/i386/pr126802-3c.c: Likewise.
* gcc.target/i386/pr126802-4a.c: Likewise.
* gcc.target/i386/pr126802-4b.c: Likewise.
* gcc.target/i386/pr126802-4c.c: Likewise.
* gcc.target/i386/pr126802-5a.c: Likewise.
* gcc.target/i386/pr126802-5b.c: Likewise.
* gcc.target/i386/pr126802-5c.c: Likewise.
* gcc.target/i386/pr126802-6a.c: Likewise.
* gcc.target/i386/pr126802-6b.c: Likewise.
* gcc.target/i386/pr126802-6c.c: Likewise.
* gcc.target/i386/pr126802-7a.c: Likewise.
* gcc.target/i386/pr126802-7b.c: Likewise.
* gcc.target/i386/pr126802-7c.c: Likewise.
--
H.J.
From 38a942fa7da7654175bb743ded67d207013a77ea Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Wed, 12 Aug 2026 06:57:32 +0800
Subject: [PATCH v3] x86: Adjust cost for vector integer conversion without
SSE4.1
Adjust the cost for non-zero array element access and vector integer
conversion without SSE4.1. For
extern char *var1;
extern int var2;
void
func (void)
{
var2 = var1[1] + var1[0];
}
we generate
movq var1(%rip), %rdx
movsbl 1(%rdx), %eax
movsbl (%rdx), %edx
addl %edx, %eax
movl %eax, var2(%rip)
instead of
movq var1(%rip), %rax
pxor %xmm1, %xmm1
pinsrw $0, (%rax), %xmm0
pcmpgtb %xmm0, %xmm1
punpcklbw %xmm1, %xmm0
movdqa %xmm0, %xmm1
psraw $15, %xmm1
punpcklwd %xmm1, %xmm0
movd %xmm0, %edx
pshufd $0xe5, %xmm0, %xmm2
movd %xmm2, %eax
addl %edx, %eax
movl %eax, var2(%rip)
with -O2 -march=x86-64. With SSE4.1 enabled, we generate
movq var1(%rip), %rax
pinsrw $0, (%rax), %xmm0
pmovsxbd %xmm0, %xmm0
movd %xmm0, %edx
pextrd $1, %xmm0, %eax
addl %edx, %eax
movl %eax, var2(%rip)
Also update gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c and
gcc.target/i386/pr125026.c as adjusting the cost for non-zero array
element access increases scalar cost so that costmodel-pr69297.c can
be fully vectorized and we generate
movd %eax, %xmm1
pshufd $0xe0, %xmm1, %xmm0
movq %xmm0, 24(%rsp)
instead of
movl %eax, 24(%rsp)
movl %eax, 28(%rsp)
for pr125026.c.
gcc/
PR target/126802
* config/i386/i386.cc (ix86_vector_costs::add_stmt_cost): Adjust
the cost for non-zero array element access and vector integer
conversion without SSE4.1.
testsuite/
PR target/126802
* gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c: Updated.
* gcc.target/i386/pr125026.c: Likewise.
* gcc.target/i386/pr126802-1a.c: New test.
* gcc.target/i386/pr126802-1b.c: Likewise.
* gcc.target/i386/pr126802-1c.c: Likewise.
* gcc.target/i386/pr126802-2a.c: Likewise.
* gcc.target/i386/pr126802-2b.c: Likewise.
* gcc.target/i386/pr126802-2c.c: Likewise.
* gcc.target/i386/pr126802-3a.c: Likewise.
* gcc.target/i386/pr126802-3b.c: Likewise.
* gcc.target/i386/pr126802-3c.c: Likewise.
* gcc.target/i386/pr126802-4a.c: Likewise.
* gcc.target/i386/pr126802-4b.c: Likewise.
* gcc.target/i386/pr126802-4c.c: Likewise.
* gcc.target/i386/pr126802-5a.c: Likewise.
* gcc.target/i386/pr126802-5b.c: Likewise.
* gcc.target/i386/pr126802-5c.c: Likewise.
* gcc.target/i386/pr126802-6a.c: Likewise.
* gcc.target/i386/pr126802-6b.c: Likewise.
* gcc.target/i386/pr126802-6c.c: Likewise.
* gcc.target/i386/pr126802-7a.c: Likewise.
* gcc.target/i386/pr126802-7b.c: Likewise.
* gcc.target/i386/pr126802-7c.c: Likewise.
Signed-off-by: H.J. Lu <[email protected]>
---
gcc/config/i386/i386.cc | 44 ++++++++++++++++++-
.../vect/costmodel/x86_64/costmodel-pr69297.c | 3 +-
gcc/testsuite/gcc.target/i386/pr125026.c | 1 -
gcc/testsuite/gcc.target/i386/pr126802-1a.c | 26 +++++++++++
gcc/testsuite/gcc.target/i386/pr126802-1b.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-1c.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-2a.c | 26 +++++++++++
gcc/testsuite/gcc.target/i386/pr126802-2b.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-2c.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-3a.c | 25 +++++++++++
gcc/testsuite/gcc.target/i386/pr126802-3b.c | 18 ++++++++
gcc/testsuite/gcc.target/i386/pr126802-3c.c | 18 ++++++++
gcc/testsuite/gcc.target/i386/pr126802-4a.c | 36 +++++++++++++++
gcc/testsuite/gcc.target/i386/pr126802-4b.c | 23 ++++++++++
gcc/testsuite/gcc.target/i386/pr126802-4c.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-5a.c | 26 +++++++++++
gcc/testsuite/gcc.target/i386/pr126802-5b.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-5c.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-6a.c | 26 +++++++++++
gcc/testsuite/gcc.target/i386/pr126802-6b.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-6c.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-7a.c | 26 +++++++++++
gcc/testsuite/gcc.target/i386/pr126802-7b.c | 21 +++++++++
gcc/testsuite/gcc.target/i386/pr126802-7c.c | 21 +++++++++
24 files changed, 524 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-1a.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-1b.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-1c.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-2a.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-2b.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-2c.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-3a.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-3b.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-3c.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-4a.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-4b.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-4c.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-5a.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-5b.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-5c.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-6a.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-6b.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-6c.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-7a.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-7b.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr126802-7c.c
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 3f00ddaa547..5a3eefdff34 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -26618,6 +26618,9 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
= (kind == scalar_stmt || kind == scalar_load || kind == scalar_store);
int stmt_cost = - 1;
+ tree rhs_type = nullptr;
+ bool vector_int_conversion_p = false;
+
bool fp = false;
machine_mode mode = scalar_p ? SImode : TImode;
@@ -26721,13 +26724,16 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
break;
case NOP_EXPR:
/* Only sign-conversions are free. */
+ rhs_type = TREE_TYPE (gimple_assign_rhs1 (stmt_info->stmt));
if (tree_nop_conversion_p
(TREE_TYPE (gimple_assign_lhs (stmt_info->stmt)),
- TREE_TYPE (gimple_assign_rhs1 (stmt_info->stmt))))
+ rhs_type))
stmt_cost = 0;
else if (fp)
stmt_cost = vec_fp_conversion_cost
(ix86_tune_cost, GET_MODE_BITSIZE (mode));
+ else if (!scalar_p)
+ vector_int_conversion_p = true;
break;
case FLOAT_EXPR:
@@ -27113,7 +27119,41 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
/ GET_MODE_BITSIZE (TYPE_MODE (ls_eltype)) + 1);
}
if (stmt_cost == -1)
- stmt_cost = ix86_default_vector_cost (kind, mode);
+ {
+ stmt_cost = ix86_default_vector_cost (kind, mode);
+
+ int scale = 0;
+ if (scalar_p)
+ {
+ if (stmt_info
+ && stmt_info->stmt
+ && gimple_code (stmt_info->stmt) == GIMPLE_ASSIGN)
+ {
+ tree lhs = gimple_assign_lhs (stmt_info->stmt);
+ if (TREE_CODE (lhs) == ARRAY_REF)
+ {
+ tree index = TREE_OPERAND (lhs, 1);
+ /* Two more instructions are needed to access non-zero
+ array element. */
+ if (TREE_CODE (index) != INTEGER_CST
+ || compare_tree_int (index, 0) != 0)
+ scale = 2;
+ }
+ }
+ }
+ else if (vector_int_conversion_p && !TARGET_SSE4_1)
+ {
+ /* Two instructions are needed to emulate vector integer
+ conversions. One more instruction is needed to emulate
+ 2-element vector conversion of QImode and HImode. */
+ machine_mode rhs_mode = TYPE_MODE (rhs_type);
+ rhs_mode = GET_MODE_INNER (rhs_mode);
+ scale = (rhs_mode == SImode || GET_MODE_NUNITS (mode) != 2
+ ? 2 : 3);
+ }
+
+ stmt_cost += COSTS_N_INSNS (1) * scale;
+ }
/* BIT_FIELD_REF <vect_**, 64, 0> with count 0 costs 0 in body. */
if (kind == vec_perm && vectype && count != 0)
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c
index ef74785f6a8..1ddf3704d11 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-pr69297.c
@@ -97,5 +97,4 @@ foo (int* diff)
return satd;
}
-/* { dg-final { scan-tree-dump "vectorization is not profitable" "slp1" } } */
-/* { dg-final { scan-tree-dump-times "Vectorizing SLP tree" 1 "slp1" } } */
+/* { dg-final { scan-tree-dump-times "Vectorizing SLP tree" 2 "slp1" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr125026.c b/gcc/testsuite/gcc.target/i386/pr125026.c
index 96ac6a9ef20..22059b42ae5 100644
--- a/gcc/testsuite/gcc.target/i386/pr125026.c
+++ b/gcc/testsuite/gcc.target/i386/pr125026.c
@@ -15,4 +15,3 @@ void g(int h[1]) {
}
/* { dg-final { scan-assembler-times "movabsq\[ \\t\]+\\\$4294967297, %r\[a-z0-9\]+" 2 { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "xmm" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-1a.c b/gcc/testsuite/gcc.target/i386/pr126802-1a.c
new file mode 100644
index 00000000000..37b9918f48f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rdx
+** movsbl 1\(%rdx\), %eax
+** movsbl \(%rdx\), %edx
+** addl %edx, %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+extern char *var1;
+extern int var2;
+
+void
+func (void)
+{
+ var2 = var1[1] + var1[0];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-1b.c b/gcc/testsuite/gcc.target/i386/pr126802-1b.c
new file mode 100644
index 00000000000..51e4d65d7e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-1b.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v2" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** pinsrw \$0, \(%rax\), %xmm0
+** pmovsxbd %xmm0, %xmm0
+** movd %xmm0, %edx
+** pextrd \$1, %xmm0, %eax
+** addl %edx, %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-1a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-1c.c b/gcc/testsuite/gcc.target/i386/pr126802-1c.c
new file mode 100644
index 00000000000..2bdbae0e416
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-1c.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** vpinsrw \$0, \(%rax\), %xmm0, %xmm0
+** vpmovsxbd %xmm0, %xmm0
+** vmovd %xmm0, %edx
+** vpextrd \$1, %xmm0, %eax
+** addl %edx, %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-1a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-2a.c b/gcc/testsuite/gcc.target/i386/pr126802-2a.c
new file mode 100644
index 00000000000..cd833388530
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-2a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rdx
+** movswl 2\(%rdx\), %eax
+** movswl \(%rdx\), %edx
+** addl %edx, %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+extern short *var1;
+extern int var2;
+
+void
+func (void)
+{
+ var2 = var1[1] + var1[0];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-2b.c b/gcc/testsuite/gcc.target/i386/pr126802-2b.c
new file mode 100644
index 00000000000..545e4372513
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-2b.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v2" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** movd \(%rax\), %xmm0
+** pmovsxwd %xmm0, %xmm0
+** movd %xmm0, %edx
+** pextrd \$1, %xmm0, %eax
+** addl %edx, %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-2a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-2c.c b/gcc/testsuite/gcc.target/i386/pr126802-2c.c
new file mode 100644
index 00000000000..abbd7d4d9a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-2c.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** vmovd \(%rax\), %xmm0
+** vpmovsxwd %xmm0, %xmm0
+** vmovd %xmm0, %edx
+** vpextrd \$1, %xmm0, %eax
+** addl %edx, %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-2a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-3a.c b/gcc/testsuite/gcc.target/i386/pr126802-3a.c
new file mode 100644
index 00000000000..b2fd9b5e03e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-3a.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rdx
+** movl 4\(%rdx\), %eax
+** addl \(%rdx\), %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+extern int *var1;
+extern int var2;
+
+void
+func (void)
+{
+ var2 = var1[1] + var1[0];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-3b.c b/gcc/testsuite/gcc.target/i386/pr126802-3b.c
new file mode 100644
index 00000000000..ca183819894
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-3b.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v2" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rdx
+** movl 4\(%rdx\), %eax
+** addl \(%rdx\), %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-3a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-3c.c b/gcc/testsuite/gcc.target/i386/pr126802-3c.c
new file mode 100644
index 00000000000..4c9c9d6f137
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-3c.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rdx
+** movl 4\(%rdx\), %eax
+** addl \(%rdx\), %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-3a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-4a.c b/gcc/testsuite/gcc.target/i386/pr126802-4a.c
new file mode 100644
index 00000000000..6461fdfbc0a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-4a.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** pxor %xmm1, %xmm1
+** movd \(%rax\), %xmm0
+** pcmpgtb %xmm0, %xmm1
+** punpcklbw %xmm1, %xmm0
+** movdqa %xmm0, %xmm1
+** psraw \$15, %xmm1
+** punpcklwd %xmm1, %xmm0
+** movdqa %xmm0, %xmm1
+** psrldq \$8, %xmm1
+** paddd %xmm1, %xmm0
+** movdqa %xmm0, %xmm1
+** psrldq \$4, %xmm1
+** paddd %xmm1, %xmm0
+** movd %xmm0, var2\(%rip\)
+** ret
+**...
+*/
+
+extern char *var1;
+extern int var2;
+
+void
+func (void)
+{
+ var2 = var1[1] + var1[0] + var1[2] + var1[3];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-4b.c b/gcc/testsuite/gcc.target/i386/pr126802-4b.c
new file mode 100644
index 00000000000..04710ec9c6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-4b.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v2" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** pmovsxbd \(%rax\), %xmm0
+** movdqa %xmm0, %xmm1
+** psrldq \$8, %xmm1
+** paddd %xmm1, %xmm0
+** movdqa %xmm0, %xmm1
+** psrldq \$4, %xmm1
+** paddd %xmm1, %xmm0
+** movd %xmm0, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-4a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-4c.c b/gcc/testsuite/gcc.target/i386/pr126802-4c.c
new file mode 100644
index 00000000000..f4257eec135
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-4c.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** vpmovsxbd \(%rax\), %xmm0
+** vpsrldq \$8, %xmm0, %xmm1
+** vpaddd %xmm1, %xmm0, %xmm0
+** vpsrldq \$4, %xmm0, %xmm1
+** vpaddd %xmm1, %xmm0, %xmm0
+** vmovd %xmm0, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-4a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-5a.c b/gcc/testsuite/gcc.target/i386/pr126802-5a.c
new file mode 100644
index 00000000000..213b34f2256
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-5a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rdx
+** movsbl 1\(%rdx\), %eax
+** movsbl \(%rdx\), %edx
+** addl %edx, %eax
+** movw %ax, var2\(%rip\)
+** ret
+**...
+*/
+
+extern char *var1;
+extern short var2;
+
+void
+func (void)
+{
+ var2 = var1[1] + var1[0];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-5b.c b/gcc/testsuite/gcc.target/i386/pr126802-5b.c
new file mode 100644
index 00000000000..08091e2befc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-5b.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v2" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** pinsrw \$0, \(%rax\), %xmm0
+** pmovsxbw %xmm0, %xmm0
+** pextrw \$0, %xmm0, %edx
+** pextrw \$1, %xmm0, %eax
+** addl %edx, %eax
+** movw %ax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-5a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-5c.c b/gcc/testsuite/gcc.target/i386/pr126802-5c.c
new file mode 100644
index 00000000000..35546403ae7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-5c.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** vpinsrw \$0, \(%rax\), %xmm0, %xmm0
+** vpmovsxbw %xmm0, %xmm0
+** vpextrw \$0, %xmm0, %edx
+** vpextrw \$1, %xmm0, %eax
+** addl %edx, %eax
+** movw %ax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-5a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-6a.c b/gcc/testsuite/gcc.target/i386/pr126802-6a.c
new file mode 100644
index 00000000000..6dd358f9b13
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-6a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rdx
+** movzbl 1\(%rdx\), %eax
+** movzbl \(%rdx\), %edx
+** addl %edx, %eax
+** movw %ax, var2\(%rip\)
+** ret
+**...
+*/
+
+extern unsigned char *var1;
+extern unsigned short var2;
+
+void
+func (void)
+{
+ var2 = var1[1] + var1[0];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-6b.c b/gcc/testsuite/gcc.target/i386/pr126802-6b.c
new file mode 100644
index 00000000000..b4018e41031
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-6b.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v2" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** pinsrw \$0, \(%rax\), %xmm0
+** pmovzxbw %xmm0, %xmm0
+** pextrw \$0, %xmm0, %edx
+** pextrw \$1, %xmm0, %eax
+** addl %edx, %eax
+** movw %ax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-6a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-6c.c b/gcc/testsuite/gcc.target/i386/pr126802-6c.c
new file mode 100644
index 00000000000..123833562e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-6c.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** vpinsrw \$0, \(%rax\), %xmm0, %xmm0
+** vpmovzxbw %xmm0, %xmm0
+** vpextrw \$0, %xmm0, %edx
+** vpextrw \$1, %xmm0, %eax
+** addl %edx, %eax
+** movw %ax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-6a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-7a.c b/gcc/testsuite/gcc.target/i386/pr126802-7a.c
new file mode 100644
index 00000000000..971c9380c7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-7a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rdx
+** movzwl 2\(%rdx\), %eax
+** movzwl \(%rdx\), %edx
+** addl %edx, %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+extern unsigned short *var1;
+extern unsigned int var2;
+
+void
+func (void)
+{
+ var2 = var1[1] + var1[0];
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-7b.c b/gcc/testsuite/gcc.target/i386/pr126802-7b.c
new file mode 100644
index 00000000000..a36a6d32c88
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-7b.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v2" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** movd \(%rax\), %xmm0
+** pmovzxwd %xmm0, %xmm0
+** movd %xmm0, %edx
+** pextrd \$1, %xmm0, %eax
+** addl %edx, %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-7a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr126802-7c.c b/gcc/testsuite/gcc.target/i386/pr126802-7c.c
new file mode 100644
index 00000000000..0396bd52b95
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126802-7c.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64-v4" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target { *-*-linux* && lp64 } } {^\t?\.} } } */
+
+/*
+**func:
+**.LFB0:
+** .cfi_startproc
+** movq var1\(%rip\), %rax
+** vmovd \(%rax\), %xmm0
+** vpmovzxwd %xmm0, %xmm0
+** vmovd %xmm0, %edx
+** vpextrd \$1, %xmm0, %eax
+** addl %edx, %eax
+** movl %eax, var2\(%rip\)
+** ret
+**...
+*/
+
+#include "pr126802-7a.c"
--
2.55.0