https://github.com/xgupta updated https://github.com/llvm/llvm-project/pull/212141
>From 2b98375c6ffd40f9952d183917dc25fb1e51ff3b Mon Sep 17 00:00:00 2001 From: Shivam Gupta <[email protected]> Date: Sun, 26 Jul 2026 20:47:26 +0530 Subject: [PATCH 1/2] [clang][CodeGen] Respect FP pragma options for fneg and calls Apply expression-specific floating-point options when emitting fneg and call instructions. This prevents these instructions from retaining fast-math flags disabled by local FP pragmas, such as #pragma clang fp reassociate(off). Builtin calls are excluded because their lowering handles floating-point options separately. Fixes #51905 --- clang/lib/CodeGen/CGExprScalar.cpp | 10 +++++++++- clang/test/CodeGen/fp-reassoc-pragma.cpp | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 8783b43846434..1d26fde39885f 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -682,6 +682,12 @@ class ScalarExprEmitter if (E->getCallReturnType(CGF.getContext())->isReferenceType()) return EmitLoadOfLValue(E); + std::optional<CodeGenFunction::CGFPOptionsRAII> FPOptsRAII; + const FunctionDecl *FD = E->getDirectCallee(); + bool IsBuiltin = FD && FD->getBuiltinID() != 0; + if (!IsBuiltin && E->getType()->hasFloatingRepresentation()) + FPOptsRAII.emplace(CGF, E); + Value *V = CGF.EmitCallExpr(E).getScalarVal(); EmitLValueAlignmentAssumption(E, V); @@ -3707,8 +3713,10 @@ Value *ScalarExprEmitter::VisitMinus(const UnaryOperator *E, Op = Visit(E->getSubExpr()); // Generate a unary FNeg for FP ops. - if (Op->getType()->isFPOrFPVectorTy()) + if (Op->getType()->isFPOrFPVectorTy()) { + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E); return Builder.CreateFNeg(Op, "fneg"); + } // Emit unary minus with EmitSub so we handle overflow cases etc. BinOpInfo BinOp; diff --git a/clang/test/CodeGen/fp-reassoc-pragma.cpp b/clang/test/CodeGen/fp-reassoc-pragma.cpp index 8b9329c40174b..45d5ecde34484 100644 --- a/clang/test/CodeGen/fp-reassoc-pragma.cpp +++ b/clang/test/CodeGen/fp-reassoc-pragma.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -O0 -triple %itanium_abi_triple -funsafe-math-optimizations -emit-llvm -o - %s | FileCheck %s --check-prefix=UNSAFE + // Simple case float fp_reassoc_simple(float a, float b, float c) { // CHECK: _Z17fp_reassoc_simplefff @@ -90,3 +92,17 @@ float fp_reassoc_call_helper(float a, float b, float c) { #pragma clang fp reassociate(on) return helper_func(a, b, c); } + + +double fp_reassoc_call_helper(bool flag, double x, double y) { + return flag ? x : y; +} + +#pragma clang fp reassociate(off) +double fp_reassoc_off_fneg_call(double x) { + // UNSAFE-LABEL: _Z24fp_reassoc_off_fneg_calld + // UNSAFE: fcmp nsz arcp afn + // UNSAFE: fneg nsz arcp afn + // UNSAFE: call nsz arcp afn + return fp_reassoc_call_helper(x < 0, -x, x); +} >From 790398200adec03fdabcfcaf0fa3a83c5d0d7a7d Mon Sep 17 00:00:00 2001 From: Shivam Gupta <[email protected]> Date: Tue, 4 Aug 2026 15:08:54 +0530 Subject: [PATCH 2/2] Addressed test case's review comments --- clang/test/CodeGen/fp-reassoc-pragma.cpp | 41 ++++++++++++------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/clang/test/CodeGen/fp-reassoc-pragma.cpp b/clang/test/CodeGen/fp-reassoc-pragma.cpp index 45d5ecde34484..ce32a93c6620c 100644 --- a/clang/test/CodeGen/fp-reassoc-pragma.cpp +++ b/clang/test/CodeGen/fp-reassoc-pragma.cpp @@ -1,15 +1,18 @@ // RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -O0 -triple %itanium_abi_triple -funsafe-math-optimizations -emit-llvm -o - %s | FileCheck %s --check-prefix=UNSAFE +float func(float); + // Simple case float fp_reassoc_simple(float a, float b, float c) { // CHECK: _Z17fp_reassoc_simplefff // CHECK: %[[A:.+]] = fadd reassoc float %b, %c -// CHECK: %[[M:.+]] = fmul reassoc float %b, %[[A]] -// CHECK-NEXT: fadd reassoc float %c, %[[M]] +// CHECK: %[[C:.+]] = tail call reassoc {{.*}} @_Z4funcf(float {{.*}} %[[A]]) +// CHECK: %[[N:.+]] = fneg reassoc float %[[C]] +// CHECK: call reassoc {{.*}} @_Z4funcf(float {{.*}} %[[N]]) #pragma clang fp reassociate(on) - a = b + c; - return a * b + c; + a = func(b + c); + return func(-a); } // Reassoc pragma should only apply to its scope @@ -67,10 +70,19 @@ float fp_file_scope_stop(float a, float b, float c) { #pragma clang fp reassociate(off) float fp_reassoc_off(float a, float b, float c) { // CHECK: _Z14fp_reassoc_offfff - // CHECK: %[[D1:.+]] = fdiv float %a, %c - // CHECK-NEXT: %[[D2:.+]] = fdiv float %b, %c - // CHECK-NEXT: fadd float %[[D1]], %[[D2]] - return (a / c) + (b / c); + // CHECK: %[[N:.+]] = fneg float %a + // CHECK: %[[C:.+]] = tail call noundef float @_Z4funcf(float noundef %[[N]]) + // CHECK: %[[D1:.+]] = fdiv float %[[C]], %c + // CHECK: %[[D2:.+]] = fdiv float %b, %c + // CHECK: fadd float %[[D2]], %[[D1]] + // + // UNSAFE: _Z14fp_reassoc_offfff + // UNSAFE: %[[N:.+]] = fneg nsz arcp afn float + // UNSAFE: %[[C:.+]] = call nsz arcp afn noundef float @_Z4funcf(float noundef %[[N]]) + // UNSAFE: %[[D1:.+]] = fdiv nsz arcp afn float %[[C]] + // UNSAFE: %[[D2:.+]] = fdiv nsz arcp afn float + // UNSAFE: fadd nsz arcp afn float %[[D1]], %[[D2]] + return (func(-a) / c) + (b / c); } // Takes latest flag @@ -93,16 +105,3 @@ float fp_reassoc_call_helper(float a, float b, float c) { return helper_func(a, b, c); } - -double fp_reassoc_call_helper(bool flag, double x, double y) { - return flag ? x : y; -} - -#pragma clang fp reassociate(off) -double fp_reassoc_off_fneg_call(double x) { - // UNSAFE-LABEL: _Z24fp_reassoc_off_fneg_calld - // UNSAFE: fcmp nsz arcp afn - // UNSAFE: fneg nsz arcp afn - // UNSAFE: call nsz arcp afn - return fp_reassoc_call_helper(x < 0, -x, x); -} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
