middle-end/99281 - avoid bitfield stores into addressable types
authorRichard Biener <rguenther@suse.de>
Fri, 26 Feb 2021 07:45:36 +0000 (08:45 +0100)
committerRichard Biener <rguenther@suse.de>
Fri, 26 Feb 2021 11:34:27 +0000 (12:34 +0100)
This avoids doing bitfield stores into the return object of calls
when using return-slot optimization and the type is addressable.
Instead we have to pass down the original target RTX to the call
expansion which otherwise tries to create a new temporary.

2021-02-26  Richard Biener  <rguenther@suse.de>

PR middle-end/99281
* expr.c (store_field): For calls with return-slot optimization
and addressable return type expand the store directly.

* g++.dg/pr99218.C: New testcase.

gcc/expr.c
gcc/testsuite/g++.dg/pr99218.C [new file with mode: 0644]

index 86dc1b6..92035c7 100644 (file)
@@ -7214,7 +7214,13 @@ store_field (rtx target, poly_int64 bitsize, poly_int64 bitpos,
              || !multiple_p (bitpos, BITS_PER_UNIT)
              || !poly_int_tree_p (DECL_SIZE (TREE_OPERAND (exp, 1)),
                                   &decl_bitsize)
-             || maybe_ne (decl_bitsize, bitsize)))
+             || maybe_ne (decl_bitsize, bitsize))
+         /* A call with an addressable return type and return-slot
+            optimization must not need bitfield operations but we must
+            pass down the original target.  */
+         && (TREE_CODE (exp) != CALL_EXPR
+             || !TREE_ADDRESSABLE (TREE_TYPE (exp))
+             || !CALL_EXPR_RETURN_SLOT_OPT (exp)))
       /* If we are expanding a MEM_REF of a non-BLKmode non-addressable
          decl we must use bitfield operations.  */
       || (known_size_p (bitsize)
diff --git a/gcc/testsuite/g++.dg/pr99218.C b/gcc/testsuite/g++.dg/pr99218.C
new file mode 100644 (file)
index 0000000..477a6a2
--- /dev/null
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-require-effective-target c++17 }
+
+struct Data
+{
+  Data() {}
+  ~Data() {}
+
+  long long i;
+};
+
+struct X
+{
+  Data a;
+  int b;
+};
+
+template<class T>
+X get(T const&)
+{
+  return X{};
+}
+
+template<class... Ts>
+struct pack_type : Ts...
+{};
+
+int main()
+{
+  pack_type<X>{get(1)};
+}