[CodeGen] Emit a call instruction instead of an invoke if the called

llvm function is marked nounwind

This fixes cases where an invoke is emitted, despite the called llvm
function being marked nounwind, because ConstructAttributeList failed to
add the attribute to the attribute list. llvm optimization passes turn
invokes into calls and optimize away the exception handling code, but
it's better to avoid emitting the code in the front-end if the called
function is known not to raise an exception.

Differential Revision: https://reviews.llvm.org/D83906
This commit is contained in:
Akira Hatanaka 2020-07-15 14:47:45 -07:00
parent 2815429d08
commit ed6b578040
20 changed files with 31 additions and 24 deletions

View File

@ -4841,6 +4841,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
} else {
// Otherwise, nounwind call sites will never throw.
CannotThrow = Attrs.hasFnAttribute(llvm::Attribute::NoUnwind);
if (auto *FPtr = dyn_cast<llvm::Function>(CalleePtr))
if (FPtr->hasFnAttribute(llvm::Attribute::NoUnwind))
CannotThrow = true;
}
// If we made a temporary, be sure to clean up after ourselves. Note that we

View File

@ -13,7 +13,7 @@ public:
virtual ~B();
};
B::~B() {
B::~B() { extern void mayThrow(); mayThrow();
}
struct C {

View File

@ -16,6 +16,8 @@ struct Container {
};
bool getBool() {
extern void mayThrow();
mayThrow();
return false;
}

View File

@ -6,13 +6,14 @@ namespace no_eh_cleanup {
void release(int *lock);
// CHECK-LABEL: define {{.*}} @_ZN13no_eh_cleanup3logERiPcS1_(
// CHECK: call void @__os_log_helper_1_2_2_4_0_8_34(
void log(int &i, char *data, char *buf) {
int lock __attribute__((cleanup(release)));
__builtin_os_log_format(buf, "%d %{public}s", i, data);
}
// An `invoke` of a `nounwind` callee is simplified to a direct
// call by an optimization in llvm. Just check that we emit `nounwind`.
// Check that the os_log_helper is marked `nounwind`.
// CHECK: define {{.*}} @__os_log_helper_1_2_2_4_0_8_34({{.*}} [[NUW:#[0-9]+]]
}

View File

@ -82,7 +82,7 @@ void parallel_atomic_ewc() {
}
}
int &foo() { return a; }
int &foo() { extern void mayThrow(); mayThrow(); return a; }
// TERM_DEBUG-LABEL: parallel_atomic
void parallel_atomic() {

View File

@ -22,7 +22,7 @@
// ALL: define {{.*}}void [[FOO:@.+]]()
void foo() {}
void foo() { extern void mayThrow(); mayThrow(); }
// ALL-LABEL: @main
// TERM_DEBUG-LABEL: @main

View File

@ -22,7 +22,7 @@ void foo();
struct S {
intptr_t a, b, c;
S(intptr_t a) : a(a) {}
operator char() { return a; }
operator char() { extern void mayThrow(); mayThrow(); return a; }
~S() {}
};

View File

@ -22,7 +22,7 @@ void foo();
struct S {
intptr_t a, b, c;
S(intptr_t a) : a(a) {}
operator char() { return a; }
operator char() { extern void mayThrow(); mayThrow(); return a; }
~S() {}
};

View File

@ -536,7 +536,7 @@ void test_precond() {
}
// TERM_DEBUG-LABEL: foo
int foo() {return 0;};
int foo() { extern void mayThrow(); mayThrow(); return 0;};
// TERM_DEBUG-LABEL: parallel_for
void parallel_for(float *a) {

View File

@ -20,7 +20,7 @@
#ifndef HEADER
#define HEADER
long long get_val() { return 0; }
long long get_val() { extern void mayThrow(); mayThrow(); return 0; }
double *g_ptr;
// CHECK-LABEL: define {{.*void}} @{{.*}}simple{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}})
@ -785,7 +785,7 @@ void widened(float *a, float *b, float *c, float *d) {
}
// TERM_DEBUG-LABEL: bar
int bar() {return 0;};
int bar() { extern void mayThrow(); mayThrow(); return 0; };
// TERM_DEBUG-LABEL: parallel_simd
void parallel_simd(float *a) {

View File

@ -19,7 +19,7 @@
// ALL: define {{.*}}void [[FOO:@.+]]()
void foo() {}
void foo() { extern void mayThrow(); mayThrow(); }
// ALL-LABEL: @main
// TERM_DEBUG-LABEL: @main

View File

@ -372,7 +372,7 @@ void runtime(float *a, float *b, float *c, float *d) {
}
// TERM_DEBUG-LABEL: foo
int foo() {return 0;};
int foo() { extern void mayThrow(); mayThrow(); return 0; };
// TERM_DEBUG-LABEL: parallel_for
// CLEANUP: parallel_for

View File

@ -22,7 +22,7 @@
#ifndef HEADER
#define HEADER
long long get_val() { return 0; }
long long get_val() { extern void mayThrow(); mayThrow(); return 0; }
double *g_ptr;
// CHECK-LABEL: define {{.*void}} @{{.*}}simple{{.*}}(float* {{.+}}, float* {{.+}}, float* {{.+}}, float* {{.+}})
@ -801,7 +801,7 @@ for (int i = 0; i < 10; ++i);
// OMP50-DAG: ![[NOVM]] = !{!"llvm.loop.vectorize.enable", i1 false}
// TERM_DEBUG-LABEL: bar
int bar() {return 0;};
int bar() { extern void mayThrow(); mayThrow(); return 0; };
// TERM_DEBUG-LABEL: parallel_simd
void parallel_simd(float *a) {

View File

@ -18,7 +18,7 @@
// CK1-DAG: [[DEF_LOC:@.+]] = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* [[STR]], i32 0, i32 0) }
// CK1-LABEL: foo
void foo() {}
void foo() { extern void mayThrow(); mayThrow(); }
void parallel_master() {
#pragma omp parallel master

View File

@ -22,7 +22,7 @@ void foo();
struct S {
intptr_t a, b, c;
S(intptr_t a) : a(a) {}
operator char() { return a; }
operator char() { extern void mayThrow(); mayThrow(); return a; }
~S() {}
};

View File

@ -10,9 +10,9 @@
#ifndef HEADER
#define HEADER
// CHECK-LABEL: foo
void foo() {};
void foo() { extern void mayThrow(); mayThrow(); };
// CHECK-LABEL: bar
void bar() {};
void bar() { extern void mayThrow(); mayThrow(); };
template <class T>
T tmain() {

View File

@ -12,9 +12,9 @@
// CHECK-DAG: [[IMPLICIT_BARRIER_SECTIONS_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
// CHECK-DAG: [[SECTIONS_LOC:@.+]] = private unnamed_addr global %{{.+}} { i32 0, i32 1026, i32 0, i32 0, i8*
// CHECK-LABEL: foo
void foo() {};
void foo() { extern void mayThrow(); mayThrow(); };
// CHECK-LABEL: bar
void bar() {};
void bar() { extern void mayThrow(); mayThrow(); };
template <class T>
T tmain() {

View File

@ -26,7 +26,7 @@
// OMP50-DAG: [[LAST_IV:@.+]] = {{.*}}common global i64 0
// OMP50-DAG: [[LAST_A:@.+]] = {{.*}}common global i32 0
long long get_val() { return 0; }
long long get_val() { extern void mayThrow(); mayThrow(); return 0; }
double *g_ptr;
struct S {
@ -798,7 +798,7 @@ void bartfoo() {
#endif // OMP5
// TERM_DEBUG-LABEL: bar
int bar() {return 0;};
int bar() { extern void mayThrow(); mayThrow(); return 0; };
// TERM_DEBUG-LABEL: parallel_simd
void parallel_simd(float *a) {

View File

@ -42,7 +42,7 @@ TestClass tc;
TestClass tc2[2];
#pragma omp threadprivate(tc, tc2)
void foo() {}
void foo() { extern void mayThrow(); mayThrow(); }
struct SS {
int a;

View File

@ -16,7 +16,7 @@
// CHECK: define {{.*}}void [[FOO:@.+]]()
void foo() {}
void foo() { extern void mayThrow(); mayThrow(); }
// CHECK-LABEL: @main
// TERM_DEBUG-LABEL: @main