@@ -457,32 +457,36 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul)
457457//
458458GenTree* Lowering::LowerBinaryArithmetic (GenTreeOp* binOp)
459459{
460- if (comp->opts .OptimizationEnabled () && binOp-> OperIs (GT_AND) )
460+ if (comp->opts .OptimizationEnabled ())
461461 {
462- GenTree* opNode = nullptr ;
463- GenTree* notNode = nullptr ;
464- if (binOp->gtGetOp1 ()->OperIs (GT_NOT))
465- {
466- notNode = binOp->gtGetOp1 ();
467- opNode = binOp->gtGetOp2 ();
468- }
469- else if (binOp->gtGetOp2 ()->OperIs (GT_NOT))
462+ if (binOp->OperIs (GT_AND))
470463 {
471- notNode = binOp->gtGetOp2 ();
472- opNode = binOp->gtGetOp1 ();
473- }
464+ GenTree* opNode = nullptr ;
465+ GenTree* notNode = nullptr ;
466+ if (binOp->gtGetOp1 ()->OperIs (GT_NOT))
467+ {
468+ notNode = binOp->gtGetOp1 ();
469+ opNode = binOp->gtGetOp2 ();
470+ }
471+ else if (binOp->gtGetOp2 ()->OperIs (GT_NOT))
472+ {
473+ notNode = binOp->gtGetOp2 ();
474+ opNode = binOp->gtGetOp1 ();
475+ }
474476
475- if (notNode != nullptr )
476- {
477- binOp->gtOp1 = opNode;
478- binOp->gtOp2 = notNode->AsUnOp ()->gtGetOp1 ();
479- binOp->ChangeOper (GT_AND_NOT);
480- BlockRange ().Remove (notNode);
477+ if (notNode != nullptr )
478+ {
479+ binOp->gtOp1 = opNode;
480+ binOp->gtOp2 = notNode->AsUnOp ()->gtGetOp1 ();
481+ binOp->ChangeOper (GT_AND_NOT);
482+ BlockRange ().Remove (notNode);
483+ }
481484 }
485+
482486#ifdef TARGET_ARM64
483- else
487+ if (binOp-> OperIs (GT_AND, GT_OR))
484488 {
485- GenTree* next = TryLowerAndToCCMP (binOp);
489+ GenTree* next = TryLowerAndOrToCCMP (binOp);
486490 if (next != nullptr )
487491 {
488492 return next;
@@ -2268,14 +2272,14 @@ void Lowering::ContainCheckCompare(GenTreeOp* cmp)
22682272
22692273#ifdef TARGET_ARM64
22702274// ------------------------------------------------------------------------
2271- // TryLowerAndToCCMP : Lower an and of two conditions into test + CCMP + SETCC nodes.
2275+ // TryLowerAndOrToCCMP : Lower AND/OR of two conditions into test + CCMP + SETCC nodes.
22722276//
22732277// Arguments:
22742278// tree - pointer to the node
22752279//
2276- GenTree* Lowering::TryLowerAndToCCMP (GenTreeOp* tree)
2280+ GenTree* Lowering::TryLowerAndOrToCCMP (GenTreeOp* tree)
22772281{
2278- assert (tree->OperIs (GT_AND));
2282+ assert (tree->OperIs (GT_AND, GT_OR ));
22792283
22802284 if (!comp->opts .OptimizationEnabled ())
22812285 {
@@ -2285,42 +2289,39 @@ GenTree* Lowering::TryLowerAndToCCMP(GenTreeOp* tree)
22852289 GenTree* op1 = tree->gtGetOp1 ();
22862290 GenTree* op2 = tree->gtGetOp2 ();
22872291
2288- // Find out whether op2 is eligible to be converted to a conditional
2292+ if ((op1->OperIsCmpCompare () && varTypeIsIntegralOrI (op1->gtGetOp1 ())) ||
2293+ (op2->OperIsCmpCompare () && varTypeIsIntegralOrI (op2->gtGetOp1 ())))
2294+ {
2295+ JITDUMP (" [%06u] is a potential candidate for CCMP:\n " , Compiler::dspTreeID (tree));
2296+ DISPTREERANGE (BlockRange (), tree);
2297+ JITDUMP (" \n " );
2298+ }
2299+
2300+ // Find out whether an operand is eligible to be converted to a conditional
22892301 // compare. It must be a normal integral relop; for example, we cannot
22902302 // conditionally perform a floating point comparison and there is no "ctst"
22912303 // instruction that would allow us to conditionally implement
22922304 // TEST_EQ/TEST_NE.
22932305 //
2294- if (!op2->OperIsCmpCompare () || !varTypeIsIntegral (op2->gtGetOp1 ()))
2295- {
2296- return nullptr ;
2297- }
2298-
2299- // For op1 we can allow more arbitrary operations that set the condition
2300- // flags; the final transformation into the flags def is done by
2301- // TryLowerConditionToFlagsNode below, but we have a quick early out here
2302- // too.
2306+ // For the other operand we can allow more arbitrary operations that set
2307+ // the condition flags; the final transformation into the flags def is done
2308+ // by TryLowerConditionToFlagsNode.
23032309 //
2304- if (!op1->OperIsCompare () && !op1->OperIs (GT_SETCC))
2310+ GenCondition cond1;
2311+ if (op2->OperIsCmpCompare () && varTypeIsIntegralOrI (op2->gtGetOp1 ()) && IsInvariantInRange (op2, tree) &&
2312+ TryLowerConditionToFlagsNode (tree, op1, &cond1))
23052313 {
2306- return nullptr ;
2314+ // Fall through, converting op2 to the CCMP
23072315 }
2308-
2309- JITDUMP (" [%06u] is a candidate for CCMP:\n " , Compiler::dspTreeID (tree));
2310- DISPTREERANGE (BlockRange (), tree);
2311- JITDUMP (" \n " );
2312-
2313- // We leave checking invariance of op1 to tree to TryLowerConditionToFlagsNode.
2314- if (!IsInvariantInRange (op2, tree))
2316+ else if (op1->OperIsCmpCompare () && varTypeIsIntegralOrI (op1->gtGetOp1 ()) && IsInvariantInRange (op1, tree) &&
2317+ TryLowerConditionToFlagsNode (tree, op2, &cond1))
23152318 {
2316- JITDUMP (" ..cannot move [%06u], bailing\n " , Compiler::dspTreeID (op2));
2317- return nullptr ;
2319+ std::swap (op1, op2);
23182320 }
2319-
2320- GenCondition cond1;
2321- if (!TryLowerConditionToFlagsNode (tree, op1, &cond1))
2321+ else
23222322 {
2323- JITDUMP (" ..could not turn [%06u] into a def of flags, bailing\n " , Compiler::dspTreeID (op1));
2323+ JITDUMP (" ..could not turn [%06u] or [%06u] into a def of flags, bailing\n " , Compiler::dspTreeID (op1),
2324+ Compiler::dspTreeID (op2));
23242325 return nullptr ;
23252326 }
23262327
@@ -2336,10 +2337,24 @@ GenTree* Lowering::TryLowerAndToCCMP(GenTreeOp* tree)
23362337 op2->gtGetOp2 ()->ClearContained ();
23372338
23382339 GenTreeCCMP* ccmp = op2->AsCCMP ();
2339- ccmp->gtCondition = cond1;
2340- // If the first comparison fails, set the condition flags to something that
2341- // makes the second one fail as well so that the overall AND failed.
2342- ccmp->gtFlagsVal = TruthifyingFlags (GenCondition::Reverse (cond2));
2340+
2341+ if (tree->OperIs (GT_AND))
2342+ {
2343+ // If the first comparison succeeds then do the second comparison.
2344+ ccmp->gtCondition = cond1;
2345+ // Otherwise set the condition flags to something that makes the second
2346+ // one fail.
2347+ ccmp->gtFlagsVal = TruthifyingFlags (GenCondition::Reverse (cond2));
2348+ }
2349+ else
2350+ {
2351+ // If the first comparison fails then do the second comparison.
2352+ ccmp->gtCondition = GenCondition::Reverse (cond1);
2353+ // Otherwise set the condition flags to something that makes the second
2354+ // one succeed.
2355+ ccmp->gtFlagsVal = TruthifyingFlags (cond2);
2356+ }
2357+
23432358 ContainCheckConditionalCompare (ccmp);
23442359
23452360 tree->SetOper (GT_SETCC);
0 commit comments