[clang][codegen] Fix another lifetime emission on alloca on non-default address space.
authorMichael Liao <michael.hliao@gmail.com>
Sun, 9 Feb 2020 18:09:19 +0000 (13:09 -0500)
committerMichael Liao <michael.hliao@gmail.com>
Mon, 10 Feb 2020 05:15:56 +0000 (00:15 -0500)
- Lifetime intrinsics expect the pointer directly from alloca. Need
  extra handling for targets with alloca on non-default (or non-zero)
  address space.

clang/lib/CodeGen/CGCall.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/test/CodeGenCXX/amdgcn-call-with-aggarg.cpp [new file with mode: 0644]

index 3edcfb2..9ef2a3b 100644 (file)
@@ -3690,8 +3690,9 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
   }
 
   AggValueSlot ArgSlot = AggValueSlot::ignored();
+  Address ArgSlotAlloca = Address::invalid();
   if (hasAggregateEvaluationKind(E->getType())) {
-    ArgSlot = CreateAggTemp(E->getType(), "agg.tmp");
+    ArgSlot = CreateAggTemp(E->getType(), "agg.tmp", &ArgSlotAlloca);
 
     // Emit a lifetime start/end for this temporary. If the type has a
     // destructor, then we need to keep it alive. FIXME: We should still be able
@@ -3699,8 +3700,9 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
     if (!E->getType().isDestructedType()) {
       uint64_t size =
           CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(E->getType()));
-      if (auto *lifetimeSize = EmitLifetimeStart(size, ArgSlot.getPointer()))
-        args.addLifetimeCleanup({ArgSlot.getPointer(), lifetimeSize});
+      if (auto *lifetimeSize =
+              EmitLifetimeStart(size, ArgSlotAlloca.getPointer()))
+        args.addLifetimeCleanup({ArgSlotAlloca.getPointer(), lifetimeSize});
     }
   }
 
index f48d8a4..7ddd38c 100644 (file)
@@ -2264,8 +2264,9 @@ public:
 
   /// CreateAggTemp - Create a temporary memory object for the given
   /// aggregate type.
-  AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp") {
-    return AggValueSlot::forAddr(CreateMemTemp(T, Name),
+  AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp",
+                             Address *Alloca = nullptr) {
+    return AggValueSlot::forAddr(CreateMemTemp(T, Name, Alloca),
                                  T.getQualifiers(),
                                  AggValueSlot::IsNotDestructed,
                                  AggValueSlot::DoesNotNeedGCBarriers,
diff --git a/clang/test/CodeGenCXX/amdgcn-call-with-aggarg.cpp b/clang/test/CodeGenCXX/amdgcn-call-with-aggarg.cpp
new file mode 100644 (file)
index 0000000..e9d3683
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm -O3 -disable-llvm-passes -o - %s | FileCheck %s
+
+struct A {
+  float x, y, z, w;
+};
+
+void foo(A a);
+
+// CHECK-LABEL: @_Z4testv
+// CHECK: %[[lvar:.*]] = alloca %struct.A, align 4, addrspace(5)
+// CHECK: %[[atmp:.*]] = alloca %struct.A, align 4, addrspace(5)
+// CHECK: %[[lcst:.*]] = bitcast %struct.A addrspace(5)* %[[lvar]] to i8 addrspace(5)*
+// CHECK: call void @llvm.lifetime.start.p5i8(i64 16, i8 addrspace(5)* %[[lcst]]
+// CHECK: %[[acst:.*]] = bitcast %struct.A addrspace(5)* %[[atmp]] to i8 addrspace(5)*
+// CHECK: call void @llvm.lifetime.start.p5i8(i64 16, i8 addrspace(5)* %[[acst]]
+void test() {
+  A a;
+  foo(a);
+}