; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s declare i16 @llvm.ushl.sat.i16(i16, i16) declare <2 x i16> @llvm.ushl.sat.v2i16(<2 x i16>, <2 x i16>) ; fold (shlsat undef, x) -> 0 define i16 @combine_shl_undef(i16 %x, i16 %y) nounwind { ; CHECK-LABEL: combine_shl_undef: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w0, wzr ; CHECK-NEXT: ret %tmp = call i16 @llvm.ushl.sat.i16(i16 undef, i16 %y) ret i16 %tmp } ; fold (shlsat x, undef) -> undef define i16 @combine_shl_by_undef(i16 %x, i16 %y) nounwind { ; CHECK-LABEL: combine_shl_by_undef: ; CHECK: // %bb.0: ; CHECK-NEXT: ret %tmp = call i16 @llvm.ushl.sat.i16(i16 %x, i16 undef) ret i16 %tmp } ; fold (shlsat poison, x) -> 0 define i16 @combine_shl_poison(i16 %x, i16 %y) nounwind { ; CHECK-LABEL: combine_shl_poison: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w0, wzr ; CHECK-NEXT: ret %tmp = call i16 @llvm.ushl.sat.i16(i16 poison, i16 %y) ret i16 %tmp } ; fold (shlsat x, poison) -> undef define i16 @combine_shl_by_poison(i16 %x, i16 %y) nounwind { ; CHECK-LABEL: combine_shl_by_poison: ; CHECK: // %bb.0: ; CHECK-NEXT: ret %tmp = call i16 @llvm.ushl.sat.i16(i16 %x, i16 poison) ret i16 %tmp } ; fold (shlsat x, bitwidth) -> undef define i16 @combine_shl_by_bitwidth(i16 %x, i16 %y) nounwind { ; CHECK-LABEL: combine_shl_by_bitwidth: ; CHECK: // %bb.0: ; CHECK-NEXT: ret %tmp = call i16 @llvm.ushl.sat.i16(i16 %x, i16 16) ret i16 %tmp } ; fold (ushlsat 0, x) -> 0 define i16 @combine_shl_zero(i16 %x, i16 %y) nounwind { ; CHECK-LABEL: combine_shl_zero: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w0, wzr ; CHECK-NEXT: ret %tmp = call i16 @llvm.ushl.sat.i16(i16 0, i16 %y) ret i16 %tmp } ; fold (ushlsat x, 0) -> x define i16 @combine_shlsat_by_zero(i16 %x, i16 %y) nounwind { ; CHECK-LABEL: combine_shlsat_by_zero: ; CHECK: // %bb.0: ; CHECK-NEXT: ret %tmp = call i16 @llvm.ushl.sat.i16(i16 %x, i16 0) ret i16 %tmp } ; fold (ushlsat c1, c2) -> c3 define i16 @combine_shlsat_constfold(i16 %x, i16 %y) nounwind { ; CHECK-LABEL: combine_shlsat_constfold: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w0, #32 ; CHECK-NEXT: ret %tmp = call i16 @llvm.ushl.sat.i16(i16 8, i16 2) ret i16 %tmp } ; fold (ushlsat c1, c2) -> sat max define i16 @combine_shlsat_satmax(i16 %x, i16 %y) nounwind { ; CHECK-LABEL: combine_shlsat_satmax: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w0, #65535 ; CHECK-NEXT: ret %tmp = call i16 @llvm.ushl.sat.i16(i16 8, i16 15) ret i16 %tmp } declare void @sink2xi16(i16, i16) ; fold (ushlsat c1, c2) -> c3 , c1/c2/c3 being vectors define void @combine_shlsat_vector() nounwind { ; CHECK-LABEL: combine_shlsat_vector: ; CHECK: // %bb.0: ; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill ; CHECK-NEXT: mov w0, #32 ; CHECK-NEXT: mov w1, #65535 ; CHECK-NEXT: bl sink2xi16 ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret %tmp = call <2 x i16> @llvm.ushl.sat.v2i16(<2 x i16><i16 8, i16 8>, <2 x i16><i16 2, i16 15>) ; Pass elements as arguments in a call to get CHECK statements that verify ; the constant folding. %e0 = extractelement <2 x i16> %tmp, i16 0 %e1 = extractelement <2 x i16> %tmp, i16 1 call void @sink2xi16(i16 %e0, i16 %e1) ret void } ; Fold shlsat -> shl, if known not to saturate. define i16 @combine_shlsat_to_shl(i16 %x) nounwind { ; CHECK-LABEL: combine_shlsat_to_shl: ; CHECK: // %bb.0: ; CHECK-NEXT: and w0, w0, #0xfffffffc ; CHECK-NEXT: ret %x2 = lshr i16 %x, 2 %tmp = call i16 @llvm.ushl.sat.i16(i16 %x2, i16 2) ret i16 %tmp } ; Do not fold shlsat -> shl. define i16 @combine_shlsat_to_shl_no_fold(i16 %x) nounwind { ; CHECK-LABEL: combine_shlsat_to_shl_no_fold: ; CHECK: // %bb.0: ; CHECK-NEXT: and w8, w0, #0xfffc ; CHECK-NEXT: lsl w9, w8, #17 ; CHECK-NEXT: lsl w8, w8, #14 ; CHECK-NEXT: cmp w8, w9, lsr #3 ; CHECK-NEXT: csinv w8, w9, wzr, eq ; CHECK-NEXT: lsr w0, w8, #16 ; CHECK-NEXT: ret %x2 = lshr i16 %x, 2 %tmp = call i16 @llvm.ushl.sat.i16(i16 %x2, i16 3) ret i16 %tmp } ; Fold shlsat -> shl, if known not to saturate. define <2 x i16> @combine_shlsat_to_shl_vec(<2 x i8> %a) nounwind { ; CHECK-LABEL: combine_shlsat_to_shl_vec: ; CHECK: // %bb.0: ; CHECK-NEXT: shl v0.2s, v0.2s, #8 ; CHECK-NEXT: ret %ext = zext <2 x i8> %a to <2 x i16> %tmp = call <2 x i16> @llvm.ushl.sat.v2i16( <2 x i16> %ext, <2 x i16> <i16 8, i16 8>) ret <2 x i16> %tmp }