430 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; https://bugs.llvm.org/show_bug.cgi?id=67735 6; Patterns:7; (x & m) | (y & ~m)8; (x & m) ^ (y & ~m)9; (x & m) + (y & ~m)10; Should be transformed into:11; (x & m) | (y & ~m)12; And then into:13; ((x ^ y) & m) ^ y14 15; ============================================================================ ;16; Most basic positive tests17; ============================================================================ ;18 19define i32 @p(i32 %x, i32 %y, i32 noundef %m) {20; CHECK-LABEL: @p(21; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]22; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -123; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]24; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]25; CHECK-NEXT: ret i32 [[RET]]26;27 %and = and i32 %x, %m28 %neg = xor i32 %m, -129 %and1 = and i32 %neg, %y30 %ret = xor i32 %and, %and131 ret i32 %ret32}33 34define <2 x i32> @p_splatvec(<2 x i32> %x, <2 x i32> %y, <2 x i32> noundef %m) {35; CHECK-LABEL: @p_splatvec(36; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], [[M:%.*]]37; CHECK-NEXT: [[NEG:%.*]] = xor <2 x i32> [[M]], splat (i32 -1)38; CHECK-NEXT: [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], [[NEG]]39; CHECK-NEXT: [[RET:%.*]] = or disjoint <2 x i32> [[AND]], [[AND1]]40; CHECK-NEXT: ret <2 x i32> [[RET]]41;42 %and = and <2 x i32> %x, %m43 %neg = xor <2 x i32> %m, <i32 -1, i32 -1>44 %and1 = and <2 x i32> %neg, %y45 %ret = xor <2 x i32> %and, %and146 ret <2 x i32> %ret47}48 49define <3 x i32> @p_vec_undef(<3 x i32> %x, <3 x i32> %y, <3 x i32> noundef %m) {50; CHECK-LABEL: @p_vec_undef(51; CHECK-NEXT: [[AND:%.*]] = and <3 x i32> [[X:%.*]], [[M:%.*]]52; CHECK-NEXT: [[NEG:%.*]] = xor <3 x i32> [[M]], <i32 -1, i32 undef, i32 -1>53; CHECK-NEXT: [[AND1:%.*]] = and <3 x i32> [[NEG]], [[Y:%.*]]54; CHECK-NEXT: [[RET:%.*]] = xor <3 x i32> [[AND]], [[AND1]]55; CHECK-NEXT: ret <3 x i32> [[RET]]56;57 %and = and <3 x i32> %x, %m58 %neg = xor <3 x i32> %m, <i32 -1, i32 undef, i32 -1>59 %and1 = and <3 x i32> %neg, %y60 %ret = xor <3 x i32> %and, %and161 ret <3 x i32> %ret62}63 64define <3 x i32> @p_vec_poison(<3 x i32> %x, <3 x i32> %y, <3 x i32> noundef %m) {65; CHECK-LABEL: @p_vec_poison(66; CHECK-NEXT: [[AND:%.*]] = and <3 x i32> [[X:%.*]], [[M:%.*]]67; CHECK-NEXT: [[NEG:%.*]] = xor <3 x i32> [[M]], <i32 -1, i32 poison, i32 -1>68; CHECK-NEXT: [[AND1:%.*]] = and <3 x i32> [[Y:%.*]], [[NEG]]69; CHECK-NEXT: [[RET:%.*]] = or disjoint <3 x i32> [[AND]], [[AND1]]70; CHECK-NEXT: ret <3 x i32> [[RET]]71;72 %and = and <3 x i32> %x, %m73 %neg = xor <3 x i32> %m, <i32 -1, i32 poison, i32 -1>74 %and1 = and <3 x i32> %neg, %y75 %ret = xor <3 x i32> %and, %and176 ret <3 x i32> %ret77}78 79; ============================================================================ ;80; Constant mask.81; ============================================================================ ;82 83define i32 @p_constmask(i32 %x, i32 %y) {84; CHECK-LABEL: @p_constmask(85; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 6528086; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], -6528187; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]88; CHECK-NEXT: ret i32 [[RET]]89;90 %and = and i32 %x, 6528091 %and1 = and i32 %y, -6528192 %ret = xor i32 %and, %and193 ret i32 %ret94}95 96define <2 x i32> @p_constmask_splatvec(<2 x i32> %x, <2 x i32> %y) {97; CHECK-LABEL: @p_constmask_splatvec(98; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], splat (i32 65280)99; CHECK-NEXT: [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], splat (i32 -65281)100; CHECK-NEXT: [[RET:%.*]] = or disjoint <2 x i32> [[AND]], [[AND1]]101; CHECK-NEXT: ret <2 x i32> [[RET]]102;103 %and = and <2 x i32> %x, <i32 65280, i32 65280>104 %and1 = and <2 x i32> %y, <i32 -65281, i32 -65281>105 %ret = xor <2 x i32> %and, %and1106 ret <2 x i32> %ret107}108 109define <2 x i32> @p_constmask_vec(<2 x i32> %x, <2 x i32> %y) {110; CHECK-LABEL: @p_constmask_vec(111; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], <i32 65280, i32 16776960>112; CHECK-NEXT: [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], <i32 -65281, i32 -16776961>113; CHECK-NEXT: [[RET:%.*]] = xor <2 x i32> [[AND]], [[AND1]]114; CHECK-NEXT: ret <2 x i32> [[RET]]115;116 %and = and <2 x i32> %x, <i32 65280, i32 16776960>117 %and1 = and <2 x i32> %y, <i32 -65281, i32 -16776961>118 %ret = xor <2 x i32> %and, %and1119 ret <2 x i32> %ret120}121 122define <3 x i32> @p_constmask_vec_undef(<3 x i32> %x, <3 x i32> %y) {123; CHECK-LABEL: @p_constmask_vec_undef(124; CHECK-NEXT: [[AND:%.*]] = and <3 x i32> [[X:%.*]], <i32 65280, i32 undef, i32 65280>125; CHECK-NEXT: [[AND1:%.*]] = and <3 x i32> [[Y:%.*]], <i32 -65281, i32 undef, i32 -65281>126; CHECK-NEXT: [[RET:%.*]] = xor <3 x i32> [[AND]], [[AND1]]127; CHECK-NEXT: ret <3 x i32> [[RET]]128;129 %and = and <3 x i32> %x, <i32 65280, i32 undef, i32 65280>130 %and1 = and <3 x i32> %y, <i32 -65281, i32 undef, i32 -65281>131 %ret = xor <3 x i32> %and, %and1132 ret <3 x i32> %ret133}134 135; ============================================================================ ;136; Constant mask with no common bits set, but common unset bits.137; ============================================================================ ;138 139define i32 @p_constmask2(i32 %x, i32 %y) {140; CHECK-LABEL: @p_constmask2(141; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 61440142; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], -65281143; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]144; CHECK-NEXT: ret i32 [[RET]]145;146 %and = and i32 %x, 61440147 %and1 = and i32 %y, -65281148 %ret = xor i32 %and, %and1149 ret i32 %ret150}151 152define <2 x i32> @p_constmask2_splatvec(<2 x i32> %x, <2 x i32> %y) {153; CHECK-LABEL: @p_constmask2_splatvec(154; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], splat (i32 61440)155; CHECK-NEXT: [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], splat (i32 -65281)156; CHECK-NEXT: [[RET:%.*]] = or disjoint <2 x i32> [[AND]], [[AND1]]157; CHECK-NEXT: ret <2 x i32> [[RET]]158;159 %and = and <2 x i32> %x, <i32 61440, i32 61440>160 %and1 = and <2 x i32> %y, <i32 -65281, i32 -65281>161 %ret = xor <2 x i32> %and, %and1162 ret <2 x i32> %ret163}164 165define <2 x i32> @p_constmask2_vec(<2 x i32> %x, <2 x i32> %y) {166; CHECK-LABEL: @p_constmask2_vec(167; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], <i32 61440, i32 16711680>168; CHECK-NEXT: [[AND1:%.*]] = and <2 x i32> [[Y:%.*]], <i32 -65281, i32 -16776961>169; CHECK-NEXT: [[RET:%.*]] = xor <2 x i32> [[AND]], [[AND1]]170; CHECK-NEXT: ret <2 x i32> [[RET]]171;172 %and = and <2 x i32> %x, <i32 61440, i32 16711680>173 %and1 = and <2 x i32> %y, <i32 -65281, i32 -16776961>174 %ret = xor <2 x i32> %and, %and1175 ret <2 x i32> %ret176}177 178define <3 x i32> @p_constmask2_vec_undef(<3 x i32> %x, <3 x i32> %y) {179; CHECK-LABEL: @p_constmask2_vec_undef(180; CHECK-NEXT: [[AND:%.*]] = and <3 x i32> [[X:%.*]], <i32 61440, i32 undef, i32 61440>181; CHECK-NEXT: [[AND1:%.*]] = and <3 x i32> [[Y:%.*]], <i32 -65281, i32 undef, i32 -65281>182; CHECK-NEXT: [[RET:%.*]] = xor <3 x i32> [[AND]], [[AND1]]183; CHECK-NEXT: ret <3 x i32> [[RET]]184;185 %and = and <3 x i32> %x, <i32 61440, i32 undef, i32 61440>186 %and1 = and <3 x i32> %y, <i32 -65281, i32 undef, i32 -65281>187 %ret = xor <3 x i32> %and, %and1188 ret <3 x i32> %ret189}190 191; ============================================================================ ;192; Commutativity.193; ============================================================================ ;194 195; Used to make sure that the IR complexity sorting does not interfere.196declare i32 @gen32()197 198define i32 @p_commutative0(i32 %x, i32 %y, i32 noundef %m) {199; CHECK-LABEL: @p_commutative0(200; CHECK-NEXT: [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]201; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1202; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]203; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]204; CHECK-NEXT: ret i32 [[RET]]205;206 %and = and i32 %m, %x ; swapped order207 %neg = xor i32 %m, -1208 %and1 = and i32 %neg, %y209 %ret = xor i32 %and, %and1210 ret i32 %ret211}212 213define i32 @p_commutative1(i32 %x, i32 noundef %m) {214; CHECK-LABEL: @p_commutative1(215; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()216; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]217; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1218; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y]], [[NEG]]219; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]220; CHECK-NEXT: ret i32 [[RET]]221;222 %y = call i32 @gen32()223 %and = and i32 %x, %m224 %neg = xor i32 %m, -1225 %and1 = and i32 %y, %neg; swapped order226 %ret = xor i32 %and, %and1227 ret i32 %ret228}229 230define i32 @p_commutative2(i32 %x, i32 %y, i32 noundef %m) {231; CHECK-LABEL: @p_commutative2(232; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]233; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1234; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]235; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]236; CHECK-NEXT: ret i32 [[RET]]237;238 %and = and i32 %x, %m239 %neg = xor i32 %m, -1240 %and1 = and i32 %neg, %y241 %ret = xor i32 %and1, %and ; swapped order242 ret i32 %ret243}244 245define i32 @p_commutative3(i32 %x, i32 noundef %m) {246; CHECK-LABEL: @p_commutative3(247; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()248; CHECK-NEXT: [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]249; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1250; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y]], [[NEG]]251; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]252; CHECK-NEXT: ret i32 [[RET]]253;254 %y = call i32 @gen32()255 %and = and i32 %m, %x ; swapped order256 %neg = xor i32 %m, -1257 %and1 = and i32 %y, %neg; swapped order258 %ret = xor i32 %and, %and1259 ret i32 %ret260}261 262define i32 @p_commutative4(i32 %x, i32 %y, i32 noundef %m) {263; CHECK-LABEL: @p_commutative4(264; CHECK-NEXT: [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]265; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1266; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]267; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]268; CHECK-NEXT: ret i32 [[RET]]269;270 %and = and i32 %m, %x ; swapped order271 %neg = xor i32 %m, -1272 %and1 = and i32 %neg, %y273 %ret = xor i32 %and1, %and ; swapped order274 ret i32 %ret275}276 277define i32 @p_commutative5(i32 %x, i32 noundef %m) {278; CHECK-LABEL: @p_commutative5(279; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()280; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]281; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1282; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y]], [[NEG]]283; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]284; CHECK-NEXT: ret i32 [[RET]]285;286 %y = call i32 @gen32()287 %and = and i32 %x, %m288 %neg = xor i32 %m, -1289 %and1 = and i32 %y, %neg; swapped order290 %ret = xor i32 %and1, %and ; swapped order291 ret i32 %ret292}293 294define i32 @p_commutative6(i32 %x, i32 noundef %m) {295; CHECK-LABEL: @p_commutative6(296; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()297; CHECK-NEXT: [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]298; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1299; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y]], [[NEG]]300; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]301; CHECK-NEXT: ret i32 [[RET]]302;303 %y = call i32 @gen32()304 %and = and i32 %m, %x ; swapped order305 %neg = xor i32 %m, -1306 %and1 = and i32 %y, %neg; swapped order307 %ret = xor i32 %and1, %and ; swapped order308 ret i32 %ret309}310 311define i32 @p_constmask_commutative(i32 %x, i32 %y) {312; CHECK-LABEL: @p_constmask_commutative(313; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 65280314; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], -65281315; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND1]], [[AND]]316; CHECK-NEXT: ret i32 [[RET]]317;318 %and = and i32 %x, 65280319 %and1 = and i32 %y, -65281320 %ret = xor i32 %and1, %and ; swapped order321 ret i32 %ret322}323 324; ============================================================================ ;325; Negative tests. Should not be folded.326; ============================================================================ ;327 328; One use only.329 330declare void @use32(i32)331 332define i32 @n0_oneuse(i32 %x, i32 %y, i32 noundef %m) {333; CHECK-LABEL: @n0_oneuse(334; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]335; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1336; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]337; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]338; CHECK-NEXT: call void @use32(i32 [[AND]])339; CHECK-NEXT: call void @use32(i32 [[NEG]])340; CHECK-NEXT: call void @use32(i32 [[AND1]])341; CHECK-NEXT: ret i32 [[RET]]342;343 %and = and i32 %x, %m344 %neg = xor i32 %m, -1345 %and1 = and i32 %neg, %y346 %ret = xor i32 %and, %and1347 call void @use32(i32 %and)348 call void @use32(i32 %neg)349 call void @use32(i32 %and1)350 ret i32 %ret351}352 353define i32 @n0_constmask_oneuse(i32 %x, i32 %y) {354; CHECK-LABEL: @n0_constmask_oneuse(355; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 65280356; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], -65281357; CHECK-NEXT: [[RET:%.*]] = or disjoint i32 [[AND]], [[AND1]]358; CHECK-NEXT: call void @use32(i32 [[AND]])359; CHECK-NEXT: call void @use32(i32 [[AND1]])360; CHECK-NEXT: ret i32 [[RET]]361;362 %and = and i32 %x, 65280363 %and1 = and i32 %y, -65281364 %ret = xor i32 %and, %and1365 call void @use32(i32 %and)366 call void @use32(i32 %and1)367 ret i32 %ret368}369 370; Bad xor constant371 372define i32 @n1_badxor(i32 %x, i32 %y, i32 %m) {373; CHECK-LABEL: @n1_badxor(374; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]375; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], 1376; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]377; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND]], [[AND1]]378; CHECK-NEXT: ret i32 [[RET]]379;380 %and = and i32 %x, %m381 %neg = xor i32 %m, 1 ; not -1382 %and1 = and i32 %neg, %y383 %ret = xor i32 %and, %and1384 ret i32 %ret385}386 387; Different mask is used388 389define i32 @n2_badmask(i32 %x, i32 %y, i32 %m1, i32 %m2) {390; CHECK-LABEL: @n2_badmask(391; CHECK-NEXT: [[AND:%.*]] = and i32 [[M1:%.*]], [[X:%.*]]392; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M2:%.*]], -1393; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], [[NEG]]394; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND]], [[AND1]]395; CHECK-NEXT: ret i32 [[RET]]396;397 %and = and i32 %m1, %x398 %neg = xor i32 %m2, -1 ; different mask, not %m1399 %and1 = and i32 %neg, %y400 %ret = xor i32 %and, %and1401 ret i32 %ret402}403 404; Different const mask is used405 406define i32 @n3_constmask_badmask(i32 %x, i32 %y) {407; CHECK-LABEL: @n3_constmask_badmask(408; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 65280409; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y:%.*]], -65280410; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND]], [[AND1]]411; CHECK-NEXT: ret i32 [[RET]]412;413 %and = and i32 %x, 65280414 %and1 = and i32 %y, -65280 ; not -65281, so they have one common bit415 %ret = xor i32 %and, %and1416 ret i32 %ret417}418 419define i32 @n3_constmask_samemask(i32 %x, i32 %y) {420; CHECK-LABEL: @n3_constmask_samemask(421; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]422; CHECK-NEXT: [[RET:%.*]] = and i32 [[AND2]], 65280423; CHECK-NEXT: ret i32 [[RET]]424;425 %and = and i32 %x, 65280426 %and1 = and i32 %y, 65280 ; both masks are the same427 %ret = xor i32 %and, %and1428 ret i32 %ret429}430