Index: llvm/test/tools/llvm-reduce/reduce-instructions-swifterror.ll =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/reduce-instructions-swifterror.ll @@ -0,0 +1,28 @@ +; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=instructions --test FileCheck --test-arg --check-prefixes=CHECK,INTERESTING --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck -check-prefixes=CHECK,RESULT %s < %t + +; Make sure verifier errors aren't produced from trying to delete +; swifterror instructions. + +%swift_error = type { i64, i8 } + +declare float @foo(ptr swifterror %error_ptr_ref) + +; CHECK-LABEL: define float @caller( +; INTERESTING: call float @foo( + +; RESULT: %error_ptr_ref = alloca swifterror ptr, align 8 +; RESULT-NEXT: %call = call float @foo(ptr swifterror %error_ptr_ref) +; RESULT-NEXT: ret float +define float @caller(ptr %error_ref) { +entry: + %error_ptr_ref = alloca swifterror ptr + store ptr null, ptr %error_ptr_ref + %call = call float @foo(ptr swifterror %error_ptr_ref) + %error_from_foo = load ptr, ptr %error_ptr_ref + %had_error_from_foo = icmp ne ptr %error_from_foo, null + %v1 = getelementptr inbounds %swift_error, ptr %error_from_foo, i64 0, i32 1 + %t = load i8, ptr %v1 + store i8 %t, ptr %error_ref + ret float 1.0 +} Index: llvm/test/tools/llvm-reduce/reduce-instructions-token-preallocated.ll =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/reduce-instructions-token-preallocated.ll @@ -0,0 +1,23 @@ +; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=instructions --test FileCheck --test-arg --check-prefixes=CHECK,INTERESTING --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck -check-prefixes=CHECK,RESULT %s < %t + +%Foo = type { i32, i32 } + +declare token @llvm.call.preallocated.setup(i32) +declare ptr @llvm.call.preallocated.arg(token, i32) +declare void @init(ptr) +declare void @foo_p(ptr preallocated(%Foo)) + +; CHECK-LABEL: define void @preallocated_with_init() { +; INTERESTING: call void @foo_p + +; RESULT: %t = call token @llvm.call.preallocated.setup(i32 1) +; RESULT-NEXT: call void @foo_p(ptr preallocated(%Foo) null) [ "preallocated"(token %t) ] +; RESULT-NEXT: ret void +define void @preallocated_with_init() { + %t = call token @llvm.call.preallocated.setup(i32 1) + %a = call ptr @llvm.call.preallocated.arg(token %t, i32 0) preallocated(%Foo) + call void @init(ptr %a) + call void @foo_p(ptr preallocated(%Foo) %a) ["preallocated"(token %t)] + ret void +} Index: llvm/test/tools/llvm-reduce/reduce-instructions-token.ll =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/reduce-instructions-token.ll @@ -0,0 +1,21 @@ +; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=instructions --test FileCheck --test-arg --check-prefixes=CHECK,INTERESTING --test-arg %s --test-arg --input-file %s -o %t +; RUN: FileCheck -check-prefixes=CHECK,RESULT %s < %t + +; CHECK-LABEL: define void @tokens( +; INTERESTING: store i32 0 +; INTERESTING: call void @llvm.token.consumer + +; RESULT: %token = call token @llvm.token.producer() +; RESULT-NEXT: store i32 0, ptr %ptr, align 4 +; RESULT-NEXT: call void @llvm.token.consumer(token %token) +; RESULT-NEXT: ret void +define void @tokens(ptr %ptr) { + %token = call token @llvm.token.producer() + store i32 0, ptr %ptr + call void @llvm.token.consumer(token %token) + store i32 1, ptr %ptr + ret void +} + +declare token @llvm.token.producer() +declare void @llvm.token.consumer(token) Index: llvm/test/tools/llvm-reduce/remove-invoked-functions.ll =================================================================== --- llvm/test/tools/llvm-reduce/remove-invoked-functions.ll +++ llvm/test/tools/llvm-reduce/remove-invoked-functions.ll @@ -1,4 +1,4 @@ -; RUN: llvm-reduce --delta-passes=instructions --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t +; RUN: llvm-reduce --abort-on-invalid-reduction --delta-passes=instructions --test FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t ; RUN: cat %t | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s ; CHECK-INTERESTINGNESS: define i32 @maybe_throwing_callee( Index: llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp @@ -17,6 +17,15 @@ using namespace llvm; +/// Filter out cases where deleting the instruction will likely cause the +/// user/def of the instruction to fail the verifier. +// +// TODO: Technically the verifier only enforces preallocated token usage and +// there is a none token. +static bool shouldAlwaysKeep(const Instruction &I) { + return I.isEHPad() || I.getType()->isTokenTy() || I.isSwiftError(); +} + /// Removes out-of-chunk arguments from functions, and modifies their calls /// accordingly. It also removes allocations of out-of-chunk arguments. static void extractInstrFromModule(Oracle &O, Module &Program) { @@ -27,9 +36,10 @@ // Removing the terminator would make the block invalid. Only iterate over // instructions before the terminator. InitInstToKeep.push_back(BB.getTerminator()); - for (auto &Inst : make_range(BB.begin(), std::prev(BB.end()))) - if (O.shouldKeep()) + for (auto &Inst : make_range(BB.begin(), std::prev(BB.end()))) { + if (shouldAlwaysKeep(Inst) || O.shouldKeep()) InitInstToKeep.push_back(&Inst); + } } // We create a vector first, then convert it to a set, so that we don't have