Skip to content

[SPIRV] enable and copy device implementation for logb and scalbn builtins #143431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

choikwa
Copy link
Contributor

@choikwa choikwa commented Jun 9, 2025

Copied from previous AMDGPU implementation commit 77de8a0, PR #129347

…ltins

Copied from previous AMDGPU implementation #77de8a0
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. labels Jun 9, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 9, 2025

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: choikwa (choikwa)

Changes

Copied from previous AMDGPU implementation #77de8a0


Patch is 69.37 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143431.diff

3 Files Affected:

  • (modified) clang/lib/CodeGen/TargetBuiltins/SPIR.cpp (+72)
  • (modified) clang/lib/CodeGen/Targets/SPIR.cpp (+1)
  • (modified) clang/test/CodeGen/logb_scalbn.c (+873)
diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
index 0687485cd3f80..d4a2eeb65374f 100644
--- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "CGBuiltin.h"
 #include "CGHLSLRuntime.h"
 #include "CodeGenFunction.h"
 #include "clang/Basic/TargetBuiltins.h"
@@ -19,6 +20,26 @@ using namespace clang;
 using namespace CodeGen;
 using namespace llvm;
 
+// Has second type mangled argument.
+static Value *
+emitBinaryExpMaybeConstrainedFPBuiltin(CodeGenFunction &CGF, const CallExpr *E,
+                                       Intrinsic::ID IntrinsicID,
+                                       Intrinsic::ID ConstrainedIntrinsicID) {
+  llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0));
+  llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1));
+
+  CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
+  if (CGF.Builder.getIsFPConstrained()) {
+    Function *F = CGF.CGM.getIntrinsic(ConstrainedIntrinsicID,
+                                       {Src0->getType(), Src1->getType()});
+    return CGF.Builder.CreateConstrainedFPCall(F, {Src0, Src1});
+  }
+
+  Function *F =
+      CGF.CGM.getIntrinsic(IntrinsicID, {Src0->getType(), Src1->getType()});
+  return CGF.Builder.CreateCall(F, {Src0, Src1});
+}
+
 Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
                                              const CallExpr *E) {
   switch (BuiltinID) {
@@ -97,6 +118,57 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID,
     Call->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
     return Call;
   }
+  case Builtin::BIlogbf:
+  case Builtin::BI__builtin_logbf: {
+    Value *Src0 = EmitScalarExpr(E->getArg(0));
+    Function *FrExpFunc = CGM.getIntrinsic(
+        Intrinsic::frexp, {Src0->getType(), Builder.getInt32Ty()});
+    CallInst *FrExp = Builder.CreateCall(FrExpFunc, Src0);
+    Value *Exp = Builder.CreateExtractValue(FrExp, 1);
+    Value *Add = Builder.CreateAdd(
+        Exp, ConstantInt::getSigned(Exp->getType(), -1), "", false, true);
+    Value *SIToFP = Builder.CreateSIToFP(Add, Builder.getFloatTy());
+    Value *Fabs =
+        emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::fabs);
+    Value *FCmpONE = Builder.CreateFCmpONE(
+        Fabs, ConstantFP::getInfinity(Builder.getFloatTy()));
+    Value *Sel1 = Builder.CreateSelect(FCmpONE, SIToFP, Fabs);
+    Value *FCmpOEQ =
+        Builder.CreateFCmpOEQ(Src0, ConstantFP::getZero(Builder.getFloatTy()));
+    Value *Sel2 = Builder.CreateSelect(
+        FCmpOEQ,
+        ConstantFP::getInfinity(Builder.getFloatTy(), /*Negative=*/true), Sel1);
+    return Sel2;
+  }
+  case Builtin::BIlogb:
+  case Builtin::BI__builtin_logb: {
+    Value *Src0 = EmitScalarExpr(E->getArg(0));
+    Function *FrExpFunc = CGM.getIntrinsic(
+        Intrinsic::frexp, {Src0->getType(), Builder.getInt32Ty()});
+    CallInst *FrExp = Builder.CreateCall(FrExpFunc, Src0);
+    Value *Exp = Builder.CreateExtractValue(FrExp, 1);
+    Value *Add = Builder.CreateAdd(
+        Exp, ConstantInt::getSigned(Exp->getType(), -1), "", false, true);
+    Value *SIToFP = Builder.CreateSIToFP(Add, Builder.getDoubleTy());
+    Value *Fabs =
+        emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::fabs);
+    Value *FCmpONE = Builder.CreateFCmpONE(
+        Fabs, ConstantFP::getInfinity(Builder.getDoubleTy()));
+    Value *Sel1 = Builder.CreateSelect(FCmpONE, SIToFP, Fabs);
+    Value *FCmpOEQ =
+        Builder.CreateFCmpOEQ(Src0, ConstantFP::getZero(Builder.getDoubleTy()));
+    Value *Sel2 = Builder.CreateSelect(
+        FCmpOEQ,
+        ConstantFP::getInfinity(Builder.getDoubleTy(), /*Negative=*/true),
+        Sel1);
+    return Sel2;
+  }
+  case Builtin::BIscalbnf:
+  case Builtin::BI__builtin_scalbnf:
+  case Builtin::BIscalbn:
+  case Builtin::BI__builtin_scalbn:
+    return emitBinaryExpMaybeConstrainedFPBuiltin(
+        *this, E, Intrinsic::ldexp, Intrinsic::experimental_constrained_ldexp);
   }
   return nullptr;
 }
diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp
index 2f1e43cdc8cc3..ad4ef1a727769 100644
--- a/clang/lib/CodeGen/Targets/SPIR.cpp
+++ b/clang/lib/CodeGen/Targets/SPIR.cpp
@@ -46,6 +46,7 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo {
   CommonSPIRTargetCodeGenInfo(std::unique_ptr<ABIInfo> ABIInfo)
       : TargetCodeGenInfo(std::move(ABIInfo)) {}
 
+  bool supportsLibCall() const override { return false; }
   LangAS getASTAllocaAddressSpace() const override {
     return getLangASFromTargetAS(
         getABIInfo().getDataLayout().getAllocaAddrSpace());
diff --git a/clang/test/CodeGen/logb_scalbn.c b/clang/test/CodeGen/logb_scalbn.c
index be5e68b5fd4b0..1f6b10f2dd604 100644
--- a/clang/test/CodeGen/logb_scalbn.c
+++ b/clang/test/CodeGen/logb_scalbn.c
@@ -4,6 +4,11 @@
 // RUN: %clang -cc1 -triple amdgcn-amd-amdhsa -o - -ffp-exception-behavior=strict -emit-llvm %s | FileCheck %s -check-prefixes=STRICT
 // RUN: %clang -cc1 -triple amdgcn-amd-amdhsa -o - -ffp-exception-behavior=maytrap -emit-llvm %s | FileCheck %s -check-prefixes=MAYTRAP
 // RUN: %clang -cc1 -triple amdgcn-amd-amdhsa -o - -fmath-errno -emit-llvm %s | FileCheck %s -check-prefixes=ERRNO
+// RUN: %clang -cc1 -triple spirv64-amd-amdhsa -o - -emit-llvm %s | FileCheck %s -check-prefixes=DEF-SPIRV
+// RUN: %clang -cc1 -triple spirv64-amd-amdhsa -o - -ffp-exception-behavior=ignore -emit-llvm %s | FileCheck %s -check-prefixes=IGNORE-SPIRV
+// RUN: %clang -cc1 -triple spirv64-amd-amdhsa -o - -ffp-exception-behavior=strict -emit-llvm %s | FileCheck %s -check-prefixes=STRICT-SPIRV
+// RUN: %clang -cc1 -triple spirv64-amd-amdhsa -o - -ffp-exception-behavior=maytrap -emit-llvm %s | FileCheck %s -check-prefixes=MAYTRAP-SPIRV
+// RUN: %clang -cc1 -triple spirv64-amd-amdhsa -o - -fmath-errno -emit-llvm %s | FileCheck %s -check-prefixes=ERRNO-SPIRV
 
 // DEFAULT-LABEL: define dso_local void @test_logbf(
 // DEFAULT-SAME: ) #[[ATTR0:[0-9]+]] {
@@ -78,6 +83,79 @@
 // ERRNO-NEXT:    store float [[CALL]], ptr [[D1_ASCAST]], align 4
 // ERRNO-NEXT:    ret void
 //
+// DEF-SPIRV-LABEL: define spir_func void @test_logbf(
+// DEF-SPIRV-SAME: ) addrspace(4) #[[ATTR0:[0-9]+]] {
+// DEF-SPIRV-NEXT:  [[ENTRY:.*:]]
+// DEF-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// DEF-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// DEF-SPIRV-NEXT:    [[TMP0:%.*]] = call addrspace(4) { float, i32 } @llvm.frexp.f32.i32(float 0x40301999A0000000)
+// DEF-SPIRV-NEXT:    [[TMP1:%.*]] = extractvalue { float, i32 } [[TMP0]], 1
+// DEF-SPIRV-NEXT:    [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1
+// DEF-SPIRV-NEXT:    [[TMP3:%.*]] = sitofp i32 [[TMP2]] to float
+// DEF-SPIRV-NEXT:    [[TMP4:%.*]] = call addrspace(4) float @llvm.fabs.f32(float 0x40301999A0000000)
+// DEF-SPIRV-NEXT:    [[TMP5:%.*]] = fcmp one float [[TMP4]], 0x7FF0000000000000
+// DEF-SPIRV-NEXT:    [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP3]], float [[TMP4]]
+// DEF-SPIRV-NEXT:    [[TMP7:%.*]] = select i1 false, float 0xFFF0000000000000, float [[TMP6]]
+// DEF-SPIRV-NEXT:    store float [[TMP7]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// DEF-SPIRV-NEXT:    ret void
+//
+// IGNORE-SPIRV-LABEL: define spir_func void @test_logbf(
+// IGNORE-SPIRV-SAME: ) addrspace(4) #[[ATTR0:[0-9]+]] {
+// IGNORE-SPIRV-NEXT:  [[ENTRY:.*:]]
+// IGNORE-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// IGNORE-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// IGNORE-SPIRV-NEXT:    [[TMP0:%.*]] = call addrspace(4) { float, i32 } @llvm.frexp.f32.i32(float 0x40301999A0000000)
+// IGNORE-SPIRV-NEXT:    [[TMP1:%.*]] = extractvalue { float, i32 } [[TMP0]], 1
+// IGNORE-SPIRV-NEXT:    [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1
+// IGNORE-SPIRV-NEXT:    [[TMP3:%.*]] = sitofp i32 [[TMP2]] to float
+// IGNORE-SPIRV-NEXT:    [[TMP4:%.*]] = call addrspace(4) float @llvm.fabs.f32(float 0x40301999A0000000)
+// IGNORE-SPIRV-NEXT:    [[TMP5:%.*]] = fcmp one float [[TMP4]], 0x7FF0000000000000
+// IGNORE-SPIRV-NEXT:    [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP3]], float [[TMP4]]
+// IGNORE-SPIRV-NEXT:    [[TMP7:%.*]] = select i1 false, float 0xFFF0000000000000, float [[TMP6]]
+// IGNORE-SPIRV-NEXT:    store float [[TMP7]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// IGNORE-SPIRV-NEXT:    ret void
+//
+// STRICT-SPIRV-LABEL: define spir_func void @test_logbf(
+// STRICT-SPIRV-SAME: ) addrspace(4) #[[ATTR0:[0-9]+]] {
+// STRICT-SPIRV-NEXT:  [[ENTRY:.*:]]
+// STRICT-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// STRICT-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// STRICT-SPIRV-NEXT:    [[TMP0:%.*]] = call addrspace(4) { float, i32 } @llvm.frexp.f32.i32(float 0x40301999A0000000)
+// STRICT-SPIRV-NEXT:    [[TMP1:%.*]] = extractvalue { float, i32 } [[TMP0]], 1
+// STRICT-SPIRV-NEXT:    [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1
+// STRICT-SPIRV-NEXT:    [[TMP3:%.*]] = sitofp i32 [[TMP2]] to float
+// STRICT-SPIRV-NEXT:    [[TMP4:%.*]] = call addrspace(4) float @llvm.fabs.f32(float 0x40301999A0000000)
+// STRICT-SPIRV-NEXT:    [[TMP5:%.*]] = fcmp one float [[TMP4]], 0x7FF0000000000000
+// STRICT-SPIRV-NEXT:    [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP3]], float [[TMP4]]
+// STRICT-SPIRV-NEXT:    [[TMP7:%.*]] = select i1 false, float 0xFFF0000000000000, float [[TMP6]]
+// STRICT-SPIRV-NEXT:    store float [[TMP7]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// STRICT-SPIRV-NEXT:    ret void
+//
+// MAYTRAP-SPIRV-LABEL: define spir_func void @test_logbf(
+// MAYTRAP-SPIRV-SAME: ) addrspace(4) #[[ATTR0:[0-9]+]] {
+// MAYTRAP-SPIRV-NEXT:  [[ENTRY:.*:]]
+// MAYTRAP-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// MAYTRAP-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// MAYTRAP-SPIRV-NEXT:    [[TMP0:%.*]] = call addrspace(4) { float, i32 } @llvm.frexp.f32.i32(float 0x40301999A0000000)
+// MAYTRAP-SPIRV-NEXT:    [[TMP1:%.*]] = extractvalue { float, i32 } [[TMP0]], 1
+// MAYTRAP-SPIRV-NEXT:    [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1
+// MAYTRAP-SPIRV-NEXT:    [[TMP3:%.*]] = sitofp i32 [[TMP2]] to float
+// MAYTRAP-SPIRV-NEXT:    [[TMP4:%.*]] = call addrspace(4) float @llvm.fabs.f32(float 0x40301999A0000000)
+// MAYTRAP-SPIRV-NEXT:    [[TMP5:%.*]] = fcmp one float [[TMP4]], 0x7FF0000000000000
+// MAYTRAP-SPIRV-NEXT:    [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP3]], float [[TMP4]]
+// MAYTRAP-SPIRV-NEXT:    [[TMP7:%.*]] = select i1 false, float 0xFFF0000000000000, float [[TMP6]]
+// MAYTRAP-SPIRV-NEXT:    store float [[TMP7]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// MAYTRAP-SPIRV-NEXT:    ret void
+//
+// ERRNO-SPIRV-LABEL: define spir_func void @test_logbf(
+// ERRNO-SPIRV-SAME: ) addrspace(4) #[[ATTR0:[0-9]+]] {
+// ERRNO-SPIRV-NEXT:  [[ENTRY:.*:]]
+// ERRNO-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// ERRNO-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// ERRNO-SPIRV-NEXT:    [[CALL:%.*]] = call spir_func addrspace(4) float @logbf(float noundef 0x40301999A0000000) #[[ATTR2:[0-9]+]]
+// ERRNO-SPIRV-NEXT:    store float [[CALL]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// ERRNO-SPIRV-NEXT:    ret void
+//
 void test_logbf() {
   float D1 = __builtin_logbf(16.1f);
 }
@@ -182,6 +260,107 @@ void test_logbf() {
 // ERRNO-NEXT:    store float [[CALL]], ptr [[D1_ASCAST]], align 4
 // ERRNO-NEXT:    ret void
 //
+// DEF-SPIRV-LABEL: define spir_func void @test_logbf_var(
+// DEF-SPIRV-SAME: float noundef [[A:%.*]]) addrspace(4) #[[ATTR0]] {
+// DEF-SPIRV-NEXT:  [[ENTRY:.*:]]
+// DEF-SPIRV-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// DEF-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// DEF-SPIRV-NEXT:    [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr [[A_ADDR]] to ptr addrspace(4)
+// DEF-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// DEF-SPIRV-NEXT:    store float [[A]], ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// DEF-SPIRV-NEXT:    [[TMP0:%.*]] = load float, ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// DEF-SPIRV-NEXT:    [[TMP1:%.*]] = call addrspace(4) { float, i32 } @llvm.frexp.f32.i32(float [[TMP0]])
+// DEF-SPIRV-NEXT:    [[TMP2:%.*]] = extractvalue { float, i32 } [[TMP1]], 1
+// DEF-SPIRV-NEXT:    [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1
+// DEF-SPIRV-NEXT:    [[TMP4:%.*]] = sitofp i32 [[TMP3]] to float
+// DEF-SPIRV-NEXT:    [[TMP5:%.*]] = load float, ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// DEF-SPIRV-NEXT:    [[TMP6:%.*]] = call addrspace(4) float @llvm.fabs.f32(float [[TMP5]])
+// DEF-SPIRV-NEXT:    [[TMP7:%.*]] = fcmp one float [[TMP6]], 0x7FF0000000000000
+// DEF-SPIRV-NEXT:    [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP4]], float [[TMP6]]
+// DEF-SPIRV-NEXT:    [[TMP9:%.*]] = fcmp oeq float [[TMP0]], 0.000000e+00
+// DEF-SPIRV-NEXT:    [[TMP10:%.*]] = select i1 [[TMP9]], float 0xFFF0000000000000, float [[TMP8]]
+// DEF-SPIRV-NEXT:    store float [[TMP10]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// DEF-SPIRV-NEXT:    ret void
+//
+// IGNORE-SPIRV-LABEL: define spir_func void @test_logbf_var(
+// IGNORE-SPIRV-SAME: float noundef [[A:%.*]]) addrspace(4) #[[ATTR0]] {
+// IGNORE-SPIRV-NEXT:  [[ENTRY:.*:]]
+// IGNORE-SPIRV-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// IGNORE-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// IGNORE-SPIRV-NEXT:    [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr [[A_ADDR]] to ptr addrspace(4)
+// IGNORE-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// IGNORE-SPIRV-NEXT:    store float [[A]], ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// IGNORE-SPIRV-NEXT:    [[TMP0:%.*]] = load float, ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// IGNORE-SPIRV-NEXT:    [[TMP1:%.*]] = call addrspace(4) { float, i32 } @llvm.frexp.f32.i32(float [[TMP0]])
+// IGNORE-SPIRV-NEXT:    [[TMP2:%.*]] = extractvalue { float, i32 } [[TMP1]], 1
+// IGNORE-SPIRV-NEXT:    [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1
+// IGNORE-SPIRV-NEXT:    [[TMP4:%.*]] = sitofp i32 [[TMP3]] to float
+// IGNORE-SPIRV-NEXT:    [[TMP5:%.*]] = load float, ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// IGNORE-SPIRV-NEXT:    [[TMP6:%.*]] = call addrspace(4) float @llvm.fabs.f32(float [[TMP5]])
+// IGNORE-SPIRV-NEXT:    [[TMP7:%.*]] = fcmp one float [[TMP6]], 0x7FF0000000000000
+// IGNORE-SPIRV-NEXT:    [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP4]], float [[TMP6]]
+// IGNORE-SPIRV-NEXT:    [[TMP9:%.*]] = fcmp oeq float [[TMP0]], 0.000000e+00
+// IGNORE-SPIRV-NEXT:    [[TMP10:%.*]] = select i1 [[TMP9]], float 0xFFF0000000000000, float [[TMP8]]
+// IGNORE-SPIRV-NEXT:    store float [[TMP10]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// IGNORE-SPIRV-NEXT:    ret void
+//
+// STRICT-SPIRV-LABEL: define spir_func void @test_logbf_var(
+// STRICT-SPIRV-SAME: float noundef [[A:%.*]]) addrspace(4) #[[ATTR0]] {
+// STRICT-SPIRV-NEXT:  [[ENTRY:.*:]]
+// STRICT-SPIRV-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// STRICT-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// STRICT-SPIRV-NEXT:    [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr [[A_ADDR]] to ptr addrspace(4)
+// STRICT-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// STRICT-SPIRV-NEXT:    store float [[A]], ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// STRICT-SPIRV-NEXT:    [[TMP0:%.*]] = load float, ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// STRICT-SPIRV-NEXT:    [[TMP1:%.*]] = call addrspace(4) { float, i32 } @llvm.frexp.f32.i32(float [[TMP0]])
+// STRICT-SPIRV-NEXT:    [[TMP2:%.*]] = extractvalue { float, i32 } [[TMP1]], 1
+// STRICT-SPIRV-NEXT:    [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1
+// STRICT-SPIRV-NEXT:    [[TMP4:%.*]] = sitofp i32 [[TMP3]] to float
+// STRICT-SPIRV-NEXT:    [[TMP5:%.*]] = load float, ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// STRICT-SPIRV-NEXT:    [[TMP6:%.*]] = call addrspace(4) float @llvm.fabs.f32(float [[TMP5]])
+// STRICT-SPIRV-NEXT:    [[TMP7:%.*]] = fcmp one float [[TMP6]], 0x7FF0000000000000
+// STRICT-SPIRV-NEXT:    [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP4]], float [[TMP6]]
+// STRICT-SPIRV-NEXT:    [[TMP9:%.*]] = fcmp oeq float [[TMP0]], 0.000000e+00
+// STRICT-SPIRV-NEXT:    [[TMP10:%.*]] = select i1 [[TMP9]], float 0xFFF0000000000000, float [[TMP8]]
+// STRICT-SPIRV-NEXT:    store float [[TMP10]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// STRICT-SPIRV-NEXT:    ret void
+//
+// MAYTRAP-SPIRV-LABEL: define spir_func void @test_logbf_var(
+// MAYTRAP-SPIRV-SAME: float noundef [[A:%.*]]) addrspace(4) #[[ATTR0]] {
+// MAYTRAP-SPIRV-NEXT:  [[ENTRY:.*:]]
+// MAYTRAP-SPIRV-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// MAYTRAP-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// MAYTRAP-SPIRV-NEXT:    [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr [[A_ADDR]] to ptr addrspace(4)
+// MAYTRAP-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// MAYTRAP-SPIRV-NEXT:    store float [[A]], ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// MAYTRAP-SPIRV-NEXT:    [[TMP0:%.*]] = load float, ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// MAYTRAP-SPIRV-NEXT:    [[TMP1:%.*]] = call addrspace(4) { float, i32 } @llvm.frexp.f32.i32(float [[TMP0]])
+// MAYTRAP-SPIRV-NEXT:    [[TMP2:%.*]] = extractvalue { float, i32 } [[TMP1]], 1
+// MAYTRAP-SPIRV-NEXT:    [[TMP3:%.*]] = add nsw i32 [[TMP2]], -1
+// MAYTRAP-SPIRV-NEXT:    [[TMP4:%.*]] = sitofp i32 [[TMP3]] to float
+// MAYTRAP-SPIRV-NEXT:    [[TMP5:%.*]] = load float, ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// MAYTRAP-SPIRV-NEXT:    [[TMP6:%.*]] = call addrspace(4) float @llvm.fabs.f32(float [[TMP5]])
+// MAYTRAP-SPIRV-NEXT:    [[TMP7:%.*]] = fcmp one float [[TMP6]], 0x7FF0000000000000
+// MAYTRAP-SPIRV-NEXT:    [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP4]], float [[TMP6]]
+// MAYTRAP-SPIRV-NEXT:    [[TMP9:%.*]] = fcmp oeq float [[TMP0]], 0.000000e+00
+// MAYTRAP-SPIRV-NEXT:    [[TMP10:%.*]] = select i1 [[TMP9]], float 0xFFF0000000000000, float [[TMP8]]
+// MAYTRAP-SPIRV-NEXT:    store float [[TMP10]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// MAYTRAP-SPIRV-NEXT:    ret void
+//
+// ERRNO-SPIRV-LABEL: define spir_func void @test_logbf_var(
+// ERRNO-SPIRV-SAME: float noundef [[A:%.*]]) addrspace(4) #[[ATTR0]] {
+// ERRNO-SPIRV-NEXT:  [[ENTRY:.*:]]
+// ERRNO-SPIRV-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// ERRNO-SPIRV-NEXT:    [[D1:%.*]] = alloca float, align 4
+// ERRNO-SPIRV-NEXT:    [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr [[A_ADDR]] to ptr addrspace(4)
+// ERRNO-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// ERRNO-SPIRV-NEXT:    store float [[A]], ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// ERRNO-SPIRV-NEXT:    [[TMP0:%.*]] = load float, ptr addrspace(4) [[A_ADDR_ASCAST]], align 4
+// ERRNO-SPIRV-NEXT:    [[CALL:%.*]] = call spir_func addrspace(4) float @logbf(float noundef [[TMP0]]) #[[ATTR2]]
+// ERRNO-SPIRV-NEXT:    store float [[CALL]], ptr addrspace(4) [[D1_ASCAST]], align 4
+// ERRNO-SPIRV-NEXT:    ret void
+//
 void test_logbf_var(float a) {
   float D1 = __builtin_logbf(a);
 }
@@ -273,6 +452,79 @@ void test_logbf_var(float a) {
 // ERRNO-NEXT:    store double [[CALL]], ptr [[D1_ASCAST]], align 8
 // ERRNO-NEXT:    ret void
 //
+// DEF-SPIRV-LABEL: define spir_func void @test_logb(
+// DEF-SPIRV-SAME: ) addrspace(4) #[[ATTR0]] {
+// DEF-SPIRV-NEXT:  [[ENTRY:.*:]]
+// DEF-SPIRV-NEXT:    [[D1:%.*]] = alloca double, align 8
+// DEF-SPIRV-NEXT:    [[D1_ASCAST:%.*]] = addrspacecast ptr [[D1]] to ptr addrspace(4)
+// DEF-SPIRV-NEXT:    [[TMP0:%.*]] = call addrspace(4) { double, i32 } @llvm.frexp.f64.i32(double 1.510000e+01)
+// DEF-SPIRV-NEXT:    [[TMP1:%.*]] = extractvalue { double, i32 } [[TMP0]], 1
+// DEF-SPIRV-NEXT:    [[TMP2:%.*]] = add nsw i32 [[TMP1]], -1
+// DEF-SPIRV-NEXT:    [[TMP3:%.*]] = sitofp i32 [[TMP2]] to double
+// DEF-SPIRV-NEXT:    [[TMP4:%.*]] = call addrspace(4) double @llvm.fabs.f64(double 1.510000e+01)
+// DEF-SPIRV-NEXT:    [[TMP5:%.*]] = fcmp one double [[TMP4]], 0x7FF0000000000000
+// DEF-SPIRV-NEXT:    [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP3]], double [[TMP4]]
+// DEF-SPIRV-NEXT:    [[TMP7:%.*]] = select i1 false, double 0xFFF0000000000000, double [[TMP6]]
+// DEF-SPIRV-NEXT:    store double [[TMP7]], ptr addrspace(4) [[D1_ASCAST...
[truncated]

@choikwa choikwa requested a review from yxsamliu June 9, 2025 19:52
@choikwa
Copy link
Contributor Author

choikwa commented Jun 11, 2025

Closed in favor of better fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants