[llvm] Add SPIRV lowering for intrinsics @llvm.fptosi.sat.* and @llvm.fptoui.sat.* (PR #125805)

Vishakh Prakash via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 5 00:22:15 PST 2025


https://github.com/Vishakh2012 updated https://github.com/llvm/llvm-project/pull/125805

>From 992bcb40e7832df28c697af867b257f83a99c362 Mon Sep 17 00:00:00 2001
From: vishakh prakash <vishakhpro2002 at gmail.com>
Date: Wed, 5 Feb 2025 11:26:03 +0530
Subject: [PATCH 1/2] FEAT: Add support for intrinsics @llvm.fptosi.sat.* and
 @llvm.fptoui.sat.* - add legalizer for G_FPTOSI_SAT and G_FPTOUI_SAT - add
 Instruction Selector for G_FPTOSI_SAT and G_FPTOUI_SAT - add lowering
 function for cases where integer is arbitrary - add supporting tests for both
 the case arbitrary and non-arbitrary   conversions

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp |  20 +-
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |   5 +
 llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp  |   5 +
 .../Target/SPIRV/SPIRVPrepareFunctions.cpp    |  87 ++++++++
 .../fp_to_arbitrary_size_int_intrinsics.ll    |  46 ++++
 .../llvm-intrinsics/fp_to_int_intrinsics.ll   | 209 ++++++++++++++++++
 6 files changed, 371 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp_to_arbitrary_size_int_intrinsics.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp_to_int_intrinsics.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 702206b8e0dc56..0887fc9c910d91 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -1337,6 +1337,24 @@ static void createSaturatedConversionDecoration(Instruction *I,
   createDecorationIntrinsic(I, SaturatedConversionNode, B);
 }
 
+/// add saturated decoration to intrinsic with "sat" keyword in it
+static void addSaturatedDecorationToIntrinsic(Instruction *I, IRBuilder<> &B) {
+  if (auto *CI = dyn_cast<CallInst>(I)) {
+    Function *F = CI->getCalledFunction();
+    if (F->isIntrinsic()) {
+      StringRef S = F->getName();
+      SmallVector<StringRef, 8> Parts;
+
+      S.split(Parts, ".", -1, false);
+
+      if (Parts.size() > 1) {
+        if (std::find(Parts.begin(), Parts.end(), "sat") != Parts.end()) {
+          createSaturatedConversionDecoration(I, B);
+        }
+      }
+    }
+  }
+}
 Instruction *SPIRVEmitIntrinsics::visitCallInst(CallInst &Call) {
   if (!Call.isInlineAsm())
     return &Call;
@@ -2399,7 +2417,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
     // Don't emit intrinsics for convergence operations.
     if (isConvergenceIntrinsic(I))
       continue;
-
+    addSaturatedDecorationToIntrinsic(I, B);
     processInstrAfterVisit(I, B);
   }
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index e7d8fe5bd8015b..2aea5189f46ad1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -603,6 +603,11 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
   case TargetOpcode::G_FPTOUI:
     return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);
 
+  case TargetOpcode::G_FPTOSI_SAT:
+    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToS);
+  case TargetOpcode::G_FPTOUI_SAT:
+    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);
+
   case TargetOpcode::G_SITOFP:
     return selectIToF(ResVReg, ResType, I, true, SPIRV::OpConvertSToF);
   case TargetOpcode::G_UITOFP:
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index fa5e0a80576d01..4ef8388efb4340 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -236,6 +236,11 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
       .legalForCartesianProduct(allIntScalarsAndVectors,
                                 allFloatScalarsAndVectors);
 
+
+  getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
+      .legalForCartesianProduct(allIntScalarsAndVectors,
+                                allFloatScalarsAndVectors);
+
   getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
       .legalForCartesianProduct(allFloatScalarsAndVectors,
                                 allScalarsAndVectors);
diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
index 028699e56a9469..12f29956563dd9 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
@@ -340,6 +340,79 @@ static void lowerFunnelShifts(IntrinsicInst *FSHIntrinsic) {
   FSHIntrinsic->setCalledFunction(FSHFunc);
 }
 
