@@ -56,6 +56,7 @@ class OptIfConversionDsc
5656 GenTree* TrySelectToCnsOpCond (GenTreeConditional* select);
5757 GenTree* TrySelectToLclOpCond (GenTreeConditional* select);
5858 GenTree* TrySelectToCondOpLcl (GenTreeConditional* select);
59+ GenTree* TrySelectToMinMax (GenTreeConditional* select);
5960
6061#ifdef DEBUG
6162 void IfConvertDump ();
@@ -205,7 +206,7 @@ bool OptIfConversionDsc::IfConvertCheckStmts(BasicBlock* block, IfConvertOperati
205206 }
206207
207208 // Ensure the operation has integer type.
208- if (!varTypeIsIntegralOrI (tree))
209+ if (!varTypeIsIntegralOrI (tree) && ! varTypeIsFloating (tree) )
209210 {
210211 return false ;
211212 }
@@ -636,6 +637,12 @@ bool OptIfConversionDsc::optIfConvert(int* pReachabilityBudget)
636637 }
637638 }
638639
640+ // We only produce float SELECTs for optimization into non-SELECTs, otherwise bail
641+ if (varTypeIsFloating (select))
642+ {
643+ return true ;
644+ }
645+
639646#ifdef TARGET_RISCV64
640647 if (select->OperIs (GT_SELECT ))
641648 {
@@ -739,6 +746,12 @@ GenTree* OptIfConversionDsc::TryOptimizeSelect(GenTreeConditional* select)
739746 return opt;
740747 }
741748
749+ opt = TrySelectToMinMax (select);
750+ if (opt != nullptr )
751+ {
752+ return opt;
753+ }
754+
742755 return nullptr ;
743756}
744757
@@ -960,6 +973,46 @@ GenTree* OptIfConversionDsc::TrySelectToCondOpLcl(GenTreeConditional* select)
960973 return nullptr ;
961974}
962975
976+ GenTree* OptIfConversionDsc::TrySelectToMinMax (GenTreeConditional* select)
977+ {
978+ #ifdef TARGET_XARCH
979+ GenTree* condInput = select->gtCond ;
980+ GenTree* trueInput = select->gtOp1 ;
981+ GenTree* falseInput = select->gtOp2 ;
982+
983+ if (!varTypeIsFloating (select) || !varTypeIsFloating (condInput->gtGetOp1 ()) || !varTypeIsFloating (condInput->gtGetOp2 ()))
984+ {
985+ return nullptr ;
986+ }
987+
988+ GenCondition cond = GenCondition::FromFloatRelop (condInput);
989+ if (cond.IsUnordered () || !cond.Is (GenCondition::Code::FLT , GenCondition::Code::FGT ))
990+ {
991+ return nullptr ;
992+ }
993+
994+ bool isMax = cond.Is (GenCondition::Code::FGT );
995+ bool reversed = !GenTree::Compare (trueInput, condInput->gtGetOp1 ());
996+ if (reversed)
997+ {
998+ // 'return a > b ? b : a;' has a GT but computes the min
999+ isMax = !isMax;
1000+ std::swap (trueInput, falseInput);
1001+ }
1002+
1003+ if (GenTree::Compare (trueInput, condInput->gtGetOp1 ()) &&
1004+ GenTree::Compare (falseInput, condInput->gtGetOp2 ()->gtEffectiveVal ()))
1005+ {
1006+ return m_compiler->gtNewSimdMinMaxNativeNode (select->TypeGet (),
1007+ reversed ? condInput->gtGetOp2 () : condInput->gtGetOp1 (),
1008+ reversed ? condInput->gtGetOp1 () : condInput->gtGetOp2 (),
1009+ select->TypeGet (), 0 , isMax);
1010+ }
1011+
1012+ #endif
1013+ return nullptr ;
1014+ }
1015+
9631016// -----------------------------------------------------------------------------
9641017// optIfConversion: If conversion
9651018//
0 commit comments