Skip to content

Commit 047ddbf

Browse files
[SPIRV] Added support for the constrained comparison intrinsics (#157439)
Added SPIR-V support for constrained floating-point comparison intrinsics (fcmp, fcmps) with lowering and tests.
1 parent dcfb904 commit 047ddbf

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,21 @@ static void lowerFunnelShifts(IntrinsicInst *FSHIntrinsic) {
335335
FSHIntrinsic->setCalledFunction(FSHFunc);
336336
}
337337

338+
static void lowerConstrainedFPCmpIntrinsic(
339+
ConstrainedFPCmpIntrinsic *ConstrainedCmpIntrinsic,
340+
SmallVector<Instruction *> &EraseFromParent) {
341+
if (!ConstrainedCmpIntrinsic)
342+
return;
343+
// Extract the floating-point values being compared
344+
Value *LHS = ConstrainedCmpIntrinsic->getArgOperand(0);
345+
Value *RHS = ConstrainedCmpIntrinsic->getArgOperand(1);
346+
FCmpInst::Predicate Pred = ConstrainedCmpIntrinsic->getPredicate();
347+
IRBuilder<> Builder(ConstrainedCmpIntrinsic);
348+
Value *FCmp = Builder.CreateFCmp(Pred, LHS, RHS);
349+
ConstrainedCmpIntrinsic->replaceAllUsesWith(FCmp);
350+
EraseFromParent.push_back(dyn_cast<Instruction>(ConstrainedCmpIntrinsic));
351+
}
352+
338353
static void lowerExpectAssume(IntrinsicInst *II) {
339354
// If we cannot use the SPV_KHR_expect_assume extension, then we need to
340355
// ignore the intrinsic and move on. It should be removed later on by LLVM.
@@ -376,6 +391,7 @@ static bool toSpvLifetimeIntrinsic(IntrinsicInst *II, Intrinsic::ID NewID) {
376391
bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
377392
bool Changed = false;
378393
const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
394+
SmallVector<Instruction *> EraseFromParent;
379395
for (BasicBlock &BB : *F) {
380396
for (Instruction &I : make_early_inc_range(BB)) {
381397
auto Call = dyn_cast<CallInst>(&I);
@@ -423,9 +439,17 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
423439
lowerPtrAnnotation(II);
424440
Changed = true;
425441
break;
442+
case Intrinsic::experimental_constrained_fcmp:
443+
case Intrinsic::experimental_constrained_fcmps:
444+
lowerConstrainedFPCmpIntrinsic(dyn_cast<ConstrainedFPCmpIntrinsic>(II),
445+
EraseFromParent);
446+
Changed = true;
447+
break;
426448
}
427449
}
428450
}
451+
for (auto *I : EraseFromParent)
452+
I->eraseFromParent();
429453
return Changed;
430454
}
431455

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK-DAG: OpFOrdEqual
5+
; CHECK-DAG: OpFOrdGreaterThan
6+
; CHECK-DAG: OpFOrdGreaterThanEqual
7+
; CHECK-DAG: OpFOrdLessThan
8+
; CHECK-DAG: OpFOrdLessThanEqual
9+
; CHECK-DAG: OpFOrdNotEqual
10+
; CHECK-DAG: OpOrdered
11+
; CHECK-DAG: OpFUnordEqual
12+
; CHECK-DAG: OpFUnordGreaterThan
13+
; CHECK-DAG: OpFUnordGreaterThanEqual
14+
; CHECK-DAG: OpFUnordLessThan
15+
; CHECK-DAG: OpFUnordLessThanEqual
16+
; CHECK-DAG: OpFUnordNotEqual
17+
; CHECK-DAG: OpUnordered
18+
19+
define dso_local spir_kernel void @test(float %a){
20+
entry:
21+
%cmp = tail call i1 @llvm.experimental.constrained.fcmps.f32(float %a, float %a, metadata !"oeq", metadata !"fpexcept.strict")
22+
%cmp1 = tail call i1 @llvm.experimental.constrained.fcmps.f32(float %a, float %a, metadata !"ogt", metadata !"fpexcept.strict")
23+
%cmp2 = tail call i1 @llvm.experimental.constrained.fcmps.f32(float %a, float %a, metadata !"oge", metadata !"fpexcept.strict")
24+
%cmp3 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"olt", metadata !"fpexcept.strict")
25+
%cmp4 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"ole", metadata !"fpexcept.strict")
26+
%cmp5 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"one", metadata !"fpexcept.strict")
27+
%cmp6 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"ord", metadata !"fpexcept.strict")
28+
%cmp7 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"ueq", metadata !"fpexcept.strict")
29+
%cmp8 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"ugt", metadata !"fpexcept.strict")
30+
%cmp9 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"uge", metadata !"fpexcept.strict")
31+
%cmp10 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"ult", metadata !"fpexcept.strict")
32+
%cmp11 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"ule", metadata !"fpexcept.strict")
33+
%cmp12 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"une", metadata !"fpexcept.strict")
34+
%cmp13 = tail call i1 @llvm.experimental.constrained.fcmp.f32(float %a, float %a, metadata !"uno", metadata !"fpexcept.strict")
35+
36+
%or1 = or i1 %cmp, %cmp1
37+
%or2 = or i1 %or1, %cmp2
38+
%or3 = or i1 %or2, %cmp3
39+
%or4 = or i1 %or3, %cmp4
40+
%or5 = or i1 %or4, %cmp5
41+
%or6 = or i1 %or5, %cmp6
42+
%or7 = or i1 %or6, %cmp7
43+
%or8 = or i1 %or7, %cmp8
44+
%or9 = or i1 %or8, %cmp9
45+
%or10 = or i1 %or9, %cmp10
46+
%or11 = or i1 %or10, %cmp11
47+
%or12 = or i1 %or11, %cmp12
48+
%or13 = or i1 %or12, %cmp13
49+
br i1 %or13, label %true_block, label %false_block
50+
true_block:
51+
ret void
52+
false_block:
53+
ret void
54+
}
55+
declare i1 @llvm.experimental.constrained.fcmps.f32(float, float, metadata, metadata)
56+
declare i1 @llvm.experimental.constrained.fcmp.f32(float, float, metadata, metadata)

0 commit comments

Comments
 (0)