Emission of `mustprogress` attribute previously occurred only within `EmitFunctionBody`, after generating the function body. Other routines for function body creation may lack the attribute, potentially leading to suboptimal optimizations later in the pipeline. Attribute emission is now anticipated prior to generating the function body. Fixes: https://github.com/llvm/llvm-project/issues/69833.
81 lines
3.7 KiB
Plaintext
81 lines
3.7 KiB
Plaintext
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
|
|
// Basic C++ test for update_cc_test_checks
|
|
// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
|
|
|
|
class Foo {
|
|
int x;
|
|
|
|
public:
|
|
explicit Foo(int x);
|
|
~Foo();
|
|
// CHECK-LABEL: @_ZNK3Foo23function_defined_inlineEi(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
|
|
// CHECK-NEXT: [[ARG_ADDR:%.*]] = alloca i32, align 4
|
|
// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
|
|
// CHECK-NEXT: store i32 [[ARG:%.*]], ptr [[ARG_ADDR]], align 4
|
|
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
|
|
// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[CLASS_FOO:%.*]], ptr [[THIS1]], i32 0, i32 0
|
|
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[X]], align 4
|
|
// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
|
|
// CHECK-NEXT: ret i32 [[ADD]]
|
|
//
|
|
inline int function_defined_inline(int arg) const {
|
|
return arg + x;
|
|
}
|
|
inline int function_defined_out_of_line(int arg) const;
|
|
};
|
|
|
|
// CHECK-LABEL: @_ZN3FooC1Ei(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
|
|
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
|
|
// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
|
|
// CHECK-NEXT: store i32 [[X:%.*]], ptr [[X_ADDR]], align 4
|
|
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
|
|
// CHECK-NEXT: call void @_ZN3FooC2Ei(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], i32 noundef [[TMP0]])
|
|
// CHECK-NEXT: ret void
|
|
//
|
|
Foo::Foo(int x) : x(x) {}
|
|
// CHECK-LABEL: @_ZN3FooD1Ev(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
|
|
// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
|
|
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
|
|
// CHECK-NEXT: call void @_ZN3FooD2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR2:[0-9]+]]
|
|
// CHECK-NEXT: ret void
|
|
//
|
|
Foo::~Foo() {}
|
|
// CHECK-LABEL: @_ZNK3Foo28function_defined_out_of_lineEi(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
|
|
// CHECK-NEXT: [[ARG_ADDR:%.*]] = alloca i32, align 4
|
|
// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
|
|
// CHECK-NEXT: store i32 [[ARG:%.*]], ptr [[ARG_ADDR]], align 4
|
|
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
|
|
// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[CLASS_FOO:%.*]], ptr [[THIS1]], i32 0, i32 0
|
|
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X]], align 4
|
|
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
|
|
// CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[TMP0]], [[TMP1]]
|
|
// CHECK-NEXT: ret i32 [[SUB]]
|
|
//
|
|
int Foo::function_defined_out_of_line(int arg) const { return x - arg; }
|
|
|
|
// Call the inline methods to ensure the LLVM IR is generated:
|
|
// CHECK-LABEL: @main(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[F:%.*]] = alloca [[CLASS_FOO:%.*]], align 4
|
|
// CHECK-NEXT: call void @_ZN3FooC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 1)
|
|
// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK3Foo23function_defined_inlineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2)
|
|
// CHECK-NEXT: [[CALL1:%.*]] = call noundef i32 @_ZNK3Foo28function_defined_out_of_lineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3)
|
|
// CHECK-NEXT: call void @_ZN3FooD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[F]]) #[[ATTR2]]
|
|
// CHECK-NEXT: ret i32 0
|
|
//
|
|
int main() {
|
|
Foo f(1);
|
|
f.function_defined_inline(2);
|
|
f.function_defined_out_of_line(3);
|
|
}
|