Skip to content

Commit

Permalink
[SYCL] Fix compiler crash. (#12324)
Browse files Browse the repository at this point in the history
The compiler was crashing when the user requested fp-accuracy for the
functions in a call of the form f1(f2(f3 ...), where f1, f2 and f3 were
fpbuiltin but the innermost function didn't have an fpbuiltin. The
current builtinID was used instead of getting the builtinID from the
current function. that created a crash in the compiler.
This patch fixes the issue and renames the function
EmitFPBuiltinIndirectCall to MaybeEmitFPBuiltinofFD .
  • Loading branch information
zahiraam authored Feb 1, 2024
1 parent 0af4ac7 commit 4fdcb58
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 24 deletions.
23 changes: 6 additions & 17 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23271,21 +23271,11 @@ static bool hasFuncNameRequestedFPAccuracy(StringRef Name,
return (FuncMapIt != LangOpts.FPAccuracyFuncMap.end());
}

llvm::CallInst *CodeGenFunction::EmitFPBuiltinIndirectCall(
llvm::CallInst *CodeGenFunction::MaybeEmitFPBuiltinofFD(
llvm::FunctionType *IRFuncTy, const SmallVectorImpl<llvm::Value *> &IRArgs,
llvm::Value *FnPtr, const FunctionDecl *FD) {
llvm::Function *Func;
llvm::Value *FnPtr, StringRef Name, unsigned FDBuiltinID) {
unsigned FPAccuracyIntrinsicID = 0;
StringRef Name;
if (CurrentBuiltinID == 0) {
// Even if the current function doesn't have a clang builtin, create
// an 'fpbuiltin-max-error' attribute for it; unless it's marked with
// an NoBuiltin attribute.
if (FD->hasAttr<NoBuiltinAttr>() ||
!FD->getNameInfo().getName().isIdentifier())
return nullptr;

Name = FD->getName();
if (FDBuiltinID == 0) {
FPAccuracyIntrinsicID =
llvm::StringSwitch<unsigned>(Name)
.Case("fadd", llvm::Intrinsic::fpbuiltin_fadd)
Expand All @@ -23300,9 +23290,7 @@ llvm::CallInst *CodeGenFunction::EmitFPBuiltinIndirectCall(
} else {
// The function has a clang builtin. Create an attribute for it
// only if it has an fpbuiltin intrinsic.
unsigned BuiltinID = getCurrentBuiltinID();
Name = CGM.getContext().BuiltinInfo.getName(BuiltinID);
switch (BuiltinID) {
switch (FDBuiltinID) {
default:
// If the function has a clang builtin but doesn't have an
// fpbuiltin, it will be generated with no 'fpbuiltin-max-error'
Expand Down Expand Up @@ -23384,7 +23372,8 @@ llvm::CallInst *CodeGenFunction::EmitFPBuiltinIndirectCall(
const LangOptions &LangOpts = getLangOpts();
if (hasFuncNameRequestedFPAccuracy(Name, LangOpts) ||
!LangOpts.FPAccuracyVal.empty()) {
Func = CGM.getIntrinsic(FPAccuracyIntrinsicID, IRArgs[0]->getType());
llvm::Function *Func =
CGM.getIntrinsic(FPAccuracyIntrinsicID, IRArgs[0]->getType());
return CreateBuiltinCallWithAttr(*this, Name, Func, ArrayRef(IRArgs),
FPAccuracyIntrinsicID);
}
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5707,8 +5707,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (!getLangOpts().FPAccuracyFuncMap.empty() ||
!getLangOpts().FPAccuracyVal.empty()) {
const auto *FD = dyn_cast_if_present<FunctionDecl>(TargetDecl);
if (FD) {
CI = EmitFPBuiltinIndirectCall(IRFuncTy, IRCallArgs, CalleePtr, FD);
if (FD && FD->getNameInfo().getName().isIdentifier()) {
CI = MaybeEmitFPBuiltinofFD(IRFuncTy, IRCallArgs, CalleePtr,
FD->getName(), FD->getBuiltinID());
if (CI)
return RValue::get(CI);
}
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -4434,9 +4434,10 @@ class CodeGenFunction : public CodeGenTypeCache {
RValue EmitIntelSYCLPtrAnnotationBuiltin(const CallExpr *E);

llvm::CallInst *
EmitFPBuiltinIndirectCall(llvm::FunctionType *IRFuncTy,
const SmallVectorImpl<llvm::Value *> &IRArgs,
llvm::Value *FnPtr, const FunctionDecl *FD);
MaybeEmitFPBuiltinofFD(llvm::FunctionType *IRFuncTy,
const SmallVectorImpl<llvm::Value *> &IRArgs,
llvm::Value *FnPtr, StringRef Name,
unsigned FDBuiltinID);

enum class MSVCIntrin;
llvm::Value *EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID, const CallExpr *E);
Expand Down
87 changes: 85 additions & 2 deletions clang/test/CodeGen/fp-accuracy.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ double rsqrt(double);
// CHECK-F3: call double @llvm.fpbuiltin.atanh.f64(double {{.*}}) #[[ATTR_F3_HIGH]]
// CHECK-F3: call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_F3_HIGH]]
// CHECK-F3: call double @llvm.fpbuiltin.cosh.f64(double {{.*}}) #[[ATTR_F3_HIGH]]
// CHECk-F3: call double @llvm.fpbuiltin.erf.f64(double {{.*}}) #[[ATTR_F3_HIGH]]
// CHECK-F3: call double @llvm.fpbuiltin.erf.f64(double {{.*}}) #[[ATTR_F3_HIGH]]
// CHECK-F3: call double @llvm.fpbuiltin.erfc.f64(double {{.*}}) #[[ATTR_F3_HIGH]]
// CHECK-F3: call double @llvm.fpbuiltin.exp.f64(double {{.*}}) #[[ATTR_F3_HIGH]]
// CHECK-F3: call double @llvm.fpbuiltin.exp10.f64(double {{.*}}) #[[ATTR_F3_HIGH]]
Expand All @@ -203,6 +203,19 @@ double rsqrt(double);
// CHECK-F3: call double @llvm.fpbuiltin.tan.f64(double {{.*}}) #[[ATTR_F3_LOW:[0-9]+]]
// CHECK-F3: call double @llvm.fpbuiltin.tanh.f64(double {{.*}}) #[[ATTR_F3_HIGH]]

// CHECK-F3-LABEL: define dso_local void @f2
// CHECK-F3: call float @llvm.fpbuiltin.cos.f32(float {{.*}}) #[[ATTR_F3_HIGH]]
// CHECK-F3: call float @llvm.fpbuiltin.sin.f32(float {{.*}}) #[[ATTR_F3_HIGH]]
// CHECK-F3: call double @llvm.fpbuiltin.tan.f64(double {{.*}}) #[[ATTR_F3_LOW]]
// CHECK-F3: call double @llvm.fpbuiltin.log10.f64(double {{.*}}) #[[ATTR_F3_MEDIUM]]
// CHECK-F3: call void @llvm.fpbuiltin.sincos.f64(double {{.*}}, ptr {{.*}}, ptr {{.*}}) #[[ATTR_F3_MEDIUM]]

// CHECK-F3-LABEL: define dso_local float @fake_exp10

// CHECK-F3-LABEL: define dso_local void @f4
// CHECK-F3: call double @llvm.fpbuiltin.exp.f64(double {{.*}}) #[[ATTR_F3_HIGH]]
// CHECK-F3: call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_F3_HIGH]]

// CHECK-F3: attributes #[[ATTR_F3_HIGH]] = {{.*}}"fpbuiltin-max-error"="1.0"
// CHECK-F3: attributes #[[ATTR_F3_MEDIUM]] = {{.*}}"fpbuiltin-max-error"="4.0"
// CHECK-F3: attributes #[[ATTR_F3_LOW]] = {{.*}}"fpbuiltin-max-error"="67108864.0"
Expand Down Expand Up @@ -414,14 +427,25 @@ void f1(float a, float b) {
// CHECK-F2: call void @llvm.fpbuiltin.sincos.f64(double {{.*}}, ptr {{.*}}, ptr {{.*}}) #[[ATTR_F2_MEDIUM]]
// CHECK-F2: call float @tanf(float {{.*}})
//
// CHECK-LABEL-F4: define dso_local void @f2
// CHECK-F4-LABEL: define dso_local void @f2
// CHECK-F4: call float @llvm.fpbuiltin.cos.f32(float {{.*}}) #[[ATTR_F4_MEDIUM]]
// CHECK-F4: call float @llvm.fpbuiltin.sin.f32(float {{.*}}) #[[ATTR_F4_MEDIUM]]
// CHECK-F4: call double @llvm.fpbuiltin.tan.f64(double {{.*}}) #[[ATTR_F4_MEDIUM]]
// CHECK-F4: call double @llvm.fpbuiltin.log10.f64(double {{.*}}) #[[ATTR_F4_MEDIUM]]
// CHECK-F4: call void @llvm.fpbuiltin.sincos.f64(double {{.*}}, ptr {{.*}}, ptr {{.*}}) #[[ATTR_F4_MEDIUM]]
// CHECK-F4: call float @tanf(float {{.*}})
//
// CHECK-F4-LABEL: define dso_local float @fake_exp10

// CHECK-F4-LABEL: define dso_local void @f3
// CHECK-F4: call float @fake_exp10(float {{.*}})

// CHECK-F4-LABEL: define dso_local void @f4
// CHECK-F4: call double @llvm.fpbuiltin.exp.f64(double {{.*}}) #[[ATTR_F4_MEDIUM]]
// CHECK-F4: call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_F4_MEDIUM]]

// CHECK-F4: attributes #[[ATTR_F4_MEDIUM]] = {{.*}}"fpbuiltin-max-error"="4.0"

// CHECK-F5-LABEL: define dso_local void @f2
// CHECK-F5: call float @llvm.cos.f32(float {{.*}})
// CHECK-F5: call float @llvm.sin.f32(float {{.*}})
Expand All @@ -430,6 +454,15 @@ void f1(float a, float b) {
// CHECK-F5: call i32 (double, ptr, ptr, ...) @sincos(double {{.*}}, ptr {{.*}}, ptr {{.*}})
// CHECK-F5: call float @tanf(float {{.*}})
//
// CHECK-F5-LABEL: define dso_local float @fake_exp10

// CHECK-F5-LABEL: define dso_local void @f3
// CHECK-F5: call float @fake_exp10(float {{.*}})

// CHECK-F5-LABEL: define dso_local void @f4
// CHECK-F5: call double @llvm.exp.f64(double {{.*}})
// CHECK-F5: call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_F5_MEDIUM]]

// CHECK-F5: attributes #[[ATTR_F5_MEDIUM]] = {{.*}}"fpbuiltin-max-error"="4.0"
// CHECK-F5: attributes #[[ATTR_F5_HIGH]] = {{.*}}"fpbuiltin-max-error"="1.0"
//
Expand All @@ -441,6 +474,15 @@ void f1(float a, float b) {
// CHECK-F6: call void @llvm.fpbuiltin.sincos.f64(double {{.*}}, ptr {{.*}}, ptr {{.*}}) #[[ATTR_F6_MEDIUM]]
// CHECK-F6: call float @tanf(float {{.*}}) #[[ATTR8:[0-9]+]]
//
// CHECK-F6-LABEL: define dso_local float @fake_exp10
//
// CHECK-F6-LABEL: define dso_local void @f3
// CHECK-F6: call float @fake_exp10(float {{.*}})

// CHECK-F6-LABEL: define dso_local void @f4
// CHECK-F6: call double @llvm.fpbuiltin.exp.f64(double {{.*}}) #[[ATTR_F6_MEDIUM]]
// CHECK-F6: call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_F6_MEDIUM]]

// CHECK-F6: attributes #[[ATTR_F6_MEDIUM]] = {{.*}}"fpbuiltin-max-error"="4.0"
// CHECK-F6: attributes #[[ATTR_F6_HIGH]] = {{.*}}"fpbuiltin-max-error"="1.0"
//
Expand All @@ -454,12 +496,36 @@ void f1(float a, float b) {

// CHECK-LABEL: define dso_local void @f3
// CHECK: call float @fake_exp10(float {{.*}})

// CHECK-LABEL: define dso_local void @f4
// CHECK: call double @llvm.fpbuiltin.exp.f64(double {{.*}}) #[[ATTR_HIGH]]
// CHECK: call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_HIGH]]

// CHECK-F1-LABEL: define dso_local void @f3
// CHECK-F1: call float @fake_exp10(float {{.*}})

// CHECK-F1-LABEL: define dso_local void @f4
// CHECK-F1: call double @llvm.exp.f64(double {{.*}})
// CHECK-F1: call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_F1_HIGH]]

// CHECK-F2-LABEL: define dso_local float @fake_exp10

// CHECK-F2-LABEL: define dso_local void @f3
// CHECK-F2: call float @fake_exp10(float {{.*}})

// CHECK-F2-LABEL: define dso_local void @f4
// CHECK-F2: call double @llvm.fpbuiltin.exp.f64(double {{.*}}) #[[ATTR_F2_MEDIUM]]
// CHECK-F2: call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_F2_CUDA]]

// CHECK-SPIR-LABEL: define dso_local spir_func float @fake_exp10
//
// CHECK-SPIR-LABEL: define dso_local spir_func void @f3
// CHECK-SPIR: call spir_func float @fake_exp10(float {{.*}})

// CHECK-SPIR-LABEL: define dso_local spir_func void @f4
// CHECK-SPIR: call double @llvm.fpbuiltin.exp.f64(double {{.*}}) #[[ATTR_SYCL5]]
// CHECK-SPIR: call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_SYCL1]]

// CHECK: attributes #[[ATTR_HIGH]] = {{.*}}"fpbuiltin-max-error"="1.0"

// CHECK-F1: attributes #[[ATTR_F1_HIGH]] = {{.*}}"fpbuiltin-max-error"="1.0"
Expand Down Expand Up @@ -526,6 +592,10 @@ void f1(float a, float b) {
// CHECK-DEFAULT-LABEL: define dso_local void @f3
// CHECK-DEFAULT: call float @fake_exp10(float {{.*}})

// CHECK-DEFAULT-LABEL: define dso_local void @f4
// CHECK-DEFAULT: call double @llvm.exp.f64(double {{.*}})
// CHECK-DEFAULT: call double @llvm.cos.f64(double {{.*}})

void f2(float a, float b) {
float sin = 0.f, cos = 0.f;

Expand All @@ -541,3 +611,16 @@ float fake_exp10(float a) __attribute__((no_builtin)){}
void f3(float a, float b) {
a = fake_exp10(b);
}

#define sz 2
double in[sz];
double out[sz];

double getInput(int i) {
return in[i];
}

void f4() {
for (int i = 0; i < sz; i++)
out[i] = cos(exp(getInput(i)));
}
29 changes: 29 additions & 0 deletions sycl/test/check_device_code/fp-accuracy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// DEFINE: %{common_opts} = -fsycl -fsycl-device-only -fno-math-errno \
// DEFINE: -ffp-accuracy=high -S -emit-llvm -o - %s

// RUN: %clangxx %{common_opts} | FileCheck %s

// RUN: %clangxx %{common_opts} -ffp-accuracy=low:exp \
// RUN: | FileCheck %s --check-prefix=CHECK-LOW-EXP

#include <sycl/sycl.hpp>

SYCL_EXTERNAL auto foo(double x) {
using namespace sycl;
return cos(exp(log(x)));
}

// CHECK-LABEL: define {{.*}}food
// CHECK: tail call double @llvm.fpbuiltin.log.f64(double {{.*}}) #[[ATTR_HIGH:[0-9]+]]
// CHECK: tail call double @llvm.fpbuiltin.exp.f64(double {{.*}}) #[[ATTR_HIGH]]
// CHECK: tail call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_HIGH]]

// CHECK: attributes #[[ATTR_HIGH]] = {{.*}}"fpbuiltin-max-error"="1.0"

// CHECK-LOW-EXP-LABEL: define {{.*}}food
// CHECK-LOW-EXP: tail call double @llvm.fpbuiltin.log.f64(double {{.*}}) #[[ATTR_F1_HIGH:[0-9]+]]
// CHECK-LOW-EXP: tail call double @llvm.fpbuiltin.exp.f64(double {{.*}}) #[[ATTR_F1_LOW:[0-9]+]]
// CHECK-LOW-EXP: tail call double @llvm.fpbuiltin.cos.f64(double {{.*}}) #[[ATTR_F1_HIGH]]

// CHECK-F1: attributes #[[ATTR_F1_HIGH]] = {{.*}}"fpbuiltin-max-error"="1.0"
// CHECK-F1: attributes #[[ATTR_F1_LOW]] = {{.*}}"fpbuiltin-max-error"="67108864.0"

0 comments on commit 4fdcb58

Please sign in to comment.