================
@@ -901,6 +901,36 @@ void
CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {
assert(!cir::MissingFeatures::incrementProfileCounter());
assert(!cir::MissingFeatures::runCleanupsScope());
+ // For a memcpy-equivalent assignment operator, copy the whole object, then
+ // fall through to emit the trailing `return *this`.
+ if (assignOp->isMemcpyEquivalentSpecialMember(getContext())) {
+ CanQualType recordTy =
+ getContext().getCanonicalTagType(assignOp->getParent());
+ LValue dest = makeNaturalAlignAddrLValue(loadCXXThis(), recordTy);
+ mlir::Value srcPtr = builder.createLoad(getLoc(assignOp->getLocation()),
+ getAddrOfLocalVar(args.back()));
+ LValue src = makeNaturalAlignAddrLValue(srcPtr, recordTy);
+ emitAggregateAssign(dest, src, recordTy);
----------------
adams381 wrote:
This block is really doing two separate jobs, and only one of them needs the
frontend.
For a trivially-copyable struct the AST already carries the work: per-field
assignment expressions, plus a `__builtin_memcpy` call for array members.
Dropping the whole-object copy and just emitting the body (which the non-memcpy
path further down already does) is exactly the "reflect the AST and let
optimization coalesce" behavior. The
`assert(!MissingFeatures::assignMemcpyizer())` there is only the coalescing
step; the per-field stores stand on their own and survive `-O3`. That case
needs no frontend change.
The union is the one that can't go through that path. Its body is empty -- just
`return *this` -- because Sema skips union fields at the FIXME in
`SemaDeclCXX.cpp:15474` (copy) and `:15863` (move). There are no copies to
leave, and a memcpyizer has nothing to coalesce on an empty body. That empty
body is the original regression here: `*++yyvsp = yylval` in `kc`, where
`YYSTYPE` is a union, whose no-op `operator=` LLVM deletes at `-O3`. Only a
real AST node or this synthesis fills it.
So two ways forward, and I'd like your and @andykaylor's call before touching
shared code (same scope question I raised on the other thread Jun 16):
1. Implement the FIXME -- form an AST node for the implied union memcpy in copy
and move assignment. That fixes classic and CIR together and lets this PR drop
the synthesis. It is a shared-AST change: it shifts classic union copy/move
codegen, likely reaches constexpr handling, and updates existing CodeGen tests,
and the FIXME has been open a long time, so I don't want to start it without a
maintainer nod.
2. If that's more than this PR should carry, narrow it to the struct/array
lowering and `errorNYI` the union body, then handle the union in its own PR
once the AST question is settled.
Which do you prefer?
https://github.com/llvm/llvm-project/pull/198918
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits