Skip to content

Commit dce6002

Browse files
[Clang][Codegen] Move floating point math intrinsic check to separate function [NFC] (llvm#168198)
This PR moves the code that checks whether an LLVM intrinsic should be generated instead of a call to floating point math functions to a separate function. This simplifies `EmitBuiltinExpr` in `CGBuiltin.cpp` and will allow us to reuse the logic in ClangIR.
1 parent bdcaa00 commit dce6002

File tree

3 files changed

+114
-77
lines changed

3 files changed

+114
-77
lines changed

clang/include/clang/Basic/Builtins.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ADT/StringMap.h"
2020
#include "llvm/ADT/StringRef.h"
2121
#include "llvm/ADT/StringTable.h"
22+
#include "llvm/TargetParser/Triple.h"
2223
#include <cstring>
2324

2425
// VC++ defines 'alloca' as an object-like macro, which interferes with our
@@ -405,6 +406,22 @@ class Context {
405406
return strchr(getAttributesString(ID), 'g') != nullptr;
406407
}
407408

409+
/// Determine whether we can generate LLVM intrinsics for the given
410+
/// builtin ID, based on whether it has side effects such as setting errno.
411+
///
412+
/// \param BuiltinID The builtin ID to check.
413+
/// \param Trip The target triple.
414+
/// \param ErrnoOverwritten Indicates whether the errno setting behavior
415+
/// has been overwritten via '#pragma float_control(precise, on/off)'.
416+
/// \param MathErrnoEnabled Indicates whether math-errno is enabled on
417+
/// command line.
418+
/// \param HasOptNoneAttr True iff 'attribute__((optnone))' is used.
419+
/// \param IsOptimizationEnabled True iff the optimization level is not 'O0'.
420+
bool shouldGenerateFPMathIntrinsic(unsigned BuiltinID, llvm::Triple Trip,
421+
std::optional<bool> ErrnoOverwritten,
422+
bool MathErrnoEnabled, bool HasOptNoneAttr,
423+
bool IsOptimizationEnabled) const;
424+
408425
const char *getRequiredFeatures(unsigned ID) const;
409426

410427
unsigned getRequiredVectorWidth(unsigned ID) const;

clang/lib/Basic/Builtins.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,96 @@ static bool builtinIsSupported(const llvm::StringTable &Strings,
197197
return true;
198198
}
199199

200+
static bool isBuiltinConstForTriple(unsigned BuiltinID, llvm::Triple Trip) {
201+
// There's a special case with the fma builtins where they are always const
202+
// if the target environment is GNU or the target is OS is Windows and we're
203+
// targeting the MSVCRT.dll environment.
204+
// FIXME: This list can be become outdated. Need to find a way to get it some
205+
// other way.
206+
switch (BuiltinID) {
207+
case Builtin::BI__builtin_fma:
208+
case Builtin::BI__builtin_fmaf:
209+
case Builtin::BI__builtin_fmal:
210+
case Builtin::BI__builtin_fmaf16:
211+
case Builtin::BIfma:
212+
case Builtin::BIfmaf:
213+
case Builtin::BIfmal: {
214+
if (Trip.isGNUEnvironment() || Trip.isOSMSVCRT())
215+
return true;
216+
break;
217+
}
218+
default:
219+
break;
220+
}
221+
222+
return false;
223+
}
224+
225+
bool Builtin::Context::shouldGenerateFPMathIntrinsic(
226+
unsigned BuiltinID, llvm::Triple Trip, std::optional<bool> ErrnoOverwritten,
227+
bool MathErrnoEnabled, bool HasOptNoneAttr,
228+
bool IsOptimizationEnabled) const {
229+
230+
// True if we are compiling at -O2 and errno has been disabled
231+
// using the '#pragma float_control(precise, off)', and
232+
// attribute opt-none hasn't been seen.
233+
bool ErrnoOverridenToFalseWithOpt = ErrnoOverwritten.has_value() &&
234+
!ErrnoOverwritten.value() &&
235+
!HasOptNoneAttr && IsOptimizationEnabled;
236+
237+
// There are LLVM math intrinsics/instructions corresponding to math library
238+
// functions except the LLVM op will never set errno while the math library
239+
// might. Also, math builtins have the same semantics as their math library
240+
// twins. Thus, we can transform math library and builtin calls to their
241+
// LLVM counterparts if the call is marked 'const' (known to never set errno).
242+
// In case FP exceptions are enabled, the experimental versions of the
243+
// intrinsics model those.
244+
bool ConstAlways =
245+
isConst(BuiltinID) || isBuiltinConstForTriple(BuiltinID, Trip);
246+
247+
bool ConstWithoutErrnoAndExceptions =
248+
isConstWithoutErrnoAndExceptions(BuiltinID);
249+
bool ConstWithoutExceptions = isConstWithoutExceptions(BuiltinID);
250+
251+
// ConstAttr is enabled in fast-math mode. In fast-math mode, math-errno is
252+
// disabled.
253+
// Math intrinsics are generated only when math-errno is disabled. Any pragmas
254+
// or attributes that affect math-errno should prevent or allow math
255+
// intrinsics to be generated. Intrinsics are generated:
256+
// 1- In fast math mode, unless math-errno is overriden
257+
// via '#pragma float_control(precise, on)', or via an
258+
// 'attribute__((optnone))'.
259+
// 2- If math-errno was enabled on command line but overriden
260+
// to false via '#pragma float_control(precise, off))' and
261+
// 'attribute__((optnone))' hasn't been used.
262+
// 3- If we are compiling with optimization and errno has been disabled
263+
// via '#pragma float_control(precise, off)', and
264+
// 'attribute__((optnone))' hasn't been used.
265+
266+
bool ConstWithoutErrnoOrExceptions =
267+
ConstWithoutErrnoAndExceptions || ConstWithoutExceptions;
268+
bool GenerateIntrinsics =
269+
(ConstAlways && !HasOptNoneAttr) ||
270+
(!MathErrnoEnabled &&
271+
!(ErrnoOverwritten.has_value() && ErrnoOverwritten.value()) &&
272+
!HasOptNoneAttr);
273+
if (!GenerateIntrinsics) {
274+
GenerateIntrinsics =
275+
ConstWithoutErrnoOrExceptions && !ConstWithoutErrnoAndExceptions;
276+
if (!GenerateIntrinsics)
277+
GenerateIntrinsics =
278+
ConstWithoutErrnoOrExceptions &&
279+
(!MathErrnoEnabled &&
280+
!(ErrnoOverwritten.has_value() && ErrnoOverwritten.value()) &&
281+
!HasOptNoneAttr);
282+
if (!GenerateIntrinsics)
283+
GenerateIntrinsics =
284+
ConstWithoutErrnoOrExceptions && ErrnoOverridenToFalseWithOpt;
285+
}
286+
287+
return GenerateIntrinsics;
288+
}
289+
200290
/// initializeBuiltins - Mark the identifiers for all the builtins with their
201291
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
202292
/// such.

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 7 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2640,84 +2640,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
26402640
// fast-math which implies math-errno.
26412641
bool OptNone = CurFuncDecl && CurFuncDecl->hasAttr<OptimizeNoneAttr>();
26422642

2643-
// True if we are compiling at -O2 and errno has been disabled
2644-
// using the '#pragma float_control(precise, off)', and
2645-
// attribute opt-none hasn't been seen.
2646-
bool ErrnoOverridenToFalseWithOpt =
2647-
ErrnoOverriden.has_value() && !ErrnoOverriden.value() && !OptNone &&
2648-
CGM.getCodeGenOpts().OptimizationLevel != 0;
2649-
2650-
// There are LLVM math intrinsics/instructions corresponding to math library
2651-
// functions except the LLVM op will never set errno while the math library
2652-
// might. Also, math builtins have the same semantics as their math library
2653-
// twins. Thus, we can transform math library and builtin calls to their
2654-
// LLVM counterparts if the call is marked 'const' (known to never set errno).
2655-
// In case FP exceptions are enabled, the experimental versions of the
2656-
// intrinsics model those.
2657-
bool ConstAlways =
2658-
getContext().BuiltinInfo.isConst(BuiltinID);
2659-
2660-
// There's a special case with the fma builtins where they are always const
2661-
// if the target environment is GNU or the target is OS is Windows and we're
2662-
// targeting the MSVCRT.dll environment.
2663-
// FIXME: This list can be become outdated. Need to find a way to get it some
2664-
// other way.
2665-
switch (BuiltinID) {
2666-
case Builtin::BI__builtin_fma:
2667-
case Builtin::BI__builtin_fmaf:
2668-
case Builtin::BI__builtin_fmal:
2669-
case Builtin::BI__builtin_fmaf16:
2670-
case Builtin::BIfma:
2671-
case Builtin::BIfmaf:
2672-
case Builtin::BIfmal: {
2673-
auto &Trip = CGM.getTriple();
2674-
if (Trip.isGNUEnvironment() || Trip.isOSMSVCRT())
2675-
ConstAlways = true;
2676-
break;
2677-
}
2678-
default:
2679-
break;
2680-
}
2643+
bool IsOptimizationEnabled = CGM.getCodeGenOpts().OptimizationLevel != 0;
2644+
2645+
bool GenerateFPMathIntrinsics =
2646+
getContext().BuiltinInfo.shouldGenerateFPMathIntrinsic(
2647+
BuiltinID, CGM.getTriple(), ErrnoOverriden, getLangOpts().MathErrno,
2648+
OptNone, IsOptimizationEnabled);
26812649

2682-
bool ConstWithoutErrnoAndExceptions =
2683-
getContext().BuiltinInfo.isConstWithoutErrnoAndExceptions(BuiltinID);
2684-
bool ConstWithoutExceptions =
2685-
getContext().BuiltinInfo.isConstWithoutExceptions(BuiltinID);
2686-
2687-
// ConstAttr is enabled in fast-math mode. In fast-math mode, math-errno is
2688-
// disabled.
2689-
// Math intrinsics are generated only when math-errno is disabled. Any pragmas
2690-
// or attributes that affect math-errno should prevent or allow math
2691-
// intrinsics to be generated. Intrinsics are generated:
2692-
// 1- In fast math mode, unless math-errno is overriden
2693-
// via '#pragma float_control(precise, on)', or via an
2694-
// 'attribute__((optnone))'.
2695-
// 2- If math-errno was enabled on command line but overriden
2696-
// to false via '#pragma float_control(precise, off))' and
2697-
// 'attribute__((optnone))' hasn't been used.
2698-
// 3- If we are compiling with optimization and errno has been disabled
2699-
// via '#pragma float_control(precise, off)', and
2700-
// 'attribute__((optnone))' hasn't been used.
2701-
2702-
bool ConstWithoutErrnoOrExceptions =
2703-
ConstWithoutErrnoAndExceptions || ConstWithoutExceptions;
2704-
bool GenerateIntrinsics =
2705-
(ConstAlways && !OptNone) ||
2706-
(!getLangOpts().MathErrno &&
2707-
!(ErrnoOverriden.has_value() && ErrnoOverriden.value()) && !OptNone);
2708-
if (!GenerateIntrinsics) {
2709-
GenerateIntrinsics =
2710-
ConstWithoutErrnoOrExceptions && !ConstWithoutErrnoAndExceptions;
2711-
if (!GenerateIntrinsics)
2712-
GenerateIntrinsics =
2713-
ConstWithoutErrnoOrExceptions &&
2714-
(!getLangOpts().MathErrno &&
2715-
!(ErrnoOverriden.has_value() && ErrnoOverriden.value()) && !OptNone);
2716-
if (!GenerateIntrinsics)
2717-
GenerateIntrinsics =
2718-
ConstWithoutErrnoOrExceptions && ErrnoOverridenToFalseWithOpt;
2719-
}
2720-
if (GenerateIntrinsics) {
2650+
if (GenerateFPMathIntrinsics) {
27212651
switch (BuiltinIDIfNoAsmLabel) {
27222652
case Builtin::BIacos:
27232653
case Builtin::BIacosf:

0 commit comments

Comments
 (0)