From 7197743de1d10b74ed0a5da46fbd56b57201cbd9 Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru Date: Wed, 19 Mar 2025 13:30:27 -0700 Subject: [PATCH] Auto upgrade bitcode to new vararg representation for coro.id.retcon.once intrinsic The signature of coro.id.retcon.once intrinsic was modified in https://github.com/swiftlang/llvm-project/pull/10015 with an extra vararg. This commit adds an auto upgrader to LLVM in order to be compatible with compilers generating old bitcode (intrinsic without the vararg). rdar://147426562 (cherry picked from commit 969660bb3160f89e7d4df1fd7ac746112f9cca56) (cherry picked from commit 2eaa148d80e4cb95d6025330698cbe5cafd3ec20) (cherry picked from commit 889ce2695d88f8d5d2ff67913d113eff32582dc6) (cherry picked from commit 031baa148305ef15edf01d83af018e38f681c580) (cherry picked from commit 98dd0628098ab9caf71fd135c8d399214fc310bd) --- llvm/lib/IR/AutoUpgrade.cpp | 13 ++++ .../coro-retcon-frame-auto-upgrade-test.ll.bc | Bin 0 -> 2568 bytes .../coro-retcon-frame-auto-upgrade-test.ll | 59 ++++++++++++++++++ .../Coroutines/coro-retcon-frame-old.ll | 56 +++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 llvm/test/Transforms/Coroutines/Inputs/coro-retcon-frame-auto-upgrade-test.ll.bc create mode 100644 llvm/test/Transforms/Coroutines/coro-retcon-frame-auto-upgrade-test.ll create mode 100644 llvm/test/Transforms/Coroutines/coro-retcon-frame-old.ll diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index 76ca7f691607d..0a5c5707f30e7 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -1102,6 +1102,13 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn, return true; } + if (!F->isVarArg() && Name == "coro.id.retcon.once") { + rename(F); + NewFn = Intrinsic::getDeclaration(F->getParent(), + Intrinsic::coro_id_retcon_once); + return true; + } + break; } case 'd': @@ -4515,6 +4522,12 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) { break; } + case Intrinsic::coro_id_retcon_once: { + SmallVector Args(CI->args()); + NewCall = Builder.CreateCall(NewFn, Args); + break; + } + case Intrinsic::vector_extract: { StringRef Name = F->getName(); Name = Name.substr(5); // Strip llvm diff --git a/llvm/test/Transforms/Coroutines/Inputs/coro-retcon-frame-auto-upgrade-test.ll.bc b/llvm/test/Transforms/Coroutines/Inputs/coro-retcon-frame-auto-upgrade-test.ll.bc new file mode 100644 index 0000000000000000000000000000000000000000..0538c7912a6927f731124a3c787c41982f01b8a1 GIT binary patch literal 2568 zcmZ8i4@?`^8Gq-)zAHFq(>M(T+p`0W=oH`rq1ds#+L$6|OIwGf5>Zy+!`Ok0fUymM zWX;Z)_J~3!L(%4GsRU~_t(&xwDB2=5>wt4o54?;v>x34R*@?-YjV35zTcl-wzGt{* z+Oxm+z4v?Hz3=aPuiiO*qgI2E93j-IWXoPT_|cDF`R9e#N|I#_M710ll?Z)CAXFeT zA{odO15uIEQAaXwuR>jI9wUa7&&%mzectI-Uh}f7eypJWth!obqKm$kU)?n93M7oB z4bKWAYR8zYElHo#7@Up6hTjs^O+(F0Y;=1=Y;y32vSN{%-%{K(GV;7ywd2;HXblgbP# zMed=zE3&zBG=cbPUVg-oZ{(XvqS16XANJf|gb)q9WEi2bO+%~yfkv_gCBqp!qU?XN zt7Ucyp}inSg52goPrYFu{q{4nc2uJ2Umz_Lq-~1alN-FF-XWYz2Ya|NPpu`wySgo}B-4#lZK!a`MAN{(*~c zbiMW0wPQbHUYZxP=THAm-$cx#JkYq&rjYZe@)!7=vFp%t9#`!P3biDF(6mhX!JgS% zYBs=T-uQZv^8aO$yn}!G6@q=_R78fJVpx}Hy2yYOk{B;9YWmUaHAL7Y1nr!Tseyhf z6z@^qMyk)%%o@+sDC_mJGrFsjT0bk#iA76Nq%G;RjgYof|42AMouH`!mkGOCB|e}RTrzewaToznHqIMcf+V%H0owKy`Md0xfHc5IL#MG>!ql5h_s|u zHGLlHL_1a2E(D?Hg+NRQc&NT|s_(HJwmrrREws>6Bn0EaKs>VZ{wi}n&HQbeSz*c6 zdf{)ge>p~ArfmJ;az-FQN`W0ry zqxw9pST(4YS=F*Z^>;VZrDkri3``%T75CCi*3CR-OK+}l+S!P1F|&2WsJm^{C5$@A z;9cXF{D$`|mz=hXqXII^u04*XxhJHeU zFD-E>6&&I40;DoBzb>O1{y4Q33-0oW*=8hXmN0r3|q`Ko~)~5If zHBg?b?0x~Vg7exOI3t=a5SFu1+qfwECL9v&QbxOE&}KQ@-;L;JIqkxvHo2Y*ZiY~; zfdk+V&lC)=2SxsS6NF$93SEShSfB#nd?rZ?w*3>hm+r8jTk6vMoOSfw$G<$Pv8Nl}<>;iRpwYfX zUijX$eRuTrqSvxzC*LF*8(bRa;^lgmY*qads~q(yKc0#!9yYvs^ZG|`BKar#3jG=} zfxShj$FTm6R5R-BLy8~d@{DmG+?j`fKTD3M@!N_Qc%W*aeLy&7%|N(eUI66TxOwpy zxAQ>zfuy;#j@KmYf5#ZZuN+;rzD{q*VJ_h~2Kb$nxP^OXCEN%Ywq4>94k~ib zg2W}91suB}af~An+65St{}((bzZ2eJz*ImImv9`D5+I37cnGjfKoXa5fY2Kd^9JA$ z^HLo1K(IU99UchyTKrsRXSbIN``UccsH3YR+#B-2zlCdS3%2xeo&L_wzN3}i?qGLi zM_Xmk7xs2{Rd#oIeNXXL-{Fp~r_)exDB$b*LbhYq(h+syO>K2G>~3$H+3Rid`YJ1{@D3GV`4OKtoSRgIeW7sGfgslv x@^=T1hN_%kU~jmi%NMG`wpOegTHz0JM|~AsZ@9anH*h$}wfQPLJ8@Xhe*qqLDI@>@ literal 0 HcmV?d00001 diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-frame-auto-upgrade-test.ll b/llvm/test/Transforms/Coroutines/coro-retcon-frame-auto-upgrade-test.ll new file mode 100644 index 0000000000000..d17929538f0e4 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-retcon-frame-auto-upgrade-test.ll @@ -0,0 +1,59 @@ +; RUN: llvm-dis < %S/Inputs/coro-retcon-frame-auto-upgrade-test.ll.bc 2>&1 | FileCheck %s + +; ModuleID = '../llvm-project/llvm/test/Transforms/Coroutines/coro-retcon-frame-auto-upgrade.bc' +; CHECK: source_filename = "../llvm-project/llvm/test/Transforms/Coroutines/coro-retcon-frame-auto-upgrade.ll" +; CHECK: target datalayout = "p:64:64:64" + +; CHECK: declare void @prototype_f(ptr, i1) + +; CHECK: declare noalias ptr @allocate(i32) + +; CHECK: declare void @deallocate(ptr) + +; CHECK: declare void @init(ptr) + +; CHECK: declare void @use(ptr) + +; CHECK: declare void @use_addr_val(i64, ptr) + +; Function Attrs: presplitcoroutine +; CHECK: define { ptr, ptr } @f(ptr %buffer) #0 { +; CHECK: entry: +; CHECK: %tmp = alloca { i64, i64 }, align 8 +; CHECK: %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0 +; CHECK: %proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1 +; CHECK: store i64 0, ptr %proj.1, align 8 +; CHECK: store i64 0, ptr %proj.2, align 8 +; CHECK: %escape_addr = ptrtoint ptr %tmp to i64 +; CHECK: %id = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 32, i32 8, ptr %buffer, ptr @prototype_f, ptr @allocate, ptr @deallocate) +; CHECK: %hdl = call ptr @llvm.coro.begin(token %id, ptr null) +; CHECK: %proj.2.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1 +; CHECK: call void @init(ptr %proj.1) +; CHECK: call void @init(ptr %proj.2.2) +; CHECK: call void @use_addr_val(i64 %escape_addr, ptr %tmp) +; CHECK: %abort = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr %tmp) +; CHECK: br i1 %abort, label %end, label %resume + +; CHECK: resume: ; preds = %entry +; CHECK: call void @use(ptr %tmp) +; CHECK: br label %end + +; CHECK: end: ; preds = %resume, %entry +; CHECK: %0 = call i1 @llvm.coro.end(ptr %hdl, i1 false, token none) +; CHECK: unreachable +; CHECK: } + +; Function Attrs: nounwind +; CHECK: declare ptr @llvm.coro.begin(token, ptr writeonly) #1 + +; Function Attrs: nounwind +; CHECK: declare i1 @llvm.coro.suspend.retcon.i1(...) #1 + +; Function Attrs: nounwind +; CHECK: declare i1 @llvm.coro.end(ptr, i1, token) #1 + +; Function Attrs: nounwind +; CHECK: declare token @llvm.coro.id.retcon.once(i32, i32, ptr, ptr, ptr, ptr, ...) #1 + +; CHECK: attributes #0 = { presplitcoroutine } +; CHECK: attributes #1 = { nounwind } \ No newline at end of file diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-frame-old.ll b/llvm/test/Transforms/Coroutines/coro-retcon-frame-old.ll new file mode 100644 index 0000000000000..21a765b6ff006 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-retcon-frame-old.ll @@ -0,0 +1,56 @@ +; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s + +target datalayout = "p:64:64:64" + +declare void @prototype_f(ptr, i1) + +declare noalias ptr @allocate(i32 %size) +declare void @deallocate(ptr %ptr) +declare void @init(ptr %ptr) +declare void @use(ptr %ptr) +declare void @use_addr_val(i64 %val, ptr %addr) + +define { ptr, ptr } @f(ptr %buffer) presplitcoroutine { +entry: + %tmp = alloca { i64, i64 }, align 8 + %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0 + %proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1 + store i64 0, ptr %proj.1, align 8 + store i64 0, ptr %proj.2, align 8 + %escape_addr = ptrtoint ptr %tmp to i64 + %id = call token (i32, i32, ptr, ptr, ptr, ptr) @llvm.coro.id.retcon.once(i32 32, i32 8, ptr %buffer, ptr @prototype_f, ptr @allocate, ptr @deallocate) + %hdl = call ptr @llvm.coro.begin(token %id, ptr null) + %proj.2.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1 + call void @init(ptr %proj.1) + call void @init(ptr %proj.2.2) + call void @use_addr_val(i64 %escape_addr, ptr %tmp) + %abort = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr %tmp) + br i1 %abort, label %end, label %resume + +resume: + call void @use(ptr %tmp) + br label %end + +end: + call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) + unreachable +} +; Make sure we don't lose writes to the frame. +; CHECK-LABEL: define { ptr, ptr } @f(ptr %buffer) { +; CHECK: [[PROJ2:%.*]] = getelementptr inbounds { i64, i64 }, ptr %buffer, i64 0, i32 1 +; CHECK: store i64 0, ptr %buffer +; CHECK: store i64 0, ptr [[PROJ2]] +; CHECK: [[ESCAPED_ADDR:%.*]] = ptrtoint ptr %buffer to i64 +; CHECK: call void @init(ptr %buffer) +; CHECK: call void @init(ptr [[PROJ2]]) +; CHECK: call void @use_addr_val(i64 [[ESCAPED_ADDR]], ptr %buffer) + +; CHECK-LABEL: define internal void @f.resume.0(ptr {{.*}} %0, i1 %1) { +; CHECK: resume: +; CHECK: call void @use(ptr %0) + +declare token @llvm.coro.id.retcon.once(i32, i32, ptr, ptr, ptr, ptr) +declare ptr @llvm.coro.begin(token, ptr) +declare i1 @llvm.coro.suspend.retcon.i1(...) +declare i1 @llvm.coro.end(ptr, i1, token) +