https://github.com/zahiraam created https://github.com/llvm/llvm-project/pull/68820
None >From 91de35737b74233f29da76573b4099bf64e8bdd4 Mon Sep 17 00:00:00 2001 From: Ammarguellat <zahira.ammarguel...@intel.com> Date: Tue, 10 Oct 2023 08:31:41 -0700 Subject: [PATCH] Add support for -fcx-limited-range and #pragma CX_LIMTED_RANGE. --- clang/include/clang/Basic/FPOptions.def | 1 + clang/include/clang/Basic/LangOptions.def | 2 + clang/include/clang/Basic/TokenKinds.def | 5 ++ clang/include/clang/Driver/Options.td | 6 ++ clang/include/clang/Parse/Parser.h | 4 ++ clang/include/clang/Sema/Sema.h | 4 ++ clang/lib/CodeGen/CGExprComplex.cpp | 59 ++++++++++------ clang/lib/Driver/ToolChains/Clang.cpp | 2 + clang/lib/Parse/ParsePragma.cpp | 40 ++++++++++- clang/lib/Parse/ParseStmt.cpp | 10 +++ clang/lib/Parse/Parser.cpp | 3 + clang/lib/Sema/SemaAttr.cpp | 7 ++ clang/test/CodeGen/cx-full-range.c | 22 ++++++ clang/test/CodeGen/pragma-cx-limited-range.c | 73 ++++++++++++++++++++ clang/test/CodeGenCXX/cx-limited-range.c | 18 +++++ 15 files changed, 233 insertions(+), 23 deletions(-) create mode 100644 clang/test/CodeGen/cx-full-range.c create mode 100644 clang/test/CodeGen/pragma-cx-limited-range.c create mode 100644 clang/test/CodeGenCXX/cx-limited-range.c diff --git a/clang/include/clang/Basic/FPOptions.def b/clang/include/clang/Basic/FPOptions.def index 5b923a1944e509a..9e56d7fcf26fdcf 100644 --- a/clang/include/clang/Basic/FPOptions.def +++ b/clang/include/clang/Basic/FPOptions.def @@ -28,4 +28,5 @@ OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc) OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, Float16ExcessPrecision) OPTION(MathErrno, bool, 1, BFloat16ExcessPrecision) +OPTION(CxLimitedRange, bool, 1, MathErrno) #undef OPTION diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index c0ea4ecb9806a5b..47513522a0d7719 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -219,6 +219,8 @@ BENIGN_LANGOPT(NoSignedZero , 1, 0, "Permit Floating Point optimization wit BENIGN_LANGOPT(AllowRecip , 1, 0, "Permit Floating Point reciprocal") BENIGN_LANGOPT(ApproxFunc , 1, 0, "Permit Floating Point approximation") +LANGOPT(CxLimitedRange, 1, 0, "Enable use of algebraic expansions of complex arithmetics.") + BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars") BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control") diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 94db56a9fd5d78c..5cd81a66ab57bc1 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -904,6 +904,11 @@ PRAGMA_ANNOTATION(pragma_fenv_access_ms) // handles them. PRAGMA_ANNOTATION(pragma_fenv_round) +// Annotation for #pragma STDC CX_LIMITED_RANGE +// The lexer produces these so that they only take effect when the parser +// handles them. +PRAGMA_ANNOTATION(pragma_cx_limited_range) + // Annotation for #pragma float_control // The lexer produces these so that they only take effect when the parser // handles them. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index ff2130c93f28ea0..a871bea6cf14cd4 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1001,6 +1001,12 @@ defm offload_uniform_block : BoolFOption<"offload-uniform-block", NegFlag<SetFalse, [], [ClangOption, CC1Option], "Don't assume">, BothFlags<[], [ClangOption], " that kernels are launched with uniform block sizes (default true for CUDA/HIP and false otherwise)">>; +def fcx_limited_range : Joined<["-"], "fcx-limited-range">, + Group<f_Group>, Visibility<[ClangOption, CC1Option]>, + HelpText<"Basic algebraic expansions of some arithmetic operations involving " + "data of type COMPLEX are disabled.">, + MarshallingInfoFlag<LangOpts<"CxLimitedRange">>; + // OpenCL-only Options def cl_opt_disable : Flag<["-"], "cl-opt-disable">, Group<opencl_Group>, Visibility<[ClangOption, CC1Option]>, diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 0e969f341bbe19f..8f2b4d50fd59e5b 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -767,6 +767,10 @@ class Parser : public CodeCompletionHandler { /// #pragma STDC FENV_ROUND... void HandlePragmaFEnvRound(); + /// Handle the annotation token produced for + /// #pragma STDC CX_LIMITED_RANGE... + void HandlePragmaCXLimitedRange(); + /// Handle the annotation token produced for /// #pragma float_control void HandlePragmaFloatControl(); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5bef0335f7891c9..f206f5de1310e1b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10948,6 +10948,10 @@ class Sema final { /// \#pragma STDC FENV_ACCESS void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled); + /// ActOnPragmaCXLimitedRange - Called on well formed + /// \#pragma STDC CX_LIMITED_RANGE + void ActOnPragmaCXLimitedRange(SourceLocation Loc, bool IsEnabled); + /// Called on well formed '\#pragma clang fp' that has option 'exceptions'. void ActOnPragmaFPExceptions(SourceLocation Loc, LangOptions::FPExceptionModeKind); diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index f3cbd1d0451ebe4..f18fdb17090968b 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -761,6 +761,21 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); if (Op.LHS.second && Op.RHS.second) { + // (a+ib)*(c+id) = (ac-bd)+i(bc+ad) + if (Op.FPFeatures.getCxLimitedRange() || + CGF.getLangOpts().CxLimitedRange) { + llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second; + llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second; + + llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr); // ac + llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi); // bd + llvm::Value *DSTr = Builder.CreateFSub(AC, BD); // ac-bd + + llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr); // bc + llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi); // ad + llvm::Value *DSTi = Builder.CreateFAdd(BC, AD); // bc+ad + return ComplexPairTy(DSTr, DSTi); + } // If both operands are complex, emit the core math directly, and then // test for NaNs. If we find NaNs in the result, we delegate to a libcall // to carefully re-compute the correct infinity representation if @@ -851,9 +866,30 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { llvm::Value *LHSr = Op.LHS.first, *LHSi = Op.LHS.second; llvm::Value *RHSr = Op.RHS.first, *RHSi = Op.RHS.second; - llvm::Value *DSTr, *DSTi; if (LHSr->getType()->isFloatingPointTy()) { + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); + if (RHSi && (Op.FPFeatures.getCxLimitedRange() || + CGF.getLangOpts().CxLimitedRange)) { + if (!LHSi) + LHSi = llvm::Constant::getNullValue(RHSi->getType()); + + // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) + llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr); // a*c + llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi); // b*d + llvm::Value *ACpBD = Builder.CreateFAdd(AC, BD); // ac+bd + + llvm::Value *CC = Builder.CreateFMul(RHSr, RHSr); // c*c + llvm::Value *DD = Builder.CreateFMul(RHSi, RHSi); // d*d + llvm::Value *CCpDD = Builder.CreateFAdd(CC, DD); // cc+dd + + llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr); // b*c + llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi); // a*d + llvm::Value *BCmAD = Builder.CreateFSub(BC, AD); // bc-ad + + DSTr = Builder.CreateFDiv(ACpBD, CCpDD); + DSTi = Builder.CreateFDiv(BCmAD, CCpDD); + } else if (RHSi && !CGF.getLangOpts().FastMath) { // If we have a complex operand on the RHS and FastMath is not allowed, we // delegate to a libcall to handle all of the complexities and minimize // underflow/overflow cases. When FastMath is allowed we construct the @@ -861,8 +897,6 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { // // FIXME: We would be able to avoid the libcall in many places if we // supported imaginary types in addition to complex types. - CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); - if (RHSi && !CGF.getLangOpts().FastMath) { BinOpInfo LibCallOp = Op; // If LHS was a real, supply a null imaginary part. if (!LHSi) @@ -884,25 +918,6 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { case llvm::Type::FP128TyID: return EmitComplexBinOpLibCall("__divtc3", LibCallOp); } - } else if (RHSi) { - if (!LHSi) - LHSi = llvm::Constant::getNullValue(RHSi->getType()); - - // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) - llvm::Value *AC = Builder.CreateFMul(LHSr, RHSr); // a*c - llvm::Value *BD = Builder.CreateFMul(LHSi, RHSi); // b*d - llvm::Value *ACpBD = Builder.CreateFAdd(AC, BD); // ac+bd - - llvm::Value *CC = Builder.CreateFMul(RHSr, RHSr); // c*c - llvm::Value *DD = Builder.CreateFMul(RHSi, RHSi); // d*d - llvm::Value *CCpDD = Builder.CreateFAdd(CC, DD); // cc+dd - - llvm::Value *BC = Builder.CreateFMul(LHSi, RHSr); // b*c - llvm::Value *AD = Builder.CreateFMul(LHSr, RHSi); // a*d - llvm::Value *BCmAD = Builder.CreateFSub(BC, AD); // bc-ad - - DSTr = Builder.CreateFDiv(ACpBD, CCpDD); - DSTi = Builder.CreateFDiv(BCmAD, CCpDD); } else { assert(LHSi && "Can have at most one non-complex operand!"); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 129adfb9fcc74d1..40d66713d34040e 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2812,6 +2812,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-mlimit-float-precision"); CmdArgs.push_back(A->getValue()); } + if (const Arg *A = Args.getLastArg(options::OPT_fcx_limited_range)) + CmdArgs.push_back("-fcx-limited-range"); for (const Arg *A : Args) { auto optID = A->getOption().getID(); diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index b3178aef64d72d7..eae4b54ecfc545c 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -137,7 +137,20 @@ struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) override { tok::OnOffSwitch OOS; - PP.LexOnOffSwitch(OOS); + if (PP.LexOnOffSwitch(OOS)) + return; + + MutableArrayRef<Token> Toks( + PP.getPreprocessorAllocator().Allocate<Token>(1), 1); + + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_cx_limited_range); + Toks[0].setLocation(Tok.getLocation()); + Toks[0].setAnnotationEndLoc(Tok.getLocation()); + Toks[0].setAnnotationValue( + reinterpret_cast<void *>(static_cast<uintptr_t>(OOS))); + PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, + /*IsReinject=*/false); } }; @@ -846,6 +859,31 @@ void Parser::HandlePragmaFEnvRound() { Actions.ActOnPragmaFEnvRound(PragmaLoc, RM); } +void Parser::HandlePragmaCXLimitedRange() { + assert(Tok.is(tok::annot_pragma_cx_limited_range)); + tok::OnOffSwitch OOS = static_cast<tok::OnOffSwitch>( + reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); + + bool IsEnabled; + switch (OOS) { + case tok::OOS_ON: + IsEnabled = true; + break; + case tok::OOS_OFF: + IsEnabled = false; + break; + case tok::OOS_DEFAULT: + // According to ISO C99 standard chapter 7.3.4, the default value + // for the pragma is ``off'. In GCC, the option -fcx-limited-range + // controls the default setting of the pragma. + IsEnabled = getLangOpts().CxLimitedRange ? true : false; + break; + } + + SourceLocation PragmaLoc = ConsumeAnnotationToken(); + Actions.ActOnPragmaCXLimitedRange(PragmaLoc, IsEnabled); +} + StmtResult Parser::HandlePragmaCaptured() { assert(Tok.is(tok::annot_pragma_captured)); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 2531147c23196ae..b6c987c4b046b41 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -447,6 +447,13 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( ConsumeAnnotationToken(); return StmtError(); + case tok::annot_pragma_cx_limited_range: + ProhibitAttributes(CXX11Attrs); + Diag(Tok, diag::err_pragma_file_or_compound_scope) + << "STDC CX_LIMITED_RANGE"; + ConsumeAnnotationToken(); + return StmtError(); + case tok::annot_pragma_float_control: ProhibitAttributes(CXX11Attrs); ProhibitAttributes(GNUAttrs); @@ -1047,6 +1054,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_fenv_round: HandlePragmaFEnvRound(); break; + case tok::annot_pragma_cx_limited_range: + HandlePragmaCXLimitedRange(); + break; case tok::annot_pragma_float_control: HandlePragmaFloatControl(); break; diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 0f930248e77174b..befa6eba0885f29 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -836,6 +836,9 @@ Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, case tok::annot_pragma_fenv_round: HandlePragmaFEnvRound(); return nullptr; + case tok::annot_pragma_cx_limited_range: + HandlePragmaCXLimitedRange(); + return nullptr; case tok::annot_pragma_float_control: HandlePragmaFloatControl(); return nullptr; diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 6dadf01ead4441b..602bc2e5ec62f3c 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -1340,6 +1340,13 @@ void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) { CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } +void Sema::ActOnPragmaCXLimitedRange(SourceLocation Loc, bool IsEnabled) { + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); + NewFPFeatures.setCxLimitedRangeOverride(IsEnabled); + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); +} + void Sema::ActOnPragmaFPExceptions(SourceLocation Loc, LangOptions::FPExceptionModeKind FPE) { setExceptionMode(Loc, FPE); diff --git a/clang/test/CodeGen/cx-full-range.c b/clang/test/CodeGen/cx-full-range.c new file mode 100644 index 000000000000000..85386b84066ec6a --- /dev/null +++ b/clang/test/CodeGen/cx-full-range.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -o - | FileCheck %s --check-prefix=FULL + +_Complex float pragma_off_mul(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE OFF + // LABEL: define {{.*}} @pragma_on_mul + // LIMITED: %[[AC:[^ ]+]] = fmul + // LIMITED-NEXT: %[[BD:[^ ]+]] = fmul + // LIMITED-NEXT: %[[RR:[^ ]+]] = fsub + // LIMITED-NEXT: %[[BC:[^ ]+]] = fmul + // LIMITED-NEXT: %[[AD:[^ ]+]] = fmul + // LIMITED-NEXT: %[[RI:[^ ]+]] = fadd + // LIMITED: ret + return a * b; +} + +_Complex float mul(_Complex float a, _Complex float b) { + // LABEL: define {{.*}} @mul + // FULL: call {{.*}} @__mulsc3( + // FULL: ret + return a * b; +} diff --git a/clang/test/CodeGen/pragma-cx-limited-range.c b/clang/test/CodeGen/pragma-cx-limited-range.c new file mode 100644 index 000000000000000..78bed931b2ec400 --- /dev/null +++ b/clang/test/CodeGen/pragma-cx-limited-range.c @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -o - | FileCheck %s + +_Complex float pragma_on_mul(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE ON + // LABEL: define {{.*}} @pragma_on_mul + // CHECK: %[[AC:[^ ]+]] = fmul + // CHECK-NEXT: %[[BD:[^ ]+]] = fmul + // CHECK-NEXT: %[[RR:[^ ]+]] = fsub + // CHECK-NEXT: %[[BC:[^ ]+]] = fmul + // CHECK-NEXT: %[[AD:[^ ]+]] = fmul + // CHECK-NEXT: %[[RI:[^ ]+]] = fadd + // CHECK: ret + return a * b; +} + +_Complex float pragma_off_mul(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE OFF + // LABEL: define {{.*}} @pragma_off_mul + // CHECK: %[[AC:[^ ]+]] = fmul + // CHECK-NEXT: %[[BD:[^ ]+]] = fmul + // CHECK-NEXT: %[[AD:[^ ]+]] = fmul + // CHECK-NEXT: %[[BC:[^ ]+]] = fmul + // CHECK-NEXT: %[[RR:[^ ]+]] = fsub + // CHECK-NEXT: %[[RI:[^ ]+]] = fadd + // CHECK: ret + return a * b; +} + +_Complex float no_pragma_mul(_Complex float a, _Complex float b) { + // LABEL: define {{.*}} @pragma_off_mul + // CHECK: %[[AC:[^ ]+]] = fmul + // CHECK-NEXT: %[[BD:[^ ]+]] = fmul + // CHECK-NEXT: %[[AD:[^ ]+]] = fmul + // CHECK-NEXT: %[[BC:[^ ]+]] = fmul + // CHECK-NEXT: %[[RR:[^ ]+]] = fsub + // CHECK-NEXT: %[[RI:[^ ]+]] = fadd + // CHECK: ret + return a * b; +} + +_Complex float pragma_on_div(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE ON + // LABEL: define {{.*}} @pragma_on_div + // CHECK: [[AC:%.*]] = fmul + // CHECK: [[BD:%.*]] = fmul + // CHECK: [[ACpBD:%.*]] = fadd + // CHECK: [[CC:%.*]] = fmul + // CHECK: [[DD:%.*]] = fmul + // CHECK: [[CCpDD:%.*]] = fadd + // CHECK: [[BC:%.*]] = fmul + // CHECK: [[AD:%.*]] = fmul + // CHECK: [[BCmAD:%.*]] = fsub + // CHECK: fdiv + // CHECK: fdiv + // CHECK: ret + return a / b; +} + +_Complex float pragma_off_div(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE OFF + // LABEL: define {{.*}} @pragma_off_div + // CHECK: call {{.*}} @__divsc3( + // CHECK: ret + return a / b; +} + +_Complex float no_pragma_div(_Complex float a, _Complex float b) { + // LABEL: define {{.*}} @no_prama_div + // CHECK: call {{.*}} @__divsc3( + // CHECK: ret + return a / b; +} diff --git a/clang/test/CodeGenCXX/cx-limited-range.c b/clang/test/CodeGenCXX/cx-limited-range.c new file mode 100644 index 000000000000000..fce0ee413fb02c9 --- /dev/null +++ b/clang/test/CodeGenCXX/cx-limited-range.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -fcx-limited-range -o - | FileCheck %s +// RUN %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown -fuse-complex-intrinsics -fcx-range=nonan -o - | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-NO-NAN +// RUN %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown -fuse-complex-intrinsics -fcx-range=full -o - | FileCheck %s --check-prefixes=CHECK-COMMON,CHECK-FULL + +_Complex float f1(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE ON + // CHECK: fdiv float + // CHECK: fdiv float + return a / b; +} + +_Complex float f2(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE ON + // CHECK: fdiv float + // CHECK: fdiv float + return a * b; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits