From: Kito Cheng Date: Wed, 2 Sep 2020 06:26:15 +0000 (+0800) Subject: PR target/96759 - Handle global variable assignment from misaligned structure/PARALLE... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=78fbe731a8822e819c4ca0e6d6f777c7a2f36bad;p=gcc.git PR target/96759 - Handle global variable assignment from misaligned structure/PARALLEL return values. In g:70cdb21e579191fe9f0f1d45e328908e59c0179e, DECL/global variable has handled misaligned stores, but it didn't handle PARALLEL values, and I refer the other part of this function, I found the PARALLEL need handled by emit_group_* functions, so I add a check, and using emit_group_store if storing a PARALLEL value, also checked this change didn't break the testcase(gcc.target/arm/unaligned-argument-3.c) added by the orginal changes. For riscv64 target, struct S {int a; double b;} will pack into a parallel value to return and it has TImode when misaligned access is supported, however TImode required 16-byte align, but it only 8-byte align, so it go to the misaligned stores handling, then it will try to generate move instruction from a PARALLEL value. Tested on following target without introduced new reguression: - riscv32/riscv64 elf - x86_64-linux - arm-eabi v2 changes: - Use maybe_emit_group_store instead of emit_group_store. - Remove push_temp_slots/pop_temp_slots, emit_group_store only require stack temp slot when dst is CONCAT or PARALLEL, however maybe_emit_group_store will always use REG for dst if needed. gcc/ChangeLog: PR target/96759 * expr.c (expand_assignment): Handle misaligned stores with PARALLEL value. gcc/testsuite/ChangeLog: PR target/96759 * g++.target/riscv/pr96759.C: New. * gcc.target/riscv/pr96759.c: New. --- diff --git a/gcc/expr.c b/gcc/expr.c index 1c79518ee4d..9d951e82522 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -5168,6 +5168,8 @@ expand_assignment (tree to, tree from, bool nontemporal) rtx reg, mem; reg = expand_expr (from, NULL_RTX, VOIDmode, EXPAND_NORMAL); + /* Handle PARALLEL. */ + reg = maybe_emit_group_store (reg, TREE_TYPE (from)); reg = force_not_mem (reg); mem = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE); if (TREE_CODE (to) == MEM_REF && REF_REVERSE_STORAGE_ORDER (to)) diff --git a/gcc/testsuite/g++.target/riscv/pr96759.C b/gcc/testsuite/g++.target/riscv/pr96759.C new file mode 100644 index 00000000000..673999a4baf --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/pr96759.C @@ -0,0 +1,8 @@ +/* { dg-options "-mno-strict-align -std=gnu++17" } */ +/* { dg-do compile } */ +struct S { + int a; + double b; +}; +S GetNumbers(); +auto [globalC, globalD] = GetNumbers(); diff --git a/gcc/testsuite/gcc.target/riscv/pr96759.c b/gcc/testsuite/gcc.target/riscv/pr96759.c new file mode 100644 index 00000000000..621c39196fc --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr96759.c @@ -0,0 +1,13 @@ +/* { dg-options "-mno-strict-align" } */ +/* { dg-do compile } */ + +struct S { + int a; + double b; +}; +struct S GetNumbers(); +struct S g; + +void foo(){ + g = GetNumbers(); +}