diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp --- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp @@ -18,6 +18,7 @@ #include "AArch64Subtarget.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/ObjCARCUtil.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" @@ -1127,9 +1128,23 @@ // Create a temporarily-floating call instruction so we can add the implicit // uses of arg registers. - unsigned Opc = getCallOpcode(MF, Info.Callee.isReg(), false); + + // Calls with operand bundle "clang.arc.attachedcall" are special. They should + // be expanded to the call, directly followed by a special marker sequence and + // a call to an ObjC library function. + unsigned Opc = 0; + if (Info.CB && objcarc::hasAttachedCallOpBundle(Info.CB)) + Opc = AArch64::BLR_RVMARKER; + else + Opc = getCallOpcode(MF, Info.Callee.isReg(), false); auto MIB = MIRBuilder.buildInstrNoInsert(Opc); + if (Opc == AArch64::BLR_RVMARKER) { + // Add a target global address for the retainRV/claimRV runtime function + // just before the call target. + Function *ARCFn = *objcarc::getAttachedARCFunction(Info.CB); + MIB.addGlobalAddress(ARCFn); + } MIB.add(Info.Callee); // Tell the call which registers are clobbered. diff --git a/llvm/test/CodeGen/AArch64/call-rv-marker.ll b/llvm/test/CodeGen/AArch64/call-rv-marker.ll --- a/llvm/test/CodeGen/AArch64/call-rv-marker.ll +++ b/llvm/test/CodeGen/AArch64/call-rv-marker.ll @@ -29,9 +29,8 @@ ; CHECK-LABEL: rv_marker_1_retain: ; CHECK: .cfi_offset w30, -16 ; CHECK-NEXT: bl foo1 -; SELDAG-NEXT: mov x29, x29 -; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue -; GISEL-NOT: mov x29, x29 +; CHECK-NEXT: mov x29, x29 +; CHECK-NEXT: bl objc_retainAutoreleasedReturnValue ; entry: %call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ] @@ -42,9 +41,8 @@ ; CHECK-LABEL: rv_marker_1_unsafeClaim: ; CHECK: .cfi_offset w30, -16 ; CHECK-NEXT: bl foo1 -; SELDAG-NEXT: mov x29, x29 -; SELDAG-NEXT: bl objc_unsafeClaimAutoreleasedReturnValue -; GISEL-NOT: mov x29, x29 +; CHECK-NEXT: mov x29, x29 +; CHECK-NEXT: bl objc_unsafeClaimAutoreleasedReturnValue ; entry: %call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_unsafeClaimAutoreleasedReturnValue) ] @@ -56,8 +54,8 @@ ; SELDAG: cinc w0, w8, eq ; GISEL: csinc w0, w8, wzr, eq ; CHECK-NEXT: bl foo0 -; SELDAG-NEXT: mov x29, x29 -; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue +; CHECK-NEXT: mov x29, x29 +; CHECK-NEXT: bl objc_retainAutoreleasedReturnValue ; CHECK-NEXT: ldr x30, [sp], #16 ; CHECK-NEXT: b foo2 ; @@ -73,8 +71,8 @@ ; CHECK-LABEL: rv_marker_3 ; CHECK: .cfi_offset w30, -32 ; CHECK-NEXT: bl foo1 -; SELDAG-NEXT: mov x29, x29 -; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue +; CHECK-NEXT: mov x29, x29 +; CHECK-NEXT: bl objc_retainAutoreleasedReturnValue ; entry: %call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ] @@ -96,8 +94,8 @@ ; CHECK-LABEL: rv_marker_4 ; CHECK: .Ltmp3: ; CHECK-NEXT: bl foo1 -; SELDAG-NEXT: mov x29, x29 -; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue +; CHECK-NEXT: mov x29, x29 +; CHECK-NEXT: bl objc_retainAutoreleasedReturnValue ; CHECK-NEXT: .Ltmp4: ; entry: @@ -139,10 +137,8 @@ ; CHECK-LABEL: rv_marker_5_indirect_call ; CHECK: ldr [[ADDR:x[0-9]+]], [ ; CHECK-NEXT: blr [[ADDR]] -; SELDAG-NEXT: mov x29, x29 -; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue -; GISEL-NOT: mov x29, x29 -; +; CHECK-NEXT: mov x29, x29 +; CHECK-NEXT: bl objc_retainAutoreleasedReturnValue entry: %0 = load i8* ()*, i8* ()** @fptr, align 8 %call = call i8* %0() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ] @@ -158,9 +154,8 @@ ; CHECK-NEXT: mov x0, x2 ; CHECK-NEXT: mov x2, [[TMP]] ; CHECK-NEXT: bl foo -; SELDAG-NEXT: mov x29, x29 -; SELDAG-NEXT: bl objc_retainAutoreleasedReturnValue -; GISEL-NOT: mov x29, x29 +; CHECK-NEXT: mov x29, x29 +; CHECK-NEXT: bl objc_retainAutoreleasedReturnValue call i8* @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ] ret void }