; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes=instcombine < %s | FileCheck %s ; Combine equality comparisons of adjacent extracted integers parts into ; a comparison of a larger part. Start with some examples... declare void @use.i32(i32) declare void @use.i8(i8) declare void @use.i1(i1) define i1 @eq_10(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_10( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[Y:%.*]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i16 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i1 [[TMP3]] ; %x.0 = trunc i32 %x to i8 %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %y.0 = trunc i32 %y to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %c.0 = icmp eq i8 %x.0, %y.0 %c.1 = icmp eq i8 %x.1, %y.1 %c.10 = and i1 %c.0, %c.1 ret i1 %c.10 } define i1 @eq_210(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_210( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i24 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[Y:%.*]] to i24 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i24 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i1 [[TMP3]] ; %x.0 = trunc i32 %x to i8 %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.0 = trunc i32 %y to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.0 = icmp eq i8 %x.0, %y.0 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.10 = and i1 %c.0, %c.1 %c.210 = and i1 %c.2, %c.10 ret i1 %c.210 } define i1 @eq_3210(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_3210( ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[TMP1]] ; %x.0 = trunc i32 %x to i8 %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %x.3.ext = lshr i32 %x, 24 %x.3 = trunc i32 %x.3.ext to i8 %y.0 = trunc i32 %y to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %y.3.ext = lshr i32 %y, 24 %y.3 = trunc i32 %y.3.ext to i8 %c.0 = icmp eq i8 %x.0, %y.0 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.3 = icmp eq i8 %x.3, %y.3 %c.10 = and i1 %c.0, %c.1 %c.210 = and i1 %c.2, %c.10 %c.3210 = and i1 %c.3, %c.210 ret i1 %c.3210 } define i1 @eq_21(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } ; Test commuted variants of eq_21. define i1 @eq_21_comm_and(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_comm_and( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.1, %c.2 ret i1 %c.210 } define i1 @eq_21_comm_eq(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_comm_eq( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %y.2, %x.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_21_comm_eq2(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_comm_eq2( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %y.1, %x.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } ; Test vector variant. define <2x i1> @eq_21_vector(<2x i32> %x, <2x i32> %y) { ; CHECK-LABEL: @eq_21_vector( ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 8, i32 8> ; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i32> [[TMP1]] to <2 x i16> ; CHECK-NEXT: [[TMP3:%.*]] = lshr <2 x i32> [[Y:%.*]], <i32 8, i32 8> ; CHECK-NEXT: [[TMP4:%.*]] = trunc <2 x i32> [[TMP3]] to <2 x i16> ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq <2 x i16> [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret <2 x i1> [[TMP5]] ; %x.321 = lshr <2x i32> %x, <i32 8, i32 8> %x.1 = trunc <2x i32> %x.321 to <2x i8> %x.32 = lshr <2x i32> %x, <i32 16, i32 16> %x.2 = trunc <2x i32> %x.32 to <2x i8> %y.321 = lshr <2x i32> %y, <i32 8, i32 8> %y.1 = trunc <2x i32> %y.321 to <2x i8> %y.32 = lshr <2x i32> %y, <i32 16, i32 16> %y.2 = trunc <2x i32> %y.32 to <2x i8> %c.1 = icmp eq <2x i8> %x.1, %y.1 %c.2 = icmp eq <2x i8> %x.2, %y.2 %c.210 = and <2x i1> %c.2, %c.1 ret <2 x i1> %c.210 } ; Test irregular bit widths. This also tests the case where ; all the involved bit widths and offsets are different. define i1 @eq_irregular_bit_widths(i31 %x, i31 %y) { ; CHECK-LABEL: @eq_irregular_bit_widths( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i31 [[X:%.*]], 7 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i31 [[TMP1]] to i11 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i31 [[Y:%.*]], 7 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i31 [[TMP3]] to i11 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i11 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i31 %x, 7 %x.1 = trunc i31 %x.321 to i6 %x.32 = lshr i31 %x, 13 %x.2 = trunc i31 %x.32 to i5 %y.321 = lshr i31 %y, 7 %y.1 = trunc i31 %y.321 to i6 %y.32 = lshr i31 %y, 13 %y.2 = trunc i31 %y.32 to i5 %c.1 = icmp eq i6 %x.1, %y.1 %c.2 = icmp eq i5 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } ; Test variants with extra uses. define i1 @eq_21_extra_use_lshr(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_extra_use_lshr( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: call void @use.i32(i32 [[X_321]]) ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_1]], [[C_2]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 call void @use.i32(i32 %x.321) %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.1, %c.2 ret i1 %c.210 } define i1 @eq_21_extra_use_trunc(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_extra_use_trunc( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: call void @use.i8(i8 [[X_1]]) ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_1]], [[C_2]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 call void @use.i8(i8 %x.1) %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.1, %c.2 ret i1 %c.210 } define i1 @eq_21_extra_use_eq1(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_extra_use_eq1( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: call void @use.i1(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_1]], [[C_2]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 call void @use.i1(i1 %c.1) %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.1, %c.2 ret i1 %c.210 } define i1 @eq_21_extra_use_eq2(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_extra_use_eq2( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: call void @use.i1(i1 [[C_2]]) ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_1]], [[C_2]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 call void @use.i1(i1 %c.2) %c.210 = and i1 %c.1, %c.2 ret i1 %c.210 } ; Logical and instead of bitwise and. define i1 @eq_21_logical(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_logical( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = select i1 %c.2, i1 %c.1, i1 false ret i1 %c.210 } ; Negative tests. define i1 @eq_21_wrong_op1(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @eq_21_wrong_op1( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[Z:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X:%.*]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %z, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_21_wrong_op2(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @eq_21_wrong_op2( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[Z:%.*]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %z, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_21_wrong_op3(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @eq_21_wrong_op3( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Z:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y:%.*]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %z, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_21_wrong_op4(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @eq_21_wrong_op4( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Z:%.*]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %z, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_21_wrong_shift1(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_wrong_shift1( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 7 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 7 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_21_wrong_shift2(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_wrong_shift2( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 15 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 15 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_21_not_adjacent(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_not_adjacent( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 17 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 17 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 17 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 17 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_shift_in_zeros(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_shift_in_zeros( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i24 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i24 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i24 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i24 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i24 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i24 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_21_wrong_pred1(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_wrong_pred1( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } define i1 @eq_21_wrong_pred2(i32 %x, i32 %y) { ; CHECK-LABEL: @eq_21_wrong_pred2( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = and i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = and i1 %c.2, %c.1 ret i1 %c.210 } ; ; Now the same thing again, but for or ne instead of and eq. ; define i1 @ne_10(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_10( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[Y:%.*]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i16 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i1 [[TMP3]] ; %x.0 = trunc i32 %x to i8 %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %y.0 = trunc i32 %y to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %c.0 = icmp ne i8 %x.0, %y.0 %c.1 = icmp ne i8 %x.1, %y.1 %c.10 = or i1 %c.0, %c.1 ret i1 %c.10 } define i1 @ne_210(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_210( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i24 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[Y:%.*]] to i24 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i24 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i1 [[TMP3]] ; %x.0 = trunc i32 %x to i8 %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.0 = trunc i32 %y to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.0 = icmp ne i8 %x.0, %y.0 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.10 = or i1 %c.0, %c.1 %c.210 = or i1 %c.2, %c.10 ret i1 %c.210 } define i1 @ne_3210(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_3210( ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[TMP1]] ; %x.0 = trunc i32 %x to i8 %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %x.3.ext = lshr i32 %x, 24 %x.3 = trunc i32 %x.3.ext to i8 %y.0 = trunc i32 %y to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %y.3.ext = lshr i32 %y, 24 %y.3 = trunc i32 %y.3.ext to i8 %c.0 = icmp ne i8 %x.0, %y.0 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.3 = icmp ne i8 %x.3, %y.3 %c.10 = or i1 %c.0, %c.1 %c.210 = or i1 %c.2, %c.10 %c.3210 = or i1 %c.3, %c.210 ret i1 %c.3210 } define i1 @ne_21(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } ; Test commuted variants of ne_21. define i1 @ne_21_comm_or(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_comm_or( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.1, %c.2 ret i1 %c.210 } define i1 @ne_21_comm_ne(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_comm_ne( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %y.2, %x.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_21_comm_ne2(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_comm_ne2( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %y.1, %x.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } ; Test vector variant. define <2x i1> @ne_21_vector(<2x i32> %x, <2x i32> %y) { ; CHECK-LABEL: @ne_21_vector( ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 8, i32 8> ; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i32> [[TMP1]] to <2 x i16> ; CHECK-NEXT: [[TMP3:%.*]] = lshr <2 x i32> [[Y:%.*]], <i32 8, i32 8> ; CHECK-NEXT: [[TMP4:%.*]] = trunc <2 x i32> [[TMP3]] to <2 x i16> ; CHECK-NEXT: [[TMP5:%.*]] = icmp ne <2 x i16> [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret <2 x i1> [[TMP5]] ; %x.321 = lshr <2x i32> %x, <i32 8, i32 8> %x.1 = trunc <2x i32> %x.321 to <2x i8> %x.32 = lshr <2x i32> %x, <i32 16, i32 16> %x.2 = trunc <2x i32> %x.32 to <2x i8> %y.321 = lshr <2x i32> %y, <i32 8, i32 8> %y.1 = trunc <2x i32> %y.321 to <2x i8> %y.32 = lshr <2x i32> %y, <i32 16, i32 16> %y.2 = trunc <2x i32> %y.32 to <2x i8> %c.1 = icmp ne <2x i8> %x.1, %y.1 %c.2 = icmp ne <2x i8> %x.2, %y.2 %c.210 = or <2x i1> %c.2, %c.1 ret <2 x i1> %c.210 } ; Test irregular bit widths. This also tests the case where ; all the involved bit widths or offsets are different. define i1 @ne_irregular_bit_widths(i31 %x, i31 %y) { ; CHECK-LABEL: @ne_irregular_bit_widths( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i31 [[X:%.*]], 7 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i31 [[TMP1]] to i11 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i31 [[Y:%.*]], 7 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i31 [[TMP3]] to i11 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i11 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i31 %x, 7 %x.1 = trunc i31 %x.321 to i6 %x.32 = lshr i31 %x, 13 %x.2 = trunc i31 %x.32 to i5 %y.321 = lshr i31 %y, 7 %y.1 = trunc i31 %y.321 to i6 %y.32 = lshr i31 %y, 13 %y.2 = trunc i31 %y.32 to i5 %c.1 = icmp ne i6 %x.1, %y.1 %c.2 = icmp ne i5 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } ; Test variants with extra uses. define i1 @ne_21_extra_use_lshr(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_extra_use_lshr( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: call void @use.i32(i32 [[X_321]]) ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_1]], [[C_2]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 call void @use.i32(i32 %x.321) %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.1, %c.2 ret i1 %c.210 } define i1 @ne_21_extra_use_trunc(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_extra_use_trunc( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: call void @use.i8(i8 [[X_1]]) ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_1]], [[C_2]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 call void @use.i8(i8 %x.1) %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.1, %c.2 ret i1 %c.210 } define i1 @ne_21_extra_use_ne1(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_extra_use_ne1( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: call void @use.i1(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_1]], [[C_2]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 call void @use.i1(i1 %c.1) %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.1, %c.2 ret i1 %c.210 } define i1 @ne_21_extra_use_ne2(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_extra_use_ne2( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: call void @use.i1(i1 [[C_2]]) ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_1]], [[C_2]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 call void @use.i1(i1 %c.2) %c.210 = or i1 %c.1, %c.2 ret i1 %c.210 } ; Logical or instead of bitwise or. define i1 @ne_21_logical(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_logical( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 ; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[TMP4:%.*]] = trunc i32 [[TMP3]] to i16 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i16 [[TMP2]], [[TMP4]] ; CHECK-NEXT: ret i1 [[TMP5]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = select i1 %c.2, i1 true, i1 %c.1 ret i1 %c.210 } ; Negative tests. define i1 @ne_21_wrong_op1(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @ne_21_wrong_op1( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[Z:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X:%.*]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %z, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_21_wrong_op2(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @ne_21_wrong_op2( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[Z:%.*]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %z, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_21_wrong_op3(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @ne_21_wrong_op3( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Z:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y:%.*]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %z, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_21_wrong_op4(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @ne_21_wrong_op4( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Z:%.*]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %z, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_21_wrong_shift1(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_wrong_shift1( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 7 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 7 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_21_wrong_shift2(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_wrong_shift2( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 15 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 15 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_21_not_adjacent(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_not_adjacent( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 17 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 17 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 17 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 17 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_shift_in_zeros(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_shift_in_zeros( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i24 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i24 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i24 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i24 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i24 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp ne i24 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_21_wrong_pred1(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_wrong_pred1( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp ne i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 } define i1 @ne_21_wrong_pred2(i32 %x, i32 %y) { ; CHECK-LABEL: @ne_21_wrong_pred2( ; CHECK-NEXT: [[X_321:%.*]] = lshr i32 [[X:%.*]], 8 ; CHECK-NEXT: [[X_1:%.*]] = trunc i32 [[X_321]] to i8 ; CHECK-NEXT: [[X_32:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[X_2:%.*]] = trunc i32 [[X_32]] to i8 ; CHECK-NEXT: [[Y_321:%.*]] = lshr i32 [[Y:%.*]], 8 ; CHECK-NEXT: [[Y_1:%.*]] = trunc i32 [[Y_321]] to i8 ; CHECK-NEXT: [[Y_32:%.*]] = lshr i32 [[Y]], 16 ; CHECK-NEXT: [[Y_2:%.*]] = trunc i32 [[Y_32]] to i8 ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[X_1]], [[Y_1]] ; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X_2]], [[Y_2]] ; CHECK-NEXT: [[C_210:%.*]] = or i1 [[C_2]], [[C_1]] ; CHECK-NEXT: ret i1 [[C_210]] ; %x.321 = lshr i32 %x, 8 %x.1 = trunc i32 %x.321 to i8 %x.32 = lshr i32 %x, 16 %x.2 = trunc i32 %x.32 to i8 %y.321 = lshr i32 %y, 8 %y.1 = trunc i32 %y.321 to i8 %y.32 = lshr i32 %y, 16 %y.2 = trunc i32 %y.32 to i8 %c.1 = icmp eq i8 %x.1, %y.1 %c.2 = icmp eq i8 %x.2, %y.2 %c.210 = or i1 %c.2, %c.1 ret i1 %c.210 }