[PATCH] D116619: [WebAssembly] Nullify unnecessary setjmp calls
Heejin Ahn via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 4 12:44:21 PST 2022
aheejin updated this revision to Diff 397377.
aheejin added a comment.
Test fix
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D116619/new/
https://reviews.llvm.org/D116619
Files:
llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
Index: llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
===================================================================
--- llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
+++ llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
@@ -131,7 +131,7 @@
; Test a case where a function has a setjmp call but no other calls that can
; longjmp. We don't need to do any transformation in this case.
-define void @setjmp_only(i8* %ptr) {
+define i32 @setjmp_only(i8* %ptr) {
; CHECK-LABEL: @setjmp_only
entry:
%buf = alloca [1 x %struct.__jmp_buf_tag], align 16
@@ -139,11 +139,12 @@
%call = call i32 @setjmp(%struct.__jmp_buf_tag* %arraydecay) #0
; free cannot longjmp
call void @free(i8* %ptr)
- ret void
+ ret i32 %call
; CHECK-NOT: @malloc
; CHECK-NOT: %setjmpTable
; CHECK-NOT: @saveSetjmp
; CHECK-NOT: @testSetjmp
+; CHECK: ret i32 0
}
; Test SSA validity
Index: llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -817,6 +817,32 @@
return false;
}
+// When a function contains a setjmp call but not other calls that can longjmp,
+// we don't do setjmp transformation for that setjmp. But we need to convert the
+// setjmp calls into "i32 0" so they don't cause link time errors. setjmp always
+// returns 0 when called directly.
+static void nullifySetjmp(Function *F) {
+ Module &M = *F->getParent();
+ IRBuilder<> IRB(M.getContext());
+ Function *SetjmpF = M.getFunction("setjmp");
+ SmallVector<Instruction *, 1> ToErase;
+
+ for (User *U : SetjmpF->users()) {
+ auto *CI = dyn_cast<CallInst>(U);
+ // FIXME 'invoke' to setjmp can happen when we use Wasm EH + Wasm SjLj, but
+ // we don't support two being used together yet.
+ if (!CI)
+ report_fatal_error("Wasm EH + Wasm SjLj is not fully supported yet");
+ BasicBlock *BB = CI->getParent();
+ if (BB->getParent() != F) // in other function
+ continue;
+ ToErase.push_back(CI);
+ CI->replaceAllUsesWith(IRB.getInt32(0));
+ }
+ for (auto *I : ToErase)
+ I->eraseFromParent();
+}
+
bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) {
LLVM_DEBUG(dbgs() << "********** Lower Emscripten EH & SjLj **********\n");
@@ -886,6 +912,10 @@
EHTypeIDF = getEmscriptenFunction(EHTypeIDTy, "llvm_eh_typeid_for", &M);
}
+ // Functions that contains calls to setjmp but don't have other longjmpable
+ // calls within them.
+ SmallPtrSet<Function *, 4> SetjmpUsersToNullify;
+
if ((EnableEmSjLj || EnableWasmSjLj) && SetjmpF) {
// Precompute setjmp users
for (User *U : SetjmpF->users()) {
@@ -896,6 +926,8 @@
// so can ignore it
if (containsLongjmpableCalls(UserF))
SetjmpUsers.insert(UserF);
+ else
+ SetjmpUsersToNullify.insert(UserF);
} else {
std::string S;
raw_string_ostream SS(S);
@@ -975,6 +1007,14 @@
runSjLjOnFunction(*F);
}
+ // Replace unnecessary setjmp calls with 0
+ if ((EnableEmSjLj | EnableWasmSjLj) && !SetjmpUsersToNullify.empty()) {
+ Changed = true;
+ assert(SetjmpF);
+ for (Function *F : SetjmpUsersToNullify)
+ nullifySetjmp(F);
+ }
+
if (!Changed) {
// Delete unused global variables and functions
if (ResumeF)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D116619.397377.patch
Type: text/x-patch
Size: 3426 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220104/a4b3659a/attachment.bin>
More information about the llvm-commits
mailing list