; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n32:64" declare void @use(i32) ; Should be eliminated define i32 @test12(i32 %A) { ; CHECK-LABEL: @test12( ; CHECK-NEXT: [[C:%.*]] = and i32 [[A:%.*]], 8 ; CHECK-NEXT: ret i32 [[C]] ; %B = or i32 %A, 4 %C = and i32 %B, 8 ret i32 %C } define i32 @test13(i32 %A) { ; CHECK-LABEL: @test13( ; CHECK-NEXT: ret i32 8 ; %B = or i32 %A, 12 ; Always equal to 8 %C = and i32 %B, 8 ret i32 %C } define i1 @test14(i32 %A, i32 %B) { ; CHECK-LABEL: @test14( ; CHECK-NEXT: [[D:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: ret i1 [[D]] ; %C1 = icmp ult i32 %A, %B %C2 = icmp ugt i32 %A, %B ; (A < B) | (A > B) === A != B %D = or i1 %C1, %C2 ret i1 %D } define i1 @test14_commuted(i32 %A, i32 %B) { ; CHECK-LABEL: @test14_commuted( ; CHECK-NEXT: [[D:%.*]] = icmp ne i32 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[D]] ; %C1 = icmp ult i32 %A, %B %C2 = icmp ult i32 %B, %A ; (A < B) | (A > B) === A != B %D = or i1 %C1, %C2 ret i1 %D } define i1 @test14_logical(i32 %A, i32 %B) { ; CHECK-LABEL: @test14_logical( ; CHECK-NEXT: [[D:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: ret i1 [[D]] ; %C1 = icmp ult i32 %A, %B %C2 = icmp ugt i32 %A, %B ; (A < B) | (A > B) === A != B %D = select i1 %C1, i1 true, i1 %C2 ret i1 %D } define i1 @test15(i32 %A, i32 %B) { ; CHECK-LABEL: @test15( ; CHECK-NEXT: [[D:%.*]] = icmp ule i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: ret i1 [[D]] ; %C1 = icmp ult i32 %A, %B %C2 = icmp eq i32 %A, %B ; (A < B) | (A == B) === A <= B %D = or i1 %C1, %C2 ret i1 %D } define i1 @test15_logical(i32 %A, i32 %B) { ; CHECK-LABEL: @test15_logical( ; CHECK-NEXT: [[D:%.*]] = icmp ule i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: ret i1 [[D]] ; %C1 = icmp ult i32 %A, %B %C2 = icmp eq i32 %A, %B ; (A < B) | (A == B) === A <= B %D = select i1 %C1, i1 true, i1 %C2 ret i1 %D } define i32 @test16(i32 %A) { ; CHECK-LABEL: @test16( ; CHECK-NEXT: ret i32 [[A:%.*]] ; %B = and i32 %A, 1 ; -2 = ~1 %C = and i32 %A, -2 ; %D = and int %B, -1 == %B %D = or i32 %B, %C ret i32 %D } define i32 @test17(i32 %A) { ; CHECK-LABEL: @test17( ; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], 5 ; CHECK-NEXT: ret i32 [[D]] ; %B = and i32 %A, 1 %C = and i32 %A, 4 ; %D = and int %B, 5 %D = or i32 %B, %C ret i32 %D } define i1 @test18(i32 %A) { ; CHECK-LABEL: @test18( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], -100 ; CHECK-NEXT: [[D:%.*]] = icmp ult i32 [[TMP1]], -50 ; CHECK-NEXT: ret i1 [[D]] ; %B = icmp sge i32 %A, 100 %C = icmp slt i32 %A, 50 %D = or i1 %B, %C ret i1 %D } define i1 @test18_logical(i32 %A) { ; CHECK-LABEL: @test18_logical( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], -100 ; CHECK-NEXT: [[D:%.*]] = icmp ult i32 [[TMP1]], -50 ; CHECK-NEXT: ret i1 [[D]] ; %B = icmp sge i32 %A, 100 %C = icmp slt i32 %A, 50 %D = select i1 %B, i1 true, i1 %C ret i1 %D } define <2 x i1> @test18vec(<2 x i32> %A) { ; CHECK-LABEL: @test18vec( ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], ; CHECK-NEXT: [[D:%.*]] = icmp ult <2 x i32> [[TMP1]], ; CHECK-NEXT: ret <2 x i1> [[D]] ; %B = icmp sge <2 x i32> %A, %C = icmp slt <2 x i32> %A, %D = or <2 x i1> %B, %C ret <2 x i1> %D } define i32 @test20(i32 %x) { ; CHECK-LABEL: @test20( ; CHECK-NEXT: ret i32 [[X:%.*]] ; %y = and i32 %x, 123 %z = or i32 %y, %x ret i32 %z } ; TODO: This should combine to t1 + 2. define i32 @test21(i32 %t1) { ; CHECK-LABEL: @test21( ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[T1:%.*]], -2 ; CHECK-NEXT: [[T3:%.*]] = add i32 [[TMP1]], 2 ; CHECK-NEXT: [[T5:%.*]] = and i32 [[T1]], 1 ; CHECK-NEXT: [[T6:%.*]] = or disjoint i32 [[T5]], [[T3]] ; CHECK-NEXT: ret i32 [[T6]] ; %t1.mask1 = add i32 %t1, 2 %t3 = and i32 %t1.mask1, -2 %t5 = and i32 %t1, 1 ;; add tmp.1, 2 %t6 = or i32 %t5, %t3 ret i32 %t6 } define i32 @test22(i32 %B) { ; CHECK-LABEL: @test22( ; CHECK-NEXT: ret i32 [[B:%.*]] ; %ELIM41 = and i32 %B, 1 %ELIM7 = and i32 %B, -2 %ELIM5 = or i32 %ELIM41, %ELIM7 ret i32 %ELIM5 } define i16 @test23(i16 %A) { ; CHECK-LABEL: @test23( ; CHECK-NEXT: [[B:%.*]] = lshr i16 [[A:%.*]], 1 ; CHECK-NEXT: [[D:%.*]] = xor i16 [[B]], -24575 ; CHECK-NEXT: ret i16 [[D]] ; %B = lshr i16 %A, 1 ;; fold or into xor %C = or i16 %B, -32768 %D = xor i16 %C, 8193 ret i16 %D } define <2 x i16> @test23vec(<2 x i16> %A) { ; CHECK-LABEL: @test23vec( ; CHECK-NEXT: [[B:%.*]] = lshr <2 x i16> [[A:%.*]], ; CHECK-NEXT: [[D:%.*]] = xor <2 x i16> [[B]], ; CHECK-NEXT: ret <2 x i16> [[D]] ; %B = lshr <2 x i16> %A, ;; fold or into xor %C = or <2 x i16> %B, %D = xor <2 x i16> %C, ret <2 x i16> %D } ; PR3266 & PR5276 define i1 @test25(i32 %A, i32 %B) { ; CHECK-LABEL: @test25( ; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[A:%.*]], 0 ; CHECK-NEXT: [[D:%.*]] = icmp ne i32 [[B:%.*]], 57 ; CHECK-NEXT: [[E_NOT:%.*]] = and i1 [[C]], [[D]] ; CHECK-NEXT: ret i1 [[E_NOT]] ; %C = icmp eq i32 %A, 0 %D = icmp eq i32 %B, 57 %E = or i1 %C, %D %F = xor i1 %E, -1 ret i1 %F } define i1 @test25_logical(i32 %A, i32 %B) { ; CHECK-LABEL: @test25_logical( ; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[A:%.*]], 0 ; CHECK-NEXT: [[D:%.*]] = icmp ne i32 [[B:%.*]], 57 ; CHECK-NEXT: [[E_NOT:%.*]] = select i1 [[C]], i1 [[D]], i1 false ; CHECK-NEXT: ret i1 [[E_NOT]] ; %C = icmp eq i32 %A, 0 %D = icmp eq i32 %B, 57 %E = select i1 %C, i1 true, i1 %D %F = xor i1 %E, -1 ret i1 %F } ; PR5634 define i1 @and_icmp_eq_0(i32 %A, i32 %B) { ; CHECK-LABEL: @and_icmp_eq_0( ; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[D]] ; %C1 = icmp eq i32 %A, 0 %C2 = icmp eq i32 %B, 0 ; (A == 0) & (A == 0) --> (A|B) == 0 %D = and i1 %C1, %C2 ret i1 %D } define <2 x i1> @and_icmp_eq_0_vector(<2 x i32> %A, <2 x i32> %B) { ; CHECK-LABEL: @and_icmp_eq_0_vector( ; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[D]] ; %C1 = icmp eq <2 x i32> %A, zeroinitializer %C2 = icmp eq <2 x i32> %B, zeroinitializer %D = and <2 x i1> %C1, %C2 ret <2 x i1> %D } define <2 x i1> @and_icmp_eq_0_vector_undef1(<2 x i32> %A, <2 x i32> %B) { ; CHECK-LABEL: @and_icmp_eq_0_vector_undef1( ; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[D]] ; %C1 = icmp eq <2 x i32> %A, %C2 = icmp eq <2 x i32> %B, %D = and <2 x i1> %C1, %C2 ret <2 x i1> %D } define <2 x i1> @and_icmp_eq_0_vector_undef2(<2 x i32> %A, <2 x i32> %B) { ; CHECK-LABEL: @and_icmp_eq_0_vector_undef2( ; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[D]] ; %C1 = icmp eq <2 x i32> %A, %C2 = icmp eq <2 x i32> %B, %D = and <2 x i1> %C1, %C2 ret <2 x i1> %D } define i1 @and_icmp_eq_0_logical(i32 %A, i32 %B) { ; CHECK-LABEL: @and_icmp_eq_0_logical( ; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[A:%.*]], 0 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[B:%.*]], 0 ; CHECK-NEXT: [[D:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false ; CHECK-NEXT: ret i1 [[D]] ; %C1 = icmp eq i32 %A, 0 %C2 = icmp eq i32 %B, 0 ; (A == 0) & (A == 0) --> (A|B) == 0 %D = select i1 %C1, i1 %C2, i1 false ret i1 %D } define i1 @test27(ptr %A, ptr %B) { ; CHECK-LABEL: @test27( ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[A:%.*]], null ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq ptr [[B:%.*]], null ; CHECK-NEXT: [[E:%.*]] = and i1 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i1 [[E]] ; %C1 = ptrtoint ptr %A to i32 %C2 = ptrtoint ptr %B to i32 %D = or i32 %C1, %C2 %E = icmp eq i32 %D, 0 ret i1 %E } define <2 x i1> @test27vec(<2 x ptr> %A, <2 x ptr> %B) { ; CHECK-LABEL: @test27vec( ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x ptr> [[A:%.*]], zeroinitializer ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x ptr> [[B:%.*]], zeroinitializer ; CHECK-NEXT: [[E:%.*]] = and <2 x i1> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i1> [[E]] ; %C1 = ptrtoint <2 x ptr> %A to <2 x i32> %C2 = ptrtoint <2 x ptr> %B to <2 x i32> %D = or <2 x i32> %C1, %C2 %E = icmp eq <2 x i32> %D, zeroinitializer ret <2 x i1> %E } ; PR5634 define i1 @test28(i32 %A, i32 %B) { ; CHECK-LABEL: @test28( ; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = icmp ne i32 [[TMP1]], 0 ; CHECK-NEXT: ret i1 [[D]] ; %C1 = icmp ne i32 %A, 0 %C2 = icmp ne i32 %B, 0 ; (A != 0) | (A != 0) --> (A|B) != 0 %D = or i1 %C1, %C2 ret i1 %D } define i1 @test28_logical(i32 %A, i32 %B) { ; CHECK-LABEL: @test28_logical( ; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[A:%.*]], 0 ; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[B:%.*]], 0 ; CHECK-NEXT: [[D:%.*]] = select i1 [[C1]], i1 true, i1 [[C2]] ; CHECK-NEXT: ret i1 [[D]] ; %C1 = icmp ne i32 %A, 0 %C2 = icmp ne i32 %B, 0 ; (A != 0) | (A != 0) --> (A|B) != 0 %D = select i1 %C1, i1 true, i1 %C2 ret i1 %D } define i1 @test29(ptr %A, ptr %B) { ; CHECK-LABEL: @test29( ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne ptr [[A:%.*]], null ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[B:%.*]], null ; CHECK-NEXT: [[E:%.*]] = or i1 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i1 [[E]] ; %C1 = ptrtoint ptr %A to i32 %C2 = ptrtoint ptr %B to i32 %D = or i32 %C1, %C2 %E = icmp ne i32 %D, 0 ret i1 %E } define <2 x i1> @test29vec(<2 x ptr> %A, <2 x ptr> %B) { ; CHECK-LABEL: @test29vec( ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x ptr> [[A:%.*]], zeroinitializer ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x ptr> [[B:%.*]], zeroinitializer ; CHECK-NEXT: [[E:%.*]] = or <2 x i1> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i1> [[E]] ; %C1 = ptrtoint <2 x ptr> %A to <2 x i32> %C2 = ptrtoint <2 x ptr> %B to <2 x i32> %D = or <2 x i32> %C1, %C2 %E = icmp ne <2 x i32> %D, zeroinitializer ret <2 x i1> %E } ; PR4216 define i32 @test30(i32 %A) { ; CHECK-LABEL: @test30( ; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], -58312 ; CHECK-NEXT: [[E:%.*]] = or disjoint i32 [[D]], 32962 ; CHECK-NEXT: ret i32 [[E]] ; %B = or i32 %A, 32962 ; 0b1000_0000_1100_0010 %C = and i32 %A, -65536 ; 0xffff0000 %D = and i32 %B, 40186 ; 0b1001_1100_1111_1010 %E = or i32 %D, %C ret i32 %E } define <2 x i32> @test30vec(<2 x i32> %A) { ; CHECK-LABEL: @test30vec( ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], ; CHECK-NEXT: [[E:%.*]] = or disjoint <2 x i32> [[TMP1]], ; CHECK-NEXT: ret <2 x i32> [[E]] ; %B = or <2 x i32> %A, %C = and <2 x i32> %A, %D = and <2 x i32> %B, %E = or <2 x i32> %D, %C ret <2 x i32> %E } ; PR4216 define i64 @test31(i64 %A) { ; CHECK-LABEL: @test31( ; CHECK-NEXT: [[E:%.*]] = and i64 [[A:%.*]], 4294908984 ; CHECK-NEXT: [[F:%.*]] = or disjoint i64 [[E]], 32962 ; CHECK-NEXT: ret i64 [[F]] ; %B = or i64 %A, 194 %D = and i64 %B, 250 %C = or i64 %A, 32768 %E = and i64 %C, 4294941696 %F = or i64 %D, %E ret i64 %F } define <2 x i64> @test31vec(<2 x i64> %A) { ; CHECK-LABEL: @test31vec( ; CHECK-NEXT: [[E:%.*]] = and <2 x i64> [[A:%.*]], ; CHECK-NEXT: [[F:%.*]] = or disjoint <2 x i64> [[E]], ; CHECK-NEXT: ret <2 x i64> [[F]] ; %B = or <2 x i64> %A, %D = and <2 x i64> %B, %C = or <2 x i64> %A, %E = and <2 x i64> %C, %F = or <2 x i64> %D, %E ret <2 x i64> %F } ; codegen is mature enough to handle vector selects. define <4 x i32> @test32(<4 x i1> %and.i1352, <4 x i32> %vecinit6.i176, <4 x i32> %vecinit6.i191) { ; CHECK-LABEL: @test32( ; CHECK-NEXT: [[OR_I:%.*]] = select <4 x i1> [[AND_I1352:%.*]], <4 x i32> [[VECINIT6_I176:%.*]], <4 x i32> [[VECINIT6_I191:%.*]] ; CHECK-NEXT: ret <4 x i32> [[OR_I]] ; %and.i135 = sext <4 x i1> %and.i1352 to <4 x i32> %and.i129 = and <4 x i32> %vecinit6.i176, %and.i135 %neg.i = xor <4 x i32> %and.i135, %and.i = and <4 x i32> %vecinit6.i191, %neg.i %or.i = or <4 x i32> %and.i, %and.i129 ret <4 x i32> %or.i } define i1 @test33(i1 %X, i1 %Y) { ; CHECK-LABEL: @test33( ; CHECK-NEXT: [[A:%.*]] = or i1 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[A]] ; %a = or i1 %X, %Y %b = or i1 %a, %X ret i1 %b } define i1 @test33_logical(i1 %X, i1 %Y) { ; CHECK-LABEL: @test33_logical( ; CHECK-NEXT: [[A:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]] ; CHECK-NEXT: ret i1 [[A]] ; %a = select i1 %X, i1 true, i1 %Y %b = select i1 %a, i1 true, i1 %X ret i1 %b } define i32 @test34(i32 %X, i32 %Y) { ; CHECK-LABEL: @test34( ; CHECK-NEXT: [[A:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i32 [[A]] ; %a = or i32 %X, %Y %b = or i32 %Y, %a ret i32 %b } define i32 @test35(i32 %a, i32 %b) { ; CHECK-LABEL: @test35( ; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], 1135 ; CHECK-NEXT: ret i32 [[TMP2]] ; %1 = or i32 %a, 1135 %2 = or i32 %1, %b ret i32 %2 } define i1 @test36(i32 %x) { ; CHECK-LABEL: @test36( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], -23 ; CHECK-NEXT: [[RET2:%.*]] = icmp ult i32 [[TMP1]], 3 ; CHECK-NEXT: ret i1 [[RET2]] ; %cmp1 = icmp eq i32 %x, 23 %cmp2 = icmp eq i32 %x, 24 %ret1 = or i1 %cmp1, %cmp2 %cmp3 = icmp eq i32 %x, 25 %ret2 = or i1 %ret1, %cmp3 ret i1 %ret2 } define i1 @test36_logical(i32 %x) { ; CHECK-LABEL: @test36_logical( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], -23 ; CHECK-NEXT: [[RET2:%.*]] = icmp ult i32 [[TMP1]], 3 ; CHECK-NEXT: ret i1 [[RET2]] ; %cmp1 = icmp eq i32 %x, 23 %cmp2 = icmp eq i32 %x, 24 %ret1 = select i1 %cmp1, i1 true, i1 %cmp2 %cmp3 = icmp eq i32 %x, 25 %ret2 = select i1 %ret1, i1 true, i1 %cmp3 ret i1 %ret2 } define i1 @test37(i32 %x) { ; CHECK-LABEL: @test37( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], 7 ; CHECK-NEXT: [[RET1:%.*]] = icmp ult i32 [[TMP1]], 31 ; CHECK-NEXT: ret i1 [[RET1]] ; %add1 = add i32 %x, 7 %cmp1 = icmp ult i32 %add1, 30 %cmp2 = icmp eq i32 %x, 23 %ret1 = or i1 %cmp1, %cmp2 ret i1 %ret1 } define i1 @test37_logical(i32 %x) { ; CHECK-LABEL: @test37_logical( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], 7 ; CHECK-NEXT: [[RET1:%.*]] = icmp ult i32 [[TMP1]], 31 ; CHECK-NEXT: ret i1 [[RET1]] ; %add1 = add i32 %x, 7 %cmp1 = icmp ult i32 %add1, 30 %cmp2 = icmp eq i32 %x, 23 %ret1 = select i1 %cmp1, i1 true, i1 %cmp2 ret i1 %ret1 } define <2 x i1> @test37_uniform(<2 x i32> %x) { ; CHECK-LABEL: @test37_uniform( ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], ; CHECK-NEXT: [[RET1:%.*]] = icmp ult <2 x i32> [[TMP1]], ; CHECK-NEXT: ret <2 x i1> [[RET1]] ; %add1 = add <2 x i32> %x, %cmp1 = icmp ult <2 x i32> %add1, %cmp2 = icmp eq <2 x i32> %x, %ret1 = or <2 x i1> %cmp1, %cmp2 ret <2 x i1> %ret1 } define <2 x i1> @test37_undef(<2 x i32> %x) { ; CHECK-LABEL: @test37_undef( ; CHECK-NEXT: [[ADD1:%.*]] = add <2 x i32> [[X:%.*]], ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i32> [[ADD1]], ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq <2 x i32> [[X]], ; CHECK-NEXT: [[RET1:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]] ; CHECK-NEXT: ret <2 x i1> [[RET1]] ; %add1 = add <2 x i32> %x, %cmp1 = icmp ult <2 x i32> %add1, %cmp2 = icmp eq <2 x i32> %x, %ret1 = or <2 x i1> %cmp1, %cmp2 ret <2 x i1> %ret1 } define i1 @test38(i32 %x) { ; CHECK-LABEL: @test38( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], 7 ; CHECK-NEXT: [[RET1:%.*]] = icmp ult i32 [[TMP1]], 31 ; CHECK-NEXT: ret i1 [[RET1]] ; %add1 = add i32 %x, 7 %cmp1 = icmp eq i32 %x, 23 %cmp2 = icmp ult i32 %add1, 30 %ret1 = or i1 %cmp1, %cmp2 ret i1 %ret1 } define i1 @test38_logical(i32 %x) { ; CHECK-LABEL: @test38_logical( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], 7 ; CHECK-NEXT: [[RET1:%.*]] = icmp ult i32 [[TMP1]], 31 ; CHECK-NEXT: ret i1 [[RET1]] ; %add1 = add i32 %x, 7 %cmp1 = icmp eq i32 %x, 23 %cmp2 = icmp ult i32 %add1, 30 %ret1 = select i1 %cmp1, i1 true, i1 %cmp2 ret i1 %ret1 } define <2 x i1> @test38_nonuniform(<2 x i32> %x) { ; CHECK-LABEL: @test38_nonuniform( ; CHECK-NEXT: [[ADD1:%.*]] = add <2 x i32> [[X:%.*]], ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq <2 x i32> [[X]], ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i32> [[ADD1]], ; CHECK-NEXT: [[RET1:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]] ; CHECK-NEXT: ret <2 x i1> [[RET1]] ; %add1 = add <2 x i32> %x, %cmp1 = icmp eq <2 x i32> %x, %cmp2 = icmp ult <2 x i32> %add1, %ret1 = or <2 x i1> %cmp1, %cmp2 ret <2 x i1> %ret1 } ; (~A & B) | A --> A | B define i32 @test39a(i32 %a, float %b) { ; CHECK-LABEL: @test39a( ; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A:%.*]], 42 ; CHECK-NEXT: [[B1:%.*]] = bitcast float [[B:%.*]] to i32 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[A1]], [[B1]] ; CHECK-NEXT: ret i32 [[OR]] ; %a1 = mul i32 %a, 42 ; thwart complexity-based ordering %b1 = bitcast float %b to i32 ; thwart complexity-based ordering %nota = xor i32 %a1, -1 %and = and i32 %nota, %b1 %or = or i32 %and, %a1 ret i32 %or } ; Commute 'and' operands: ; (B & ~A) | A --> A | B define i32 @test39b(i32 %a, float %b) { ; CHECK-LABEL: @test39b( ; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A:%.*]], 42 ; CHECK-NEXT: [[B1:%.*]] = bitcast float [[B:%.*]] to i32 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[A1]], [[B1]] ; CHECK-NEXT: ret i32 [[OR]] ; %a1 = mul i32 %a, 42 ; thwart complexity-based ordering %b1 = bitcast float %b to i32 ; thwart complexity-based ordering %nota = xor i32 %a1, -1 %and = and i32 %b1, %nota %or = or i32 %and, %a1 ret i32 %or } ; Commute 'or' operands: ; A | (~A & B) --> A | B define i32 @test39c(i32 %a, float %b) { ; CHECK-LABEL: @test39c( ; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A:%.*]], 42 ; CHECK-NEXT: [[B1:%.*]] = bitcast float [[B:%.*]] to i32 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[A1]], [[B1]] ; CHECK-NEXT: ret i32 [[OR]] ; %a1 = mul i32 %a, 42 ; thwart complexity-based ordering %b1 = bitcast float %b to i32 ; thwart complexity-based ordering %nota = xor i32 %a1, -1 %and = and i32 %nota, %b1 %or = or i32 %a1, %and ret i32 %or } ; Commute 'and' operands: ; A | (B & ~A) --> A | B define i32 @test39d(i32 %a, float %b) { ; CHECK-LABEL: @test39d( ; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A:%.*]], 42 ; CHECK-NEXT: [[B1:%.*]] = bitcast float [[B:%.*]] to i32 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[A1]], [[B1]] ; CHECK-NEXT: ret i32 [[OR]] ; %a1 = mul i32 %a, 42 ; thwart complexity-based ordering %b1 = bitcast float %b to i32 ; thwart complexity-based ordering %nota = xor i32 %a1, -1 %and = and i32 %b1, %nota %or = or i32 %a1, %and ret i32 %or } define i32 @test40(i32 %a, i32 %b) { ; CHECK-LABEL: @test40( ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], -1 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR]], [[B:%.*]] ; CHECK-NEXT: ret i32 [[OR]] ; %and = and i32 %a, %b %xor = xor i32 %a, -1 %or = or i32 %and, %xor ret i32 %or } define i32 @test40b(i32 %a, i32 %b) { ; CHECK-LABEL: @test40b( ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], -1 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR]], [[B:%.*]] ; CHECK-NEXT: ret i32 [[OR]] ; %and = and i32 %b, %a %xor = xor i32 %a, -1 %or = or i32 %and, %xor ret i32 %or } define i32 @test40c(i32 %a, i32 %b) { ; CHECK-LABEL: @test40c( ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], -1 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR]], [[B:%.*]] ; CHECK-NEXT: ret i32 [[OR]] ; %and = and i32 %b, %a %xor = xor i32 %a, -1 %or = or i32 %xor, %and ret i32 %or } define i32 @test40d(i32 %a, i32 %b) { ; CHECK-LABEL: @test40d( ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], -1 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR]], [[B:%.*]] ; CHECK-NEXT: ret i32 [[OR]] ; %and = and i32 %a, %b %xor = xor i32 %a, -1 %or = or i32 %xor, %and ret i32 %or } define i32 @test45(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @test45( ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[TMP1]], [[Y:%.*]] ; CHECK-NEXT: ret i32 [[OR1]] ; %or = or i32 %y, %z %and = and i32 %x, %or %or1 = or i32 %and, %y ret i32 %or1 } define i32 @test45_commuted1(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @test45_commuted1( ; CHECK-NEXT: [[YY:%.*]] = mul i32 [[Y:%.*]], [[Y]] ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], [[Z:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[YY]], [[TMP1]] ; CHECK-NEXT: ret i32 [[OR1]] ; %yy = mul i32 %y, %y ; thwart complexity-based ordering %or = or i32 %yy, %z %and = and i32 %or, %x %or1 = or i32 %yy, %and ret i32 %or1 } define i32 @test45_commuted2(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @test45_commuted2( ; CHECK-NEXT: [[YY:%.*]] = mul i32 [[Y:%.*]], [[Y]] ; CHECK-NEXT: [[XX:%.*]] = mul i32 [[X:%.*]], [[X]] ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[XX]], [[Z:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[YY]], [[TMP1]] ; CHECK-NEXT: ret i32 [[OR1]] ; %yy = mul i32 %y, %y ; thwart complexity-based ordering %xx = mul i32 %x, %x ; thwart complexity-based ordering %or = or i32 %yy, %z %and = and i32 %xx, %or %or1 = or i32 %and, %yy ret i32 %or1 } define i32 @test45_commuted3(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @test45_commuted3( ; CHECK-NEXT: [[YY:%.*]] = mul i32 [[Y:%.*]], [[Y]] ; CHECK-NEXT: [[ZZ:%.*]] = mul i32 [[Z:%.*]], [[Z]] ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ZZ]], [[X:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[YY]], [[TMP1]] ; CHECK-NEXT: ret i32 [[OR1]] ; %yy = mul i32 %y, %y ; thwart complexity-based ordering %zz = mul i32 %z, %z ; thwart complexity-based ordering %or = or i32 %zz, %yy %and = and i32 %or, %x %or1 = or i32 %and, %yy ret i32 %or1 } define i1 @test46(i8 signext %c) { ; CHECK-LABEL: @test46( ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[C:%.*]], -33 ; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], -65 ; CHECK-NEXT: [[OR:%.*]] = icmp ult i8 [[TMP2]], 26 ; CHECK-NEXT: ret i1 [[OR]] ; %c.off = add i8 %c, -97 %cmp1 = icmp ult i8 %c.off, 26 %c.off17 = add i8 %c, -65 %cmp2 = icmp ult i8 %c.off17, 26 %or = or i1 %cmp1, %cmp2 ret i1 %or } define i1 @test46_logical(i8 signext %c) { ; CHECK-LABEL: @test46_logical( ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[C:%.*]], -33 ; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], -65 ; CHECK-NEXT: [[OR:%.*]] = icmp ult i8 [[TMP2]], 26 ; CHECK-NEXT: ret i1 [[OR]] ; %c.off = add i8 %c, -97 %cmp1 = icmp ult i8 %c.off, 26 %c.off17 = add i8 %c, -65 %cmp2 = icmp ult i8 %c.off17, 26 %or = select i1 %cmp1, i1 true, i1 %cmp2 ret i1 %or } define <2 x i1> @test46_uniform(<2 x i8> %c) { ; CHECK-LABEL: @test46_uniform( ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[C:%.*]], ; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[TMP1]], ; CHECK-NEXT: [[OR:%.*]] = icmp ult <2 x i8> [[TMP2]], ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %c.off = add <2 x i8> %c, %cmp1 = icmp ult <2 x i8> %c.off, %c.off17 = add <2 x i8> %c, %cmp2 = icmp ult <2 x i8> %c.off17, %or = or <2 x i1> %cmp1, %cmp2 ret <2 x i1> %or } define <2 x i1> @test46_undef(<2 x i8> %c) { ; CHECK-LABEL: @test46_undef( ; CHECK-NEXT: [[C_OFF:%.*]] = add <2 x i8> [[C:%.*]], ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i8> [[C_OFF]], ; CHECK-NEXT: [[C_OFF17:%.*]] = add <2 x i8> [[C]], ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i8> [[C_OFF17]], ; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %c.off = add <2 x i8> %c, %cmp1 = icmp ult <2 x i8> %c.off, %c.off17 = add <2 x i8> %c, %cmp2 = icmp ult <2 x i8> %c.off17, %or = or <2 x i1> %cmp1, %cmp2 ret <2 x i1> %or } ; This is the variant of the above pattern where one of the ranges is ; represented with an add. define i1 @two_ranges_to_mask_and_range_degenerate(i16 %x) { ; CHECK-LABEL: @two_ranges_to_mask_and_range_degenerate( ; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X:%.*]], -20 ; CHECK-NEXT: [[OR:%.*]] = icmp ult i16 [[TMP1]], 12 ; CHECK-NEXT: ret i1 [[OR]] ; %cmp1 = icmp ult i16 %x, 12 %cmp2 = icmp uge i16 %x, 16 %cmp3 = icmp ult i16 %x, 28 %and = and i1 %cmp2, %cmp3 %or = or i1 %cmp1, %and ret i1 %or } define i1 @test47(i8 signext %c) { ; CHECK-LABEL: @test47( ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[C:%.*]], -33 ; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], -65 ; CHECK-NEXT: [[OR:%.*]] = icmp ult i8 [[TMP2]], 27 ; CHECK-NEXT: ret i1 [[OR]] ; %c.off = add i8 %c, -65 %cmp1 = icmp ule i8 %c.off, 26 %c.off17 = add i8 %c, -97 %cmp2 = icmp ule i8 %c.off17, 26 %or = or i1 %cmp1, %cmp2 ret i1 %or } define i1 @test47_logical(i8 signext %c) { ; CHECK-LABEL: @test47_logical( ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[C:%.*]], -33 ; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], -65 ; CHECK-NEXT: [[OR:%.*]] = icmp ult i8 [[TMP2]], 27 ; CHECK-NEXT: ret i1 [[OR]] ; %c.off = add i8 %c, -65 %cmp1 = icmp ule i8 %c.off, 26 %c.off17 = add i8 %c, -97 %cmp2 = icmp ule i8 %c.off17, 26 %or = select i1 %cmp1, i1 true, i1 %cmp2 ret i1 %or } define <2 x i1> @test47_nonuniform(<2 x i8> %c) { ; CHECK-LABEL: @test47_nonuniform( ; CHECK-NEXT: [[C_OFF:%.*]] = add <2 x i8> [[C:%.*]], ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i8> [[C_OFF]], ; CHECK-NEXT: [[C_OFF17:%.*]] = add <2 x i8> [[C]], ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i8> [[C_OFF17]], ; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %c.off = add <2 x i8> %c, %cmp1 = icmp ule <2 x i8> %c.off, %c.off17 = add <2 x i8> %c, %cmp2 = icmp ule <2 x i8> %c.off17, %or = or <2 x i1> %cmp1, %cmp2 ret <2 x i1> %or } define i32 @test49(i1 %C) { ; CHECK-LABEL: @test49( ; CHECK-NEXT: [[V:%.*]] = select i1 [[C:%.*]], i32 1019, i32 123 ; CHECK-NEXT: ret i32 [[V]] ; %A = select i1 %C, i32 1000, i32 10 %V = or i32 %A, 123 ret i32 %V } define <2 x i32> @test49vec(i1 %C) { ; CHECK-LABEL: @test49vec( ; CHECK-NEXT: [[V:%.*]] = select i1 [[C:%.*]], <2 x i32> , <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[V]] ; %A = select i1 %C, <2 x i32> , <2 x i32> %V = or <2 x i32> %A, ret <2 x i32> %V } define <2 x i32> @test49vec2(i1 %C) { ; CHECK-LABEL: @test49vec2( ; CHECK-NEXT: [[V:%.*]] = select i1 [[C:%.*]], <2 x i32> , <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[V]] ; %A = select i1 %C, <2 x i32> , <2 x i32> %V = or <2 x i32> %A, ret <2 x i32> %V } define i32 @test50(i1 %which) { ; CHECK-LABEL: @test50( ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]] ; CHECK: delay: ; CHECK-NEXT: br label [[FINAL]] ; CHECK: final: ; CHECK-NEXT: [[A:%.*]] = phi i32 [ 1019, [[ENTRY:%.*]] ], [ 123, [[DELAY]] ] ; CHECK-NEXT: ret i32 [[A]] ; entry: br i1 %which, label %final, label %delay delay: br label %final final: %A = phi i32 [ 1000, %entry ], [ 10, %delay ] %value = or i32 %A, 123 ret i32 %value } define <2 x i32> @test50vec(i1 %which) { ; CHECK-LABEL: @test50vec( ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]] ; CHECK: delay: ; CHECK-NEXT: br label [[FINAL]] ; CHECK: final: ; CHECK-NEXT: [[A:%.*]] = phi <2 x i32> [ , [[ENTRY:%.*]] ], [ , [[DELAY]] ] ; CHECK-NEXT: ret <2 x i32> [[A]] ; entry: br i1 %which, label %final, label %delay delay: br label %final final: %A = phi <2 x i32> [ , %entry ], [ , %delay ] %value = or <2 x i32> %A, ret <2 x i32> %value } define <2 x i32> @test50vec2(i1 %which) { ; CHECK-LABEL: @test50vec2( ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]] ; CHECK: delay: ; CHECK-NEXT: br label [[FINAL]] ; CHECK: final: ; CHECK-NEXT: [[A:%.*]] = phi <2 x i32> [ , [[ENTRY:%.*]] ], [ , [[DELAY]] ] ; CHECK-NEXT: ret <2 x i32> [[A]] ; entry: br i1 %which, label %final, label %delay delay: br label %final final: %A = phi <2 x i32> [ , %entry ], [ , %delay ] %value = or <2 x i32> %A, ret <2 x i32> %value } ; In the next 4 tests, vary the types and predicates for extra coverage. ; (X | (Y & ~X)) -> (X | Y), where 'not' is an inverted cmp define i1 @or_andn_cmp_1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @or_andn_cmp_1( ; CHECK-NEXT: [[X:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[X]], [[Y]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp sgt i32 %a, %b %x_inv = icmp sle i32 %a, %b %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering %and = and i1 %y, %x_inv %or = or i1 %x, %and ret i1 %or } define i1 @or_andn_cmp_1_logical(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @or_andn_cmp_1_logical( ; CHECK-NEXT: [[X:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = select i1 [[X]], i1 true, i1 [[Y]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp sgt i32 %a, %b %x_inv = icmp sle i32 %a, %b %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering %and = select i1 %y, i1 %x_inv, i1 false %or = select i1 %x, i1 true, i1 %and ret i1 %or } ; Commute the 'or': ; ((Y & ~X) | X) -> (X | Y), where 'not' is an inverted cmp define <2 x i1> @or_andn_cmp_2(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) { ; CHECK-LABEL: @or_andn_cmp_2( ; CHECK-NEXT: [[X:%.*]] = icmp sge <2 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt <2 x i32> [[C:%.*]], ; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[Y]], [[X]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %x = icmp sge <2 x i32> %a, %b %x_inv = icmp slt <2 x i32> %a, %b %y = icmp ugt <2 x i32> %c, ; thwart complexity-based ordering %and = and <2 x i1> %y, %x_inv %or = or <2 x i1> %and, %x ret <2 x i1> %or } ; Commute the 'and': ; (X | (~X & Y)) -> (X | Y), where 'not' is an inverted cmp define i1 @or_andn_cmp_3(i72 %a, i72 %b, i72 %c) { ; CHECK-LABEL: @or_andn_cmp_3( ; CHECK-NEXT: [[X:%.*]] = icmp ugt i72 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i72 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[X]], [[Y]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp ugt i72 %a, %b %x_inv = icmp ule i72 %a, %b %y = icmp ugt i72 %c, 42 ; thwart complexity-based ordering %and = and i1 %x_inv, %y %or = or i1 %x, %and ret i1 %or } define i1 @or_andn_cmp_3_logical(i72 %a, i72 %b, i72 %c) { ; CHECK-LABEL: @or_andn_cmp_3_logical( ; CHECK-NEXT: [[X:%.*]] = icmp ugt i72 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i72 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = select i1 [[X]], i1 true, i1 [[Y]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp ugt i72 %a, %b %x_inv = icmp ule i72 %a, %b %y = icmp ugt i72 %c, 42 ; thwart complexity-based ordering %and = select i1 %x_inv, i1 %y, i1 false %or = select i1 %x, i1 true, i1 %and ret i1 %or } ; Commute the 'or': ; ((~X & Y) | X) -> (X | Y), where 'not' is an inverted cmp define <3 x i1> @or_andn_cmp_4(<3 x i32> %a, <3 x i32> %b, <3 x i32> %c) { ; CHECK-LABEL: @or_andn_cmp_4( ; CHECK-NEXT: [[X:%.*]] = icmp eq <3 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt <3 x i32> [[C:%.*]], ; CHECK-NEXT: [[OR:%.*]] = or <3 x i1> [[Y]], [[X]] ; CHECK-NEXT: ret <3 x i1> [[OR]] ; %x = icmp eq <3 x i32> %a, %b %x_inv = icmp ne <3 x i32> %a, %b %y = icmp ugt <3 x i32> %c, ; thwart complexity-based ordering %and = and <3 x i1> %x_inv, %y %or = or <3 x i1> %and, %x ret <3 x i1> %or } ; In the next 4 tests, vary the types and predicates for extra coverage. ; (~X | (Y & X)) -> (~X | Y), where 'not' is an inverted cmp define i1 @orn_and_cmp_1(i37 %a, i37 %b, i37 %c) { ; CHECK-LABEL: @orn_and_cmp_1( ; CHECK-NEXT: [[X_INV:%.*]] = icmp sle i37 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i37 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[X_INV]], [[Y]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp sgt i37 %a, %b %x_inv = icmp sle i37 %a, %b %y = icmp ugt i37 %c, 42 ; thwart complexity-based ordering %and = and i1 %y, %x %or = or i1 %x_inv, %and ret i1 %or } define i1 @orn_and_cmp_1_logical(i37 %a, i37 %b, i37 %c) { ; CHECK-LABEL: @orn_and_cmp_1_logical( ; CHECK-NEXT: [[X_INV:%.*]] = icmp sle i37 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i37 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = select i1 [[X_INV]], i1 true, i1 [[Y]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp sgt i37 %a, %b %x_inv = icmp sle i37 %a, %b %y = icmp ugt i37 %c, 42 ; thwart complexity-based ordering %and = select i1 %y, i1 %x, i1 false %or = select i1 %x_inv, i1 true, i1 %and ret i1 %or } ; Commute the 'or': ; ((Y & X) | ~X) -> (~X | Y), where 'not' is an inverted cmp define i1 @orn_and_cmp_2(i16 %a, i16 %b, i16 %c) { ; CHECK-LABEL: @orn_and_cmp_2( ; CHECK-NEXT: [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i16 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[Y]], [[X_INV]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp sge i16 %a, %b %x_inv = icmp slt i16 %a, %b %y = icmp ugt i16 %c, 42 ; thwart complexity-based ordering %and = and i1 %y, %x %or = or i1 %and, %x_inv ret i1 %or } define i1 @orn_and_cmp_2_logical(i16 %a, i16 %b, i16 %c) { ; CHECK-LABEL: @orn_and_cmp_2_logical( ; CHECK-NEXT: [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i16 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = select i1 [[Y]], i1 true, i1 [[X_INV]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp sge i16 %a, %b %x_inv = icmp slt i16 %a, %b %y = icmp ugt i16 %c, 42 ; thwart complexity-based ordering %and = select i1 %y, i1 %x, i1 false %or = select i1 %and, i1 true, i1 %x_inv ret i1 %or } ; Commute the 'and': ; (~X | (X & Y)) -> (~X | Y), where 'not' is an inverted cmp define <4 x i1> @orn_and_cmp_3(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) { ; CHECK-LABEL: @orn_and_cmp_3( ; CHECK-NEXT: [[X_INV:%.*]] = icmp ule <4 x i32> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt <4 x i32> [[C:%.*]], ; CHECK-NEXT: [[OR:%.*]] = or <4 x i1> [[X_INV]], [[Y]] ; CHECK-NEXT: ret <4 x i1> [[OR]] ; %x = icmp ugt <4 x i32> %a, %b %x_inv = icmp ule <4 x i32> %a, %b %y = icmp ugt <4 x i32> %c, ; thwart complexity-based ordering %and = and <4 x i1> %x, %y %or = or <4 x i1> %x_inv, %and ret <4 x i1> %or } ; Commute the 'or': ; ((X & Y) | ~X) -> (~X | Y), where 'not' is an inverted cmp define i1 @orn_and_cmp_4(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @orn_and_cmp_4( ; CHECK-NEXT: [[X_INV:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[Y]], [[X_INV]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp eq i32 %a, %b %x_inv = icmp ne i32 %a, %b %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering %and = and i1 %x, %y %or = or i1 %and, %x_inv ret i1 %or } define i1 @orn_and_cmp_4_logical(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @orn_and_cmp_4_logical( ; CHECK-NEXT: [[X_INV:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42 ; CHECK-NEXT: [[OR:%.*]] = select i1 [[X_INV]], i1 true, i1 [[Y]] ; CHECK-NEXT: ret i1 [[OR]] ; %x = icmp eq i32 %a, %b %x_inv = icmp ne i32 %a, %b %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering %and = select i1 %x, i1 %y, i1 false %or = select i1 %and, i1 true, i1 %x_inv ret i1 %or } ; The constant vectors are inverses. Make sure we can turn this into a select without crashing trying to truncate the constant to 16xi1. define <16 x i1> @test51(<16 x i1> %arg, <16 x i1> %arg1) { ; CHECK-LABEL: @test51( ; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <16 x i1> [[ARG:%.*]], <16 x i1> [[ARG1:%.*]], <16 x i32> ; CHECK-NEXT: ret <16 x i1> [[TMP3]] ; %tmp = and <16 x i1> %arg, %tmp2 = and <16 x i1> %arg1, %tmp3 = or <16 x i1> %tmp, %tmp2 ret <16 x i1> %tmp3 } ; This would infinite loop because it reaches a transform ; that was not expecting a constant-foldable value. define i32 @PR46712(i1 %x, i1 %y, i1 %b, i64 %z) { ; CHECK-LABEL: @PR46712( ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[B:%.*]], label [[TRUE:%.*]], label [[END:%.*]] ; CHECK: true: ; CHECK-NEXT: [[BOOL5_NOT:%.*]] = icmp eq i64 [[Z:%.*]], 0 ; CHECK-NEXT: [[TMP0:%.*]] = zext i1 [[BOOL5_NOT]] to i32 ; CHECK-NEXT: br label [[END]] ; CHECK: end: ; CHECK-NEXT: [[T5:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP0]], [[TRUE]] ] ; CHECK-NEXT: ret i32 [[T5]] ; entry: %t2 = or i1 %x, %y %conv = sext i1 %t2 to i32 %cmp = icmp sge i32 %conv, 1 %conv2 = zext i1 %cmp to i64 br i1 %b, label %true, label %end true: %bool4 = icmp eq i64 %conv2, 0 %bool5 = icmp ne i64 %z, 0 %and = and i1 %bool4, %bool5 %sel = select i1 %and, i1 false, i1 true br label %end end: %t5 = phi i1 [ 0, %entry ], [ %sel, %true ] %conv8 = zext i1 %t5 to i32 ret i32 %conv8 } define i32 @PR46712_logical(i1 %x, i1 %y, i1 %b, i64 %z) { ; CHECK-LABEL: @PR46712_logical( ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[B:%.*]], label [[TRUE:%.*]], label [[END:%.*]] ; CHECK: true: ; CHECK-NEXT: [[BOOL5_NOT:%.*]] = icmp eq i64 [[Z:%.*]], 0 ; CHECK-NEXT: [[TMP0:%.*]] = zext i1 [[BOOL5_NOT]] to i32 ; CHECK-NEXT: br label [[END]] ; CHECK: end: ; CHECK-NEXT: [[T5:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP0]], [[TRUE]] ] ; CHECK-NEXT: ret i32 [[T5]] ; entry: %t2 = select i1 %x, i1 true, i1 %y %conv = sext i1 %t2 to i32 %cmp = icmp sge i32 %conv, 1 %conv2 = zext i1 %cmp to i64 br i1 %b, label %true, label %end true: %bool4 = icmp eq i64 %conv2, 0 %bool5 = icmp ne i64 %z, 0 %and = select i1 %bool4, i1 %bool5, i1 false %sel = select i1 %and, i1 false, i1 true br label %end end: %t5 = phi i1 [ 0, %entry ], [ %sel, %true ] %conv8 = zext i1 %t5 to i32 ret i32 %conv8 } ; (~x & y) | ~(x | y) --> ~x define i32 @PR38929(i32 %0, i32 %1) { ; CHECK-LABEL: @PR38929( ; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP0:%.*]], -1 ; CHECK-NEXT: ret i32 [[TMP3]] ; %3 = xor i32 %0, -1 %4 = and i32 %3, %1 %5 = or i32 %1, %0 %6 = xor i32 %5, -1 %7 = or i32 %4, %6 ret i32 %7 } define i32 @test1(i32 %x, i32 %y) { ; CHECK-LABEL: @test1( ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR1]] ; %xor = xor i32 %y, %x %or = or i32 %y, %x %neg = xor i32 %or, -1 %or1 = or i32 %xor, %neg ret i32 %or1 } define i32 @test2(i32 %x, i32 %y) { ; CHECK-LABEL: @test2( ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR1]] ; %or = or i32 %x, %y %neg = xor i32 %or, -1 %xor = xor i32 %y, %x %or1 = or i32 %xor, %neg ret i32 %or1 } define i32 @test3(i32 %x, i32 %y) { ; CHECK-LABEL: @test3( ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR1]] ; %or = or i32 %y, %x %neg = xor i32 %or, -1 %xor = xor i32 %x, %y %or1 = or i32 %xor, %neg ret i32 %or1 } define <2 x i32> @test4_vec(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @test4_vec( ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = xor <2 x i32> [[TMP1]], ; CHECK-NEXT: ret <2 x i32> [[OR1]] ; %or = or <2 x i32> %y, %x %neg = xor <2 x i32> %or, %xor = xor <2 x i32> %y, %x %or1 = or <2 x i32> %xor, %neg ret <2 x i32> %or1 } define i32 @test5_use(i32 %x, i32 %y) { ; CHECK-LABEL: @test5_use( ; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[OR]], -1 ; CHECK-NEXT: call void @use(i32 [[NEG]]) ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y]], [[X]] ; CHECK-NEXT: [[OR1:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR1]] ; %or = or i32 %y, %x %neg = xor i32 %or, -1 %xor = xor i32 %y, %x call void @use(i32 %neg) %or1 = or i32 %xor, %neg ret i32 %or1 } define i32 @test5_use2(i32 %x, i32 %y) { ; CHECK-LABEL: @test5_use2( ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: call void @use(i32 [[XOR]]) ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y]], [[X]] ; CHECK-NEXT: [[OR1:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR1]] ; %or = or i32 %y, %x %neg = xor i32 %or, -1 %xor = xor i32 %y, %x call void @use(i32 %xor) %or1 = or i32 %xor, %neg ret i32 %or1 } define i32 @test5_use3(i32 %x, i32 %y) { ; CHECK-LABEL: @test5_use3( ; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[OR]], -1 ; CHECK-NEXT: call void @use(i32 [[NEG]]) ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]] ; CHECK-NEXT: call void @use(i32 [[XOR]]) ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[XOR]], [[NEG]] ; CHECK-NEXT: ret i32 [[OR1]] ; %or = or i32 %y, %x %neg = xor i32 %or, -1 call void @use(i32 %neg) %xor = xor i32 %y, %x call void @use(i32 %xor) %or1 = or i32 %xor, %neg ret i32 %or1 } define i8 @ashr_bitwidth_mask(i8 %x, i8 %y) { ; CHECK-LABEL: @ashr_bitwidth_mask( ; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 7 ; CHECK-NEXT: [[R:%.*]] = or i8 [[SIGN]], [[Y:%.*]] ; CHECK-NEXT: ret i8 [[R]] ; %sign = ashr i8 %x, 7 %r = or i8 %sign, %y ret i8 %r } define <2 x i8> @ashr_bitwidth_mask_vec_commute(<2 x i8> %x, <2 x i8> %py) { ; CHECK-LABEL: @ashr_bitwidth_mask_vec_commute( ; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], ; CHECK-NEXT: [[SIGN:%.*]] = ashr <2 x i8> [[X:%.*]], ; CHECK-NEXT: [[R:%.*]] = or <2 x i8> [[Y]], [[SIGN]] ; CHECK-NEXT: ret <2 x i8> [[R]] ; %y = mul <2 x i8> %py, ; thwart complexity-based ordering %sign = ashr <2 x i8> %x, %r = or <2 x i8> %y, %sign ret <2 x i8> %r } define i32 @ashr_bitwidth_mask_use(i32 %x, i32 %y) { ; CHECK-LABEL: @ashr_bitwidth_mask_use( ; CHECK-NEXT: [[SIGN:%.*]] = ashr i32 [[X:%.*]], 7 ; CHECK-NEXT: call void @use(i32 [[SIGN]]) ; CHECK-NEXT: [[R:%.*]] = or i32 [[SIGN]], [[Y:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %sign = ashr i32 %x, 7 call void @use(i32 %sign) %r = or i32 %sign, %y ret i32 %r } define i8 @ashr_not_bitwidth_mask(i8 %x, i8 %y) { ; CHECK-LABEL: @ashr_not_bitwidth_mask( ; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 6 ; CHECK-NEXT: [[R:%.*]] = or i8 [[SIGN]], [[Y:%.*]] ; CHECK-NEXT: ret i8 [[R]] ; %sign = ashr i8 %x, 6 %r = or i8 %sign, %y ret i8 %r } define i8 @lshr_bitwidth_mask(i8 %x, i8 %y) { ; CHECK-LABEL: @lshr_bitwidth_mask( ; CHECK-NEXT: [[SIGN:%.*]] = lshr i8 [[X:%.*]], 7 ; CHECK-NEXT: [[R:%.*]] = or i8 [[SIGN]], [[Y:%.*]] ; CHECK-NEXT: ret i8 [[R]] ; %sign = lshr i8 %x, 7 %r = or i8 %sign, %y ret i8 %r } define i1 @cmp_overlap(i32 %x) { ; CHECK-LABEL: @cmp_overlap( ; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[X:%.*]], 1 ; CHECK-NEXT: ret i1 [[R]] ; %isneg = icmp slt i32 %x, 0 %negx = sub i32 0, %x %isnotneg = icmp sgt i32 %negx, -1 %r = or i1 %isneg, %isnotneg ret i1 %r } define <2 x i1> @cmp_overlap_splat(<2 x i5> %x) { ; CHECK-LABEL: @cmp_overlap_splat( ; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i5> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[R]] ; %isneg = icmp slt <2 x i5> %x, zeroinitializer %negx = sub <2 x i5> zeroinitializer, %x %isnotneg = icmp sgt <2 x i5> %negx, %r = or <2 x i1> %isneg, %isnotneg ret <2 x i1> %r } define i32 @mul_no_common_bits(i32 %p1, i32 %p2) { ; CHECK-LABEL: @mul_no_common_bits( ; CHECK-NEXT: [[X:%.*]] = and i32 [[P1:%.*]], 7 ; CHECK-NEXT: [[Y:%.*]] = shl i32 [[P2:%.*]], 3 ; CHECK-NEXT: [[TMP1:%.*]] = or disjoint i32 [[Y]], 1 ; CHECK-NEXT: [[R:%.*]] = mul i32 [[X]], [[TMP1]] ; CHECK-NEXT: ret i32 [[R]] ; %x = and i32 %p1, 7 %y = shl i32 %p2, 3 %m = mul i32 %x, %y %r = or i32 %m, %x ret i32 %r } define i32 @mul_no_common_bits_const_op(i32 %p) { ; CHECK-LABEL: @mul_no_common_bits_const_op( ; CHECK-NEXT: [[X:%.*]] = and i32 [[P:%.*]], 7 ; CHECK-NEXT: [[R:%.*]] = mul nuw nsw i32 [[X]], 25 ; CHECK-NEXT: ret i32 [[R]] ; %x = and i32 %p, 7 %m = mul i32 %x, 24 %r = or i32 %m, %x ret i32 %r } define <2 x i12> @mul_no_common_bits_commute(<2 x i12> %p) { ; CHECK-LABEL: @mul_no_common_bits_commute( ; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i12> [[P:%.*]] to <2 x i1> ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP1]], <2 x i12> , <2 x i12> zeroinitializer ; CHECK-NEXT: ret <2 x i12> [[R]] ; %x = and <2 x i12> %p, %m = mul <2 x i12> %x, %r = or <2 x i12> %x, %m ret <2 x i12> %r } define i32 @mul_no_common_bits_commute2(i32 %p1, i32 %p2) { ; CHECK-LABEL: @mul_no_common_bits_commute2( ; CHECK-NEXT: [[X:%.*]] = and i32 [[P1:%.*]], 7 ; CHECK-NEXT: [[Y:%.*]] = shl i32 [[P2:%.*]], 3 ; CHECK-NEXT: [[M:%.*]] = mul i32 [[Y]], [[X]] ; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[M]], [[X]] ; CHECK-NEXT: ret i32 [[R]] ; %x = and i32 %p1, 7 %y = shl i32 %p2, 3 %m = mul i32 %y, %x %r = or i32 %m, %x ret i32 %r } define i32 @mul_no_common_bits_disjoint(i32 %x, i32 %y) { ; CHECK-LABEL: @mul_no_common_bits_disjoint( ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[Y:%.*]], 1 ; CHECK-NEXT: [[R:%.*]] = mul i32 [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %m = mul i32 %x, %y %r = or disjoint i32 %m, %x ret i32 %r } define i32 @mul_no_common_bits_const_op_disjoint(i32 %x, i32 %y) { ; CHECK-LABEL: @mul_no_common_bits_const_op_disjoint( ; CHECK-NEXT: [[R:%.*]] = mul i32 [[X:%.*]], 25 ; CHECK-NEXT: ret i32 [[R]] ; %m = mul i32 %x, 24 %r = or disjoint i32 %m, %x ret i32 %r } ; negative test - extra use requires extra instructions define i32 @mul_no_common_bits_uses(i32 %p1, i32 %p2) { ; CHECK-LABEL: @mul_no_common_bits_uses( ; CHECK-NEXT: [[X:%.*]] = and i32 [[P1:%.*]], 7 ; CHECK-NEXT: [[Y:%.*]] = shl i32 [[P2:%.*]], 3 ; CHECK-NEXT: [[M:%.*]] = mul i32 [[X]], [[Y]] ; CHECK-NEXT: call void @use(i32 [[M]]) ; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[M]], [[X]] ; CHECK-NEXT: ret i32 [[R]] ; %x = and i32 %p1, 7 %y = shl i32 %p2, 3 %m = mul i32 %x, %y call void @use(i32 %m) %r = or i32 %m, %x ret i32 %r } ; negative test - probably not good to create an extra mul define i32 @mul_no_common_bits_const_op_uses(i32 %p) { ; CHECK-LABEL: @mul_no_common_bits_const_op_uses( ; CHECK-NEXT: [[X:%.*]] = and i32 [[P:%.*]], 7 ; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[X]], 24 ; CHECK-NEXT: call void @use(i32 [[M]]) ; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[M]], [[X]] ; CHECK-NEXT: ret i32 [[R]] ; %x = and i32 %p, 7 %m = mul i32 %x, 24 call void @use(i32 %m) %r = or i32 %m, %x ret i32 %r } ; negative test - %x and %m may have set 3rd bit define i32 @mul_common_bits(i32 %p) { ; CHECK-LABEL: @mul_common_bits( ; CHECK-NEXT: [[X:%.*]] = and i32 [[P:%.*]], 7 ; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[X]], 12 ; CHECK-NEXT: [[R:%.*]] = or i32 [[M]], [[X]] ; CHECK-NEXT: ret i32 [[R]] ; %x = and i32 %p, 7 %m = mul i32 %x, 12 %r = or i32 %m, %x ret i32 %r } define <4 x i1> @and_or_not_or_logical_vec(<4 x i32> %ap, <4 x i32> %bp) { ; CHECK-LABEL: @and_or_not_or_logical_vec( ; CHECK-NEXT: [[A:%.*]] = icmp ne <4 x i32> [[AP:%.*]], zeroinitializer ; CHECK-NEXT: ret <4 x i1> [[A]] ; %A = icmp eq <4 x i32> %ap, zeroinitializer %B = icmp eq <4 x i32> %bp, zeroinitializer %V = xor <4 x i1> %A, %X = select <4 x i1> %B, <4 x i1> %V, <4 x i1> zeroinitializer %W = or <4 x i1> %B, %A %Y = xor <4 x i1> %W, %Z = or <4 x i1> %X, %Y ret <4 x i1> %Z } ; Make sure SimplifyDemandedBits drops the disjoint flag. define i8 @drop_disjoint(i8 %x) { ; CHECK-LABEL: @drop_disjoint( ; CHECK-NEXT: [[B:%.*]] = or i8 [[X:%.*]], 1 ; CHECK-NEXT: ret i8 [[B]] ; %a = and i8 %x, -2 %b = or disjoint i8 %a, 1 ret i8 %b } ; Make sure we drop disjoint when combining the Ors. define i32 @assoc_cast_assoc_disjoint(i16 %x) { ; CHECK-LABEL: @assoc_cast_assoc_disjoint( ; CHECK-NEXT: [[B:%.*]] = zext i16 [[X:%.*]] to i32 ; CHECK-NEXT: [[C:%.*]] = or i32 [[B]], 65537 ; CHECK-NEXT: ret i32 [[C]] ; %a = or i16 %x, 1 %b = zext i16 %a to i32 %c = or disjoint i32 %b, 65536 ret i32 %c } ; (X & C1) | C2 -> X & (C1 | C2) iff (X & C2) == C2 define i32 @test_or_and_disjoint(i32 %a) { ; CHECK-LABEL: @test_or_and_disjoint( ; CHECK-NEXT: [[A0:%.*]] = and i32 [[A:%.*]], 24 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A0]], 8 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[A2:%.*]] = and i32 [[A]], 15 ; CHECK-NEXT: ret i32 [[A2]] ; CHECK: if.else: ; CHECK-NEXT: ret i32 0 ; %a0 = and i32 %a, 24 %cmp = icmp eq i32 %a0, 8 br i1 %cmp, label %if.then, label %if.else if.then: %a1 = and i32 %a, 7 %a2 = or i32 %a1, 8 ret i32 %a2 if.else: ret i32 0 } define i32 @test_or_and_mixed(i32 %a) { ; CHECK-LABEL: @test_or_and_mixed( ; CHECK-NEXT: [[A0:%.*]] = and i32 [[A:%.*]], 27 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A0]], 11 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[A2:%.*]] = and i32 [[A]], 15 ; CHECK-NEXT: ret i32 [[A2]] ; CHECK: if.else: ; CHECK-NEXT: ret i32 0 ; %a0 = and i32 %a, 27 %cmp = icmp eq i32 %a0, 11 br i1 %cmp, label %if.then, label %if.else if.then: %a1 = and i32 %a, 7 %a2 = or i32 %a1, 11 ret i32 %a2 if.else: ret i32 0 } ; Negative tests define i32 @test_or_and_disjoint_fail(i32 %a) { ; CHECK-LABEL: @test_or_and_disjoint_fail( ; CHECK-NEXT: [[A0:%.*]] = and i32 [[A:%.*]], 24 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A0]], 16 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[A1:%.*]] = and i32 [[A]], 7 ; CHECK-NEXT: [[A2:%.*]] = or disjoint i32 [[A1]], 8 ; CHECK-NEXT: ret i32 [[A2]] ; CHECK: if.else: ; CHECK-NEXT: ret i32 0 ; %a0 = and i32 %a, 24 %cmp = icmp eq i32 %a0, 16 br i1 %cmp, label %if.then, label %if.else if.then: %a1 = and i32 %a, 7 %a2 = or i32 %a1, 8 ret i32 %a2 if.else: ret i32 0 } define i32 @test_or_and_disjoint_multiuse(i32 %a) { ; CHECK-LABEL: @test_or_and_disjoint_multiuse( ; CHECK-NEXT: [[A0:%.*]] = and i32 [[A:%.*]], 24 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A0]], 8 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[A1:%.*]] = and i32 [[A]], 7 ; CHECK-NEXT: call void @use(i32 [[A1]]) ; CHECK-NEXT: [[A2:%.*]] = or disjoint i32 [[A1]], 8 ; CHECK-NEXT: ret i32 [[A2]] ; CHECK: if.else: ; CHECK-NEXT: ret i32 0 ; %a0 = and i32 %a, 24 %cmp = icmp eq i32 %a0, 8 br i1 %cmp, label %if.then, label %if.else if.then: %a1 = and i32 %a, 7 call void @use(i32 %a1) %a2 = or i32 %a1, 8 ret i32 %a2 if.else: ret i32 0 }