================
@@ -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

Reply via email to