@@ -519,6 +519,90 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
519
519
}
520
520
}
521
521
break ;
522
+ case Intrinsic::minnum:
523
+ case Intrinsic::maxnum: {
524
+ Value *Arg0 = II->getArgOperand (0 );
525
+ Value *Arg1 = II->getArgOperand (1 );
526
+
527
+ // fmin(x, x) -> x
528
+ if (Arg0 == Arg1)
529
+ return ReplaceInstUsesWith (CI, Arg0);
530
+
531
+ const ConstantFP *C0 = dyn_cast<ConstantFP>(Arg0);
532
+ const ConstantFP *C1 = dyn_cast<ConstantFP>(Arg1);
533
+
534
+ // Canonicalize constants into the RHS.
535
+ if (C0 && !C1) {
536
+ II->setArgOperand (0 , Arg1);
537
+ II->setArgOperand (1 , Arg0);
538
+ return II;
539
+ }
540
+
541
+ // fmin(x, nan) -> x
542
+ if (C1 && C1->isNaN ())
543
+ return ReplaceInstUsesWith (CI, Arg0);
544
+
545
+ // This is the value because if undef were NaN, we would return the other
546
+ // value and cannot return a NaN unless both operands are.
547
+ //
548
+ // fmin(undef, x) -> x
549
+ if (isa<UndefValue>(Arg0))
550
+ return ReplaceInstUsesWith (CI, Arg1);
551
+
552
+ // fmin(x, undef) -> x
553
+ if (isa<UndefValue>(Arg1))
554
+ return ReplaceInstUsesWith (CI, Arg0);
555
+
556
+ Value *X = nullptr ;
557
+ Value *Y = nullptr ;
558
+ if (II->getIntrinsicID () == Intrinsic::minnum) {
559
+ // fmin(x, fmin(x, y)) -> fmin(x, y)
560
+ // fmin(y, fmin(x, y)) -> fmin(x, y)
561
+ if (match (Arg1, m_FMin (m_Value (X), m_Value (Y)))) {
562
+ if (Arg0 == X || Arg0 == Y)
563
+ return ReplaceInstUsesWith (CI, Arg1);
564
+ }
565
+
566
+ // fmin(fmin(x, y), x) -> fmin(x, y)
567
+ // fmin(fmin(x, y), y) -> fmin(x, y)
568
+ if (match (Arg0, m_FMin (m_Value (X), m_Value (Y)))) {
569
+ if (Arg1 == X || Arg1 == Y)
570
+ return ReplaceInstUsesWith (CI, Arg0);
571
+ }
572
+
573
+ // TODO: fmin(nnan x, inf) -> x
574
+ // TODO: fmin(nnan ninf x, flt_max) -> x
575
+ if (C1 && C1->isInfinity ()) {
576
+ // fmin(x, -inf) -> -inf
577
+ if (C1->isNegative ())
578
+ return ReplaceInstUsesWith (CI, Arg1);
579
+ }
580
+ } else {
581
+ assert (II->getIntrinsicID () == Intrinsic::maxnum);
582
+ // fmax(x, fmax(x, y)) -> fmax(x, y)
583
+ // fmax(y, fmax(x, y)) -> fmax(x, y)
584
+ if (match (Arg1, m_FMax (m_Value (X), m_Value (Y)))) {
585
+ if (Arg0 == X || Arg0 == Y)
586
+ return ReplaceInstUsesWith (CI, Arg1);
587
+ }
588
+
589
+ // fmax(fmax(x, y), x) -> fmax(x, y)
590
+ // fmax(fmax(x, y), y) -> fmax(x, y)
591
+ if (match (Arg0, m_FMax (m_Value (X), m_Value (Y)))) {
592
+ if (Arg1 == X || Arg1 == Y)
593
+ return ReplaceInstUsesWith (CI, Arg0);
594
+ }
595
+
596
+ // TODO: fmax(nnan x, -inf) -> x
597
+ // TODO: fmax(nnan ninf x, -flt_max) -> x
598
+ if (C1 && C1->isInfinity ()) {
599
+ // fmax(x, inf) -> inf
600
+ if (!C1->isNegative ())
601
+ return ReplaceInstUsesWith (CI, Arg1);
602
+ }
603
+ }
604
+ break ;
605
+ }
522
606
case Intrinsic::ppc_altivec_lvx:
523
607
case Intrinsic::ppc_altivec_lvxl:
524
608
// Turn PPC lvx -> load if the pointer is known aligned.
0 commit comments