================
@@ -0,0 +1,107 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o
%t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o
%t-cir.ll
+// RUN: FileCheck --check-prefixes=LLVM,LLVM-CIR --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefixes=LLVM,OGCG --input-file=%t.ll %s
+
+struct DA {
+ unsigned a : 31;
+ unsigned b : 1;
+ void *p;
+ void *q;
+};
+
+struct I {
+ unsigned a : 31;
+ unsigned b : 1;
+ unsigned w : 31;
+ unsigned u : 1;
+ unsigned long v;
+ void *t;
+};
+
+union U {
+ struct DA d;
+ struct I i;
+};
+
+unsigned readW(union U x) { return x.i.w; }
+
+// CIR: cir.func{{.*}} @readW(%arg0: !cir.ptr<!rec_U> {llvm.align = 8 :
i64, llvm.byval = !rec_U, llvm.noundef} loc({{.+}})) -> !u32i
+// CIR: %[[X:.*]] = cir.alloca "x" align(8) init : !cir.ptr<!rec_U>
+// CIR: cir.copy %arg0 align(8) to %[[X]] align(8) : !cir.ptr<!rec_U>
+
+// LLVM: define dso_local i32 @readW(ptr noundef byval(%union.U) align 8
%[[ARG:.+]])
+// LLVM-CIR: %[[X:.+]] = alloca %union.U, align 8
+// LLVM-CIR: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[X]], ptr
align 8 %[[ARG]], i64 24, i1 false)
----------------
adams381 wrote:
You are right that OGCG reads the incoming slot in place. The byval pointer is
already the callee's own copy, allocated by the caller, so there is nothing for
a callee-side copy to protect, and a write through the parameter can go
straight to that slot.
Two things are worth separating though. The callee-side copy is not new here.
It was already a load of the whole record followed by a store into the
parameter's slot, and this patch only changes what fills that slot, so the
union's padding survives. Removing the copy improves a shape that predates
this change, but is scope creep.
That is a good follow-up to this one. I have that removal working. It drops
the parameter's spill and points the slot's uses at the incoming pointer, and
it also drops the temp when a function forwards its own byval parameter, which
then matches OGCG byte for byte. It's kind of big because a call is rewritten
together with its callee rather than with the function containing it, so the
operand can still be in its pre-rewrite form when the call is reached. That
means every indirect parameter has to be read before the rewrite starts for the
answer to be stable.
https://github.com/llvm/llvm-project/pull/224672
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits