forked from OSchip/llvm-project
[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:
parent
2815429d08
commit
ed6b578040
|
@ -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
|
||||
|
|
|
@ -13,7 +13,7 @@ public:
|
|||
virtual ~B();
|
||||
};
|
||||
|
||||
B::~B() {
|
||||
B::~B() { extern void mayThrow(); mayThrow();
|
||||
}
|
||||
|
||||
struct C {
|
||||
|
|
|
@ -16,6 +16,8 @@ struct Container {
|
|||
};
|
||||
|
||||
bool getBool() {
|
||||
extern void mayThrow();
|
||||
mayThrow();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -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]+]]
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
// ALL: define {{.*}}void [[FOO:@.+]]()
|
||||
|
||||
void foo() {}
|
||||
void foo() { extern void mayThrow(); mayThrow(); }
|
||||
|
||||
// ALL-LABEL: @main
|
||||
// TERM_DEBUG-LABEL: @main
|
||||
|
|
|
@ -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() {}
|
||||
};
|
||||
|
||||
|
|
|
@ -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() {}
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
// ALL: define {{.*}}void [[FOO:@.+]]()
|
||||
|
||||
void foo() {}
|
||||
void foo() { extern void mayThrow(); mayThrow(); }
|
||||
|
||||
// ALL-LABEL: @main
|
||||
// TERM_DEBUG-LABEL: @main
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {}
|
||||
};
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
// CHECK: define {{.*}}void [[FOO:@.+]]()
|
||||
|
||||
void foo() {}
|
||||
void foo() { extern void mayThrow(); mayThrow(); }
|
||||
|
||||
// CHECK-LABEL: @main
|
||||
// TERM_DEBUG-LABEL: @main
|
||||
|
|
Loading…
Reference in New Issue