+static std::vector<Instruction *> lowerFPTOISat(IntrinsicInst *FptosiIntrinsi) {
+  // follows implementation from SPIRV-LLVM Biderectional translator
+  std::vector<Instruction *> ToErase;
+
+  if (isa<VectorType>(FptosiIntrinsi->getType()))
+    return ToErase;
+
+  auto IID = FptosiIntrinsi->getIntrinsicID();
+  auto IntBitWidth = FptosiIntrinsi->getType()->getScalarSizeInBits();
+
+  if (IntBitWidth == 8 || IntBitWidth == 16 || IntBitWidth == 32 ||
+      IntBitWidth == 64)
+    return ToErase;
+
+  if (IID == Intrinsic::fptosi_sat) {
+    auto *User = FptosiIntrinsi->getUniqueUndroppableUser();
+    if (!User || !isa<SExtInst>(User))
+      return ToErase;
+
+    auto *SExtI = dyn_cast<SExtInst>(User);
+    auto *NewIType = SExtI->getType();
+    IRBuilder<> IRB(FptosiIntrinsi);
+
+    auto *NewII = IRB.CreateIntrinsic(
+        IID, {NewIType, FptosiIntrinsi->getOperand(0)->getType()},
+        FptosiIntrinsi->getOperand(0));
+
+    Constant *MaxVal = ConstantInt::get(
+        NewIType, APInt::getSignedMaxValue(IntBitWidth).getSExtValue());
+
+    Constant *MinVal = ConstantInt::get(
+        NewIType, APInt::getSignedMinValue(IntBitWidth).getSExtValue());
+
+    auto *GTMax = IRB.CreateICmp(CmpInst::ICMP_SGE, NewII, MaxVal);
+    auto *LTMin = IRB.CreateICmp(CmpInst::ICMP_SLE, NewII, MinVal);
+    auto *SatMax = IRB.CreateSelect(GTMax, MaxVal, NewII);
+    auto *SatMin = IRB.CreateSelect(LTMin, MinVal, SatMax);
+
+    SExtI->replaceAllUsesWith(SatMin);
+    ToErase.push_back(SExtI);
+    ToErase.push_back(FptosiIntrinsi);
+  }
+
+  if (IID == Intrinsic::fptoui_sat) {
+    // Identify zext (user of II). Make sure that's the only use of II.
+
+    auto *User = FptosiIntrinsi->getUniqueUndroppableUser();
+
+    if (!User || !isa<ZExtInst>(User))
+      return ToErase;
+
+    auto *ZExtI = dyn_cast<ZExtInst>(User);
+    auto *NewIType = ZExtI->getType();
+    IRBuilder<> IRB(FptosiIntrinsi);
+    auto *NewII = IRB.CreateIntrinsic(
+        IID, {NewIType, FptosiIntrinsi->getOperand(0)->getType()},
+        FptosiIntrinsi->getOperand(0));
+
+    Constant *MaxVal = ConstantInt::get(
+        NewIType, APInt::getMaxValue(IntBitWidth).getZExtValue());
+
+    auto *GTMax = IRB.CreateICmp(CmpInst::ICMP_UGE, NewII, MaxVal);
+    auto *SatMax = IRB.CreateSelect(GTMax, MaxVal, NewII);
+
+    ZExtI->replaceAllUsesWith(SatMax);
+
+    ToErase.push_back(ZExtI);
+    ToErase.push_back(FptosiIntrinsi);
+  }
+
+  return ToErase;
+}
+
 static void lowerExpectAssume(IntrinsicInst *II) {
   // If we cannot use the SPV_KHR_expect_assume extension, then we need to
   // ignore the intrinsic and move on. It should be removed later on by LLVM.
@@ -385,6 +458,7 @@ static bool toSpvOverloadedIntrinsic(IntrinsicInst *II, Intrinsic::ID NewID,
 // or calls to proper generated functions. Returns True if F was modified.
 bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
   bool Changed = false;
+  std::vector<Instruction *> ToErase;
   for (BasicBlock &BB : *F) {
     for (Instruction &I : BB) {
       auto Call = dyn_cast<CallInst>(&I);
@@ -421,11 +495,24 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
         break;
       case Intrinsic::ptr_annotation:
         lowerPtrAnnotation(II);
+        Changed = true;
+        break;
+      case Intrinsic::fptosi_sat:
+      case Intrinsic::fptoui_sat:
+        ToErase = lowerFPTOISat(II);
+        if (ToErase.empty()) break;
+
         Changed = true;
         break;
       }
     }
   }
+
+  for (Instruction *V : ToErase) {
+    assert(V->user_empty());
+    V->dropAllReferences();
+    V->eraseFromParent();
+  }
   return Changed;
 }
 
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp_to_arbitrary_size_int_intrinsics.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp_to_arbitrary_size_int_intrinsics.ll
new file mode 100644
index 00000000000000..0c975dcf79a09b
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp_to_arbitrary_size_int_intrinsics.ll
@@ -0,0 +1,46 @@
+;; Ensure @llvm.fptosi.sat.* and @llvm.fptoui.sat.* intrinsics are translated
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unkown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unkown-unknown %s -o - -filetype=obj | spirv-val %}
+ 
+; CHECK-DAG: OpCapability Kernel
+; CHECK-DAG: OpDecorate %[[#SAT1:]] SaturatedConversion
+; CHECK-DAG: OpDecorate %[[#SAT2:]] SaturatedConversion
+; CHECK-DAG: %[[#INT64TY:]] = OpTypeInt  64 0
+; CHECK-DAG: %[[#BOOLTY:]] = OpTypeBool 
+; CHECK-DAG: %[[#IS2MIN:]] = OpConstant %[[#INT64TY]]
+; CHECK-DAG: %[[#I2SMAX:]] = OpConstant %[[#INT64TY]] 
+; CHECK-DAG: %[[#SAT1]] = OpConvertFToS %[[#INT64TY]] %[[#]]
+; CHECK-DAG: %[[#SGRES:]] = OpSGreaterThanEqual %[[#BOOLTY]] %[[#SAT1]] %[[#I2SMAX]]
+; CHECK-DAG: %[[#SLERES:]] = OpSLessThanEqual %[[#BOOLTY]] %[[#SAT1]] %[[#IS2MIN]]
+; CHECK-DAG: %[[#SELRES1:]] = OpSelect %[[#INT64TY]] %[[#SGRES]] %[[#I2SMAX]] %[[#SAT1]]
+; CHECK-DAG: %[[#SELRES2:]] = OpSelect %[[#INT64TY]] %[[#SLERES]] %[[#IS2MIN]] %[[#SELRES1]]
+ 
+define spir_kernel void @testfunction_float_to_signed_i2(float %input) {
+entry:
+    %ptr = alloca i64
+   %0 = call i2 @llvm.fptosi.sat.i2.f32(float %input)
+   %1 = sext i2 %0 to i64
+   store i64 %1, i64* %ptr
+   ret void
+
+}
+declare i2 @llvm.fptosi.sat.i2.f32(float)
+
+
+; CHECK-DAG: %[[#I2UMAX:]] = OpConstant %[[#INT64TY]] 3 
+; CHECK-DAG: %[[#SAT2]] = OpConvertFToU %[[#INT64TY]] %[[#]] 
+; CHECK-DAG: %[[#UGERES:]] = OpUGreaterThanEqual %[[#BOOLTY]] %[[#SAT2]] %[[#I2UMAX]]
+; CHECK-DAG: %[[#SELRES1U:]] = OpSelect %[[#INT64TY]] %[[#UGERES]] %[[#I2UMAX]] %[[#SAT2]]
+
+define spir_kernel void @testfunction_float_to_unsigned_i2(float %input) {
+entry:
+   %ptr = alloca i64
+   %0 = call i2 @llvm.fptoui.sat.i2.f32(float %input)
+   %1 = zext i2 %0 to i64
+   store i64 %1, i64* %ptr
+   ret void
+
+}
+declare i2 @llvm.fptoui.sat.i2.f32(float)
+ 
+ 
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp_to_int_intrinsics.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp_to_int_intrinsics.ll
new file mode 100644
index 00000000000000..002abc6d6d5dbc
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp_to_int_intrinsics.ll
@@ -0,0 +1,209 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unkown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unkown-unknown %s -o - -filetype=obj | spirv-val %}
+ 
+; CHECK: OpDecorate %[[#SAT1:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT2:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT3:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT4:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT5:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT6:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT7:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT8:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT9:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT10:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT11:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT12:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT13:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT14:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT15:]] SaturatedConversion
+ 
+
+; CHECK: %[[#SAT1:]] = OpConvertFToS %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_float_to_signed_i8(float %input) {
+entry:
+   %ptr = alloca i8
+   %0 = call i8 @llvm.fptosi.sat.i8.f32(float %input)
+   store i8 %0, i8* %ptr
+   ret void
+
+}
+declare i8 @llvm.fptosi.sat.i8.f32(float)
+ 
+ 
+; CHECK: %[[#SAT2:]] = OpConvertFToS %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_float_to_signed_i16(float %input) {
+entry:
+   %ptr = alloca i16
+   %0 = call i16 @llvm.fptosi.sat.i16.f32(float %input)
+   store i16 %0, i16* %ptr
+   ret void
+
+}
+declare i16 @llvm.fptosi.sat.i16.f32(float)
+ 
+; CHECK: %[[#SAT3:]] = OpConvertFToS %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_float_to_signed_i32(float %input) {
+entry:
+   %ptr = alloca i32
+   %0 = call i32 @llvm.fptosi.sat.i32.f32(float %input)
+   store i32 %0, i32* %ptr
+   ret void
+
+}
+declare i32 @llvm.fptosi.sat.i32.f32(float)
+ 
+
+; CHECK: %[[#SAT4:]] = OpConvertFToS %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_float_to_signed_i64(float %input) {
+entry:
+   %ptr = alloca i64
+   %0 = call i64 @llvm.fptosi.sat.i64.f32(float %input)
+   store i64 %0, i64* %ptr
+   ret void
+}
+declare i64 @llvm.fptosi.sat.i64.f32(float)
+ 
+
+; CHECK: %[[#SAT5:]] = OpConvertFToS %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_double_to_signed_i8(double %input) {
+entry:
+   %ptr = alloca i8
+   %0 = call i8 @llvm.fptosi.sat.i8.f64(double %input)
+   store i8 %0, i8* %ptr
+   ret void
+}
+declare i8 @llvm.fptosi.sat.i8.f64(double)
+ 
+
+; CHECK: %[[#SAT6:]] = OpConvertFToS %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_double_to_signed_i16(double %input) {
+entry:
+   %ptr = alloca i16
+   %0 = call i16 @llvm.fptosi.sat.i16.f64(double %input)
+   store i16 %0, i16* %ptr
+   ret void
+}
+declare i16 @llvm.fptosi.sat.i16.f64(double)
+ 
+ 
+; CHECK: %[[#SAT7:]] = OpConvertFToS %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_double_to_signed_i32(double %input) {
+entry:
+   %ptr = alloca i32
+   %0 = call i32 @llvm.fptosi.sat.i32.f64(double %input)
+   store i32 %0, i32* %ptr
+   ret void
+}
+declare i32 @llvm.fptosi.sat.i32.f64(double)
+ 
+ 
+; CHECK: %[[#SAT8:]] = OpConvertFToS %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_double_to_signed_i64(double %input) {
+entry:
+   %ptr = alloca i64
+   %0 = call i64 @llvm.fptosi.sat.i64.f64(double %input)
+   store i64 %0, i64* %ptr
+   ret void
+}
+declare i64 @llvm.fptosi.sat.i64.f64(double)
+ 
+ 
+ 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; unsigned output
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+; CHECK: %[[#SAT8:]] = OpConvertFToU %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_float_to_unsigned_i8(float %input) {
+entry:
+   %ptr = alloca i8
+   %0 = call i8 @llvm.fptoui.sat.i8.f32(float %input)
+   store i8 %0, i8* %ptr
+   ret void
+}
+declare i8 @llvm.fptoui.sat.i8.f32(float)
+ 
+
+; CHECK: %[[#SAT9:]] = OpConvertFToU %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_float_to_unsigned_i16(float %input) {
+entry:
+   %ptr = alloca i16
+   %0 = call i16 @llvm.fptoui.sat.i16.f32(float %input)
+   store i16 %0, i16* %ptr
+   ret void
+}
+declare i16 @llvm.fptoui.sat.i16.f32(float)
+
+
+; CHECK: %[[#SAT10:]] = OpConvertFToU %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_float_to_unsigned_i32(float %input) {
+entry:
+   %ptr = alloca i32
+   %0 = call i32 @llvm.fptoui.sat.i32.f32(float %input)
+   store i32 %0, i32* %ptr
+   ret void
+}
+declare i32 @llvm.fptoui.sat.i32.f32(float)
+ 
+
+; CHECK: %[[#SAT11:]] = OpConvertFToU %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_float_to_unsigned_i64(float %input) {
+entry:
+   %ptr = alloca i64
+   %0 = call i64 @llvm.fptoui.sat.i64.f32(float %input)
+   store i64 %0, i64* %ptr
+   ret void
+}
+declare i64 @llvm.fptoui.sat.i64.f32(float)
+ 
+
+; CHECK: %[[#SAT12:]] = OpConvertFToU %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_double_to_unsigned_i8(double %input) {
+entry:
+   %ptr = alloca i8
+   %0 = call i8 @llvm.fptoui.sat.i8.f64(double %input)
+   store i8 %0, i8* %ptr
+   ret void
+}
+declare i8 @llvm.fptoui.sat.i8.f64(double)
+ 
+
+; CHECK: %[[#SAT13:]] = OpConvertFToU %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_double_to_unsigned_i16(double %input) {
+entry:
+   %ptr = alloca i16
+   %0 = call i16 @llvm.fptoui.sat.i16.f64(double %input)
+   store i16 %0, i16* %ptr
+   ret void
+}
+declare i16 @llvm.fptoui.sat.i16.f64(double)
+ 
+
+; CHECK: %[[#SAT14:]] = OpConvertFToU %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_double_to_unsigned_i32(double %input) {
+entry:
+   %ptr = alloca i32
+   %0 = call i32 @llvm.fptoui.sat.i32.f64(double %input)
+   store i32 %0, i32* %ptr
+   ret void
+}
+declare i32 @llvm.fptoui.sat.i32.f64(double)
+ 
+
+; CHECK: %[[#SAT15:]] = OpConvertFToU %{{[0-9]+}} %[[#]]
+define spir_kernel void @testfunction_double_to_unsigned_i64(double %input) {
+entry:
+   %ptr = alloca i64
+   %0 = call i64 @llvm.fptoui.sat.i64.f64(double %input)
+   store i64 %0, i64* %ptr
+   ret void
+}
+declare i64 @llvm.fptoui.sat.i64.f64(double)
+ 
+ 
+ 
+ 

>From f1a9d3bc8e98ce07296a685a3b2a65761312d806 Mon Sep 17 00:00:00 2001
From: Vishakh Prakash <vishakhpro2002 at gmail.com>
Date: Wed, 5 Feb 2025 08:20:33 +0000
Subject: [PATCH 2/2] minor formatting change

---
 llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
index 12f29956563dd9..19d17e1749cea3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
@@ -500,7 +500,8 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
       case Intrinsic::fptosi_sat:
       case Intrinsic::fptoui_sat:
         ToErase = lowerFPTOISat(II);
-        if (ToErase.empty()) break;
+        if (ToErase.empty()) 
+          break;
 
         Changed = true;
         break;



More information about the llvm-commits mailing list