Index: llvm/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -4228,6 +4228,35 @@ defm : SIMDVectorLShiftLongBySizeBHSPats; defm : SIMDVectorLShiftLongBySizeBHSPats; +// trunc(umin(X, 255)) -> UQXTRN v8i8 +def : Pat<(v8i8 (trunc (umin (v8i16 V128:$Vn), + (v8i16 (AArch64NvCast (v2i64 (AArch64movi_edit (i32 85)))))))), + (UQXTNv8i8 V128:$Vn)>; +// trunc(umin(X, 65535)) -> UQXTRN v4i16 +def : Pat<(v4i16 (trunc (umin (v4i32 V128:$Vn), + (v4i32 (AArch64NvCast (v2i64 (AArch64movi_edit (i32 51)))))))), + (UQXTNv4i16 V128:$Vn)>; +// trunc(smin(smax(X, -32768), 32767)) -> SQXTRN +// with reversed min/max +def : Pat<(v8i8 (trunc (smin (smax (v8i16 V128:$Vn), + (v8i16 (AArch64mvni_shift (i32 127), (i32 0)))), + (v8i16 (AArch64movi_shift (i32 127), (i32 0)))))), + (SQXTNv8i8 V128:$Vn)>; +def : Pat<(v8i8 (trunc (smax (smin (v8i16 V128:$Vn), + (v8i16 (AArch64movi_shift (i32 127), (i32 0)))), + (v8i16 (AArch64mvni_shift (i32 127), (i32 0)))))), + (SQXTNv8i8 V128:$Vn)>; +// trunc(smin(smax(X, -128), 128)) -> SQXTRN +// with reversed min/max +def : Pat<(v4i16 (trunc (smin (smax (v4i32 V128:$Vn), + (v4i32 (AArch64mvni_msl (i32 127), (i32 264)))), + (v4i32 (AArch64movi_msl (i32 127), (i32 264)))))), + (SQXTNv4i16 V128:$Vn)>; +def : Pat<(v4i16 (trunc (smax (smin (v4i32 V128:$Vn), + (v4i32 (AArch64movi_msl (i32 127), (i32 264)))), + (v4i32 (AArch64mvni_msl (i32 127), (i32 264)))))), + (SQXTNv4i16 V128:$Vn)>; + //===----------------------------------------------------------------------===// // Advanced SIMD three vector instructions. //===----------------------------------------------------------------------===// Index: llvm/test/CodeGen/AArch64/qmovn.ll =================================================================== --- llvm/test/CodeGen/AArch64/qmovn.ll +++ llvm/test/CodeGen/AArch64/qmovn.ll @@ -4,11 +4,7 @@ define <4 x i16> @vqmovni32_smaxmin(<4 x i32> %s0) { ; CHECK-LABEL: vqmovni32_smaxmin: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: movi v1.4s, #127, msl #8 -; CHECK-NEXT: smin v0.4s, v0.4s, v1.4s -; CHECK-NEXT: mvni v1.4s, #127, msl #8 -; CHECK-NEXT: smax v0.4s, v0.4s, v1.4s -; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: sqxtn v0.4h, v0.4s ; CHECK-NEXT: ret entry: %c1 = icmp slt <4 x i32> %s0, @@ -22,11 +18,7 @@ define <4 x i16> @vqmovni32_sminmax(<4 x i32> %s0) { ; CHECK-LABEL: vqmovni32_sminmax: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mvni v1.4s, #127, msl #8 -; CHECK-NEXT: smax v0.4s, v0.4s, v1.4s -; CHECK-NEXT: movi v1.4s, #127, msl #8 -; CHECK-NEXT: smin v0.4s, v0.4s, v1.4s -; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: sqxtn v0.4h, v0.4s ; CHECK-NEXT: ret entry: %c1 = icmp sgt <4 x i32> %s0, @@ -40,9 +32,7 @@ define <4 x i16> @vqmovni32_umaxmin(<4 x i32> %s0) { ; CHECK-LABEL: vqmovni32_umaxmin: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: movi v1.2d, #0x00ffff0000ffff -; CHECK-NEXT: umin v0.4s, v0.4s, v1.4s -; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: uqxtn v0.4h, v0.4s ; CHECK-NEXT: ret entry: %c1 = icmp ult <4 x i32> %s0, @@ -54,11 +44,7 @@ define <8 x i8> @vqmovni16_smaxmin(<8 x i16> %s0) { ; CHECK-LABEL: vqmovni16_smaxmin: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: movi v1.8h, #127 -; CHECK-NEXT: smin v0.8h, v0.8h, v1.8h -; CHECK-NEXT: mvni v1.8h, #127 -; CHECK-NEXT: smax v0.8h, v0.8h, v1.8h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: sqxtn v0.8b, v0.8h ; CHECK-NEXT: ret entry: %c1 = icmp slt <8 x i16> %s0, @@ -72,11 +58,7 @@ define <8 x i8> @vqmovni16_sminmax(<8 x i16> %s0) { ; CHECK-LABEL: vqmovni16_sminmax: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mvni v1.8h, #127 -; CHECK-NEXT: smax v0.8h, v0.8h, v1.8h -; CHECK-NEXT: movi v1.8h, #127 -; CHECK-NEXT: smin v0.8h, v0.8h, v1.8h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: sqxtn v0.8b, v0.8h ; CHECK-NEXT: ret entry: %c1 = icmp sgt <8 x i16> %s0, @@ -90,9 +72,7 @@ define <8 x i8> @vqmovni16_umaxmin(<8 x i16> %s0) { ; CHECK-LABEL: vqmovni16_umaxmin: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: movi v1.2d, #0xff00ff00ff00ff -; CHECK-NEXT: umin v0.8h, v0.8h, v1.8h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uqxtn v0.8b, v0.8h ; CHECK-NEXT: ret entry: %c1 = icmp ult <8 x i16> %s0,