1171 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -S -passes=early-cse -earlycse-debug-hash | FileCheck %s3; RUN: opt < %s -S -passes='early-cse<memssa>' | FileCheck %s4 5define void @test1(float %A, float %B, ptr %PA, ptr %PB) {6; CHECK-LABEL: @test1(7; CHECK-NEXT: [[C:%.*]] = fadd float [[A:%.*]], [[B:%.*]]8; CHECK-NEXT: store float [[C]], ptr [[PA:%.*]], align 49; CHECK-NEXT: store float [[C]], ptr [[PB:%.*]], align 410; CHECK-NEXT: ret void11;12 %C = fadd float %A, %B13 store float %C, ptr %PA14 %D = fadd float %B, %A15 store float %D, ptr %PB16 ret void17}18 19define void @test2(float %A, float %B, ptr %PA, ptr %PB) {20; CHECK-LABEL: @test2(21; CHECK-NEXT: [[C:%.*]] = fcmp oeq float [[A:%.*]], [[B:%.*]]22; CHECK-NEXT: store i1 [[C]], ptr [[PA:%.*]], align 123; CHECK-NEXT: store i1 [[C]], ptr [[PB:%.*]], align 124; CHECK-NEXT: ret void25;26 %C = fcmp oeq float %A, %B27 store i1 %C, ptr %PA28 %D = fcmp oeq float %B, %A29 store i1 %D, ptr %PB30 ret void31}32 33define void @test3(float %A, float %B, ptr %PA, ptr %PB) {34; CHECK-LABEL: @test3(35; CHECK-NEXT: [[C:%.*]] = fcmp uge float [[A:%.*]], [[B:%.*]]36; CHECK-NEXT: store i1 [[C]], ptr [[PA:%.*]], align 137; CHECK-NEXT: store i1 [[C]], ptr [[PB:%.*]], align 138; CHECK-NEXT: ret void39;40 %C = fcmp uge float %A, %B41 store i1 %C, ptr %PA42 %D = fcmp ule float %B, %A43 store i1 %D, ptr %PB44 ret void45}46 47define void @test4(i32 %A, i32 %B, ptr %PA, ptr %PB) {48; CHECK-LABEL: @test4(49; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]50; CHECK-NEXT: store i1 [[C]], ptr [[PA:%.*]], align 151; CHECK-NEXT: store i1 [[C]], ptr [[PB:%.*]], align 152; CHECK-NEXT: ret void53;54 %C = icmp eq i32 %A, %B55 store i1 %C, ptr %PA56 %D = icmp eq i32 %B, %A57 store i1 %D, ptr %PB58 ret void59}60 61define void @test5(i32 %A, i32 %B, ptr %PA, ptr %PB) {62; CHECK-LABEL: @test5(63; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]64; CHECK-NEXT: store i1 [[C]], ptr [[PA:%.*]], align 165; CHECK-NEXT: store i1 [[C]], ptr [[PB:%.*]], align 166; CHECK-NEXT: ret void67;68 %C = icmp sgt i32 %A, %B69 store i1 %C, ptr %PA70 %D = icmp slt i32 %B, %A71 store i1 %D, ptr %PB72 ret void73}74 75; Test degenerate case of commuted compare of identical comparands.76 77define void @test6(float %f, ptr %p1, ptr %p2) {78; CHECK-LABEL: @test6(79; CHECK-NEXT: [[C1:%.*]] = fcmp ult float [[F:%.*]], [[F]]80; CHECK-NEXT: store i1 [[C1]], ptr [[P1:%.*]], align 181; CHECK-NEXT: store i1 [[C1]], ptr [[P2:%.*]], align 182; CHECK-NEXT: ret void83;84 %c1 = fcmp ult float %f, %f85 %c2 = fcmp ugt float %f, %f86 store i1 %c1, ptr %p187 store i1 %c2, ptr %p288 ret void89}90 91; Min/max operands may be commuted in the compare and select.92 93define i8 @smin_commute(i8 %a, i8 %b) {94; CHECK-LABEL: @smin_commute(95; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]96; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[B]], [[A]]97; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]98; CHECK-NEXT: [[R:%.*]] = mul i8 [[M1]], [[M1]]99; CHECK-NEXT: ret i8 [[R]]100;101 %cmp1 = icmp slt i8 %a, %b102 %cmp2 = icmp slt i8 %b, %a103 %m1 = select i1 %cmp1, i8 %a, i8 %b104 %m2 = select i1 %cmp2, i8 %b, i8 %a105 %r = mul i8 %m1, %m2106 ret i8 %r107}108 109; Min/max can also have a swapped predicate and select operands.110 111define i1 @smin_swapped(i8 %a, i8 %b) {112; CHECK-LABEL: @smin_swapped(113; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]114; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], [[B]]115; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]116; CHECK-NEXT: ret i1 true117;118 %cmp1 = icmp sgt i8 %a, %b119 %cmp2 = icmp slt i8 %a, %b120 %m1 = select i1 %cmp1, i8 %b, i8 %a121 %m2 = select i1 %cmp2, i8 %a, i8 %b122 %r = icmp eq i8 %m2, %m1123 ret i1 %r124}125 126; Min/max can also have an inverted predicate and select operands.127 128define i1 @smin_inverted(i8 %a, i8 %b) {129; CHECK-LABEL: @smin_inverted(130; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]131; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true132; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]133; CHECK-NEXT: ret i1 true134;135 %cmp1 = icmp slt i8 %a, %b136 %cmp2 = xor i1 %cmp1, -1137 %m1 = select i1 %cmp1, i8 %a, i8 %b138 %m2 = select i1 %cmp2, i8 %b, i8 %a139 %r = icmp eq i8 %m1, %m2140 ret i1 %r141}142 143define i8 @smax_commute(i8 %a, i8 %b) {144; CHECK-LABEL: @smax_commute(145; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]146; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[B]], [[A]]147; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]148; CHECK-NEXT: ret i8 0149;150 %cmp1 = icmp sgt i8 %a, %b151 %cmp2 = icmp sgt i8 %b, %a152 %m1 = select i1 %cmp1, i8 %a, i8 %b153 %m2 = select i1 %cmp2, i8 %b, i8 %a154 %r = urem i8 %m2, %m1155 ret i8 %r156}157 158define i8 @smax_swapped(i8 %a, i8 %b) {159; CHECK-LABEL: @smax_swapped(160; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]161; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], [[B]]162; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]163; CHECK-NEXT: ret i8 1164;165 %cmp1 = icmp slt i8 %a, %b166 %cmp2 = icmp sgt i8 %a, %b167 %m1 = select i1 %cmp1, i8 %b, i8 %a168 %m2 = select i1 %cmp2, i8 %a, i8 %b169 %r = sdiv i8 %m1, %m2170 ret i8 %r171}172 173define i1 @smax_inverted(i8 %a, i8 %b) {174; CHECK-LABEL: @smax_inverted(175; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]176; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true177; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]178; CHECK-NEXT: ret i1 true179;180 %cmp1 = icmp sgt i8 %a, %b181 %cmp2 = xor i1 %cmp1, -1182 %m1 = select i1 %cmp1, i8 %a, i8 %b183 %m2 = select i1 %cmp2, i8 %b, i8 %a184 %r = icmp eq i8 %m1, %m2185 ret i1 %r186}187 188define i8 @umin_commute(i8 %a, i8 %b) {189; CHECK-LABEL: @umin_commute(190; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]191; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[B]], [[A]]192; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]193; CHECK-NEXT: ret i8 0194;195 %cmp1 = icmp ult i8 %a, %b196 %cmp2 = icmp ult i8 %b, %a197 %m1 = select i1 %cmp1, i8 %a, i8 %b198 %m2 = select i1 %cmp2, i8 %b, i8 %a199 %r = sub i8 %m2, %m1200 ret i8 %r201}202 203; Choose a vector type just to show that works.204 205define <2 x i8> @umin_swapped(<2 x i8> %a, <2 x i8> %b) {206; CHECK-LABEL: @umin_swapped(207; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i8> [[A:%.*]], [[B:%.*]]208; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i8> [[A]], [[B]]209; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[CMP1]], <2 x i8> [[B]], <2 x i8> [[A]]210; CHECK-NEXT: ret <2 x i8> zeroinitializer211;212 %cmp1 = icmp ugt <2 x i8> %a, %b213 %cmp2 = icmp ult <2 x i8> %a, %b214 %m1 = select <2 x i1> %cmp1, <2 x i8> %b, <2 x i8> %a215 %m2 = select <2 x i1> %cmp2, <2 x i8> %a, <2 x i8> %b216 %r = sub <2 x i8> %m2, %m1217 ret <2 x i8> %r218}219 220define i1 @umin_inverted(i8 %a, i8 %b) {221; CHECK-LABEL: @umin_inverted(222; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]223; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true224; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]225; CHECK-NEXT: ret i1 true226;227 %cmp1 = icmp ult i8 %a, %b228 %cmp2 = xor i1 %cmp1, -1229 %m1 = select i1 %cmp1, i8 %a, i8 %b230 %m2 = select i1 %cmp2, i8 %b, i8 %a231 %r = icmp eq i8 %m1, %m2232 ret i1 %r233}234 235define i8 @umax_commute(i8 %a, i8 %b) {236; CHECK-LABEL: @umax_commute(237; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]]238; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 [[B]], [[A]]239; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]240; CHECK-NEXT: ret i8 1241;242 %cmp1 = icmp ugt i8 %a, %b243 %cmp2 = icmp ugt i8 %b, %a244 %m1 = select i1 %cmp1, i8 %a, i8 %b245 %m2 = select i1 %cmp2, i8 %b, i8 %a246 %r = udiv i8 %m1, %m2247 ret i8 %r248}249 250define i8 @umax_swapped(i8 %a, i8 %b) {251; CHECK-LABEL: @umax_swapped(252; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]253; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 [[A]], [[B]]254; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]255; CHECK-NEXT: [[R:%.*]] = add i8 [[M1]], [[M1]]256; CHECK-NEXT: ret i8 [[R]]257;258 %cmp1 = icmp ult i8 %a, %b259 %cmp2 = icmp ugt i8 %a, %b260 %m1 = select i1 %cmp1, i8 %b, i8 %a261 %m2 = select i1 %cmp2, i8 %a, i8 %b262 %r = add i8 %m2, %m1263 ret i8 %r264}265 266define i1 @umax_inverted(i8 %a, i8 %b) {267; CHECK-LABEL: @umax_inverted(268; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]]269; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true270; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]271; CHECK-NEXT: ret i1 true272;273 %cmp1 = icmp ugt i8 %a, %b274 %cmp2 = xor i1 %cmp1, -1275 %m1 = select i1 %cmp1, i8 %a, i8 %b276 %m2 = select i1 %cmp2, i8 %b, i8 %a277 %r = icmp eq i8 %m1, %m2278 ret i1 %r279}280 281; Min/max may exist with non-canonical operands. Value tracking can match those.282; But we do not use value tracking, so we expect instcombine will canonicalize283; this code to a form that allows CSE.284 285define i8 @smax_nsw(i8 %a, i8 %b) {286; CHECK-LABEL: @smax_nsw(287; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]]288; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], [[B]]289; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[SUB]], 0290; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 0, i8 [[SUB]]291; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 [[SUB]], i8 0292; CHECK-NEXT: [[R:%.*]] = sub i8 [[M2]], [[M1]]293; CHECK-NEXT: ret i8 [[R]]294;295 %sub = sub nsw i8 %a, %b296 %cmp1 = icmp slt i8 %a, %b297 %cmp2 = icmp sgt i8 %sub, 0298 %m1 = select i1 %cmp1, i8 0, i8 %sub299 %m2 = select i1 %cmp2, i8 %sub, i8 0300 %r = sub i8 %m2, %m1301 ret i8 %r302}303 304 305define i8 @abs_swapped_sge(i8 %a) {306; CHECK-LABEL: @abs_swapped_sge(307; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]308; CHECK-NEXT: [[CMP1:%.*]] = icmp sge i8 [[A]], 0309; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0310; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]311; CHECK-NEXT: ret i8 0312;313 %neg = sub i8 0, %a314 %cmp1 = icmp sge i8 %a, 0315 %cmp2 = icmp slt i8 %a, 0316 %m1 = select i1 %cmp1, i8 %a, i8 %neg317 %m2 = select i1 %cmp2, i8 %neg, i8 %a318 %r = xor i8 %m2, %m1319 ret i8 %r320}321 322define i8 @nabs_swapped_sge(i8 %a) {323; CHECK-LABEL: @nabs_swapped_sge(324; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]325; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], 0326; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i8 [[A]], 0327; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]328; CHECK-NEXT: ret i8 0329;330 %neg = sub i8 0, %a331 %cmp1 = icmp slt i8 %a, 0332 %cmp2 = icmp sge i8 %a, 0333 %m1 = select i1 %cmp1, i8 %a, i8 %neg334 %m2 = select i1 %cmp2, i8 %neg, i8 %a335 %r = xor i8 %m2, %m1336 ret i8 %r337}338 339; Abs/nabs may exist with non-canonical operands. Value tracking can match those.340; But we do not use value tracking, so we expect instcombine will canonicalize341; this code to a form that allows CSE.342 343define i8 @abs_swapped(i8 %a) {344; CHECK-LABEL: @abs_swapped(345; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]346; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A]], 0347; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0348; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]349; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 [[NEG]], i8 [[A]]350; CHECK-NEXT: [[R:%.*]] = or i8 [[M2]], [[M1]]351; CHECK-NEXT: ret i8 [[R]]352;353 %neg = sub i8 0, %a354 %cmp1 = icmp sgt i8 %a, 0355 %cmp2 = icmp slt i8 %a, 0356 %m1 = select i1 %cmp1, i8 %a, i8 %neg357 %m2 = select i1 %cmp2, i8 %neg, i8 %a358 %r = or i8 %m2, %m1359 ret i8 %r360}361 362define i8 @abs_inverted(i8 %a) {363; CHECK-LABEL: @abs_inverted(364; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]365; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A]], 0366; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true367; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]368; CHECK-NEXT: ret i8 [[M1]]369;370 %neg = sub i8 0, %a371 %cmp1 = icmp sgt i8 %a, 0372 %cmp2 = xor i1 %cmp1, -1373 %m1 = select i1 %cmp1, i8 %a, i8 %neg374 %m2 = select i1 %cmp2, i8 %neg, i8 %a375 %r = or i8 %m2, %m1376 ret i8 %r377}378 379; Abs/nabs may exist with non-canonical operands. Value tracking can match those.380; But we do not use value tracking, so we expect instcombine will canonicalize381; this code to a form that allows CSE.382 383define i8 @nabs_swapped(i8 %a) {384; CHECK-LABEL: @nabs_swapped(385; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]386; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], 0387; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], 0388; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]389; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 [[NEG]], i8 [[A]]390; CHECK-NEXT: [[R:%.*]] = xor i8 [[M2]], [[M1]]391; CHECK-NEXT: ret i8 [[R]]392;393 %neg = sub i8 0, %a394 %cmp1 = icmp slt i8 %a, 0395 %cmp2 = icmp sgt i8 %a, 0396 %m1 = select i1 %cmp1, i8 %a, i8 %neg397 %m2 = select i1 %cmp2, i8 %neg, i8 %a398 %r = xor i8 %m2, %m1399 ret i8 %r400}401 402define i8 @nabs_inverted(i8 %a) {403; CHECK-LABEL: @nabs_inverted(404; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]405; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], 0406; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true407; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]408; CHECK-NEXT: ret i8 0409;410 %neg = sub i8 0, %a411 %cmp1 = icmp slt i8 %a, 0412 %cmp2 = xor i1 %cmp1, -1413 %m1 = select i1 %cmp1, i8 %a, i8 %neg414 %m2 = select i1 %cmp2, i8 %neg, i8 %a415 %r = xor i8 %m2, %m1416 ret i8 %r417}418 419; Abs/nabs may exist with non-canonical operands. Value tracking can match those.420; But we do not use value tracking, so we expect instcombine will canonicalize421; this code to a form that allows CSE.422 423; compares are different.424define i8 @abs_different_constants(i8 %a) {425; CHECK-LABEL: @abs_different_constants(426; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]427; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A]], -1428; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0429; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]430; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 [[NEG]], i8 [[A]]431; CHECK-NEXT: [[R:%.*]] = or i8 [[M2]], [[M1]]432; CHECK-NEXT: ret i8 [[R]]433;434 %neg = sub i8 0, %a435 %cmp1 = icmp sgt i8 %a, -1436 %cmp2 = icmp slt i8 %a, 0437 %m1 = select i1 %cmp1, i8 %a, i8 %neg438 %m2 = select i1 %cmp2, i8 %neg, i8 %a439 %r = or i8 %m2, %m1440 ret i8 %r441}442 443; Abs/nabs may exist with non-canonical operands. Value tracking can match those.444; But we do not use value tracking, so we expect instcombine will canonicalize445; this code to a form that allows CSE.446 447define i8 @nabs_different_constants(i8 %a) {448; CHECK-LABEL: @nabs_different_constants(449; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]450; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], 0451; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], -1452; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]453; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 [[NEG]], i8 [[A]]454; CHECK-NEXT: [[R:%.*]] = xor i8 [[M2]], [[M1]]455; CHECK-NEXT: ret i8 [[R]]456;457 %neg = sub i8 0, %a458 %cmp1 = icmp slt i8 %a, 0459 %cmp2 = icmp sgt i8 %a, -1460 %m1 = select i1 %cmp1, i8 %a, i8 %neg461 %m2 = select i1 %cmp2, i8 %neg, i8 %a462 %r = xor i8 %m2, %m1463 ret i8 %r464}465 466; https://bugs.llvm.org/show_bug.cgi?id=41101467; Detect equivalence of selects with commuted operands: 'not' cond.468 469define i32 @select_not_cond(i1 %cond, i32 %t, i32 %f) {470; CHECK-LABEL: @select_not_cond(471; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true472; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]473; CHECK-NEXT: ret i32 0474;475 %not = xor i1 %cond, -1476 %m1 = select i1 %cond, i32 %t, i32 %f477 %m2 = select i1 %not, i32 %f, i32 %t478 %r = xor i32 %m2, %m1479 ret i32 %r480}481 482; Detect equivalence of selects with commuted operands: 'not' cond with vector select.483 484define <2 x double> @select_not_cond_commute_vec(<2 x i1> %cond, <2 x double> %t, <2 x double> %f) {485; CHECK-LABEL: @select_not_cond_commute_vec(486; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[COND:%.*]], splat (i1 true)487; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[COND]], <2 x double> [[T:%.*]], <2 x double> [[F:%.*]]488; CHECK-NEXT: ret <2 x double> splat (double 1.000000e+00)489;490 %not = xor <2 x i1> %cond, <i1 -1, i1 -1>491 %m1 = select <2 x i1> %cond, <2 x double> %t, <2 x double> %f492 %m2 = select <2 x i1> %not, <2 x double> %f, <2 x double> %t493 %r = fdiv nnan <2 x double> %m1, %m2494 ret <2 x double> %r495}496 497; Negative test - select ops must be commuted.498 499define i32 @select_not_cond_wrong_select_ops(i1 %cond, i32 %t, i32 %f) {500; CHECK-LABEL: @select_not_cond_wrong_select_ops(501; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true502; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]503; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T]], i32 [[F]]504; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]505; CHECK-NEXT: ret i32 [[R]]506;507 %not = xor i1 %cond, -1508 %m1 = select i1 %cond, i32 %t, i32 %f509 %m2 = select i1 %not, i32 %t, i32 %f510 %r = xor i32 %m2, %m1511 ret i32 %r512}513 514; Negative test - not a 'not'.515 516define i32 @select_not_cond_wrong_cond(i1 %cond, i32 %t, i32 %f) {517; CHECK-LABEL: @select_not_cond_wrong_cond(518; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND:%.*]], i32 [[T:%.*]], i32 [[F:%.*]]519; CHECK-NEXT: [[M2:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]520; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]521; CHECK-NEXT: ret i32 [[R]]522;523 %not = xor i1 %cond, -2524 %m1 = select i1 %cond, i32 %t, i32 %f525 %m2 = select i1 %not, i32 %f, i32 %t526 %r = xor i32 %m2, %m1527 ret i32 %r528}529 530; Detect equivalence of selects with commuted operands: inverted pred with fcmps.531 532define i32 @select_invert_pred_cond(float %x, i32 %t, i32 %f) {533; CHECK-LABEL: @select_invert_pred_cond(534; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01535; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01536; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]537; CHECK-NEXT: ret i32 0538;539 %cond = fcmp ueq float %x, 42.0540 %invcond = fcmp one float %x, 42.0541 %m1 = select i1 %cond, i32 %t, i32 %f542 %m2 = select i1 %invcond, i32 %f, i32 %t543 %r = xor i32 %m2, %m1544 ret i32 %r545}546 547; Detect equivalence of selects with commuted operands: inverted pred with icmps and vectors.548 549define <2 x i32> @select_invert_pred_cond_commute_vec(<2 x i8> %x, <2 x i32> %t, <2 x i32> %f) {550; CHECK-LABEL: @select_invert_pred_cond_commute_vec(551; CHECK-NEXT: [[COND:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 42, i8 -1>552; CHECK-NEXT: [[INVCOND:%.*]] = icmp sle <2 x i8> [[X]], <i8 42, i8 -1>553; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[T:%.*]], <2 x i32> [[F:%.*]]554; CHECK-NEXT: ret <2 x i32> zeroinitializer555;556 %cond = icmp sgt <2 x i8> %x, <i8 42, i8 -1>557 %invcond = icmp sle <2 x i8> %x, <i8 42, i8 -1>558 %m1 = select <2 x i1> %cond, <2 x i32> %t, <2 x i32> %f559 %m2 = select <2 x i1> %invcond, <2 x i32> %f, <2 x i32> %t560 %r = xor <2 x i32> %m1, %m2561 ret <2 x i32> %r562}563 564; Negative test - select ops must be commuted.565 566define i32 @select_invert_pred_wrong_select_ops(float %x, i32 %t, i32 %f) {567; CHECK-LABEL: @select_invert_pred_wrong_select_ops(568; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01569; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01570; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[F:%.*]], i32 [[T:%.*]]571; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]572; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]573; CHECK-NEXT: ret i32 [[R]]574;575 %cond = fcmp ueq float %x, 42.0576 %invcond = fcmp one float %x, 42.0577 %m1 = select i1 %cond, i32 %f, i32 %t578 %m2 = select i1 %invcond, i32 %f, i32 %t579 %r = xor i32 %m2, %m1580 ret i32 %r581}582 583; Negative test - not an inverted predicate.584 585define i32 @select_invert_pred_wrong_cond(float %x, i32 %t, i32 %f) {586; CHECK-LABEL: @select_invert_pred_wrong_cond(587; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01588; CHECK-NEXT: [[INVCOND:%.*]] = fcmp une float [[X]], 4.200000e+01589; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]590; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]591; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]592; CHECK-NEXT: ret i32 [[R]]593;594 %cond = fcmp ueq float %x, 42.0595 %invcond = fcmp une float %x, 42.0596 %m1 = select i1 %cond, i32 %t, i32 %f597 %m2 = select i1 %invcond, i32 %f, i32 %t598 %r = xor i32 %m2, %m1599 ret i32 %r600}601 602; Negative test - cmp ops must match.603 604define i32 @select_invert_pred_wrong_cmp_ops(float %x, i32 %t, i32 %f) {605; CHECK-LABEL: @select_invert_pred_wrong_cmp_ops(606; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01607; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.300000e+01608; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]609; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]610; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]611; CHECK-NEXT: ret i32 [[R]]612;613 %cond = fcmp ueq float %x, 42.0614 %invcond = fcmp one float %x, 43.0615 %m1 = select i1 %cond, i32 %t, i32 %f616 %m2 = select i1 %invcond, i32 %f, i32 %t617 %r = xor i32 %m2, %m1618 ret i32 %r619}620 621; If we have both an inverted predicate and a 'not' op, recognize the double-negation.622 623define i32 @select_not_invert_pred_cond(i8 %x, i32 %t, i32 %f) {624; CHECK-LABEL: @select_not_invert_pred_cond(625; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X:%.*]], 42626; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X]], 42627; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true628; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]629; CHECK-NEXT: ret i32 0630;631 %cond = icmp ugt i8 %x, 42632 %invcond = icmp ule i8 %x, 42633 %not = xor i1 %invcond, -1634 %m1 = select i1 %cond, i32 %t, i32 %f635 %m2 = select i1 %not, i32 %t, i32 %f636 %r = sub i32 %m1, %m2637 ret i32 %r638}639 640; If we have both an inverted predicate and a 'not' op, recognize the double-negation.641 642define i32 @select_not_invert_pred_cond_commute(i8 %x, i8 %y, i32 %t, i32 %f) {643; CHECK-LABEL: @select_not_invert_pred_cond_commute(644; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]645; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true646; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]647; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]648; CHECK-NEXT: ret i32 0649;650 %invcond = icmp ule i8 %x, %y651 %not = xor i1 %invcond, -1652 %m2 = select i1 %not, i32 %t, i32 %f653 %cond = icmp ugt i8 %x, %y654 %m1 = select i1 %cond, i32 %t, i32 %f655 %r = sub i32 %m2, %m1656 ret i32 %r657}658 659; Negative test - not an inverted predicate.660 661define i32 @select_not_invert_pred_cond_wrong_pred(i8 %x, i8 %y, i32 %t, i32 %f) {662; CHECK-LABEL: @select_not_invert_pred_cond_wrong_pred(663; CHECK-NEXT: [[INVCOND:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]664; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true665; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]666; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]667; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]668; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]669; CHECK-NEXT: ret i32 [[R]]670;671 %invcond = icmp ult i8 %x, %y672 %not = xor i1 %invcond, -1673 %m2 = select i1 %not, i32 %t, i32 %f674 %cond = icmp ugt i8 %x, %y675 %m1 = select i1 %cond, i32 %t, i32 %f676 %r = sub i32 %m2, %m1677 ret i32 %r678}679 680; Negative test - cmp ops must match.681 682define i32 @select_not_invert_pred_cond_wrong_cmp_op(i8 %x, i8 %y, i32 %t, i32 %f) {683; CHECK-LABEL: @select_not_invert_pred_cond_wrong_cmp_op(684; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], 42685; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true686; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]687; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y:%.*]]688; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]689; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]690; CHECK-NEXT: ret i32 [[R]]691;692 %invcond = icmp ule i8 %x, 42693 %not = xor i1 %invcond, -1694 %m2 = select i1 %not, i32 %t, i32 %f695 %cond = icmp ugt i8 %x, %y696 %m1 = select i1 %cond, i32 %t, i32 %f697 %r = sub i32 %m2, %m1698 ret i32 %r699}700 701; Negative test - select ops must be same (and not commuted).702 703define i32 @select_not_invert_pred_cond_wrong_select_op(i8 %x, i8 %y, i32 %t, i32 %f) {704; CHECK-LABEL: @select_not_invert_pred_cond_wrong_select_op(705; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]706; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true707; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]708; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]709; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]710; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]711; CHECK-NEXT: ret i32 [[R]]712;713 %invcond = icmp ule i8 %x, %y714 %not = xor i1 %invcond, -1715 %m2 = select i1 %not, i32 %t, i32 %f716 %cond = icmp ugt i8 %x, %y717 %m1 = select i1 %cond, i32 %f, i32 %t718 %r = sub i32 %m2, %m1719 ret i32 %r720}721 722; This test is a reproducer for a bug involving inverted min/max selects723; hashing differently but comparing as equal. It exhibits such a pair of724; values, and we run this test with -earlycse-debug-hash which would catch725; the disagreement and fail if it regressed.726; EarlyCSE should be able to detect the 2nd redundant `select` and eliminate727; it.728define i32 @inverted_max(i32 %i) {729; CHECK-LABEL: @inverted_max(730; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 0, [[I:%.*]]731; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP]], i32 [[I]], i32 0732; CHECK-NEXT: [[CMPINV:%.*]] = icmp sgt i32 0, [[I]]733; CHECK-NEXT: [[R:%.*]] = add i32 [[M1]], [[M1]]734; CHECK-NEXT: ret i32 [[R]]735;736 %cmp = icmp sle i32 0, %i737 %m1 = select i1 %cmp, i32 %i, i32 0738 %cmpinv = icmp sgt i32 0, %i739 %m2 = select i1 %cmpinv, i32 0, i32 %i740 %r = add i32 %m1, %m2741 ret i32 %r742}743 744; This test is a reproducer for a bug involving inverted min/max selects745; hashing differently but comparing as equal. It exhibits such a pair of746; values, and we run this test with -earlycse-debug-hash which would catch747; the disagreement and fail if it regressed. This test also includes a748; negation of each negation to check for the same issue one level deeper.749define void @not_not_min(ptr %px, ptr %py, ptr %pout) {750; CHECK-LABEL: @not_not_min(751; CHECK-NEXT: [[X:%.*]] = load volatile i32, ptr [[PX:%.*]], align 4752; CHECK-NEXT: [[Y:%.*]] = load volatile i32, ptr [[PY:%.*]], align 4753; CHECK-NEXT: [[CMPA:%.*]] = icmp slt i32 [[X]], [[Y]]754; CHECK-NEXT: [[CMPB:%.*]] = xor i1 [[CMPA]], true755; CHECK-NEXT: [[RA:%.*]] = select i1 [[CMPA]], i32 [[X]], i32 [[Y]]756; CHECK-NEXT: store volatile i32 [[RA]], ptr [[POUT:%.*]], align 4757; CHECK-NEXT: store volatile i32 [[RA]], ptr [[POUT]], align 4758; CHECK-NEXT: store volatile i32 [[RA]], ptr [[POUT]], align 4759; CHECK-NEXT: ret void760;761 %x = load volatile i32, ptr %px762 %y = load volatile i32, ptr %py763 %cmpa = icmp slt i32 %x, %y764 %cmpb = xor i1 %cmpa, -1765 %cmpc = xor i1 %cmpb, -1766 %ra = select i1 %cmpa, i32 %x, i32 %y767 %rb = select i1 %cmpb, i32 %y, i32 %x768 %rc = select i1 %cmpc, i32 %x, i32 %y769 store volatile i32 %ra, ptr %pout770 store volatile i32 %rb, ptr %pout771 store volatile i32 %rc, ptr %pout772 773 ret void774}775 776; This would cause an assert/crash because we matched777; a ValueTracking select pattern that required 'nsw'778; on an operand, but we remove that flag as part of779; CSE matching/hashing.780 781define void @PR41083_1(i32 %span_left, i32 %clip_left) {782; CHECK-LABEL: @PR41083_1(783; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CLIP_LEFT:%.*]], [[SPAN_LEFT:%.*]]784; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[CLIP_LEFT]], [[SPAN_LEFT]]785; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0786; CHECK-NEXT: ret void787;788 %cmp = icmp sgt i32 %clip_left, %span_left789 %sub = sub nsw i32 %clip_left, %span_left790 %cond = select i1 %cmp, i32 %sub, i32 0791 %cmp83292 = icmp slt i32 %cond, undef792 %sub2 = sub i32 %clip_left, %span_left793 %sel2 = select i1 %cmp, i32 %sub2, i32 0794 ret void795}796 797; This would cause an assert/crash because we matched798; a ValueTracking select pattern that required 'nsw'799; on an operand, but we remove that flag as part of800; CSE matching/hashing.801 802define i32 @PR41083_2(i32 %p) {803; CHECK-LABEL: @PR41083_2(804; CHECK-NEXT: [[S:%.*]] = sub i32 0, [[P:%.*]]805; CHECK-NEXT: [[A:%.*]] = ashr exact i32 [[S]], 2806; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 0, [[A]]807; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A]]808; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 0809; CHECK-NEXT: [[M:%.*]] = mul i32 [[SEL]], [[SUB]]810; CHECK-NEXT: ret i32 [[M]]811;812 %s = sub i32 0, %p813 %a = ashr exact i32 %s, 2814 %cmp = icmp sgt i32 0, %a815 %sub = sub nsw i32 0, %a816 %sel = select i1 %cmp, i32 %sub, i32 0817 %s2 = sub i32 0, %a818 %m = mul i32 %sel, %s2819 ret i32 %m820}821 822define float @maxnum(float %a, float %b) {823; CHECK-LABEL: @maxnum(824; CHECK-NEXT: [[X:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float [[B:%.*]])825; CHECK-NEXT: ret float 1.000000e+00826;827 %x = call float @llvm.maxnum.f32(float %a, float %b)828 %y = call float @llvm.maxnum.f32(float %b, float %a)829 %r = fdiv nnan float %x, %y830 ret float %r831}832 833define <2 x float> @minnum(<2 x float> %a, <2 x float> %b) {834; CHECK-LABEL: @minnum(835; CHECK-NEXT: [[X:%.*]] = call fast <2 x float> @llvm.minnum.v2f32(<2 x float> [[A:%.*]], <2 x float> [[B:%.*]])836; CHECK-NEXT: ret <2 x float> splat (float 1.000000e+00)837;838 %x = call fast <2 x float> @llvm.minnum.v2f32(<2 x float> %a, <2 x float> %b)839 %y = call fast <2 x float> @llvm.minnum.v2f32(<2 x float> %b, <2 x float> %a)840 %r = fdiv nnan <2 x float> %x, %y841 ret <2 x float> %r842}843 844define <2 x double> @maximum(<2 x double> %a, <2 x double> %b) {845; CHECK-LABEL: @maximum(846; CHECK-NEXT: [[X:%.*]] = call <2 x double> @llvm.maximum.v2f64(<2 x double> [[A:%.*]], <2 x double> [[B:%.*]])847; CHECK-NEXT: ret <2 x double> splat (double 1.000000e+00)848;849 %x = call fast <2 x double> @llvm.maximum.v2f64(<2 x double> %a, <2 x double> %b)850 %y = call <2 x double> @llvm.maximum.v2f64(<2 x double> %b, <2 x double> %a)851 %r = fdiv nnan <2 x double> %x, %y852 ret <2 x double> %r853}854 855define double @minimum(double %a, double %b) {856; CHECK-LABEL: @minimum(857; CHECK-NEXT: [[X:%.*]] = call double @llvm.minimum.f64(double [[A:%.*]], double [[B:%.*]])858; CHECK-NEXT: ret double 1.000000e+00859;860 %x = call nsz double @llvm.minimum.f64(double %a, double %b)861 %y = call ninf double @llvm.minimum.f64(double %b, double %a)862 %r = fdiv nnan double %x, %y863 ret double %r864}865define i16 @sadd_ov(i16 %a, i16 %b) {866; CHECK-LABEL: @sadd_ov(867; CHECK-NEXT: [[X:%.*]] = call { i16, i1 } @llvm.sadd.with.overflow.i16(i16 [[A:%.*]], i16 [[B:%.*]])868; CHECK-NEXT: [[X1:%.*]] = extractvalue { i16, i1 } [[X]], 0869; CHECK-NEXT: ret i16 [[X1]]870;871 %x = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b)872 %y = call {i16, i1} @llvm.sadd.with.overflow.i16(i16 %b, i16 %a)873 %x1 = extractvalue {i16, i1} %x, 0874 %y1 = extractvalue {i16, i1} %y, 0875 %o = or i16 %x1, %y1876 ret i16 %o877}878 879define <5 x i65> @uadd_ov(<5 x i65> %a, <5 x i65> %b) {880; CHECK-LABEL: @uadd_ov(881; CHECK-NEXT: [[X:%.*]] = call { <5 x i65>, <5 x i1> } @llvm.uadd.with.overflow.v5i65(<5 x i65> [[A:%.*]], <5 x i65> [[B:%.*]])882; CHECK-NEXT: [[X1:%.*]] = extractvalue { <5 x i65>, <5 x i1> } [[X]], 0883; CHECK-NEXT: ret <5 x i65> [[X1]]884;885 %x = call {<5 x i65>, <5 x i1>} @llvm.uadd.with.overflow.v5i65(<5 x i65> %a, <5 x i65> %b)886 %y = call {<5 x i65>, <5 x i1>} @llvm.uadd.with.overflow.v5i65(<5 x i65> %b, <5 x i65> %a)887 %x1 = extractvalue {<5 x i65>, <5 x i1>} %x, 0888 %y1 = extractvalue {<5 x i65>, <5 x i1>} %y, 0889 %o = or <5 x i65> %x1, %y1890 ret <5 x i65> %o891}892 893define i37 @smul_ov(i37 %a, i37 %b) {894; CHECK-LABEL: @smul_ov(895; CHECK-NEXT: [[X:%.*]] = call { i37, i1 } @llvm.smul.with.overflow.i37(i37 [[A:%.*]], i37 [[B:%.*]])896; CHECK-NEXT: [[X1:%.*]] = extractvalue { i37, i1 } [[X]], 0897; CHECK-NEXT: ret i37 [[X1]]898;899 %x = call {i37, i1} @llvm.smul.with.overflow.i37(i37 %a, i37 %b)900 %y = call {i37, i1} @llvm.smul.with.overflow.i37(i37 %b, i37 %a)901 %x1 = extractvalue {i37, i1} %x, 0902 %y1 = extractvalue {i37, i1} %y, 0903 %o = or i37 %x1, %y1904 ret i37 %o905}906 907define <2 x i31> @umul_ov(<2 x i31> %a, <2 x i31> %b) {908; CHECK-LABEL: @umul_ov(909; CHECK-NEXT: [[X:%.*]] = call { <2 x i31>, <2 x i1> } @llvm.umul.with.overflow.v2i31(<2 x i31> [[A:%.*]], <2 x i31> [[B:%.*]])910; CHECK-NEXT: [[X1:%.*]] = extractvalue { <2 x i31>, <2 x i1> } [[X]], 0911; CHECK-NEXT: ret <2 x i31> [[X1]]912;913 %x = call {<2 x i31>, <2 x i1>} @llvm.umul.with.overflow.v2i31(<2 x i31> %a, <2 x i31> %b)914 %y = call {<2 x i31>, <2 x i1>} @llvm.umul.with.overflow.v2i31(<2 x i31> %b, <2 x i31> %a)915 %x1 = extractvalue {<2 x i31>, <2 x i1>} %x, 0916 %y1 = extractvalue {<2 x i31>, <2 x i1>} %y, 0917 %o = or <2 x i31> %x1, %y1918 ret <2 x i31> %o919}920 921define i64 @sadd_sat(i64 %a, i64 %b) {922; CHECK-LABEL: @sadd_sat(923; CHECK-NEXT: [[X:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])924; CHECK-NEXT: ret i64 [[X]]925;926 %x = call i64 @llvm.sadd.sat.i64(i64 %a, i64 %b)927 %y = call i64 @llvm.sadd.sat.i64(i64 %b, i64 %a)928 %o = or i64 %x, %y929 ret i64 %o930}931 932define <2 x i64> @uadd_sat(<2 x i64> %a, <2 x i64> %b) {933; CHECK-LABEL: @uadd_sat(934; CHECK-NEXT: [[X:%.*]] = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> [[A:%.*]], <2 x i64> [[B:%.*]])935; CHECK-NEXT: ret <2 x i64> [[X]]936;937 %x = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %a, <2 x i64> %b)938 %y = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %b, <2 x i64> %a)939 %o = or <2 x i64> %x, %y940 ret <2 x i64> %o941}942 943define <2 x i64> @smax(<2 x i64> %a, <2 x i64> %b) {944; CHECK-LABEL: @smax(945; CHECK-NEXT: [[X:%.*]] = call <2 x i64> @llvm.smax.v2i64(<2 x i64> [[A:%.*]], <2 x i64> [[B:%.*]])946; CHECK-NEXT: ret <2 x i64> [[X]]947;948 %x = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %a, <2 x i64> %b)949 %y = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %b, <2 x i64> %a)950 %o = or <2 x i64> %x, %y951 ret <2 x i64> %o952}953 954define i4 @smin(i4 %a, i4 %b) {955; CHECK-LABEL: @smin(956; CHECK-NEXT: [[X:%.*]] = call i4 @llvm.smin.i4(i4 [[A:%.*]], i4 [[B:%.*]])957; CHECK-NEXT: ret i4 [[X]]958;959 %x = call i4 @llvm.smin.i4(i4 %a, i4 %b)960 %y = call i4 @llvm.smin.i4(i4 %b, i4 %a)961 %o = or i4 %x, %y962 ret i4 %o963}964 965define i67 @umax(i67 %a, i67 %b) {966; CHECK-LABEL: @umax(967; CHECK-NEXT: [[X:%.*]] = call i67 @llvm.umax.i67(i67 [[A:%.*]], i67 [[B:%.*]])968; CHECK-NEXT: ret i67 [[X]]969;970 %x = call i67 @llvm.umax.i67(i67 %a, i67 %b)971 %y = call i67 @llvm.umax.i67(i67 %b, i67 %a)972 %o = or i67 %x, %y973 ret i67 %o974}975 976define <3 x i17> @umin(<3 x i17> %a, <3 x i17> %b) {977; CHECK-LABEL: @umin(978; CHECK-NEXT: [[X:%.*]] = call <3 x i17> @llvm.umin.v3i17(<3 x i17> [[A:%.*]], <3 x i17> [[B:%.*]])979; CHECK-NEXT: ret <3 x i17> [[X]]980;981 %x = call <3 x i17> @llvm.umin.v3i17(<3 x i17> %a, <3 x i17> %b)982 %y = call <3 x i17> @llvm.umin.v3i17(<3 x i17> %b, <3 x i17> %a)983 %o = or <3 x i17> %x, %y984 ret <3 x i17> %o985}986 987; Negative test - mismatched intrinsics988 989define i4 @smin_umin(i4 %a, i4 %b) {990; CHECK-LABEL: @smin_umin(991; CHECK-NEXT: [[X:%.*]] = call i4 @llvm.smin.i4(i4 [[A:%.*]], i4 [[B:%.*]])992; CHECK-NEXT: [[Y:%.*]] = call i4 @llvm.umin.i4(i4 [[B]], i4 [[A]])993; CHECK-NEXT: [[O:%.*]] = or i4 [[X]], [[Y]]994; CHECK-NEXT: ret i4 [[O]]995;996 %x = call i4 @llvm.smin.i4(i4 %a, i4 %b)997 %y = call i4 @llvm.umin.i4(i4 %b, i4 %a)998 %o = or i4 %x, %y999 ret i4 %o1000}1001 1002define i16 @smul_fix(i16 %a, i16 %b) {1003; CHECK-LABEL: @smul_fix(1004; CHECK-NEXT: [[X:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 3)1005; CHECK-NEXT: ret i16 [[X]]1006;1007 %x = call i16 @llvm.smul.fix.i16(i16 %a, i16 %b, i32 3)1008 %y = call i16 @llvm.smul.fix.i16(i16 %b, i16 %a, i32 3)1009 %o = or i16 %x, %y1010 ret i16 %o1011}1012 1013define i16 @umul_fix(i16 %a, i16 %b, i32 %s) {1014; CHECK-LABEL: @umul_fix(1015; CHECK-NEXT: [[X:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 1)1016; CHECK-NEXT: ret i16 [[X]]1017;1018 %x = call i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 1)1019 %y = call i16 @llvm.umul.fix.i16(i16 %b, i16 %a, i32 1)1020 %o = or i16 %x, %y1021 ret i16 %o1022}1023 1024define <3 x i16> @smul_fix_sat(<3 x i16> %a, <3 x i16> %b) {1025; CHECK-LABEL: @smul_fix_sat(1026; CHECK-NEXT: [[X:%.*]] = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> [[A:%.*]], <3 x i16> [[B:%.*]], i32 2)1027; CHECK-NEXT: ret <3 x i16> [[X]]1028;1029 %x = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> %a, <3 x i16> %b, i32 2)1030 %y = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> %b, <3 x i16> %a, i32 2)1031 %o = or <3 x i16> %x, %y1032 ret <3 x i16> %o1033}1034 1035define <3 x i16> @umul_fix_sat(<3 x i16> %a, <3 x i16> %b) {1036; CHECK-LABEL: @umul_fix_sat(1037; CHECK-NEXT: [[X:%.*]] = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> [[A:%.*]], <3 x i16> [[B:%.*]], i32 3)1038; CHECK-NEXT: ret <3 x i16> [[X]]1039;1040 %x = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> %a, <3 x i16> %b, i32 3)1041 %y = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> %b, <3 x i16> %a, i32 3)1042 %o = or <3 x i16> %x, %y1043 ret <3 x i16> %o1044}1045 1046define i16 @umul_smul_fix(i16 %a, i16 %b, i32 %s) {1047; CHECK-LABEL: @umul_smul_fix(1048; CHECK-NEXT: [[X:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 1)1049; CHECK-NEXT: [[Y:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[B]], i16 [[A]], i32 1)1050; CHECK-NEXT: [[O:%.*]] = or i16 [[X]], [[Y]]1051; CHECK-NEXT: ret i16 [[O]]1052;1053 %x = call i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 1)1054 %y = call i16 @llvm.smul.fix.i16(i16 %b, i16 %a, i32 1)1055 %o = or i16 %x, %y1056 ret i16 %o1057}1058 1059define i16 @umul_fix_scale(i16 %a, i16 %b, i32 %s) {1060; CHECK-LABEL: @umul_fix_scale(1061; CHECK-NEXT: [[X:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 1)1062; CHECK-NEXT: [[Y:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[B]], i16 [[A]], i32 2)1063; CHECK-NEXT: [[O:%.*]] = or i16 [[X]], [[Y]]1064; CHECK-NEXT: ret i16 [[O]]1065;1066 %x = call i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 1)1067 %y = call i16 @llvm.umul.fix.i16(i16 %b, i16 %a, i32 2)1068 %o = or i16 %x, %y1069 ret i16 %o1070}1071 1072define float @fma(float %a, float %b, float %c) {1073; CHECK-LABEL: @fma(1074; CHECK-NEXT: [[X:%.*]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[C:%.*]])1075; CHECK-NEXT: ret float 1.000000e+001076;1077 %x = call float @llvm.fma.f32(float %a, float %b, float %c)1078 %y = call float @llvm.fma.f32(float %b, float %a, float %c)1079 %r = fdiv nnan float %x, %y1080 ret float %r1081}1082 1083define float @fma_fail(float %a, float %b, float %c) {1084; CHECK-LABEL: @fma_fail(1085; CHECK-NEXT: [[X:%.*]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[C:%.*]])1086; CHECK-NEXT: [[Y:%.*]] = call float @llvm.fma.f32(float [[A]], float [[C]], float [[B]])1087; CHECK-NEXT: [[R:%.*]] = fdiv nnan float [[X]], [[Y]]1088; CHECK-NEXT: ret float [[R]]1089;1090 %x = call float @llvm.fma.f32(float %a, float %b, float %c)1091 %y = call float @llvm.fma.f32(float %a, float %c, float %b)1092 %r = fdiv nnan float %x, %y1093 ret float %r1094}1095 1096define float @fma_different_add_ops(float %a, float %b, float %c, float %d) {1097; CHECK-LABEL: @fma_different_add_ops(1098; CHECK-NEXT: [[X:%.*]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[C:%.*]])1099; CHECK-NEXT: [[Y:%.*]] = call float @llvm.fma.f32(float [[B]], float [[A]], float [[D:%.*]])1100; CHECK-NEXT: [[R:%.*]] = fdiv nnan float [[X]], [[Y]]1101; CHECK-NEXT: ret float [[R]]1102;1103 %x = call float @llvm.fma.f32(float %a, float %b, float %c)1104 %y = call float @llvm.fma.f32(float %b, float %a, float %d)1105 %r = fdiv nnan float %x, %y1106 ret float %r1107}1108 1109define <2 x double> @fmuladd(<2 x double> %a, <2 x double> %b, <2 x double> %c) {1110; CHECK-LABEL: @fmuladd(1111; CHECK-NEXT: [[X:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[A:%.*]], <2 x double> [[B:%.*]], <2 x double> [[C:%.*]])1112; CHECK-NEXT: ret <2 x double> splat (double 1.000000e+00)1113;1114 %x = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c)1115 %y = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %b, <2 x double> %a, <2 x double> %c)1116 %r = fdiv nnan <2 x double> %x, %y1117 ret <2 x double> %r1118}1119 1120define <2 x double> @fmuladd_fail1(<2 x double> %a, <2 x double> %b, <2 x double> %c) {1121; CHECK-LABEL: @fmuladd_fail1(1122; CHECK-NEXT: [[X:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[A:%.*]], <2 x double> [[B:%.*]], <2 x double> [[C:%.*]])1123; CHECK-NEXT: [[Y:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[C]], <2 x double> [[B]], <2 x double> [[A]])1124; CHECK-NEXT: [[R:%.*]] = fdiv nnan <2 x double> [[X]], [[Y]]1125; CHECK-NEXT: ret <2 x double> [[R]]1126;1127 %x = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c)1128 %y = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %c, <2 x double> %b, <2 x double> %a)1129 %r = fdiv nnan <2 x double> %x, %y1130 ret <2 x double> %r1131}1132 1133define <2 x double> @fmuladd_fail2(<2 x double> %a, <2 x double> %b, <2 x double> %c) {1134; CHECK-LABEL: @fmuladd_fail2(1135; CHECK-NEXT: [[X:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[A:%.*]], <2 x double> [[B:%.*]], <2 x double> [[C:%.*]])1136; CHECK-NEXT: [[Y:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[A]], <2 x double> [[C]], <2 x double> [[B]])1137; CHECK-NEXT: [[R:%.*]] = fdiv nnan <2 x double> [[X]], [[Y]]1138; CHECK-NEXT: ret <2 x double> [[R]]1139;1140 %x = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c)1141 %y = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> %c, <2 x double> %b)1142 %r = fdiv nnan <2 x double> %x, %y1143 ret <2 x double> %r1144}1145 1146declare float @llvm.maxnum.f32(float, float)1147declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>)1148declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>)1149declare double @llvm.minimum.f64(double, double)1150 1151declare {i16, i1} @llvm.sadd.with.overflow.i16(i16, i16)1152declare {<5 x i65>, <5 x i1>} @llvm.uadd.with.overflow.v5i65(<5 x i65>, <5 x i65>)1153declare {i37, i1} @llvm.smul.with.overflow.i37(i37, i37)1154declare {<2 x i31>, <2 x i1>} @llvm.umul.with.overflow.v2i31(<2 x i31>, <2 x i31>)1155declare i64 @llvm.sadd.sat.i64(i64, i64)1156declare <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64>, <2 x i64>)1157 1158declare <2 x i64> @llvm.smax.v2i64(<2 x i64>, <2 x i64>)1159declare i4 @llvm.smin.i4(i4, i4)1160declare i4 @llvm.umin.i4(i4, i4)1161declare i67 @llvm.umax.i67(i67, i67)1162declare <3 x i17> @llvm.umin.v3i17(<3 x i17>, <3 x i17>)1163 1164declare i16 @llvm.smul.fix.i16(i16, i16, i32)1165declare i16 @llvm.umul.fix.i16(i16, i16, i32)1166declare <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16>, <3 x i16>, i32)1167declare <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16>, <3 x i16>, i32)1168 1169declare float @llvm.fma.f32(float, float, float)1170declare <2 x double> @llvm.fmuladd.v2f64(<2 x double>, <2 x double>, <2 x double>)1171