; 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> ; 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> 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> ; 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> 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> ; 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> 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> [[Y]], [[X]] ; 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> [[Y]], [[X]] ; 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_splat_udiv_splat_x( %x, %y) { ; CHECK-LABEL: @vscale_splat_udiv_splat_x( ; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector [[X:%.*]], poison, zeroinitializer ; CHECK-NEXT: [[B:%.*]] = udiv [[XSPLAT]], [[Y:%.*]] ; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector [[B]], poison, zeroinitializer ; CHECK-NEXT: ret [[BSPLAT]] ; %xsplat = shufflevector %x, poison, zeroinitializer %b = udiv %xsplat, %y %bsplat = shufflevector %b, poison, zeroinitializer ret %bsplat } define @vscale_splat_urem_splat_x( %x, %y) { ; CHECK-LABEL: @vscale_splat_urem_splat_x( ; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector [[X:%.*]], poison, zeroinitializer ; CHECK-NEXT: [[B:%.*]] = urem [[XSPLAT]], [[Y:%.*]] ; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector [[B]], poison, zeroinitializer ; CHECK-NEXT: ret [[BSPLAT]] ; %xsplat = shufflevector %x, poison, zeroinitializer %b = urem %xsplat, %y %bsplat = shufflevector %b, poison, zeroinitializer ret %bsplat } define @vscale_splat_binop_splat_y( %x, %y) { ; CHECK-LABEL: @vscale_splat_binop_splat_y( ; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector [[Y:%.*]], poison, zeroinitializer ; CHECK-NEXT: [[B:%.*]] = sdiv [[X:%.*]], [[YSPLAT]] ; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector [[B]], poison, zeroinitializer ; CHECK-NEXT: ret [[BSPLAT]] ; %ysplat = shufflevector %y, poison, zeroinitializer %b = sdiv %x, %ysplat %bsplat = shufflevector %b, poison, zeroinitializer ret %bsplat } define @vscale_splat_binop_splat_x_splat_y( %x, %y) { ; CHECK-LABEL: @vscale_splat_binop_splat_x_splat_y( ; CHECK-NEXT: [[TMP1:%.*]] = ashr [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[B:%.*]] = shufflevector [[TMP1]], poison, zeroinitializer ; CHECK-NEXT: ret [[B]] ; %xsplat = shufflevector %x, poison, zeroinitializer %ysplat = shufflevector %y, poison, zeroinitializer %b = ashr %xsplat, %ysplat %bsplat = shufflevector %b, poison, zeroinitializer ret %bsplat } define @vscale_splat_binop_splat_x_splat_y_calls( %x, %y) { ; CHECK-LABEL: @vscale_splat_binop_splat_x_splat_y_calls( ; CHECK-NEXT: [[XSPLAT:%.*]] = shufflevector [[X:%.*]], poison, zeroinitializer ; CHECK-NEXT: call void @use_v( [[XSPLAT]]) ; CHECK-NEXT: [[YSPLAT:%.*]] = shufflevector [[Y:%.*]], poison, zeroinitializer ; CHECK-NEXT: call void @use_v( [[YSPLAT]]) ; CHECK-NEXT: [[TMP1:%.*]] = lshr [[X]], [[Y]] ; CHECK-NEXT: [[BSPLAT:%.*]] = shufflevector [[TMP1]], poison, zeroinitializer ; CHECK-NEXT: ret [[BSPLAT]] ; %xsplat = shufflevector %x, poison, zeroinitializer call void @use_v( %xsplat) %ysplat = shufflevector %y, poison, zeroinitializer call void @use_v( %ysplat) %b = lshr %xsplat, %ysplat %bsplat = shufflevector %b, poison, zeroinitializer ret %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> 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()