1; RUN: opt < %s -instsimplify -S | FileCheck %s 2 3; In the next 16 tests (4 commutes * 2 (and/or) * 2 optional ptrtoint casts), 4; eliminate the simple (not) null check because that compare is implied by the 5; masked compare of the same operand. 6; Vary types between scalar and vector and weird for extra coverage. 7 8; or (icmp eq (and X, ?), 0), (icmp eq X, 0) --> icmp eq (and X, ?), 0 9 10define i1 @or_cmps_eq_zero_with_mask_commute1(i64 %x, i64 %y) { 11; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute1( 12; CHECK-NEXT: [[SOMEBITS:%.*]] = and i64 %x, %y 13; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i64 [[SOMEBITS]], 0 14; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_ZERO]] 15; 16 %isnull = icmp eq i64 %x, 0 17 %somebits = and i64 %x, %y 18 %somebits_are_zero = icmp eq i64 %somebits, 0 19 %r = or i1 %somebits_are_zero, %isnull 20 ret i1 %r 21} 22 23; or (icmp eq X, 0), (icmp eq (and X, ?), 0) --> icmp eq (and X, ?), 0 24 25define <2 x i1> @or_cmps_eq_zero_with_mask_commute2(<2 x i64> %x, <2 x i64> %y) { 26; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute2( 27; CHECK-NEXT: [[SOMEBITS:%.*]] = and <2 x i64> %x, %y 28; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i64> [[SOMEBITS]], zeroinitializer 29; CHECK-NEXT: ret <2 x i1> [[SOMEBITS_ARE_ZERO]] 30; 31 %isnull = icmp eq <2 x i64> %x, zeroinitializer 32 %somebits = and <2 x i64> %x, %y 33 %somebits_are_zero = icmp eq <2 x i64> %somebits, zeroinitializer 34 %r = or <2 x i1> %isnull, %somebits_are_zero 35 ret <2 x i1> %r 36} 37 38; or (icmp eq (and ?, X), 0), (icmp eq X, 0) --> icmp eq (and ?, X), 0 39 40define i1 @or_cmps_eq_zero_with_mask_commute3(i4 %x, i4 %y) { 41; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute3( 42; CHECK-NEXT: [[SOMEBITS:%.*]] = and i4 %y, %x 43; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i4 [[SOMEBITS]], 0 44; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_ZERO]] 45; 46 %isnull = icmp eq i4 %x, 0 47 %somebits = and i4 %y, %x 48 %somebits_are_zero = icmp eq i4 %somebits, 0 49 %r = or i1 %somebits_are_zero, %isnull 50 ret i1 %r 51} 52 53; or (icmp eq X, 0), (icmp eq (and ?, X), 0) --> icmp eq (and ?, X), 0 54 55define <2 x i1> @or_cmps_eq_zero_with_mask_commute4(<2 x i4> %x, <2 x i4> %y) { 56; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute4( 57; CHECK-NEXT: [[SOMEBITS:%.*]] = and <2 x i4> %y, %x 58; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i4> [[SOMEBITS]], zeroinitializer 59; CHECK-NEXT: ret <2 x i1> [[SOMEBITS_ARE_ZERO]] 60; 61 %isnull = icmp eq <2 x i4> %x, zeroinitializer 62 %somebits = and <2 x i4> %y, %x 63 %somebits_are_zero = icmp eq <2 x i4> %somebits, zeroinitializer 64 %r = or <2 x i1> %isnull, %somebits_are_zero 65 ret <2 x i1> %r 66} 67 68; and (icmp ne (and X, ?), 0), (icmp ne X, 0) --> icmp ne (and X, ?), 0 69 70define <3 x i1> @and_cmps_eq_zero_with_mask_commute1(<3 x i4> %x, <3 x i4> %y) { 71; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute1( 72; CHECK-NEXT: [[SOMEBITS:%.*]] = and <3 x i4> %x, %y 73; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i4> [[SOMEBITS]], zeroinitializer 74; CHECK-NEXT: ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]] 75; 76 %isnotnull = icmp ne <3 x i4> %x, zeroinitializer 77 %somebits = and <3 x i4> %x, %y 78 %somebits_are_not_zero = icmp ne <3 x i4> %somebits, zeroinitializer 79 %r = and <3 x i1> %somebits_are_not_zero, %isnotnull 80 ret <3 x i1> %r 81} 82 83; and (icmp ne X, 0), (icmp ne (and X, ?), 0) --> icmp ne (and X, ?), 0 84 85define i1 @and_cmps_eq_zero_with_mask_commute2(i4 %x, i4 %y) { 86; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute2( 87; CHECK-NEXT: [[SOMEBITS:%.*]] = and i4 %x, %y 88; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i4 [[SOMEBITS]], 0 89; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_NOT_ZERO]] 90; 91 %isnotnull = icmp ne i4 %x, 0 92 %somebits = and i4 %x, %y 93 %somebits_are_not_zero = icmp ne i4 %somebits, 0 94 %r = and i1 %isnotnull, %somebits_are_not_zero 95 ret i1 %r 96} 97 98; and (icmp ne (and ?, X), 0), (icmp ne X, 0) --> icmp ne (and ?, X), 0 99 100define <3 x i1> @and_cmps_eq_zero_with_mask_commute3(<3 x i64> %x, <3 x i64> %y) { 101; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute3( 102; CHECK-NEXT: [[SOMEBITS:%.*]] = and <3 x i64> %y, %x 103; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i64> [[SOMEBITS]], zeroinitializer 104; CHECK-NEXT: ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]] 105; 106 %isnotnull = icmp ne <3 x i64> %x, zeroinitializer 107 %somebits = and <3 x i64> %y, %x 108 %somebits_are_not_zero = icmp ne <3 x i64> %somebits, zeroinitializer 109 %r = and <3 x i1> %somebits_are_not_zero, %isnotnull 110 ret <3 x i1> %r 111} 112 113; and (icmp ne X, 0), (icmp ne (and ?, X), 0) --> icmp ne (and ?, X), 0 114 115define i1 @and_cmps_eq_zero_with_mask_commute4(i64 %x, i64 %y) { 116; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute4( 117; CHECK-NEXT: [[SOMEBITS:%.*]] = and i64 %y, %x 118; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i64 [[SOMEBITS]], 0 119; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_NOT_ZERO]] 120; 121 %isnotnull = icmp ne i64 %x, 0 122 %somebits = and i64 %y, %x 123 %somebits_are_not_zero = icmp ne i64 %somebits, 0 124 %r = and i1 %isnotnull, %somebits_are_not_zero 125 ret i1 %r 126} 127 128; or (icmp eq (and (ptrtoint P), ?), 0), (icmp eq P, 0) --> icmp eq (and (ptrtoint P), ?), 0 129 130define i1 @or_cmps_ptr_eq_zero_with_mask_commute1(i64* %p, i64 %y) { 131; CHECK-LABEL: @or_cmps_ptr_eq_zero_with_mask_commute1( 132; CHECK-NEXT: [[X:%.*]] = ptrtoint i64* %p to i64 133; CHECK-NEXT: [[SOMEBITS:%.*]] = and i64 [[X]], %y 134; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i64 [[SOMEBITS]], 0 135; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_ZERO]] 136; 137 %isnull = icmp eq i64* %p, null 138 %x = ptrtoint i64* %p to i64 139 %somebits = and i64 %x, %y 140 %somebits_are_zero = icmp eq i64 %somebits, 0 141 %r = or i1 %somebits_are_zero, %isnull 142 ret i1 %r 143} 144 145; or (icmp eq P, 0), (icmp eq (and (ptrtoint P), ?), 0) --> icmp eq (and (ptrtoint P), ?), 0 146 147define <2 x i1> @or_cmps_ptr_eq_zero_with_mask_commute2(<2 x i64*> %p, <2 x i64> %y) { 148; CHECK-LABEL: @or_cmps_ptr_eq_zero_with_mask_commute2( 149; CHECK-NEXT: [[X:%.*]] = ptrtoint <2 x i64*> %p to <2 x i64> 150; CHECK-NEXT: [[SOMEBITS:%.*]] = and <2 x i64> [[X]], %y 151; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i64> [[SOMEBITS]], zeroinitializer 152; CHECK-NEXT: ret <2 x i1> [[SOMEBITS_ARE_ZERO]] 153; 154 %isnull = icmp eq <2 x i64*> %p, zeroinitializer 155 %x = ptrtoint <2 x i64*> %p to <2 x i64> 156 %somebits = and <2 x i64> %x, %y 157 %somebits_are_zero = icmp eq <2 x i64> %somebits, zeroinitializer 158 %r = or <2 x i1> %isnull, %somebits_are_zero 159 ret <2 x i1> %r 160} 161 162; or (icmp eq (and ?, (ptrtoint P)), 0), (icmp eq P, 0) --> icmp eq (and ?, (ptrtoint P)), 0 163 164define i1 @or_cmps_ptr_eq_zero_with_mask_commute3(i4* %p, i4 %y) { 165; CHECK-LABEL: @or_cmps_ptr_eq_zero_with_mask_commute3( 166; CHECK-NEXT: [[X:%.*]] = ptrtoint i4* %p to i4 167; CHECK-NEXT: [[SOMEBITS:%.*]] = and i4 %y, [[X]] 168; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i4 [[SOMEBITS]], 0 169; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_ZERO]] 170; 171 %isnull = icmp eq i4* %p, null 172 %x = ptrtoint i4* %p to i4 173 %somebits = and i4 %y, %x 174 %somebits_are_zero = icmp eq i4 %somebits, 0 175 %r = or i1 %somebits_are_zero, %isnull 176 ret i1 %r 177} 178 179; or (icmp eq P, 0), (icmp eq (and ?, (ptrtoint P)), 0) --> icmp eq (and ?, (ptrtoint P)), 0 180 181define <2 x i1> @or_cmps_ptr_eq_zero_with_mask_commute4(<2 x i4*> %p, <2 x i4> %y) { 182; CHECK-LABEL: @or_cmps_ptr_eq_zero_with_mask_commute4( 183; CHECK-NEXT: [[X:%.*]] = ptrtoint <2 x i4*> %p to <2 x i4> 184; CHECK-NEXT: [[SOMEBITS:%.*]] = and <2 x i4> %y, [[X]] 185; CHECK-NEXT: [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i4> [[SOMEBITS]], zeroinitializer 186; CHECK-NEXT: ret <2 x i1> [[SOMEBITS_ARE_ZERO]] 187; 188 %isnull = icmp eq <2 x i4*> %p, zeroinitializer 189 %x = ptrtoint <2 x i4*> %p to <2 x i4> 190 %somebits = and <2 x i4> %y, %x 191 %somebits_are_zero = icmp eq <2 x i4> %somebits, zeroinitializer 192 %r = or <2 x i1> %isnull, %somebits_are_zero 193 ret <2 x i1> %r 194} 195 196; and (icmp ne (and (ptrtoint P), ?), 0), (icmp ne P, 0) --> icmp ne (and (ptrtoint P), ?), 0 197 198define <3 x i1> @and_cmps_ptr_eq_zero_with_mask_commute1(<3 x i4*> %p, <3 x i4> %y) { 199; CHECK-LABEL: @and_cmps_ptr_eq_zero_with_mask_commute1( 200; CHECK-NEXT: [[X:%.*]] = ptrtoint <3 x i4*> %p to <3 x i4> 201; CHECK-NEXT: [[SOMEBITS:%.*]] = and <3 x i4> [[X]], %y 202; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i4> [[SOMEBITS]], zeroinitializer 203; CHECK-NEXT: ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]] 204; 205 %isnotnull = icmp ne <3 x i4*> %p, zeroinitializer 206 %x = ptrtoint <3 x i4*> %p to <3 x i4> 207 %somebits = and <3 x i4> %x, %y 208 %somebits_are_not_zero = icmp ne <3 x i4> %somebits, zeroinitializer 209 %r = and <3 x i1> %somebits_are_not_zero, %isnotnull 210 ret <3 x i1> %r 211} 212 213; and (icmp ne P, 0), (icmp ne (and (ptrtoint P), ?), 0) --> icmp ne (and (ptrtoint P), ?), 0 214 215define i1 @and_cmps_ptr_eq_zero_with_mask_commute2(i4* %p, i4 %y) { 216; CHECK-LABEL: @and_cmps_ptr_eq_zero_with_mask_commute2( 217; CHECK-NEXT: [[X:%.*]] = ptrtoint i4* %p to i4 218; CHECK-NEXT: [[SOMEBITS:%.*]] = and i4 [[X]], %y 219; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i4 [[SOMEBITS]], 0 220; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_NOT_ZERO]] 221; 222 %isnotnull = icmp ne i4* %p, null 223 %x = ptrtoint i4* %p to i4 224 %somebits = and i4 %x, %y 225 %somebits_are_not_zero = icmp ne i4 %somebits, 0 226 %r = and i1 %isnotnull, %somebits_are_not_zero 227 ret i1 %r 228} 229 230; and (icmp ne (and ?, (ptrtoint P)), 0), (icmp ne P, 0) --> icmp ne (and ?, (ptrtoint P)), 0 231 232define <3 x i1> @and_cmps_ptr_eq_zero_with_mask_commute3(<3 x i64*> %p, <3 x i64> %y) { 233; CHECK-LABEL: @and_cmps_ptr_eq_zero_with_mask_commute3( 234; CHECK-NEXT: [[X:%.*]] = ptrtoint <3 x i64*> %p to <3 x i64> 235; CHECK-NEXT: [[SOMEBITS:%.*]] = and <3 x i64> %y, [[X]] 236; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i64> [[SOMEBITS]], zeroinitializer 237; CHECK-NEXT: ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]] 238; 239 %isnotnull = icmp ne <3 x i64*> %p, zeroinitializer 240 %x = ptrtoint <3 x i64*> %p to <3 x i64> 241 %somebits = and <3 x i64> %y, %x 242 %somebits_are_not_zero = icmp ne <3 x i64> %somebits, zeroinitializer 243 %r = and <3 x i1> %somebits_are_not_zero, %isnotnull 244 ret <3 x i1> %r 245} 246 247; and (icmp ne P, 0), (icmp ne (and ?, (ptrtoint P)), 0) --> icmp ne (and ?, (ptrtoint P)), 0 248 249define i1 @and_cmps_ptr_eq_zero_with_mask_commute4(i64* %p, i64 %y) { 250; CHECK-LABEL: @and_cmps_ptr_eq_zero_with_mask_commute4( 251; CHECK-NEXT: [[X:%.*]] = ptrtoint i64* %p to i64 252; CHECK-NEXT: [[SOMEBITS:%.*]] = and i64 %y, [[X]] 253; CHECK-NEXT: [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i64 [[SOMEBITS]], 0 254; CHECK-NEXT: ret i1 [[SOMEBITS_ARE_NOT_ZERO]] 255; 256 %isnotnull = icmp ne i64* %p, null 257 %x = ptrtoint i64* %p to i64 258 %somebits = and i64 %y, %x 259 %somebits_are_not_zero = icmp ne i64 %somebits, 0 260 %r = and i1 %isnotnull, %somebits_are_not_zero 261 ret i1 %r 262} 263 264