https://gcc.gnu.org/g:6450419c8536c359629e80c47c42c0d71e3e28a3

commit r15-11288-g6450419c8536c359629e80c47c42c0d71e3e28a3
Author: Andrew Pinski <[email protected]>
Date:   Wed Mar 11 13:01:08 2026 -0700

    simplify-rtx: Fix the case where subreg of a vec_concat could fail 
[PR123822]
    
    So combine (rightfully) produces:
    (subreg:DD (vec_concat:V2DI (const_int -1 [0xffffffffffffffff])
            (reg:DI 145 [ _22 ])) 0)
    
    And then calls simplify_subreg on it.
    simplify_subreg then sees it can remove the vec_concat as this is
    the lower part and try to do `(subreg:DD (const_int -1 
[0xffffffffffffffff]))`
    but that is an invalid constant for DF64 so simplify_subreg rejects
    that and returns NULL but there is code in simplify_subreg to create
    a SUBREG then if the subreg validates. The problem is we are using DImode
    for the inner mode and that validates but when gen_rtx_SUBREG is called
    the inner mode of DImode is not there; only VOIDmode.
    So the fix is to check for VOIDmode before the call to validate_subreg.
    
    Bootstrapped and tested on x86_64-linux-gnu. And lightly tested for 
aarch64-linux-gnu.
    
            PR rtl-optimization/123822
    
    gcc/ChangeLog:
    
            * simplify-rtx.cc (simplify_context::simplify_subreg): Check the
            mode of the part to be non-VOIDmode before calling gen_rtx_SUBREG.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/torture/pr123822-1.c: New test.
    
    Signed-off-by: Andrew Pinski <[email protected]>
    (cherry picked from commit 794acc6340cb2869a74fc69104c38ac5c2840a91)

Diff:
---
 gcc/simplify-rtx.cc                       |  3 ++-
 gcc/testsuite/gcc.dg/torture/pr123822-1.c | 16 ++++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index f8c12d64f0bc..5a520cccf3fe 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -8184,7 +8184,8 @@ simplify_context::simplify_subreg (machine_mode 
outermode, rtx op,
       res = simplify_subreg (outermode, part, part_mode, final_offset);
       if (res)
        return res;
-      if (validate_subreg (outermode, part_mode, part, final_offset))
+      if (GET_MODE (part) != VOIDmode
+         && validate_subreg (outermode, part_mode, part, final_offset))
        return gen_rtx_SUBREG (outermode, part, final_offset);
       return NULL_RTX;
     }
diff --git a/gcc/testsuite/gcc.dg/torture/pr123822-1.c 
b/gcc/testsuite/gcc.dg/torture/pr123822-1.c
new file mode 100644
index 000000000000..38dd05507d1c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr123822-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-ffast-math" } */
+/* { dg-require-effective-target dfp } */
+
+/* PR rtl-optimization/123822 */
+
+typedef __attribute__((__vector_size__(16))) _Decimal64 D;
+
+int i;
+D d;
+
+void
+foo()
+{
+  d /= (D)(d >= *(D *)__builtin_memset(&d, i, 3));
+}

Reply via email to