Skip to content

Commit 8d369a7

Browse files
gysitaleclearmind
authored andcommitted
[mlir][llvm] Saturation arithmetic intrinsics.
Add the saturation arithmetic intrinsics to the LLVM dialect. Reviewed By: Dinistro Differential Revision: https://reviews.llvm.org/D150676 (cherry picked from commit c04cf58dfc5430f0c82c8ef42c3a8cb43f84020b)
1 parent 25c39d6 commit 8d369a7

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,17 @@ def LLVM_CoroResumeOp : LLVM_IntrOp<"coro.resume", [], [], [], 0> {
276276
let assemblyFormat = "$handle attr-dict";
277277
}
278278

279+
//
280+
// Saturation Arithmetic Intrinsics.
281+
//
282+
283+
def LLVM_SAddSat : LLVM_BinarySameArgsIntrOpI<"sadd.sat">;
284+
def LLVM_UAddSat : LLVM_BinarySameArgsIntrOpI<"uadd.sat">;
285+
def LLVM_SSubSat : LLVM_BinarySameArgsIntrOpI<"ssub.sat">;
286+
def LLVM_USubSat : LLVM_BinarySameArgsIntrOpI<"usub.sat">;
287+
def LLVM_SSHLSat : LLVM_BinarySameArgsIntrOpI<"sshl.sat">;
288+
def LLVM_USHLSat : LLVM_BinarySameArgsIntrOpI<"ushl.sat">;
289+
279290
//
280291
// Debug function intrinsics.
281292
//

mlir/test/Target/LLVMIR/Import/intrinsic.ll

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,60 @@ define void @umul_with_overflow_test(i32 %0, i32 %1, <8 x i32> %2, <8 x i32> %3)
447447
ret void
448448
}
449449

450+
; CHECK-LABEL: llvm.func @sadd_sat_test
451+
define void @sadd_sat_test(i32 %0, i32 %1, <8 x i32> %2, <8 x i32> %3) {
452+
; CHECK: llvm.intr.sadd.sat(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
453+
%5 = call i32 @llvm.sadd.sat.i32(i32 %0, i32 %1)
454+
; CHECK: llvm.intr.sadd.sat(%{{.*}}, %{{.*}}) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
455+
%6 = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %2, <8 x i32> %3)
456+
ret void
457+
}
458+
459+
; CHECK-LABEL: llvm.func @uadd_sat_test
460+
define void @uadd_sat_test(i32 %0, i32 %1, <8 x i32> %2, <8 x i32> %3) {
461+
; CHECK: llvm.intr.uadd.sat(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
462+
%5 = call i32 @llvm.uadd.sat.i32(i32 %0, i32 %1)
463+
; CHECK: llvm.intr.uadd.sat(%{{.*}}, %{{.*}}) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
464+
%6 = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %2, <8 x i32> %3)
465+
ret void
466+
}
467+
468+
; CHECK-LABEL: llvm.func @ssub_sat_test
469+
define void @ssub_sat_test(i32 %0, i32 %1, <8 x i32> %2, <8 x i32> %3) {
470+
; CHECK: llvm.intr.ssub.sat(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
471+
%5 = call i32 @llvm.ssub.sat.i32(i32 %0, i32 %1)
472+
; CHECK: llvm.intr.ssub.sat(%{{.*}}, %{{.*}}) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
473+
%6 = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %2, <8 x i32> %3)
474+
ret void
475+
}
476+
477+
; CHECK-LABEL: llvm.func @usub_sat_test
478+
define void @usub_sat_test(i32 %0, i32 %1, <8 x i32> %2, <8 x i32> %3) {
479+
; CHECK: llvm.intr.usub.sat(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
480+
%5 = call i32 @llvm.usub.sat.i32(i32 %0, i32 %1)
481+
; CHECK: llvm.intr.usub.sat(%{{.*}}, %{{.*}}) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
482+
%6 = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %2, <8 x i32> %3)
483+
ret void
484+
}
485+
486+
; CHECK-LABEL: llvm.func @sshl_sat_test
487+
define void @sshl_sat_test(i32 %0, i32 %1, <8 x i32> %2, <8 x i32> %3) {
488+
; CHECK: llvm.intr.sshl.sat(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
489+
%5 = call i32 @llvm.sshl.sat.i32(i32 %0, i32 %1)
490+
; CHECK: llvm.intr.sshl.sat(%{{.*}}, %{{.*}}) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
491+
%6 = call <8 x i32> @llvm.sshl.sat.v8i32(<8 x i32> %2, <8 x i32> %3)
492+
ret void
493+
}
494+
495+
; CHECK-LABEL: llvm.func @ushl_sat_test
496+
define void @ushl_sat_test(i32 %0, i32 %1, <8 x i32> %2, <8 x i32> %3) {
497+
; CHECK: llvm.intr.ushl.sat(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
498+
%5 = call i32 @llvm.ushl.sat.i32(i32 %0, i32 %1)
499+
; CHECK: llvm.intr.ushl.sat(%{{.*}}, %{{.*}}) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
500+
%6 = call <8 x i32> @llvm.ushl.sat.v8i32(<8 x i32> %2, <8 x i32> %3)
501+
ret void
502+
}
503+
450504
; CHECK-LABEL: llvm.func @va_intrinsics_test
451505
define void @va_intrinsics_test(ptr %0, ptr %1) {
452506
; CHECK: llvm.intr.vastart %{{.*}}
@@ -771,6 +825,18 @@ declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32)
771825
declare { <8 x i32>, <8 x i1> } @llvm.smul.with.overflow.v8i32(<8 x i32>, <8 x i32>)
772826
declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32)
773827
declare { <8 x i32>, <8 x i1> } @llvm.umul.with.overflow.v8i32(<8 x i32>, <8 x i32>)
828+
declare i32 @llvm.sadd.sat.i32(i32, i32)
829+
declare <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32>, <8 x i32>)
830+
declare i32 @llvm.uadd.sat.i32(i32, i32)
831+
declare <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32>, <8 x i32>)
832+
declare i32 @llvm.ssub.sat.i32(i32, i32)
833+
declare <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32>, <8 x i32>)
834+
declare i32 @llvm.usub.sat.i32(i32, i32)
835+
declare <8 x i32> @llvm.usub.sat.v8i32(<8 x i32>, <8 x i32>)
836+
declare i32 @llvm.sshl.sat.i32(i32, i32)
837+
declare <8 x i32> @llvm.sshl.sat.v8i32(<8 x i32>, <8 x i32>)
838+
declare i32 @llvm.ushl.sat.i32(i32, i32)
839+
declare <8 x i32> @llvm.ushl.sat.v8i32(<8 x i32>, <8 x i32>)
774840
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
775841
declare ptr @llvm.coro.begin(token, ptr writeonly)
776842
declare i64 @llvm.coro.size.i64()

mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,60 @@ llvm.func @umul_with_overflow_test(%arg0: i32, %arg1: i32, %arg2: vector<8xi32>,
466466
llvm.return
467467
}
468468

469+
// CHECK-LABEL: @sadd_sat_test
470+
llvm.func @sadd_sat_test(%arg0: i32, %arg1: i32, %arg2: vector<8xi32>, %arg3: vector<8xi32>) {
471+
// CHECK: call i32 @llvm.sadd.sat.i32
472+
"llvm.intr.sadd.sat"(%arg0, %arg1) : (i32, i32) -> i32
473+
// CHECK: call <8 x i32> @llvm.sadd.sat.v8i32
474+
"llvm.intr.sadd.sat"(%arg2, %arg3) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
475+
llvm.return
476+
}
477+
478+
// CHECK-LABEL: @uadd_sat_test
479+
llvm.func @uadd_sat_test(%arg0: i32, %arg1: i32, %arg2: vector<8xi32>, %arg3: vector<8xi32>) {
480+
// CHECK: call i32 @llvm.uadd.sat.i32
481+
"llvm.intr.uadd.sat"(%arg0, %arg1) : (i32, i32) -> i32
482+
// CHECK: call <8 x i32> @llvm.uadd.sat.v8i32
483+
"llvm.intr.uadd.sat"(%arg2, %arg3) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
484+
llvm.return
485+
}
486+
487+
// CHECK-LABEL: @ssub_sat_test
488+
llvm.func @ssub_sat_test(%arg0: i32, %arg1: i32, %arg2: vector<8xi32>, %arg3: vector<8xi32>) {
489+
// CHECK: call i32 @llvm.ssub.sat.i32
490+
"llvm.intr.ssub.sat"(%arg0, %arg1) : (i32, i32) -> i32
491+
// CHECK: call <8 x i32> @llvm.ssub.sat.v8i32
492+
"llvm.intr.ssub.sat"(%arg2, %arg3) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
493+
llvm.return
494+
}
495+
496+
// CHECK-LABEL: @usub_sat_test
497+
llvm.func @usub_sat_test(%arg0: i32, %arg1: i32, %arg2: vector<8xi32>, %arg3: vector<8xi32>) {
498+
// CHECK: call i32 @llvm.usub.sat.i32
499+
"llvm.intr.usub.sat"(%arg0, %arg1) : (i32, i32) -> i32
500+
// CHECK: call <8 x i32> @llvm.usub.sat.v8i32
501+
"llvm.intr.usub.sat"(%arg2, %arg3) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
502+
llvm.return
503+
}
504+
505+
// CHECK-LABEL: @sshl_sat_test
506+
llvm.func @sshl_sat_test(%arg0: i32, %arg1: i32, %arg2: vector<8xi32>, %arg3: vector<8xi32>) {
507+
// CHECK: call i32 @llvm.sshl.sat.i32
508+
"llvm.intr.sshl.sat"(%arg0, %arg1) : (i32, i32) -> i32
509+
// CHECK: call <8 x i32> @llvm.sshl.sat.v8i32
510+
"llvm.intr.sshl.sat"(%arg2, %arg3) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
511+
llvm.return
512+
}
513+
514+
// CHECK-LABEL: @ushl_sat_test
515+
llvm.func @ushl_sat_test(%arg0: i32, %arg1: i32, %arg2: vector<8xi32>, %arg3: vector<8xi32>) {
516+
// CHECK: call i32 @llvm.ushl.sat.i32
517+
"llvm.intr.ushl.sat"(%arg0, %arg1) : (i32, i32) -> i32
518+
// CHECK: call <8 x i32> @llvm.ushl.sat.v8i32
519+
"llvm.intr.ushl.sat"(%arg2, %arg3) : (vector<8xi32>, vector<8xi32>) -> vector<8xi32>
520+
llvm.return
521+
}
522+
469523
// CHECK-LABEL: @coro_id
470524
llvm.func @coro_id(%arg0: i32, %arg1: !llvm.ptr<i8>) {
471525
// CHECK: call token @llvm.coro.id
@@ -811,6 +865,18 @@ llvm.func @lifetime(%p: !llvm.ptr) {
811865
// CHECK-DAG: declare { <8 x i32>, <8 x i1> } @llvm.usub.with.overflow.v8i32(<8 x i32>, <8 x i32>) #0
812866
// CHECK-DAG: declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32)
813867
// CHECK-DAG: declare { <8 x i32>, <8 x i1> } @llvm.umul.with.overflow.v8i32(<8 x i32>, <8 x i32>) #0
868+
// CHECK-DAG: declare i32 @llvm.sadd.sat.i32(i32, i32)
869+
// CHECK-DAG: declare <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32>, <8 x i32>)
870+
// CHECK-DAG: declare i32 @llvm.uadd.sat.i32(i32, i32)
871+
// CHECK-DAG: declare <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32>, <8 x i32>)
872+
// CHECK-DAG: declare i32 @llvm.ssub.sat.i32(i32, i32)
873+
// CHECK-DAG: declare <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32>, <8 x i32>)
874+
// CHECK-DAG: declare i32 @llvm.usub.sat.i32(i32, i32)
875+
// CHECK-DAG: declare <8 x i32> @llvm.usub.sat.v8i32(<8 x i32>, <8 x i32>)
876+
// CHECK-DAG: declare i32 @llvm.sshl.sat.i32(i32, i32)
877+
// CHECK-DAG: declare <8 x i32> @llvm.sshl.sat.v8i32(<8 x i32>, <8 x i32>)
878+
// CHECK-DAG: declare i32 @llvm.ushl.sat.i32(i32, i32)
879+
// CHECK-DAG: declare <8 x i32> @llvm.ushl.sat.v8i32(<8 x i32>, <8 x i32>)
814880
// CHECK-DAG: declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
815881
// CHECK-DAG: declare ptr @llvm.coro.begin(token, ptr writeonly)
816882
// CHECK-DAG: declare i64 @llvm.coro.size.i64()

0 commit comments

Comments
 (0)