Skip to content

Commit 69e1ea8

Browse files
authored
[SPIR-V] Add support for usub.sat intrinsic (#665) (#2279)
Translate usub.sat(a, b) as (a > b) ? a - b : 0 sequence.
1 parent e7bae05 commit 69e1ea8

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,20 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
20452045
return BM->addBinaryInst(OpFAdd, Ty, Mul,
20462046
transValue(II->getArgOperand(2), BB), BB);
20472047
}
2048+
case Intrinsic::usub_sat: {
2049+
// usub.sat(a, b) -> (a > b) ? a - b : 0
2050+
SPIRVType *Ty = transType(II->getType());
2051+
Type *BoolTy = IntegerType::getInt1Ty(M->getContext());
2052+
SPIRVValue *FirstArgVal = transValue(II->getArgOperand(0), BB);
2053+
SPIRVValue *SecondArgVal = transValue(II->getArgOperand(1), BB);
2054+
2055+
SPIRVValue *Sub =
2056+
BM->addBinaryInst(OpISub, Ty, FirstArgVal, SecondArgVal, BB);
2057+
SPIRVValue *Cmp = BM->addCmpInst(OpUGreaterThan, transType(BoolTy),
2058+
FirstArgVal, SecondArgVal, BB);
2059+
SPIRVValue *Zero = transValue(Constant::getNullValue(II->getType()), BB);
2060+
return BM->addSelectInst(Cmp, Sub, Zero, BB);
2061+
}
20482062
case Intrinsic::memset: {
20492063
// Generally there is no direct mapping of memset to SPIR-V. But it turns
20502064
// out that memset is emitted by Clang for initialization in default

llvm-spirv/test/usub-sat.ll

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
; RUN: llvm-as %s -o %t.bc
2+
; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s
3+
; RUN: llvm-spirv %t.bc -o %t.spv
4+
; RUN: spirv-val %t.spv
5+
6+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
7+
target triple = "spir64-unknown-unknown"
8+
9+
; Function Attrs: nounwind readnone
10+
define spir_func i32 @Test(i32 %x) local_unnamed_addr #0 {
11+
entry:
12+
%0 = call i32 @llvm.usub.sat.i32(i32 3, i32 %x)
13+
ret i32 %0
14+
}
15+
16+
; CHECK: Constant {{[0-9]+}} [[three:[0-9]+]] 3
17+
; CHECK: Constant {{[0-9]+}} [[zero:[0-9]+]] 0
18+
19+
; CHECK: Function
20+
; CHECK: FunctionParameter {{[0-9]+}} [[x:[0-9]+]]
21+
; CHECK: ISub {{[0-9]+}} [[sub_res:[0-9]+]] [[three]] [[x]]
22+
; CHECK: UGreaterThan {{[0-9]+}} [[cmp_res:[0-9]+]] [[three]] [[x]]
23+
; CHECK: Select {{[0-9]+}} [[sel_res:[0-9]+]] [[cmp_res]] [[sub_res]] [[zero]]
24+
; CHECK: ReturnValue [[sel_res]]
25+
26+
; Function Attrs: nounwind readnone speculatable willreturn
27+
declare i32 @llvm.usub.sat.i32(i32, i32) #1
28+
29+
attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "denorms-are-zero"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
30+
attributes #1 = { nounwind readnone speculatable willreturn }
31+
32+
!llvm.module.flags = !{!0}
33+
!opencl.ocl.version = !{!1}
34+
!opencl.spir.version = !{!2}
35+
36+
!0 = !{i32 1, !"wchar_size", i32 4}
37+
!1 = !{i32 1, i32 0}
38+
!2 = !{i32 1, i32 2}

0 commit comments

Comments
 (0)