; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes='instcombine' -S %s | FileCheck %s
define <4 x i8> @splat_binop_non_splat_x(<4 x i8> %x, <4 x i8> %y) {
; CHECK-LABEL: @splat_binop_non_splat_x(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> <i32 0, i32 2, i32 poison, i32 poison>
; CHECK-NEXT: call void @use(<4 x i8> [[XSPLAT]])
; CHECK-NEXT: [[B:%.*]] = add <4 x i8> [[XSPLAT]], [[Y:%.*]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[B]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: ret <4 x i8> [[BSPLAT]]
;
%xsplat = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
call void @use(<4 x i8> %xsplat)
%b = add <4 x i8> %xsplat, %y
%bsplat = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32> zeroinitializer
ret <4 x i8> %bsplat
}
define <4 x i8> @non_splat_binop_splat_x(<4 x i8> %x, <4 x i8> %y) {
; CHECK-LABEL: @non_splat_binop_splat_x(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: call void @use(<4 x i8> [[XSPLAT]])
; CHECK-NEXT: [[B:%.*]] = sub <4 x i8> [[XSPLAT]], [[Y:%.*]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[B]], <4 x i8> poison, <4 x i32> <i32 0, i32 2, i32 poison, i32 poison>
; CHECK-NEXT: ret <4 x i8> [[BSPLAT]]
;
%xsplat = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> zeroinitializer
call void @use(<4 x i8> %xsplat)
%b = sub <4 x i8> %xsplat, %y
%bsplat = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
ret <4 x i8> %bsplat
}
define <4 x i32> @splat_binop_splat_changes_x_length(<8 x i32> %x, <4 x i32> %y) {
; CHECK-LABEL: @splat_binop_splat_changes_x_length(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <8 x i32> [[X:%.*]], <8 x i32> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: call void @use(<4 x i32> [[XSPLAT]])
; CHECK-NEXT: [[B:%.*]] = mul <4 x i32> [[XSPLAT]], [[Y:%.*]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: ret <4 x i32> [[BSPLAT]]
;
%xsplat = shufflevector <8 x i32> %x, <8 x i32> poison, <4 x i32> zeroinitializer
call void @use(<4 x i32> %xsplat)
%b = mul <4 x i32> %xsplat, %y
%bsplat = shufflevector <4 x i32> %b, <4 x i32> poison, <4 x i32> zeroinitializer
ret <4 x i32> %bsplat
}
define <4 x i8> @splat_binop_splat_x(<4 x i8> %x, <4 x i8> %y) {
; CHECK-LABEL: @splat_binop_splat_x(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: call void @use(<4 x i8> [[XSPLAT]])
; CHECK-NEXT: [[TMP1:%.*]] = add nsw <4 x i8> [[X]], [[Y:%.*]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: ret <4 x i8> [[BSPLAT]]
;
%xsplat = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> zeroinitializer
call void @use(<4 x i8> %xsplat)
%b = add nsw <4 x i8> %xsplat, %y
%bsplat = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32> zeroinitializer
ret <4 x i8> %bsplat
}
define <4 x i8> @splat_binop_splat_y(<4 x i8> %x, <4 x i8> %y) {
; CHECK-LABEL: @splat_binop_splat_y(
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: call void @use(<4 x i8> [[YSPLAT]])
; CHECK-NEXT: [[TMP1:%.*]] = sub <4 x i8> [[X:%.*]], [[Y]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> <i32 poison, i32 0, i32 0, i32 0>
; CHECK-NEXT: ret <4 x i8> [[BSPLAT]]
;
%ysplat = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> zeroinitializer
call void @use(<4 x i8> %ysplat)
%b = sub <4 x i8> %x, %ysplat
%bsplat = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32><i32 poison, i32 0, i32 0, i32 0>
ret <4 x i8> %bsplat
}
define <4 x i8> @splat_binop_splat_x_splat_y(<4 x i8> %x, <4 x i8> %y) {
; CHECK-LABEL: @splat_binop_splat_x_splat_y(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: call void @use(<4 x i8> [[XSPLAT]])
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: call void @use(<4 x i8> [[YSPLAT]])
; CHECK-NEXT: [[TMP1:%.*]] = mul nuw <4 x i8> [[X]], [[Y]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: ret <4 x i8> [[BSPLAT]]
;
%xsplat = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> zeroinitializer
call void @use(<4 x i8> %xsplat)
%ysplat = shufflevector <4 x i8> %y, <4 x i8> poison, <4 x i32> zeroinitializer
call void @use(<4 x i8> %ysplat)
%b = mul nuw <4 x i8> %xsplat, %ysplat
%bsplat = shufflevector <4 x i8> %b, <4 x i8> poison, <4 x i32> zeroinitializer
ret <4 x i8> %bsplat
}
define <4 x float> @splat_binop_splat_x_splat_y_fmath_flags(<4 x float> %x, <4 x float> %y) {
; CHECK-LABEL: @splat_binop_splat_x_splat_y_fmath_flags(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <4 x float> [[X:%.*]], <4 x float> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: call void @use(<4 x float> [[XSPLAT]])
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <4 x float> [[Y:%.*]], <4 x float> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: call void @use(<4 x float> [[YSPLAT]])
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast <4 x float> [[X]], [[Y]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <4 x float> [[TMP1]], <4 x float> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: ret <4 x float> [[BSPLAT]]
;
%xsplat = shufflevector <4 x float> %x, <4 x float> poison, <4 x i32> zeroinitializer
call void @use(<4 x float> %xsplat)
%ysplat = shufflevector <4 x float> %y, <4 x float> poison, <4 x i32> zeroinitializer
call void @use(<4 x float> %ysplat)
%b = fmul fast <4 x float> %xsplat, %ysplat
%bsplat = shufflevector <4 x float> %b, <4 x float> poison, <4 x i32> zeroinitializer
ret <4 x float> %bsplat
}
define <vscale x 4 x i32> @vscale_splat_udiv_splat_x(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
; CHECK-LABEL: @vscale_splat_udiv_splat_x(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[X:%.*]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: [[B:%.*]] = udiv <vscale x 4 x i32> [[XSPLAT]], [[Y:%.*]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[B]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: ret <vscale x 4 x i32> [[BSPLAT]]
;
%xsplat = shufflevector <vscale x 4 x i32> %x, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
%b = udiv <vscale x 4 x i32> %xsplat, %y
%bsplat = shufflevector <vscale x 4 x i32> %b, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
ret <vscale x 4 x i32> %bsplat
}
define <vscale x 4 x i32> @vscale_splat_urem_splat_x(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
; CHECK-LABEL: @vscale_splat_urem_splat_x(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[X:%.*]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: [[B:%.*]] = urem <vscale x 4 x i32> [[XSPLAT]], [[Y:%.*]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[B]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: ret <vscale x 4 x i32> [[BSPLAT]]
;
%xsplat = shufflevector <vscale x 4 x i32> %x, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
%b = urem <vscale x 4 x i32> %xsplat, %y
%bsplat = shufflevector <vscale x 4 x i32> %b, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
ret <vscale x 4 x i32> %bsplat
}
define <vscale x 4 x i32> @vscale_splat_binop_splat_y(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
; CHECK-LABEL: @vscale_splat_binop_splat_y(
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[Y:%.*]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: [[B:%.*]] = sdiv <vscale x 4 x i32> [[X:%.*]], [[YSPLAT]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[B]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: ret <vscale x 4 x i32> [[BSPLAT]]
;
%ysplat = shufflevector <vscale x 4 x i32> %y, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
%b = sdiv <vscale x 4 x i32> %x, %ysplat
%bsplat = shufflevector <vscale x 4 x i32> %b, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
ret <vscale x 4 x i32> %bsplat
}
define <vscale x 4 x i32> @vscale_splat_binop_splat_x_splat_y(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
; CHECK-LABEL: @vscale_splat_binop_splat_x_splat_y(
; CHECK-NEXT: [[TMP1:%.*]] = ashr <vscale x 4 x i32> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[B:%.*]] = shufflevector <vscale x 4 x i32> [[TMP1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: ret <vscale x 4 x i32> [[B]]
;
%xsplat = shufflevector <vscale x 4 x i32> %x, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
%ysplat = shufflevector <vscale x 4 x i32> %y, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
%b = ashr <vscale x 4 x i32> %xsplat, %ysplat
%bsplat = shufflevector <vscale x 4 x i32> %b, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
ret <vscale x 4 x i32> %bsplat
}
define <vscale x 4 x i32> @vscale_splat_binop_splat_x_splat_y_calls(<vscale x 4 x i32> %x, <vscale x 4 x i32> %y) {
; CHECK-LABEL: @vscale_splat_binop_splat_x_splat_y_calls(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[X:%.*]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: call void @use_v(<vscale x 4 x i32> [[XSPLAT]])
; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[Y:%.*]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: call void @use_v(<vscale x 4 x i32> [[YSPLAT]])
; CHECK-NEXT: [[TMP1:%.*]] = lshr <vscale x 4 x i32> [[X]], [[Y]]
; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector <vscale x 4 x i32> [[TMP1]], <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
; CHECK-NEXT: ret <vscale x 4 x i32> [[BSPLAT]]
;
%xsplat = shufflevector <vscale x 4 x i32> %x, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
call void @use_v(<vscale x 4 x i32> %xsplat)
%ysplat = shufflevector <vscale x 4 x i32> %y, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
call void @use_v(<vscale x 4 x i32> %ysplat)
%b = lshr <vscale x 4 x i32> %xsplat, %ysplat
%bsplat = shufflevector <vscale x 4 x i32> %b, <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer
ret <vscale x 4 x i32> %bsplat
}
define <2 x double> @shuffle_op2_0th_element_mask(ptr %a, ptr %b) {
; CHECK-LABEL: @shuffle_op2_0th_element_mask(
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[A:%.*]], align 16
; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr [[B:%.*]], align 16
; CHECK-NEXT: [[TMP3:%.*]] = fsub <2 x double> [[TMP2]], [[TMP1]]
; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x double> [[TMP3]], <2 x double> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: ret <2 x double> [[SHUFFLE]]
;
%1 = load <2 x double>, ptr %a, align 16
%2 = shufflevector <2 x double> %1, <2 x double> poison, <2 x i32> zeroinitializer
%3 = load <2 x double>, ptr %b, align 16
%sub = fsub <2 x double> %3, %2
%shuffle = shufflevector <2 x double> %sub, <2 x double> %sub, <2 x i32> <i32 2, i32 2>
ret <2 x double> %shuffle
}
; This should not create an extra binop.
define <2 x i4> @splat_binop_splat_uses(<2 x i4> %x, <2 x i4> %y) {
; CHECK-LABEL: @splat_binop_splat_uses(
; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector <2 x i4> [[X:%.*]], <2 x i4> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[XY:%.*]] = mul <2 x i4> [[XSPLAT]], [[Y:%.*]]
; CHECK-NEXT: [[MSPLAT:%.*]] = shufflevector <2 x i4> [[XY]], <2 x i4> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[RES:%.*]] = add <2 x i4> [[XY]], [[MSPLAT]]
; CHECK-NEXT: ret <2 x i4> [[RES]]
;
%xsplat = shufflevector <2 x i4> %x, <2 x i4> poison, <2 x i32> zeroinitializer
%xy = mul <2 x i4> %xsplat, %y
%msplat = shufflevector <2 x i4> %xy, <2 x i4> poison, <2 x i32> zeroinitializer
%res = add <2 x i4> %xy, %msplat
ret <2 x i4> %res
}
declare void @use(<4 x i8>)
declare void @use_v(<vscale x 4 x i32>)