; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- | FileCheck %s ; Negative test: bitcast from float to int (optimization should not apply) define <4 x i32> @and_bitcast_v4f32_to_v4i32(<4 x float> %a, <4 x float> %b) { ; CHECK-LABEL: @and_bitcast_v4f32_to_v4i32( ; CHECK-NEXT: [[BC1:%.*]] = bitcast <4 x float> [[A:%.*]] to <4 x i32> ; CHECK-NEXT: [[BC2:%.*]] = bitcast <4 x float> [[B:%.*]] to <4 x i32> ; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[BC1]], [[BC2]] ; CHECK-NEXT: ret <4 x i32> [[AND]] ; %bc1 = bitcast <4 x float> %a to <4 x i32> %bc2 = bitcast <4 x float> %b to <4 x i32> %and = and <4 x i32> %bc1, %bc2 ret <4 x i32> %and } ; Test bitwise operations with integer-to-integer bitcast define <2 x i32> @or_bitcast_v4i16_to_v2i32(<4 x i16> %a, <4 x i16> %b) { ; CHECK-LABEL: @or_bitcast_v4i16_to_v2i32( ; CHECK-NEXT: [[B:%.*]] = or <4 x i16> [[A:%.*]], [[B1:%.*]] ; CHECK-NEXT: [[BC2:%.*]] = bitcast <4 x i16> [[B]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[BC2]] ; %bc1 = bitcast <4 x i16> %a to <2 x i32> %bc2 = bitcast <4 x i16> %b to <2 x i32> %or = or <2 x i32> %bc1, %bc2 ret <2 x i32> %or } define <16 x i8> @xor_bitcast_v2i64_to_v16i8(<2 x i64> %a, <2 x i64> %b) { ; CHECK-LABEL: @xor_bitcast_v2i64_to_v16i8( ; CHECK-NEXT: [[B:%.*]] = xor <2 x i64> [[A:%.*]], [[B1:%.*]] ; CHECK-NEXT: [[BC2:%.*]] = bitcast <2 x i64> [[B]] to <16 x i8> ; CHECK-NEXT: ret <16 x i8> [[BC2]] ; %bc1 = bitcast <2 x i64> %a to <16 x i8> %bc2 = bitcast <2 x i64> %b to <16 x i8> %xor = xor <16 x i8> %bc1, %bc2 ret <16 x i8> %xor } ; Test bitwise operations with truncate define <4 x i16> @and_trunc_v4i32_to_v4i16(<4 x i32> %a, <4 x i32> %b) { ; CHECK-LABEL: @and_trunc_v4i32_to_v4i16( ; CHECK-NEXT: [[AND_INNER:%.*]] = and <4 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[AND:%.*]] = trunc <4 x i32> [[AND_INNER]] to <4 x i16> ; CHECK-NEXT: ret <4 x i16> [[AND]] ; %t1 = trunc <4 x i32> %a to <4 x i16> %t2 = trunc <4 x i32> %b to <4 x i16> %and = and <4 x i16> %t1, %t2 ret <4 x i16> %and } define <8 x i8> @or_trunc_v8i16_to_v8i8(<8 x i16> %a, <8 x i16> %b) { ; CHECK-LABEL: @or_trunc_v8i16_to_v8i8( ; CHECK-NEXT: [[OR_INNER:%.*]] = or <8 x i16> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[OR:%.*]] = trunc <8 x i16> [[OR_INNER]] to <8 x i8> ; CHECK-NEXT: ret <8 x i8> [[OR]] ; %t1 = trunc <8 x i16> %a to <8 x i8> %t2 = trunc <8 x i16> %b to <8 x i8> %or = or <8 x i8> %t1, %t2 ret <8 x i8> %or } define <2 x i32> @xor_trunc_v2i64_to_v2i32(<2 x i64> %a, <2 x i64> %b) { ; CHECK-LABEL: @xor_trunc_v2i64_to_v2i32( ; CHECK-NEXT: [[XOR_INNER:%.*]] = xor <2 x i64> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = trunc <2 x i64> [[XOR_INNER]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[XOR]] ; %t1 = trunc <2 x i64> %a to <2 x i32> %t2 = trunc <2 x i64> %b to <2 x i32> %xor = xor <2 x i32> %t1, %t2 ret <2 x i32> %xor } ; Test bitwise operations with zero extend define <4 x i32> @and_zext_v4i16_to_v4i32(<4 x i16> %a, <4 x i16> %b) { ; CHECK-LABEL: @and_zext_v4i16_to_v4i32( ; CHECK-NEXT: [[AND_INNER:%.*]] = and <4 x i16> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[AND:%.*]] = zext <4 x i16> [[AND_INNER]] to <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[AND]] ; %z1 = zext <4 x i16> %a to <4 x i32> %z2 = zext <4 x i16> %b to <4 x i32> %and = and <4 x i32> %z1, %z2 ret <4 x i32> %and } define <8 x i16> @or_zext_v8i8_to_v8i16(<8 x i8> %a, <8 x i8> %b) { ; CHECK-LABEL: @or_zext_v8i8_to_v8i16( ; CHECK-NEXT: [[OR_INNER:%.*]] = or <8 x i8> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[OR:%.*]] = zext <8 x i8> [[OR_INNER]] to <8 x i16> ; CHECK-NEXT: ret <8 x i16> [[OR]] ; %z1 = zext <8 x i8> %a to <8 x i16> %z2 = zext <8 x i8> %b to <8 x i16> %or = or <8 x i16> %z1, %z2 ret <8 x i16> %or } define <2 x i64> @xor_zext_v2i32_to_v2i64(<2 x i32> %a, <2 x i32> %b) { ; CHECK-LABEL: @xor_zext_v2i32_to_v2i64( ; CHECK-NEXT: [[XOR_INNER:%.*]] = xor <2 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = zext <2 x i32> [[XOR_INNER]] to <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[XOR]] ; %z1 = zext <2 x i32> %a to <2 x i64> %z2 = zext <2 x i32> %b to <2 x i64> %xor = xor <2 x i64> %z1, %z2 ret <2 x i64> %xor } ; Test bitwise operations with sign extend define <4 x i32> @and_sext_v4i16_to_v4i32(<4 x i16> %a, <4 x i16> %b) { ; CHECK-LABEL: @and_sext_v4i16_to_v4i32( ; CHECK-NEXT: [[AND_INNER:%.*]] = and <4 x i16> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[AND:%.*]] = sext <4 x i16> [[AND_INNER]] to <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[AND]] ; %s1 = sext <4 x i16> %a to <4 x i32> %s2 = sext <4 x i16> %b to <4 x i32> %and = and <4 x i32> %s1, %s2 ret <4 x i32> %and } define <8 x i16> @or_sext_v8i8_to_v8i16(<8 x i8> %a, <8 x i8> %b) { ; CHECK-LABEL: @or_sext_v8i8_to_v8i16( ; CHECK-NEXT: [[OR_INNER:%.*]] = or <8 x i8> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[OR:%.*]] = sext <8 x i8> [[OR_INNER]] to <8 x i16> ; CHECK-NEXT: ret <8 x i16> [[OR]] ; %s1 = sext <8 x i8> %a to <8 x i16> %s2 = sext <8 x i8> %b to <8 x i16> %or = or <8 x i16> %s1, %s2 ret <8 x i16> %or } define <2 x i64> @xor_sext_v2i32_to_v2i64(<2 x i32> %a, <2 x i32> %b) { ; CHECK-LABEL: @xor_sext_v2i32_to_v2i64( ; CHECK-NEXT: [[XOR_INNER:%.*]] = xor <2 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = sext <2 x i32> [[XOR_INNER]] to <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[XOR]] ; %s1 = sext <2 x i32> %a to <2 x i64> %s2 = sext <2 x i32> %b to <2 x i64> %xor = xor <2 x i64> %s1, %s2 ret <2 x i64> %xor } ; Negative test: mismatched cast types (zext and sext) define <4 x i32> @and_zext_sext_mismatch(<4 x i16> %a, <4 x i16> %b) { ; CHECK-LABEL: @and_zext_sext_mismatch( ; CHECK-NEXT: [[Z1:%.*]] = zext <4 x i16> [[A:%.*]] to <4 x i32> ; CHECK-NEXT: [[S2:%.*]] = sext <4 x i16> [[B:%.*]] to <4 x i32> ; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[Z1]], [[S2]] ; CHECK-NEXT: ret <4 x i32> [[AND]] ; %z1 = zext <4 x i16> %a to <4 x i32> %s2 = sext <4 x i16> %b to <4 x i32> %and = and <4 x i32> %z1, %s2 ret <4 x i32> %and } ; Negative test: mismatched source types define <4 x i32> @or_zext_different_src_types(<4 x i16> %a, <4 x i8> %b) { ; CHECK-LABEL: @or_zext_different_src_types( ; CHECK-NEXT: [[Z1:%.*]] = zext <4 x i16> [[A:%.*]] to <4 x i32> ; CHECK-NEXT: [[Z2:%.*]] = zext <4 x i8> [[B:%.*]] to <4 x i32> ; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[Z1]], [[Z2]] ; CHECK-NEXT: ret <4 x i32> [[OR]] ; %z1 = zext <4 x i16> %a to <4 x i32> %z2 = zext <4 x i8> %b to <4 x i32> %or = or <4 x i32> %z1, %z2 ret <4 x i32> %or } ; Negative test: scalar types (not vectors) define i32 @xor_zext_scalar(i16 %a, i16 %b) { ; CHECK-LABEL: @xor_zext_scalar( ; CHECK-NEXT: [[Z1:%.*]] = zext i16 [[A:%.*]] to i32 ; CHECK-NEXT: [[Z2:%.*]] = zext i16 [[B:%.*]] to i32 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Z1]], [[Z2]] ; CHECK-NEXT: ret i32 [[XOR]] ; %z1 = zext i16 %a to i32 %z2 = zext i16 %b to i32 %xor = xor i32 %z1, %z2 ret i32 %xor } ; Test multi-use: one cast has multiple uses define <4 x i32> @and_zext_multiuse(<4 x i16> %a, <4 x i16> %b) { ; CHECK-LABEL: @and_zext_multiuse( ; CHECK-NEXT: [[Z1:%.*]] = zext <4 x i16> [[A:%.*]] to <4 x i32> ; CHECK-NEXT: [[AND_INNER:%.*]] = and <4 x i16> [[A]], [[B:%.*]] ; CHECK-NEXT: [[AND:%.*]] = zext <4 x i16> [[AND_INNER]] to <4 x i32> ; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[Z1]], [[AND]] ; CHECK-NEXT: ret <4 x i32> [[ADD]] ; %z1 = zext <4 x i16> %a to <4 x i32> %z2 = zext <4 x i16> %b to <4 x i32> %and = and <4 x i32> %z1, %z2 %add = add <4 x i32> %z1, %and ; z1 has multiple uses ret <4 x i32> %add } ; Test with different vector sizes define <16 x i16> @or_zext_v16i8_to_v16i16(<16 x i8> %a, <16 x i8> %b) { ; CHECK-LABEL: @or_zext_v16i8_to_v16i16( ; CHECK-NEXT: [[OR_INNER:%.*]] = or <16 x i8> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[OR:%.*]] = zext <16 x i8> [[OR_INNER]] to <16 x i16> ; CHECK-NEXT: ret <16 x i16> [[OR]] ; %z1 = zext <16 x i8> %a to <16 x i16> %z2 = zext <16 x i8> %b to <16 x i16> %or = or <16 x i16> %z1, %z2 ret <16 x i16> %or } ; Test bitcast with different element counts define <8 x i16> @xor_bitcast_v4i32_to_v8i16(<4 x i32> %a, <4 x i32> %b) { ; CHECK-LABEL: @xor_bitcast_v4i32_to_v8i16( ; CHECK-NEXT: [[XOR_INNER:%.*]] = xor <4 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = bitcast <4 x i32> [[XOR_INNER]] to <8 x i16> ; CHECK-NEXT: ret <8 x i16> [[XOR]] ; %bc1 = bitcast <4 x i32> %a to <8 x i16> %bc2 = bitcast <4 x i32> %b to <8 x i16> %xor = xor <8 x i16> %bc1, %bc2 ret <8 x i16> %xor } ; Test truncate with flag preservation define <4 x i16> @and_trunc_nuw_nsw(<4 x i32> %a, <4 x i32> %b) { ; CHECK-LABEL: @and_trunc_nuw_nsw( ; CHECK-NEXT: [[AND_INNER:%.*]] = and <4 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[AND:%.*]] = trunc nuw nsw <4 x i32> [[AND_INNER]] to <4 x i16> ; CHECK-NEXT: ret <4 x i16> [[AND]] ; %t1 = trunc nuw nsw <4 x i32> %a to <4 x i16> %t2 = trunc nuw nsw <4 x i32> %b to <4 x i16> %and = and <4 x i16> %t1, %t2 ret <4 x i16> %and } ; Test sign extend with nneg flag define <4 x i32> @or_zext_nneg(<4 x i16> %a, <4 x i16> %b) { ; CHECK-LABEL: @or_zext_nneg( ; CHECK-NEXT: [[OR_INNER:%.*]] = or <4 x i16> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[OR:%.*]] = zext nneg <4 x i16> [[OR_INNER]] to <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[OR]] ; %z1 = zext nneg <4 x i16> %a to <4 x i32> %z2 = zext nneg <4 x i16> %b to <4 x i32> %or = or <4 x i32> %z1, %z2 ret <4 x i32> %or } ; Test bitwise operations with integer-to-integer bitcast with one constant define <2 x i32> @or_bitcast_v4i16_to_v2i32_constant(<4 x i16> %a) { ; CHECK-LABEL: @or_bitcast_v4i16_to_v2i32_constant( ; CHECK-NEXT: [[A:%.*]] = or <4 x i16> [[A1:%.*]], ; CHECK-NEXT: [[BC1:%.*]] = bitcast <4 x i16> [[A]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[BC1]] ; %bc1 = bitcast <4 x i16> %a to <2 x i32> %or = or <2 x i32> %bc1, ret <2 x i32> %or } define <2 x i32> @or_bitcast_v4i16_to_v2i32_constant_commuted(<4 x i16> %a) { ; CHECK-LABEL: @or_bitcast_v4i16_to_v2i32_constant_commuted( ; CHECK-NEXT: [[A:%.*]] = or <4 x i16> [[A1:%.*]], ; CHECK-NEXT: [[BC1:%.*]] = bitcast <4 x i16> [[A]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[BC1]] ; %bc1 = bitcast <4 x i16> %a to <2 x i32> %or = or <2 x i32> , %bc1 ret <2 x i32> %or } ; Test bitwise operations with truncate and one constant define <4 x i16> @or_trunc_v4i32_to_v4i16_constant(<4 x i32> %a) { ; CHECK-LABEL: @or_trunc_v4i32_to_v4i16_constant( ; CHECK-NEXT: [[A:%.*]] = or <4 x i32> [[A1:%.*]], ; CHECK-NEXT: [[T1:%.*]] = trunc <4 x i32> [[A]] to <4 x i16> ; CHECK-NEXT: ret <4 x i16> [[T1]] ; %t1 = trunc <4 x i32> %a to <4 x i16> %or = or <4 x i16> %t1, ret <4 x i16> %or } ; Test bitwise operations with zero extend and one constant define <4 x i32> @or_zext_v4i16_to_v4i32_constant(<4 x i16> %a) { ; CHECK-LABEL: @or_zext_v4i16_to_v4i32_constant( ; CHECK-NEXT: [[A:%.*]] = or <4 x i16> [[A1:%.*]], ; CHECK-NEXT: [[Z1:%.*]] = zext <4 x i16> [[A]] to <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[Z1]] ; %z1 = zext <4 x i16> %a to <4 x i32> %or = or <4 x i32> %z1, ret <4 x i32> %or } define <4 x i32> @or_zext_v4i8_to_v4i32_constant_with_loss(<4 x i8> %a) { ; CHECK-LABEL: @or_zext_v4i8_to_v4i32_constant_with_loss( ; CHECK-NEXT: [[Z1:%.*]] = zext <4 x i8> [[A:%.*]] to <4 x i32> ; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[Z1]], ; CHECK-NEXT: ret <4 x i32> [[OR]] ; %z1 = zext <4 x i8> %a to <4 x i32> %or = or <4 x i32> %z1, ret <4 x i32> %or } ; Test bitwise operations with sign extend and one constant define <4 x i32> @or_sext_v4i8_to_v4i32_positive_constant(<4 x i8> %a) { ; CHECK-LABEL: @or_sext_v4i8_to_v4i32_positive_constant( ; CHECK-NEXT: [[A:%.*]] = or <4 x i8> [[A1:%.*]], ; CHECK-NEXT: [[S1:%.*]] = sext <4 x i8> [[A]] to <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[S1]] ; %s1 = sext <4 x i8> %a to <4 x i32> %or = or <4 x i32> %s1, ret <4 x i32> %or } define <4 x i32> @or_sext_v4i8_to_v4i32_minus_constant(<4 x i8> %a) { ; CHECK-LABEL: @or_sext_v4i8_to_v4i32_minus_constant( ; CHECK-NEXT: [[A:%.*]] = or <4 x i8> [[A1:%.*]], ; CHECK-NEXT: [[S1:%.*]] = sext <4 x i8> [[A]] to <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[S1]] ; %s1 = sext <4 x i8> %a to <4 x i32> %or = or <4 x i32> %s1, ret <4 x i32> %or } define <4 x i32> @or_sext_v4i8_to_v4i32_constant_with_loss(<4 x i8> %a) { ; CHECK-LABEL: @or_sext_v4i8_to_v4i32_constant_with_loss( ; CHECK-NEXT: [[Z1:%.*]] = sext <4 x i8> [[A:%.*]] to <4 x i32> ; CHECK-NEXT: [[OR:%.*]] = or <4 x i32> [[Z1]], ; CHECK-NEXT: ret <4 x i32> [[OR]] ; %z1 = sext <4 x i8> %a to <4 x i32> %or = or <4 x i32> %z1, ret <4 x i32> %or } ; Test truncate with flag preservation and one constant define <4 x i16> @and_trunc_nuw_nsw_constant(<4 x i32> %a) { ; CHECK-LABEL: @and_trunc_nuw_nsw_constant( ; CHECK-NEXT: [[AND_INNER:%.*]] = and <4 x i32> [[A:%.*]], ; CHECK-NEXT: [[AND:%.*]] = trunc <4 x i32> [[AND_INNER]] to <4 x i16> ; CHECK-NEXT: ret <4 x i16> [[AND]] ; %t1 = trunc nuw nsw <4 x i32> %a to <4 x i16> %and = and <4 x i16> %t1, ret <4 x i16> %and } define <4 x i8> @and_trunc_nuw_nsw_minus_constant(<4 x i32> %a) { ; CHECK-LABEL: @and_trunc_nuw_nsw_minus_constant( ; CHECK-NEXT: [[AND_INNER:%.*]] = and <4 x i32> [[A:%.*]], ; CHECK-NEXT: [[AND:%.*]] = trunc <4 x i32> [[AND_INNER]] to <4 x i8> ; CHECK-NEXT: ret <4 x i8> [[AND]] ; %t1 = trunc nuw nsw <4 x i32> %a to <4 x i8> %and = and <4 x i8> %t1, ret <4 x i8> %and } define <4 x i8> @and_trunc_nuw_nsw_multiconstant(<4 x i32> %a) { ; CHECK-LABEL: @and_trunc_nuw_nsw_multiconstant( ; CHECK-NEXT: [[AND_INNER:%.*]] = and <4 x i32> [[A:%.*]], ; CHECK-NEXT: [[AND:%.*]] = trunc <4 x i32> [[AND_INNER]] to <4 x i8> ; CHECK-NEXT: ret <4 x i8> [[AND]] ; %t1 = trunc nuw nsw <4 x i32> %a to <4 x i8> %and = and <4 x i8> %t1, ret <4 x i8> %and } ; Test sign extend with nneg flag and one constant define <4 x i32> @or_zext_nneg_constant(<4 x i16> %a) { ; CHECK-LABEL: @or_zext_nneg_constant( ; CHECK-NEXT: [[OR_INNER:%.*]] = or <4 x i16> [[A:%.*]], ; CHECK-NEXT: [[OR:%.*]] = zext <4 x i16> [[OR_INNER]] to <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[OR]] ; %z1 = zext nneg <4 x i16> %a to <4 x i32> %or = or <4 x i32> %z1, ret <4 x i32> %or } define <4 x i32> @or_zext_nneg_minus_constant(<4 x i8> %a) { ; CHECK-LABEL: @or_zext_nneg_minus_constant( ; CHECK-NEXT: [[OR_INNER:%.*]] = or <4 x i8> [[A:%.*]], ; CHECK-NEXT: [[OR:%.*]] = zext <4 x i8> [[OR_INNER]] to <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[OR]] ; %z1 = zext nneg <4 x i8> %a to <4 x i32> %or = or <4 x i32> %z1, ret <4 x i32> %or } define <4 x i32> @or_zext_nneg_multiconstant(<4 x i8> %a) { ; CHECK-LABEL: @or_zext_nneg_multiconstant( ; CHECK-NEXT: [[OR_INNER:%.*]] = or <4 x i8> [[A:%.*]], ; CHECK-NEXT: [[OR:%.*]] = zext <4 x i8> [[OR_INNER]] to <4 x i32> ; CHECK-NEXT: ret <4 x i32> [[OR]] ; %z1 = zext nneg <4 x i8> %a to <4 x i32> %or = or <4 x i32> %z1, ret <4 x i32> %or } ; Negative test: bitcast from scalar float to vector int (optimization should not apply) define <2 x i16> @and_bitcast_f32_to_v2i16_constant(float %a) { ; CHECK-LABEL: @and_bitcast_f32_to_v2i16_constant( ; CHECK-NEXT: [[BC2:%.*]] = bitcast float [[B:%.*]] to <2 x i16> ; CHECK-NEXT: [[AND:%.*]] = and <2 x i16> , [[BC2]] ; CHECK-NEXT: ret <2 x i16> [[AND]] ; %bc = bitcast float %a to <2 x i16> %and = and <2 x i16> , %bc ret <2 x i16> %and } define <2 x i16> @and_bitcast_f32_to_v2i16(float %a, float %b) { ; CHECK-LABEL: @and_bitcast_f32_to_v2i16( ; CHECK-NEXT: [[BC1:%.*]] = bitcast float [[A:%.*]] to <2 x i16> ; CHECK-NEXT: [[BC2:%.*]] = bitcast float [[B:%.*]] to <2 x i16> ; CHECK-NEXT: [[AND:%.*]] = and <2 x i16> [[BC1]], [[BC2]] ; CHECK-NEXT: ret <2 x i16> [[AND]] ; %bc1 = bitcast float %a to <2 x i16> %bc2 = bitcast float %b to <2 x i16> %and = and <2 x i16> %bc1, %bc2 ret <2 x i16> %and } ; Negative test: bitcast from vector float to scalar int (optimization should not apply) define i64 @and_bitcast_v2f32_to_i64_constant(<2 x float> %a) { ; CHECK-LABEL: @and_bitcast_v2f32_to_i64_constant( ; CHECK-NEXT: [[BC2:%.*]] = bitcast <2 x float> [[B:%.*]] to i64 ; CHECK-NEXT: [[AND:%.*]] = and i64 123, [[BC2]] ; CHECK-NEXT: ret i64 [[AND]] ; %bc = bitcast <2 x float> %a to i64 %and = and i64 123, %bc ret i64 %and } define i64 @and_bitcast_v2f32_to_i64(<2 x float> %a, <2 x float> %b) { ; CHECK-LABEL: @and_bitcast_v2f32_to_i64( ; CHECK-NEXT: [[BC1:%.*]] = bitcast <2 x float> [[A:%.*]] to i64 ; CHECK-NEXT: [[BC2:%.*]] = bitcast <2 x float> [[B:%.*]] to i64 ; CHECK-NEXT: [[AND:%.*]] = and i64 [[BC1]], [[BC2]] ; CHECK-NEXT: ret i64 [[AND]] ; %bc1 = bitcast <2 x float> %a to i64 %bc2 = bitcast <2 x float> %b to i64 %and = and i64 %bc1, %bc2 ret i64 %and } ; Test no-op bitcast define i16 @xor_bitcast_i16_to_i16_constant(i16 %a) { ; CHECK-LABEL: @xor_bitcast_i16_to_i16_constant( ; CHECK-NEXT: [[BC2:%.*]] = bitcast i16 [[B:%.*]] to i16 ; CHECK-NEXT: [[OR:%.*]] = xor i16 123, [[BC2]] ; CHECK-NEXT: ret i16 [[OR]] ; %bc = bitcast i16 %a to i16 %or = xor i16 123, %bc ret i16 %or } define i16 @xor_bitcast_i16_to_i16(i16 %a, i16 %b) { ; CHECK-LABEL: @xor_bitcast_i16_to_i16( ; CHECK-NEXT: [[BC1:%.*]] = bitcast i16 [[A:%.*]] to i16 ; CHECK-NEXT: [[BC2:%.*]] = bitcast i16 [[B:%.*]] to i16 ; CHECK-NEXT: [[OR:%.*]] = xor i16 [[BC1]], [[BC2]] ; CHECK-NEXT: ret i16 [[OR]] ; %bc1 = bitcast i16 %a to i16 %bc2 = bitcast i16 %b to i16 %or = xor i16 %bc1, %bc2 ret i16 %or } ; Test bitwise operations with integer vector to integer bitcast define <16 x i1> @xor_bitcast_i16_to_v16i1_constant(i16 %a) { ; CHECK-LABEL: @xor_bitcast_i16_to_v16i1_constant( ; CHECK-NEXT: [[B:%.*]] = xor i16 [[A:%.*]], -1 ; CHECK-NEXT: [[BC2:%.*]] = bitcast i16 [[B]] to <16 x i1> ; CHECK-NEXT: ret <16 x i1> [[BC2]] ; %bc = bitcast i16 %a to <16 x i1> %or = xor <16 x i1> %bc, splat (i1 true) ret <16 x i1> %or } define <16 x i1> @xor_bitcast_i16_to_v16i1(i16 %a, i16 %b) { ; CHECK-LABEL: @xor_bitcast_i16_to_v16i1( ; CHECK-NEXT: [[B1:%.*]] = xor i16 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[BC3:%.*]] = bitcast i16 [[B1]] to <16 x i1> ; CHECK-NEXT: ret <16 x i1> [[BC3]] ; %bc1 = bitcast i16 %a to <16 x i1> %bc2 = bitcast i16 %b to <16 x i1> %or = xor <16 x i1> %bc1, %bc2 ret <16 x i1> %or } ; Test bitwise operations with integer vector to integer bitcast define i16 @or_bitcast_v16i1_to_i16_constant(<16 x i1> %a) { ; CHECK-LABEL: @or_bitcast_v16i1_to_i16_constant( ; CHECK-NEXT: [[BC2:%.*]] = bitcast <16 x i1> [[B:%.*]] to i16 ; CHECK-NEXT: [[OR:%.*]] = or i16 [[BC2]], 3 ; CHECK-NEXT: ret i16 [[OR]] ; %bc = bitcast <16 x i1> %a to i16 %or = or i16 %bc, 3 ret i16 %or } define i16 @or_bitcast_v16i1_to_i16(<16 x i1> %a, <16 x i1> %b) { ; CHECK-LABEL: @or_bitcast_v16i1_to_i16( ; CHECK-NEXT: [[BC1:%.*]] = bitcast <16 x i1> [[A:%.*]] to i16 ; CHECK-NEXT: [[BC2:%.*]] = bitcast <16 x i1> [[B:%.*]] to i16 ; CHECK-NEXT: [[OR:%.*]] = or i16 [[BC1]], [[BC2]] ; CHECK-NEXT: ret i16 [[OR]] ; %bc1 = bitcast <16 x i1> %a to i16 %bc2 = bitcast <16 x i1> %b to i16 %or = or i16 %bc1, %bc2 ret i16 %or }