; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 ; RUN: llc -verify-machineinstrs -mcpu=pwr10 -mtriple=powerpc64le-unknown-linux-gnu \ ; RUN: -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s --check-prefix=POWER10-LE ; RUN: llc -verify-machineinstrs -mcpu=pwr10 -mtriple=powerpc64-ibm-aix-xcoff \ ; RUN: -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s --check-prefix=POWER10-BE ; RUN: llc -verify-machineinstrs -mcpu=pwr10 -mtriple=powerpc-ibm-aix-xcoff \ ; RUN: -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s --check-prefix=POWER3210-BE ; RUN: llc -verify-machineinstrs -mcpu=pwr9 -mtriple=powerpc64le-unknown-linux-gnu \ ; RUN: -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s --check-prefix=POWER9-LE ; RUN: llc -verify-machineinstrs -mcpu=pwr9 -mtriple=powerpc64-ibm-aix-xcoff \ ; RUN: -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s --check-prefix=POWER9-BE ; Test VSRO + VSR peephole optimization to VSRQ on Power10+ ; This should combine consecutive VSRO (Vector Shift Right Octet) and VSR (Vector Shift Right) ; instructions using the same shift amount into a single VSRQ (Vector Shift Right Quadword) ; instruction when targeting Power10 or later processors. declare <4 x i32> @llvm.ppc.altivec.vsr(<4 x i32>, <4 x i32>) declare <4 x i32> @llvm.ppc.altivec.vsro(<4 x i32>, <4 x i32>) define <16 x i8> @shiftright128_v16i8(<16 x i8> %in, i8 zeroext %sh) { ; POWER10-LE-LABEL: shiftright128_v16i8: ; POWER10-LE: # %bb.0: # %entry ; POWER10-LE-NEXT: mtvsrd v3, r5 ; POWER10-LE-NEXT: vspltb v3, v3, 7 ; POWER10-LE-NEXT: vsrq v2, v2, v3 ; POWER10-LE-NEXT: blr ; ; POWER10-BE-LABEL: shiftright128_v16i8: ; POWER10-BE: # %bb.0: # %entry ; POWER10-BE-NEXT: mtvsrwz v3, r3 ; POWER10-BE-NEXT: vspltb v3, v3, 7 ; POWER10-BE-NEXT: vsrq v2, v2, v3 ; POWER10-BE-NEXT: blr ; ; POWER3210-BE-LABEL: shiftright128_v16i8: ; POWER3210-BE: # %bb.0: # %entry ; POWER3210-BE-NEXT: mtvsrwz v3, r3 ; POWER3210-BE-NEXT: vspltb v3, v3, 7 ; POWER3210-BE-NEXT: vsrq v2, v2, v3 ; POWER3210-BE-NEXT: blr ; ; POWER9-LE-LABEL: shiftright128_v16i8: ; POWER9-LE: # %bb.0: # %entry ; POWER9-LE-NEXT: mtvsrd v3, r5 ; POWER9-LE-NEXT: vspltb v3, v3, 7 ; POWER9-LE-NEXT: vsro v2, v2, v3 ; POWER9-LE-NEXT: vsr v2, v2, v3 ; POWER9-LE-NEXT: blr ; ; POWER9-BE-LABEL: shiftright128_v16i8: ; POWER9-BE: # %bb.0: # %entry ; POWER9-BE-NEXT: mtvsrwz v3, r3 ; POWER9-BE-NEXT: vspltb v3, v3, 7 ; POWER9-BE-NEXT: vsro v2, v2, v3 ; POWER9-BE-NEXT: vsr v2, v2, v3 ; POWER9-BE-NEXT: blr entry: %splat.splatinsert.i = insertelement <16 x i8> poison, i8 %sh, i64 0 %splat.splat.i = shufflevector <16 x i8> %splat.splatinsert.i, <16 x i8> poison, <16 x i32> zeroinitializer %0 = bitcast <16 x i8> %in to <4 x i32> %1 = bitcast <16 x i8> %splat.splat.i to <4 x i32> %2 = tail call <4 x i32> @llvm.ppc.altivec.vsro(<4 x i32> %0, <4 x i32> %1) %3 = tail call <4 x i32> @llvm.ppc.altivec.vsr(<4 x i32> %2, <4 x i32> %1) %4 = bitcast <4 x i32> %3 to <16 x i8> ret <16 x i8> %4 } define <4 x i32> @shiftright128_v4i32(<4 x i32> %in, i8 zeroext %sh) { ; POWER10-LE-LABEL: shiftright128_v4i32: ; POWER10-LE: # %bb.0: # %entry ; POWER10-LE-NEXT: mtvsrd v3, r5 ; POWER10-LE-NEXT: vspltb v3, v3, 7 ; POWER10-LE-NEXT: vsrq v2, v2, v3 ; POWER10-LE-NEXT: blr ; ; POWER10-BE-LABEL: shiftright128_v4i32: ; POWER10-BE: # %bb.0: # %entry ; POWER10-BE-NEXT: mtvsrwz v3, r3 ; POWER10-BE-NEXT: vspltb v3, v3, 7 ; POWER10-BE-NEXT: vsrq v2, v2, v3 ; POWER10-BE-NEXT: blr ; ; POWER3210-BE-LABEL: shiftright128_v4i32: ; POWER3210-BE: # %bb.0: # %entry ; POWER3210-BE-NEXT: mtvsrwz v3, r3 ; POWER3210-BE-NEXT: vspltb v3, v3, 7 ; POWER3210-BE-NEXT: vsrq v2, v2, v3 ; POWER3210-BE-NEXT: blr ; ; POWER9-LE-LABEL: shiftright128_v4i32: ; POWER9-LE: # %bb.0: # %entry ; POWER9-LE-NEXT: mtvsrd v3, r5 ; POWER9-LE-NEXT: vspltb v3, v3, 7 ; POWER9-LE-NEXT: vsro v2, v2, v3 ; POWER9-LE-NEXT: vsr v2, v2, v3 ; POWER9-LE-NEXT: blr ; ; POWER9-BE-LABEL: shiftright128_v4i32: ; POWER9-BE: # %bb.0: # %entry ; POWER9-BE-NEXT: mtvsrwz v3, r3 ; POWER9-BE-NEXT: vspltb v3, v3, 7 ; POWER9-BE-NEXT: vsro v2, v2, v3 ; POWER9-BE-NEXT: vsr v2, v2, v3 ; POWER9-BE-NEXT: blr entry: %splat.splatinsert.i = insertelement <16 x i8> poison, i8 %sh, i64 0 %splat.splat.i = shufflevector <16 x i8> %splat.splatinsert.i, <16 x i8> poison, <16 x i32> zeroinitializer %0 = bitcast <16 x i8> %splat.splat.i to <4 x i32> %1 = tail call <4 x i32> @llvm.ppc.altivec.vsro(<4 x i32> %in, <4 x i32> %0) %2 = tail call <4 x i32> @llvm.ppc.altivec.vsr(<4 x i32> %1, <4 x i32> %0) ret <4 x i32> %2 } define <2 x i64> @shiftright128_v2i64(<2 x i64> %in, i8 zeroext %sh) { ; POWER10-LE-LABEL: shiftright128_v2i64: ; POWER10-LE: # %bb.0: # %entry ; POWER10-LE-NEXT: mtvsrd v3, r5 ; POWER10-LE-NEXT: vspltb v3, v3, 7 ; POWER10-LE-NEXT: vsrq v2, v2, v3 ; POWER10-LE-NEXT: blr ; ; POWER10-BE-LABEL: shiftright128_v2i64: ; POWER10-BE: # %bb.0: # %entry ; POWER10-BE-NEXT: mtvsrwz v3, r3 ; POWER10-BE-NEXT: vspltb v3, v3, 7 ; POWER10-BE-NEXT: vsrq v2, v2, v3 ; POWER10-BE-NEXT: blr ; ; POWER3210-BE-LABEL: shiftright128_v2i64: ; POWER3210-BE: # %bb.0: # %entry ; POWER3210-BE-NEXT: mtvsrwz v3, r3 ; POWER3210-BE-NEXT: vspltb v3, v3, 7 ; POWER3210-BE-NEXT: vsrq v2, v2, v3 ; POWER3210-BE-NEXT: blr ; ; POWER9-LE-LABEL: shiftright128_v2i64: ; POWER9-LE: # %bb.0: # %entry ; POWER9-LE-NEXT: mtvsrd v3, r5 ; POWER9-LE-NEXT: vspltb v3, v3, 7 ; POWER9-LE-NEXT: vsro v2, v2, v3 ; POWER9-LE-NEXT: vsr v2, v2, v3 ; POWER9-LE-NEXT: blr ; ; POWER9-BE-LABEL: shiftright128_v2i64: ; POWER9-BE: # %bb.0: # %entry ; POWER9-BE-NEXT: mtvsrwz v3, r3 ; POWER9-BE-NEXT: vspltb v3, v3, 7 ; POWER9-BE-NEXT: vsro v2, v2, v3 ; POWER9-BE-NEXT: vsr v2, v2, v3 ; POWER9-BE-NEXT: blr entry: %splat.splatinsert.i = insertelement <16 x i8> poison, i8 %sh, i64 0 %splat.splat.i = shufflevector <16 x i8> %splat.splatinsert.i, <16 x i8> poison, <16 x i32> zeroinitializer %0 = bitcast <2 x i64> %in to <4 x i32> %1 = bitcast <16 x i8> %splat.splat.i to <4 x i32> %2 = tail call <4 x i32> @llvm.ppc.altivec.vsro(<4 x i32> %0, <4 x i32> %1) %3 = tail call <4 x i32> @llvm.ppc.altivec.vsr(<4 x i32> %2, <4 x i32> %1) %4 = bitcast <4 x i32> %3 to <2 x i64> ret <2 x i64> %4 } define <8 x i16> @shiftright128_v8i16(<8 x i16> %in, i8 zeroext %sh) { ; POWER10-LE-LABEL: shiftright128_v8i16: ; POWER10-LE: # %bb.0: # %entry ; POWER10-LE-NEXT: mtvsrd v3, r5 ; POWER10-LE-NEXT: vspltb v3, v3, 7 ; POWER10-LE-NEXT: vsrq v2, v2, v3 ; POWER10-LE-NEXT: blr ; ; POWER10-BE-LABEL: shiftright128_v8i16: ; POWER10-BE: # %bb.0: # %entry ; POWER10-BE-NEXT: mtvsrwz v3, r3 ; POWER10-BE-NEXT: vspltb v3, v3, 7 ; POWER10-BE-NEXT: vsrq v2, v2, v3 ; POWER10-BE-NEXT: blr ; ; POWER3210-BE-LABEL: shiftright128_v8i16: ; POWER3210-BE: # %bb.0: # %entry ; POWER3210-BE-NEXT: mtvsrwz v3, r3 ; POWER3210-BE-NEXT: vspltb v3, v3, 7 ; POWER3210-BE-NEXT: vsrq v2, v2, v3 ; POWER3210-BE-NEXT: blr ; ; POWER9-LE-LABEL: shiftright128_v8i16: ; POWER9-LE: # %bb.0: # %entry ; POWER9-LE-NEXT: mtvsrd v3, r5 ; POWER9-LE-NEXT: vspltb v3, v3, 7 ; POWER9-LE-NEXT: vsro v2, v2, v3 ; POWER9-LE-NEXT: vsr v2, v2, v3 ; POWER9-LE-NEXT: blr ; ; POWER9-BE-LABEL: shiftright128_v8i16: ; POWER9-BE: # %bb.0: # %entry ; POWER9-BE-NEXT: mtvsrwz v3, r3 ; POWER9-BE-NEXT: vspltb v3, v3, 7 ; POWER9-BE-NEXT: vsro v2, v2, v3 ; POWER9-BE-NEXT: vsr v2, v2, v3 ; POWER9-BE-NEXT: blr entry: %splat.splatinsert.i = insertelement <16 x i8> poison, i8 %sh, i64 0 %splat.splat.i = shufflevector <16 x i8> %splat.splatinsert.i, <16 x i8> poison, <16 x i32> zeroinitializer %0 = bitcast <8 x i16> %in to <4 x i32> %1 = bitcast <16 x i8> %splat.splat.i to <4 x i32> %2 = tail call <4 x i32> @llvm.ppc.altivec.vsro(<4 x i32> %0, <4 x i32> %1) %3 = tail call <4 x i32> @llvm.ppc.altivec.vsr(<4 x i32> %2, <4 x i32> %1) %4 = bitcast <4 x i32> %3 to <8 x i16> ret <8 x i16> %4 } ; Test case with different vectors (should not optimize - different shift amount registers) define <16 x i8> @no_optimization_different_shifts(<16 x i8> %in, i8 zeroext %sh1, i8 zeroext %sh2) { ; POWER10-LE-LABEL: no_optimization_different_shifts: ; POWER10-LE: # %bb.0: # %entry ; POWER10-LE-NEXT: mtvsrd v3, r5 ; POWER10-LE-NEXT: mtvsrd v4, r6 ; POWER10-LE-NEXT: vspltb v3, v3, 7 ; POWER10-LE-NEXT: vspltb v4, v4, 7 ; POWER10-LE-NEXT: vsro v2, v2, v3 ; POWER10-LE-NEXT: vsr v2, v2, v4 ; POWER10-LE-NEXT: blr ; ; POWER10-BE-LABEL: no_optimization_different_shifts: ; POWER10-BE: # %bb.0: # %entry ; POWER10-BE-NEXT: mtvsrwz v3, r3 ; POWER10-BE-NEXT: mtvsrwz v4, r4 ; POWER10-BE-NEXT: vspltb v3, v3, 7 ; POWER10-BE-NEXT: vspltb v4, v4, 7 ; POWER10-BE-NEXT: vsro v2, v2, v3 ; POWER10-BE-NEXT: vsr v2, v2, v4 ; POWER10-BE-NEXT: blr ; ; POWER3210-BE-LABEL: no_optimization_different_shifts: ; POWER3210-BE: # %bb.0: # %entry ; POWER3210-BE-NEXT: mtvsrwz v3, r3 ; POWER3210-BE-NEXT: mtvsrwz v4, r4 ; POWER3210-BE-NEXT: vspltb v3, v3, 7 ; POWER3210-BE-NEXT: vspltb v4, v4, 7 ; POWER3210-BE-NEXT: vsro v2, v2, v3 ; POWER3210-BE-NEXT: vsr v2, v2, v4 ; POWER3210-BE-NEXT: blr ; ; POWER9-LE-LABEL: no_optimization_different_shifts: ; POWER9-LE: # %bb.0: # %entry ; POWER9-LE-NEXT: mtvsrd v3, r5 ; POWER9-LE-NEXT: mtvsrd v4, r6 ; POWER9-LE-NEXT: vspltb v3, v3, 7 ; POWER9-LE-NEXT: vspltb v4, v4, 7 ; POWER9-LE-NEXT: vsro v2, v2, v3 ; POWER9-LE-NEXT: vsr v2, v2, v4 ; POWER9-LE-NEXT: blr ; ; POWER9-BE-LABEL: no_optimization_different_shifts: ; POWER9-BE: # %bb.0: # %entry ; POWER9-BE-NEXT: mtvsrwz v3, r3 ; POWER9-BE-NEXT: mtvsrwz v4, r4 ; POWER9-BE-NEXT: vspltb v3, v3, 7 ; POWER9-BE-NEXT: vspltb v4, v4, 7 ; POWER9-BE-NEXT: vsro v2, v2, v3 ; POWER9-BE-NEXT: vsr v2, v2, v4 ; POWER9-BE-NEXT: blr entry: %splat.splatinsert.i = insertelement <16 x i8> poison, i8 %sh1, i64 0 %splat.splat.i = shufflevector <16 x i8> %splat.splatinsert.i, <16 x i8> poison, <16 x i32> zeroinitializer %splat.splatinsert.i2 = insertelement <16 x i8> poison, i8 %sh2, i64 0 %splat.splat.i2 = shufflevector <16 x i8> %splat.splatinsert.i2, <16 x i8> poison, <16 x i32> zeroinitializer %0 = bitcast <16 x i8> %in to <4 x i32> %1 = bitcast <16 x i8> %splat.splat.i to <4 x i32> %2 = bitcast <16 x i8> %splat.splat.i2 to <4 x i32> %3 = tail call <4 x i32> @llvm.ppc.altivec.vsro(<4 x i32> %0, <4 x i32> %1) %4 = tail call <4 x i32> @llvm.ppc.altivec.vsr(<4 x i32> %3, <4 x i32> %2) %5 = bitcast <4 x i32> %4 to <16 x i8> ret <16 x i8> %5 } ; Test case with multiple uses of VSRO result (should not optimize) define <16 x i8> @no_optimization_multiple_uses(<16 x i8> %in, i8 zeroext %sh) { ; POWER10-LE-LABEL: no_optimization_multiple_uses: ; POWER10-LE: # %bb.0: # %entry ; POWER10-LE-NEXT: mtvsrd v3, r5 ; POWER10-LE-NEXT: vspltb v3, v3, 7 ; POWER10-LE-NEXT: vsro v2, v2, v3 ; POWER10-LE-NEXT: vsr v3, v2, v3 ; POWER10-LE-NEXT: vaddubm v2, v2, v3 ; POWER10-LE-NEXT: blr ; ; POWER10-BE-LABEL: no_optimization_multiple_uses: ; POWER10-BE: # %bb.0: # %entry ; POWER10-BE-NEXT: mtvsrwz v3, r3 ; POWER10-BE-NEXT: vspltb v3, v3, 7 ; POWER10-BE-NEXT: vsro v2, v2, v3 ; POWER10-BE-NEXT: vsr v3, v2, v3 ; POWER10-BE-NEXT: vaddubm v2, v2, v3 ; POWER10-BE-NEXT: blr ; ; POWER3210-BE-LABEL: no_optimization_multiple_uses: ; POWER3210-BE: # %bb.0: # %entry ; POWER3210-BE-NEXT: mtvsrwz v3, r3 ; POWER3210-BE-NEXT: vspltb v3, v3, 7 ; POWER3210-BE-NEXT: vsro v2, v2, v3 ; POWER3210-BE-NEXT: vsr v3, v2, v3 ; POWER3210-BE-NEXT: vaddubm v2, v2, v3 ; POWER3210-BE-NEXT: blr ; ; POWER9-LE-LABEL: no_optimization_multiple_uses: ; POWER9-LE: # %bb.0: # %entry ; POWER9-LE-NEXT: mtvsrd v3, r5 ; POWER9-LE-NEXT: vspltb v3, v3, 7 ; POWER9-LE-NEXT: vsro v2, v2, v3 ; POWER9-LE-NEXT: vsr v3, v2, v3 ; POWER9-LE-NEXT: vaddubm v2, v2, v3 ; POWER9-LE-NEXT: blr ; ; POWER9-BE-LABEL: no_optimization_multiple_uses: ; POWER9-BE: # %bb.0: # %entry ; POWER9-BE-NEXT: mtvsrwz v3, r3 ; POWER9-BE-NEXT: vspltb v3, v3, 7 ; POWER9-BE-NEXT: vsro v2, v2, v3 ; POWER9-BE-NEXT: vsr v3, v2, v3 ; POWER9-BE-NEXT: vaddubm v2, v2, v3 ; POWER9-BE-NEXT: blr entry: %splat.splatinsert.i = insertelement <16 x i8> poison, i8 %sh, i64 0 %splat.splat.i = shufflevector <16 x i8> %splat.splatinsert.i, <16 x i8> poison, <16 x i32> zeroinitializer %0 = bitcast <16 x i8> %in to <4 x i32> %1 = bitcast <16 x i8> %splat.splat.i to <4 x i32> %2 = tail call <4 x i32> @llvm.ppc.altivec.vsro(<4 x i32> %0, <4 x i32> %1) %3 = tail call <4 x i32> @llvm.ppc.altivec.vsr(<4 x i32> %2, <4 x i32> %1) %4 = bitcast <4 x i32> %3 to <16 x i8> %5 = bitcast <4 x i32> %2 to <16 x i8> %6 = add <16 x i8> %5, %4 ret <16 x i8> %6 }