1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -S -early-cse -earlycse-debug-hash | FileCheck %s 3; RUN: opt < %s -S -basic-aa -early-cse-memssa | FileCheck %s 4 5define void @test1(float %A, float %B, float* %PA, float* %PB) { 6; CHECK-LABEL: @test1( 7; CHECK-NEXT: [[C:%.*]] = fadd float [[A:%.*]], [[B:%.*]] 8; CHECK-NEXT: store float [[C]], float* [[PA:%.*]], align 4 9; CHECK-NEXT: store float [[C]], float* [[PB:%.*]], align 4 10; CHECK-NEXT: ret void 11; 12 %C = fadd float %A, %B 13 store float %C, float* %PA 14 %D = fadd float %B, %A 15 store float %D, float* %PB 16 ret void 17} 18 19define void @test2(float %A, float %B, i1* %PA, i1* %PB) { 20; CHECK-LABEL: @test2( 21; CHECK-NEXT: [[C:%.*]] = fcmp oeq float [[A:%.*]], [[B:%.*]] 22; CHECK-NEXT: store i1 [[C]], i1* [[PA:%.*]], align 1 23; CHECK-NEXT: store i1 [[C]], i1* [[PB:%.*]], align 1 24; CHECK-NEXT: ret void 25; 26 %C = fcmp oeq float %A, %B 27 store i1 %C, i1* %PA 28 %D = fcmp oeq float %B, %A 29 store i1 %D, i1* %PB 30 ret void 31} 32 33define void @test3(float %A, float %B, i1* %PA, i1* %PB) { 34; CHECK-LABEL: @test3( 35; CHECK-NEXT: [[C:%.*]] = fcmp uge float [[A:%.*]], [[B:%.*]] 36; CHECK-NEXT: store i1 [[C]], i1* [[PA:%.*]], align 1 37; CHECK-NEXT: store i1 [[C]], i1* [[PB:%.*]], align 1 38; CHECK-NEXT: ret void 39; 40 %C = fcmp uge float %A, %B 41 store i1 %C, i1* %PA 42 %D = fcmp ule float %B, %A 43 store i1 %D, i1* %PB 44 ret void 45} 46 47define void @test4(i32 %A, i32 %B, i1* %PA, i1* %PB) { 48; CHECK-LABEL: @test4( 49; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 50; CHECK-NEXT: store i1 [[C]], i1* [[PA:%.*]], align 1 51; CHECK-NEXT: store i1 [[C]], i1* [[PB:%.*]], align 1 52; CHECK-NEXT: ret void 53; 54 %C = icmp eq i32 %A, %B 55 store i1 %C, i1* %PA 56 %D = icmp eq i32 %B, %A 57 store i1 %D, i1* %PB 58 ret void 59} 60 61define void @test5(i32 %A, i32 %B, i1* %PA, i1* %PB) { 62; CHECK-LABEL: @test5( 63; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] 64; CHECK-NEXT: store i1 [[C]], i1* [[PA:%.*]], align 1 65; CHECK-NEXT: store i1 [[C]], i1* [[PB:%.*]], align 1 66; CHECK-NEXT: ret void 67; 68 %C = icmp sgt i32 %A, %B 69 store i1 %C, i1* %PA 70 %D = icmp slt i32 %B, %A 71 store i1 %D, i1* %PB 72 ret void 73} 74 75; Test degenerate case of commuted compare of identical comparands. 76 77define void @test6(float %f, i1* %p1, i1* %p2) { 78; CHECK-LABEL: @test6( 79; CHECK-NEXT: [[C1:%.*]] = fcmp ult float [[F:%.*]], [[F]] 80; CHECK-NEXT: store i1 [[C1]], i1* [[P1:%.*]], align 1 81; CHECK-NEXT: store i1 [[C1]], i1* [[P2:%.*]], align 1 82; CHECK-NEXT: ret void 83; 84 %c1 = fcmp ult float %f, %f 85 %c2 = fcmp ugt float %f, %f 86 store i1 %c1, i1* %p1 87 store i1 %c2, i1* %p2 88 ret void 89} 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, %b 102 %cmp2 = icmp slt i8 %b, %a 103 %m1 = select i1 %cmp1, i8 %a, i8 %b 104 %m2 = select i1 %cmp2, i8 %b, i8 %a 105 %r = mul i8 %m1, %m2 106 ret i8 %r 107} 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 true 117; 118 %cmp1 = icmp sgt i8 %a, %b 119 %cmp2 = icmp slt i8 %a, %b 120 %m1 = select i1 %cmp1, i8 %b, i8 %a 121 %m2 = select i1 %cmp2, i8 %a, i8 %b 122 %r = icmp eq i8 %m2, %m1 123 ret i1 %r 124} 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]], true 132; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]] 133; CHECK-NEXT: ret i1 true 134; 135 %cmp1 = icmp slt i8 %a, %b 136 %cmp2 = xor i1 %cmp1, -1 137 %m1 = select i1 %cmp1, i8 %a, i8 %b 138 %m2 = select i1 %cmp2, i8 %b, i8 %a 139 %r = icmp eq i8 %m1, %m2 140 ret i1 %r 141} 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 0 149; 150 %cmp1 = icmp sgt i8 %a, %b 151 %cmp2 = icmp sgt i8 %b, %a 152 %m1 = select i1 %cmp1, i8 %a, i8 %b 153 %m2 = select i1 %cmp2, i8 %b, i8 %a 154 %r = urem i8 %m2, %m1 155 ret i8 %r 156} 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 1 164; 165 %cmp1 = icmp slt i8 %a, %b 166 %cmp2 = icmp sgt i8 %a, %b 167 %m1 = select i1 %cmp1, i8 %b, i8 %a 168 %m2 = select i1 %cmp2, i8 %a, i8 %b 169 %r = sdiv i8 %m1, %m2 170 ret i8 %r 171} 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]], true 177; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]] 178; CHECK-NEXT: ret i1 true 179; 180 %cmp1 = icmp sgt i8 %a, %b 181 %cmp2 = xor i1 %cmp1, -1 182 %m1 = select i1 %cmp1, i8 %a, i8 %b 183 %m2 = select i1 %cmp2, i8 %b, i8 %a 184 %r = icmp eq i8 %m1, %m2 185 ret i1 %r 186} 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 0 194; 195 %cmp1 = icmp ult i8 %a, %b 196 %cmp2 = icmp ult i8 %b, %a 197 %m1 = select i1 %cmp1, i8 %a, i8 %b 198 %m2 = select i1 %cmp2, i8 %b, i8 %a 199 %r = sub i8 %m2, %m1 200 ret i8 %r 201} 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> zeroinitializer 211; 212 %cmp1 = icmp ugt <2 x i8> %a, %b 213 %cmp2 = icmp ult <2 x i8> %a, %b 214 %m1 = select <2 x i1> %cmp1, <2 x i8> %b, <2 x i8> %a 215 %m2 = select <2 x i1> %cmp2, <2 x i8> %a, <2 x i8> %b 216 %r = sub <2 x i8> %m2, %m1 217 ret <2 x i8> %r 218} 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]], true 224; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]] 225; CHECK-NEXT: ret i1 true 226; 227 %cmp1 = icmp ult i8 %a, %b 228 %cmp2 = xor i1 %cmp1, -1 229 %m1 = select i1 %cmp1, i8 %a, i8 %b 230 %m2 = select i1 %cmp2, i8 %b, i8 %a 231 %r = icmp eq i8 %m1, %m2 232 ret i1 %r 233} 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 1 241; 242 %cmp1 = icmp ugt i8 %a, %b 243 %cmp2 = icmp ugt i8 %b, %a 244 %m1 = select i1 %cmp1, i8 %a, i8 %b 245 %m2 = select i1 %cmp2, i8 %b, i8 %a 246 %r = udiv i8 %m1, %m2 247 ret i8 %r 248} 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, %b 259 %cmp2 = icmp ugt i8 %a, %b 260 %m1 = select i1 %cmp1, i8 %b, i8 %a 261 %m2 = select i1 %cmp2, i8 %a, i8 %b 262 %r = add i8 %m2, %m1 263 ret i8 %r 264} 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]], true 270; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]] 271; CHECK-NEXT: ret i1 true 272; 273 %cmp1 = icmp ugt i8 %a, %b 274 %cmp2 = xor i1 %cmp1, -1 275 %m1 = select i1 %cmp1, i8 %a, i8 %b 276 %m2 = select i1 %cmp2, i8 %b, i8 %a 277 %r = icmp eq i8 %m1, %m2 278 ret i1 %r 279} 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 canonicalize 283; 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]], 0 290; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 0, i8 [[SUB]] 291; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 [[SUB]], i8 0 292; CHECK-NEXT: [[R:%.*]] = sub i8 [[M2]], [[M1]] 293; CHECK-NEXT: ret i8 [[R]] 294; 295 %sub = sub nsw i8 %a, %b 296 %cmp1 = icmp slt i8 %a, %b 297 %cmp2 = icmp sgt i8 %sub, 0 298 %m1 = select i1 %cmp1, i8 0, i8 %sub 299 %m2 = select i1 %cmp2, i8 %sub, i8 0 300 %r = sub i8 %m2, %m1 301 ret i8 %r 302} 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]], 0 309; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0 310; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]] 311; CHECK-NEXT: ret i8 0 312; 313 %neg = sub i8 0, %a 314 %cmp1 = icmp sge i8 %a, 0 315 %cmp2 = icmp slt i8 %a, 0 316 %m1 = select i1 %cmp1, i8 %a, i8 %neg 317 %m2 = select i1 %cmp2, i8 %neg, i8 %a 318 %r = xor i8 %m2, %m1 319 ret i8 %r 320} 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]], 0 326; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i8 [[A]], 0 327; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]] 328; CHECK-NEXT: ret i8 0 329; 330 %neg = sub i8 0, %a 331 %cmp1 = icmp slt i8 %a, 0 332 %cmp2 = icmp sge i8 %a, 0 333 %m1 = select i1 %cmp1, i8 %a, i8 %neg 334 %m2 = select i1 %cmp2, i8 %neg, i8 %a 335 %r = xor i8 %m2, %m1 336 ret i8 %r 337} 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 canonicalize 341; 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]], 0 347; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0 348; 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, %a 354 %cmp1 = icmp sgt i8 %a, 0 355 %cmp2 = icmp slt i8 %a, 0 356 %m1 = select i1 %cmp1, i8 %a, i8 %neg 357 %m2 = select i1 %cmp2, i8 %neg, i8 %a 358 %r = or i8 %m2, %m1 359 ret i8 %r 360} 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]], 0 366; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true 367; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]] 368; CHECK-NEXT: ret i8 [[M1]] 369; 370 %neg = sub i8 0, %a 371 %cmp1 = icmp sgt i8 %a, 0 372 %cmp2 = xor i1 %cmp1, -1 373 %m1 = select i1 %cmp1, i8 %a, i8 %neg 374 %m2 = select i1 %cmp2, i8 %neg, i8 %a 375 %r = or i8 %m2, %m1 376 ret i8 %r 377} 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 canonicalize 381; 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]], 0 387; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], 0 388; 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, %a 394 %cmp1 = icmp slt i8 %a, 0 395 %cmp2 = icmp sgt i8 %a, 0 396 %m1 = select i1 %cmp1, i8 %a, i8 %neg 397 %m2 = select i1 %cmp2, i8 %neg, i8 %a 398 %r = xor i8 %m2, %m1 399 ret i8 %r 400} 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]], 0 406; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true 407; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]] 408; CHECK-NEXT: ret i8 0 409; 410 %neg = sub i8 0, %a 411 %cmp1 = icmp slt i8 %a, 0 412 %cmp2 = xor i1 %cmp1, -1 413 %m1 = select i1 %cmp1, i8 %a, i8 %neg 414 %m2 = select i1 %cmp2, i8 %neg, i8 %a 415 %r = xor i8 %m2, %m1 416 ret i8 %r 417} 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 canonicalize 421; 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]], -1 428; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0 429; 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, %a 435 %cmp1 = icmp sgt i8 %a, -1 436 %cmp2 = icmp slt i8 %a, 0 437 %m1 = select i1 %cmp1, i8 %a, i8 %neg 438 %m2 = select i1 %cmp2, i8 %neg, i8 %a 439 %r = or i8 %m2, %m1 440 ret i8 %r 441} 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 canonicalize 445; 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]], 0 451; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], -1 452; 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, %a 458 %cmp1 = icmp slt i8 %a, 0 459 %cmp2 = icmp sgt i8 %a, -1 460 %m1 = select i1 %cmp1, i8 %a, i8 %neg 461 %m2 = select i1 %cmp2, i8 %neg, i8 %a 462 %r = xor i8 %m2, %m1 463 ret i8 %r 464} 465 466; https://bugs.llvm.org/show_bug.cgi?id=41101 467; 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:%.*]], true 472; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]] 473; CHECK-NEXT: ret i32 0 474; 475 %not = xor i1 %cond, -1 476 %m1 = select i1 %cond, i32 %t, i32 %f 477 %m2 = select i1 %not, i32 %f, i32 %t 478 %r = xor i32 %m2, %m1 479 ret i32 %r 480} 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:%.*]], <i1 true, 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> <double 1.000000e+00, 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> %f 492 %m2 = select <2 x i1> %not, <2 x double> %f, <2 x double> %t 493 %r = fdiv nnan <2 x double> %m1, %m2 494 ret <2 x double> %r 495} 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:%.*]], true 502; 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, -1 508 %m1 = select i1 %cond, i32 %t, i32 %f 509 %m2 = select i1 %not, i32 %t, i32 %f 510 %r = xor i32 %m2, %m1 511 ret i32 %r 512} 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, -2 524 %m1 = select i1 %cond, i32 %t, i32 %f 525 %m2 = select i1 %not, i32 %f, i32 %t 526 %r = xor i32 %m2, %m1 527 ret i32 %r 528} 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+01 535; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01 536; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]] 537; CHECK-NEXT: ret i32 0 538; 539 %cond = fcmp ueq float %x, 42.0 540 %invcond = fcmp one float %x, 42.0 541 %m1 = select i1 %cond, i32 %t, i32 %f 542 %m2 = select i1 %invcond, i32 %f, i32 %t 543 %r = xor i32 %m2, %m1 544 ret i32 %r 545} 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> zeroinitializer 555; 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> %f 559 %m2 = select <2 x i1> %invcond, <2 x i32> %f, <2 x i32> %t 560 %r = xor <2 x i32> %m1, %m2 561 ret <2 x i32> %r 562} 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+01 569; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01 570; 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.0 576 %invcond = fcmp one float %x, 42.0 577 %m1 = select i1 %cond, i32 %f, i32 %t 578 %m2 = select i1 %invcond, i32 %f, i32 %t 579 %r = xor i32 %m2, %m1 580 ret i32 %r 581} 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+01 588; CHECK-NEXT: [[INVCOND:%.*]] = fcmp une float [[X]], 4.200000e+01 589; 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.0 595 %invcond = fcmp une float %x, 42.0 596 %m1 = select i1 %cond, i32 %t, i32 %f 597 %m2 = select i1 %invcond, i32 %f, i32 %t 598 %r = xor i32 %m2, %m1 599 ret i32 %r 600} 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+01 607; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.300000e+01 608; 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.0 614 %invcond = fcmp one float %x, 43.0 615 %m1 = select i1 %cond, i32 %t, i32 %f 616 %m2 = select i1 %invcond, i32 %f, i32 %t 617 %r = xor i32 %m2, %m1 618 ret i32 %r 619} 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:%.*]], 42 626; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X]], 42 627; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true 628; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]] 629; CHECK-NEXT: ret i32 0 630; 631 %cond = icmp ugt i8 %x, 42 632 %invcond = icmp ule i8 %x, 42 633 %not = xor i1 %invcond, -1 634 %m1 = select i1 %cond, i32 %t, i32 %f 635 %m2 = select i1 %not, i32 %t, i32 %f 636 %r = sub i32 %m1, %m2 637 ret i32 %r 638} 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]], true 646; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]] 647; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]] 648; CHECK-NEXT: ret i32 0 649; 650 %invcond = icmp ule i8 %x, %y 651 %not = xor i1 %invcond, -1 652 %m2 = select i1 %not, i32 %t, i32 %f 653 %cond = icmp ugt i8 %x, %y 654 %m1 = select i1 %cond, i32 %t, i32 %f 655 %r = sub i32 %m2, %m1 656 ret i32 %r 657} 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]], true 665; 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, %y 672 %not = xor i1 %invcond, -1 673 %m2 = select i1 %not, i32 %t, i32 %f 674 %cond = icmp ugt i8 %x, %y 675 %m1 = select i1 %cond, i32 %t, i32 %f 676 %r = sub i32 %m2, %m1 677 ret i32 %r 678} 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:%.*]], 42 685; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true 686; 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, 42 693 %not = xor i1 %invcond, -1 694 %m2 = select i1 %not, i32 %t, i32 %f 695 %cond = icmp ugt i8 %x, %y 696 %m1 = select i1 %cond, i32 %t, i32 %f 697 %r = sub i32 %m2, %m1 698 ret i32 %r 699} 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]], true 707; 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, %y 714 %not = xor i1 %invcond, -1 715 %m2 = select i1 %not, i32 %t, i32 %f 716 %cond = icmp ugt i8 %x, %y 717 %m1 = select i1 %cond, i32 %f, i32 %t 718 %r = sub i32 %m2, %m1 719 ret i32 %r 720} 721 722; This test is a reproducer for a bug involving inverted min/max selects 723; hashing differently but comparing as equal. It exhibits such a pair of 724; values, and we run this test with -earlycse-debug-hash which would catch 725; the disagreement and fail if it regressed. 726; EarlyCSE should be able to detect the 2nd redundant `select` and eliminate 727; 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 0 732; 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, %i 737 %m1 = select i1 %cmp, i32 %i, i32 0 738 %cmpinv = icmp sgt i32 0, %i 739 %m2 = select i1 %cmpinv, i32 0, i32 %i 740 %r = add i32 %m1, %m2 741 ret i32 %r 742} 743 744; This test is a reproducer for a bug involving inverted min/max selects 745; hashing differently but comparing as equal. It exhibits such a pair of 746; values, and we run this test with -earlycse-debug-hash which would catch 747; the disagreement and fail if it regressed. This test also includes a 748; negation of each negation to check for the same issue one level deeper. 749define void @not_not_min(i32* %px, i32* %py, i32* %pout) { 750; CHECK-LABEL: @not_not_min( 751; CHECK-NEXT: [[X:%.*]] = load volatile i32, i32* [[PX:%.*]], align 4 752; CHECK-NEXT: [[Y:%.*]] = load volatile i32, i32* [[PY:%.*]], align 4 753; CHECK-NEXT: [[CMPA:%.*]] = icmp slt i32 [[X]], [[Y]] 754; CHECK-NEXT: [[CMPB:%.*]] = xor i1 [[CMPA]], true 755; CHECK-NEXT: [[RA:%.*]] = select i1 [[CMPA]], i32 [[X]], i32 [[Y]] 756; CHECK-NEXT: store volatile i32 [[RA]], i32* [[POUT:%.*]], align 4 757; CHECK-NEXT: store volatile i32 [[RA]], i32* [[POUT]], align 4 758; CHECK-NEXT: store volatile i32 [[RA]], i32* [[POUT]], align 4 759; CHECK-NEXT: ret void 760; 761 %x = load volatile i32, i32* %px 762 %y = load volatile i32, i32* %py 763 %cmpa = icmp slt i32 %x, %y 764 %cmpb = xor i1 %cmpa, -1 765 %cmpc = xor i1 %cmpb, -1 766 %ra = select i1 %cmpa, i32 %x, i32 %y 767 %rb = select i1 %cmpb, i32 %y, i32 %x 768 %rc = select i1 %cmpc, i32 %x, i32 %y 769 store volatile i32 %ra, i32* %pout 770 store volatile i32 %rb, i32* %pout 771 store volatile i32 %rc, i32* %pout 772 773 ret void 774} 775 776; This would cause an assert/crash because we matched 777; a ValueTracking select pattern that required 'nsw' 778; on an operand, but we remove that flag as part of 779; 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 0 786; CHECK-NEXT: ret void 787; 788 %cmp = icmp sgt i32 %clip_left, %span_left 789 %sub = sub nsw i32 %clip_left, %span_left 790 %cond = select i1 %cmp, i32 %sub, i32 0 791 %cmp83292 = icmp slt i32 %cond, undef 792 %sub2 = sub i32 %clip_left, %span_left 793 %sel2 = select i1 %cmp, i32 %sub2, i32 0 794 ret void 795} 796 797; This would cause an assert/crash because we matched 798; a ValueTracking select pattern that required 'nsw' 799; on an operand, but we remove that flag as part of 800; 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]], 2 806; 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 0 809; CHECK-NEXT: [[M:%.*]] = mul i32 [[SEL]], [[SUB]] 810; CHECK-NEXT: ret i32 [[M]] 811; 812 %s = sub i32 0, %p 813 %a = ashr exact i32 %s, 2 814 %cmp = icmp sgt i32 0, %a 815 %sub = sub nsw i32 0, %a 816 %sel = select i1 %cmp, i32 %sub, i32 0 817 %s2 = sub i32 0, %a 818 %m = mul i32 %sel, %s2 819 ret i32 %m 820} 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+00 826; 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, %y 830 ret float %r 831} 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> <float 1.000000e+00, 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, %y 841 ret <2 x float> %r 842} 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> <double 1.000000e+00, 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, %y 852 ret <2 x double> %r 853} 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+00 859; 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, %y 863 ret double %r 864} 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]], 0 869; 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, 0 874 %y1 = extractvalue {i16, i1} %y, 0 875 %o = or i16 %x1, %y1 876 ret i16 %o 877} 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]], 0 883; 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, 0 888 %y1 = extractvalue {<5 x i65>, <5 x i1>} %y, 0 889 %o = or <5 x i65> %x1, %y1 890 ret <5 x i65> %o 891} 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]], 0 897; 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, 0 902 %y1 = extractvalue {i37, i1} %y, 0 903 %o = or i37 %x1, %y1 904 ret i37 %o 905} 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]], 0 911; 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, 0 916 %y1 = extractvalue {<2 x i31>, <2 x i1>} %y, 0 917 %o = or <2 x i31> %x1, %y1 918 ret <2 x i31> %o 919} 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, %y 929 ret i64 %o 930} 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, %y 940 ret <2 x i64> %o 941} 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, %y 951 ret <2 x i64> %o 952} 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, %y 962 ret i4 %o 963} 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, %y 973 ret i67 %o 974} 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, %y 984 ret <3 x i17> %o 985} 986 987; Negative test - mismatched intrinsics 988 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, %y 999 ret i4 %o 1000} 1001 1002; TODO: handle >2 args 1003 1004define i16 @smul_fix(i16 %a, i16 %b) { 1005; CHECK-LABEL: @smul_fix( 1006; CHECK-NEXT: [[X:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 3) 1007; CHECK-NEXT: [[Y:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[B]], i16 [[A]], i32 3) 1008; CHECK-NEXT: [[O:%.*]] = or i16 [[X]], [[Y]] 1009; CHECK-NEXT: ret i16 [[O]] 1010; 1011 %x = call i16 @llvm.smul.fix.i16(i16 %a, i16 %b, i32 3) 1012 %y = call i16 @llvm.smul.fix.i16(i16 %b, i16 %a, i32 3) 1013 %o = or i16 %x, %y 1014 ret i16 %o 1015} 1016 1017; TODO: handle >2 args 1018 1019define i16 @umul_fix(i16 %a, i16 %b, i32 %s) { 1020; CHECK-LABEL: @umul_fix( 1021; CHECK-NEXT: [[X:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 1) 1022; CHECK-NEXT: [[Y:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[B]], i16 [[A]], i32 1) 1023; CHECK-NEXT: [[O:%.*]] = or i16 [[X]], [[Y]] 1024; CHECK-NEXT: ret i16 [[O]] 1025; 1026 %x = call i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 1) 1027 %y = call i16 @llvm.umul.fix.i16(i16 %b, i16 %a, i32 1) 1028 %o = or i16 %x, %y 1029 ret i16 %o 1030} 1031 1032; TODO: handle >2 args 1033 1034define <3 x i16> @smul_fix_sat(<3 x i16> %a, <3 x i16> %b) { 1035; CHECK-LABEL: @smul_fix_sat( 1036; CHECK-NEXT: [[X:%.*]] = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> [[A:%.*]], <3 x i16> [[B:%.*]], i32 2) 1037; CHECK-NEXT: [[Y:%.*]] = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> [[B]], <3 x i16> [[A]], i32 2) 1038; CHECK-NEXT: [[O:%.*]] = or <3 x i16> [[X]], [[Y]] 1039; CHECK-NEXT: ret <3 x i16> [[O]] 1040; 1041 %x = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> %a, <3 x i16> %b, i32 2) 1042 %y = call <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16> %b, <3 x i16> %a, i32 2) 1043 %o = or <3 x i16> %x, %y 1044 ret <3 x i16> %o 1045} 1046 1047; TODO: handle >2 args 1048 1049define <3 x i16> @umul_fix_sat(<3 x i16> %a, <3 x i16> %b) { 1050; CHECK-LABEL: @umul_fix_sat( 1051; CHECK-NEXT: [[X:%.*]] = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> [[A:%.*]], <3 x i16> [[B:%.*]], i32 3) 1052; CHECK-NEXT: [[Y:%.*]] = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> [[B]], <3 x i16> [[A]], i32 3) 1053; CHECK-NEXT: [[O:%.*]] = or <3 x i16> [[X]], [[Y]] 1054; CHECK-NEXT: ret <3 x i16> [[O]] 1055; 1056 %x = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> %a, <3 x i16> %b, i32 3) 1057 %y = call <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16> %b, <3 x i16> %a, i32 3) 1058 %o = or <3 x i16> %x, %y 1059 ret <3 x i16> %o 1060} 1061 1062define i16 @umul_smul_fix(i16 %a, i16 %b, i32 %s) { 1063; CHECK-LABEL: @umul_smul_fix( 1064; CHECK-NEXT: [[X:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 1) 1065; CHECK-NEXT: [[Y:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[B]], i16 [[A]], i32 1) 1066; CHECK-NEXT: [[O:%.*]] = or i16 [[X]], [[Y]] 1067; CHECK-NEXT: ret i16 [[O]] 1068; 1069 %x = call i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 1) 1070 %y = call i16 @llvm.smul.fix.i16(i16 %b, i16 %a, i32 1) 1071 %o = or i16 %x, %y 1072 ret i16 %o 1073} 1074 1075define i16 @umul_fix_scale(i16 %a, i16 %b, i32 %s) { 1076; CHECK-LABEL: @umul_fix_scale( 1077; CHECK-NEXT: [[X:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[A:%.*]], i16 [[B:%.*]], i32 1) 1078; CHECK-NEXT: [[Y:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[B]], i16 [[A]], i32 2) 1079; CHECK-NEXT: [[O:%.*]] = or i16 [[X]], [[Y]] 1080; CHECK-NEXT: ret i16 [[O]] 1081; 1082 %x = call i16 @llvm.umul.fix.i16(i16 %a, i16 %b, i32 1) 1083 %y = call i16 @llvm.umul.fix.i16(i16 %b, i16 %a, i32 2) 1084 %o = or i16 %x, %y 1085 ret i16 %o 1086} 1087 1088; TODO: handle >2 args 1089 1090define float @fma(float %a, float %b, float %c) { 1091; CHECK-LABEL: @fma( 1092; CHECK-NEXT: [[X:%.*]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[C:%.*]]) 1093; CHECK-NEXT: [[Y:%.*]] = call float @llvm.fma.f32(float [[B]], float [[A]], float [[C]]) 1094; CHECK-NEXT: [[R:%.*]] = fdiv nnan float [[X]], [[Y]] 1095; CHECK-NEXT: ret float [[R]] 1096; 1097 %x = call float @llvm.fma.f32(float %a, float %b, float %c) 1098 %y = call float @llvm.fma.f32(float %b, float %a, float %c) 1099 %r = fdiv nnan float %x, %y 1100 ret float %r 1101} 1102 1103define float @fma_different_add_ops(float %a, float %b, float %c, float %d) { 1104; CHECK-LABEL: @fma_different_add_ops( 1105; CHECK-NEXT: [[X:%.*]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[C:%.*]]) 1106; CHECK-NEXT: [[Y:%.*]] = call float @llvm.fma.f32(float [[B]], float [[A]], float [[D:%.*]]) 1107; CHECK-NEXT: [[R:%.*]] = fdiv nnan float [[X]], [[Y]] 1108; CHECK-NEXT: ret float [[R]] 1109; 1110 %x = call float @llvm.fma.f32(float %a, float %b, float %c) 1111 %y = call float @llvm.fma.f32(float %b, float %a, float %d) 1112 %r = fdiv nnan float %x, %y 1113 ret float %r 1114} 1115 1116; TODO: handle >2 args 1117 1118define <2 x double> @fmuladd(<2 x double> %a, <2 x double> %b, <2 x double> %c) { 1119; CHECK-LABEL: @fmuladd( 1120; CHECK-NEXT: [[X:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[A:%.*]], <2 x double> [[B:%.*]], <2 x double> [[C:%.*]]) 1121; CHECK-NEXT: [[Y:%.*]] = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[B]], <2 x double> [[A]], <2 x double> [[C]]) 1122; CHECK-NEXT: [[R:%.*]] = fdiv nnan <2 x double> [[X]], [[Y]] 1123; CHECK-NEXT: ret <2 x double> [[R]] 1124; 1125 %x = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c) 1126 %y = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %b, <2 x double> %a, <2 x double> %c) 1127 %r = fdiv nnan <2 x double> %x, %y 1128 ret <2 x double> %r 1129} 1130 1131declare float @llvm.maxnum.f32(float, float) 1132declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>) 1133declare <2 x double> @llvm.maximum.v2f64(<2 x double>, <2 x double>) 1134declare double @llvm.minimum.f64(double, double) 1135 1136declare {i16, i1} @llvm.sadd.with.overflow.i16(i16, i16) 1137declare {<5 x i65>, <5 x i1>} @llvm.uadd.with.overflow.v5i65(<5 x i65>, <5 x i65>) 1138declare {i37, i1} @llvm.smul.with.overflow.i37(i37, i37) 1139declare {<2 x i31>, <2 x i1>} @llvm.umul.with.overflow.v2i31(<2 x i31>, <2 x i31>) 1140declare i64 @llvm.sadd.sat.i64(i64, i64) 1141declare <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64>, <2 x i64>) 1142 1143declare <2 x i64> @llvm.smax.v2i64(<2 x i64>, <2 x i64>) 1144declare i4 @llvm.smin.i4(i4, i4) 1145declare i4 @llvm.umin.i4(i4, i4) 1146declare i67 @llvm.umax.i67(i67, i67) 1147declare <3 x i17> @llvm.umin.v3i17(<3 x i17>, <3 x i17>) 1148 1149declare i16 @llvm.smul.fix.i16(i16, i16, i32) 1150declare i16 @llvm.umul.fix.i16(i16, i16, i32) 1151declare <3 x i16> @llvm.smul.fix.sat.v3i16(<3 x i16>, <3 x i16>, i32) 1152declare <3 x i16> @llvm.umul.fix.sat.v3i16(<3 x i16>, <3 x i16>, i32) 1153 1154declare float @llvm.fma.f32(float, float, float) 1155declare <2 x double> @llvm.fmuladd.v2f64(<2 x double>, <2 x double>, <2 x double>) 1156