llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) <details> <summary>Changes</summary> The crux of this paper is that floating point expressions can be evaluated in a wider format, but the return statement in a function should still return a value of the function's return type rather than the wider format type. Note, this is an Annex F conformance requirement and we do not currently claim conformance to Annex F, so technically we conform either way. --- Full diff: https://github.com/llvm/llvm-project/pull/101214.diff 2 Files Affected: - (added) clang/test/C/C11/n1396.c (+140) - (modified) clang/www/c_status.html (+1-1) ``````````diff diff --git a/clang/test/C/C11/n1396.c b/clang/test/C/C11/n1396.c new file mode 100644 index 0000000000000..311b343e2b715 --- /dev/null +++ b/clang/test/C/C11/n1396.c @@ -0,0 +1,140 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +/* WG14 N1396: Clang 15 + * Wide function returns (alternate proposal) + * + * This only applies if attempting to conform to Annex F. Clang is not claiming + * conformance to Annex F, but we do aim for conformance. This means that the + * return statement converts the value to the return type of the function + * rather than return the result in a wider evaluation format. We test this by + * using a return statement without a cast and ensure it produces the same IR + * as a return statement with an explicit cast. + * + * We claim Clang 15 for conformance because that's the first version that + * supported #pragma clang fp eval_method source|extended + */ + +// CHECK-LABEL: define dso_local float @extended_float_func( +// CHECK-SAME: float noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[X]], ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fpext float [[TMP0]] to double +// CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 1.000000e+00 +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[MUL]] to float +// CHECK-NEXT: ret float [[CONV1]] +// +float extended_float_func(float x) { +#pragma clang fp eval_method(extended) + return x * 1.0f; +} + +// CHECK-LABEL: define dso_local float @extended_float_func_cast( +// CHECK-SAME: float noundef [[X:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[X]], ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fpext float [[TMP0]] to double +// CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 1.000000e+00 +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[MUL]] to float +// CHECK-NEXT: ret float [[CONV1]] +// +float extended_float_func_cast(float x) { +#pragma clang fp eval_method(extended) + return (float)(x * 1.0f); +} + +// CHECK-LABEL: define dso_local float @extended_double_func( +// CHECK-SAME: float noundef [[X:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[X]], ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fpext float [[TMP0]] to double +// CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 1.000000e+00 +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[MUL]] to float +// CHECK-NEXT: ret float [[CONV1]] +// +float extended_double_func(float x) { +#pragma clang fp eval_method(extended) + return x * 1.0; +} + +// CHECK-LABEL: define dso_local float @extended_double_func_cast( +// CHECK-SAME: float noundef [[X:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[X]], ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fpext float [[TMP0]] to double +// CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 1.000000e+00 +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[MUL]] to float +// CHECK-NEXT: ret float [[CONV1]] +// +float extended_double_func_cast(float x) { +#pragma clang fp eval_method(extended) + return (float)(x * 1.0); +} + +// CHECK-LABEL: define dso_local float @float_source_func( +// CHECK-SAME: float noundef [[X:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[X]], ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[MUL:%.*]] = fmul float [[TMP0]], 1.000000e+00 +// CHECK-NEXT: ret float [[MUL]] +// +float float_source_func(float x) { +#pragma clang fp eval_method(source) + return x * 1.0f; +} + +// CHECK-LABEL: define dso_local float @float_source_func_cast( +// CHECK-SAME: float noundef [[X:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[X]], ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[MUL:%.*]] = fmul float [[TMP0]], 1.000000e+00 +// CHECK-NEXT: ret float [[MUL]] +// +float float_source_func_cast(float x) { +#pragma clang fp eval_method(source) + return (float)(x * 1.0f); +} + +// CHECK-LABEL: define dso_local float @double_source_func( +// CHECK-SAME: float noundef [[X:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[X]], ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fpext float [[TMP0]] to double +// CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 1.000000e+00 +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[MUL]] to float +// CHECK-NEXT: ret float [[CONV1]] +// +float double_source_func(float x) { +#pragma clang fp eval_method(source) + return x * 1.0; +} + +// CHECK-LABEL: define dso_local float @double_source_func_cast( +// CHECK-SAME: float noundef [[X:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store float [[X]], ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[X_ADDR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = fpext float [[TMP0]] to double +// CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 1.000000e+00 +// CHECK-NEXT: [[CONV1:%.*]] = fptrunc double [[MUL]] to float +// CHECK-NEXT: ret float [[CONV1]] +// +float double_source_func_cast(float x) { +#pragma clang fp eval_method(source) + return (float)(x * 1.0); +} diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 3ea70b0163c70..025bd08712279 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -501,7 +501,7 @@ <h2 id="c11">C11 implementation status</h2> <tr> <td>Wide function returns (alternate proposal)</td> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1396.htm">N1396</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Clang 15</td> </tr> <tr id="alignment"> <td rowspan="3">Alignment</td> `````````` </details> https://github.com/llvm/llvm-project/pull/101214 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits