Skip to content

Commit f9cf601

Browse files
alexcovingtonSergey Andreenko
and
Sergey Andreenko
authored
Gtneg mul divoptimizations (#45604)
* GT_NEG optimization for multiplication and division * Distribute negation over parenthetical multiplication or division. * Removing duplicate logic that I had put in accidently. * Check overflow and other conditions before performing morph * Resolved merge conflict and cleanup morph.cpp * Formatting morph.cpp * Returning tree after performing smpop again to fix flags * Formatting * Added check for optimizations, formatting. * Using gtIsActiveCSE_Candidate instead of fgGlobalMorph * Update src/coreclr/jit/morph.cpp Co-authored-by: Sergey Andreenko <[email protected]> * Formatting * delete formatting changes. * Add a test. * Change the conditions a bit. * Better names for the tests. Co-authored-by: Sergey Andreenko <[email protected]>
1 parent 0fd7a3f commit f9cf601

File tree

3 files changed

+411
-0
lines changed

3 files changed

+411
-0
lines changed

src/coreclr/jit/morph.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11909,6 +11909,21 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
1190911909
return fgMorphCast(tree);
1191011910

1191111911
case GT_MUL:
11912+
if (opts.OptimizationEnabled() && !optValnumCSE_phase && !tree->gtOverflow())
11913+
{
11914+
// MUL(NEG(a), C) => MUL(a, NEG(C))
11915+
if (op1->OperIs(GT_NEG) && !op1->gtGetOp1()->IsCnsIntOrI() && op2->IsCnsIntOrI() &&
11916+
!op2->IsIconHandle())
11917+
{
11918+
GenTree* newOp1 = op1->gtGetOp1();
11919+
GenTree* newConst = gtNewIconNode(-op2->AsIntCon()->IconValue(), op2->TypeGet());
11920+
DEBUG_DESTROY_NODE(op1);
11921+
DEBUG_DESTROY_NODE(op2);
11922+
tree->AsOp()->gtOp1 = newOp1;
11923+
tree->AsOp()->gtOp2 = newConst;
11924+
return fgMorphSmpOp(tree, mac);
11925+
}
11926+
}
1191211927

1191311928
#ifndef TARGET_64BIT
1191411929
if (typ == TYP_LONG)
@@ -12056,6 +12071,24 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
1205612071
return fgMorphSmpOp(tree, mac);
1205712072
}
1205812073

12074+
if (opts.OptimizationEnabled() && !optValnumCSE_phase)
12075+
{
12076+
// DIV(NEG(a), C) => DIV(a, NEG(C))
12077+
if (op1->OperIs(GT_NEG) && !op1->gtGetOp1()->IsCnsIntOrI() && op2->IsCnsIntOrI() &&
12078+
!op2->IsIconHandle())
12079+
{
12080+
ssize_t op2Value = op2->AsIntCon()->IconValue();
12081+
if (op2Value != 1 && op2Value != -1) // Div must throw exception for int(long).MinValue / -1.
12082+
{
12083+
tree->AsOp()->gtOp1 = op1->gtGetOp1();
12084+
DEBUG_DESTROY_NODE(op1);
12085+
tree->AsOp()->gtOp2 = gtNewIconNode(-op2Value, op2->TypeGet());
12086+
DEBUG_DESTROY_NODE(op2);
12087+
return fgMorphSmpOp(tree, mac);
12088+
}
12089+
}
12090+
}
12091+
1205912092
#ifndef TARGET_64BIT
1206012093
if (typ == TYP_LONG)
1206112094
{
@@ -13920,6 +13953,35 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
1392013953
return child;
1392113954
}
1392213955

13956+
// Distribute negation over simple multiplication/division expressions
13957+
if (opts.OptimizationEnabled() && !optValnumCSE_phase && tree->OperIs(GT_NEG) &&
13958+
op1->OperIs(GT_MUL, GT_DIV))
13959+
{
13960+
GenTreeOp* mulOrDiv = op1->AsOp();
13961+
GenTree* op1op1 = mulOrDiv->gtGetOp1();
13962+
GenTree* op1op2 = mulOrDiv->gtGetOp2();
13963+
13964+
if (!op1op1->IsCnsIntOrI() && op1op2->IsCnsIntOrI() && !op1op2->IsIconHandle())
13965+
{
13966+
// NEG(MUL(a, C)) => MUL(a, -C)
13967+
// NEG(DIV(a, C)) => DIV(a, -C), except when C = {-1, 1}
13968+
ssize_t constVal = op1op2->AsIntCon()->IconValue();
13969+
if ((mulOrDiv->OperIs(GT_DIV) && (constVal != -1) && (constVal != 1)) ||
13970+
(mulOrDiv->OperIs(GT_MUL) && !mulOrDiv->gtOverflow()))
13971+
{
13972+
GenTree* newOp1 = op1op1; // a
13973+
GenTree* newOp2 = gtNewIconNode(-constVal, op1op2->TypeGet()); // -C
13974+
mulOrDiv->gtOp1 = newOp1;
13975+
mulOrDiv->gtOp2 = newOp2;
13976+
13977+
DEBUG_DESTROY_NODE(tree);
13978+
DEBUG_DESTROY_NODE(op1op2);
13979+
13980+
return mulOrDiv;
13981+
}
13982+
}
13983+
}
13984+
1392313985
/* Any constant cases should have been folded earlier */
1392413986
noway_assert(!op1->OperIsConst() || !opts.OptEnabled(CLFLG_CONSTANTFOLD) || optValnumCSE_phase);
1392513987
break;

0 commit comments

Comments
 (0)