brintos

brintos / llvm-project-archived public Read only

0
0
Text · 41.9 KiB · edafecc Raw
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