@@ -2377,20 +2377,60 @@ void CodeGen::genCodeForMulHi(GenTreeOp* treeNode)
2377
2377
2378
2378
// Generate code for ADD, SUB, MUL, DIV, UDIV, AND, AND_NOT, OR and XOR
2379
2379
// This method is expected to have called genConsumeOperands() before calling it.
2380
- void CodeGen::genCodeForBinary(GenTreeOp* treeNode )
2380
+ void CodeGen::genCodeForBinary(GenTreeOp* tree )
2381
2381
{
2382
- const genTreeOps oper = treeNode ->OperGet();
2383
- regNumber targetReg = treeNode ->GetRegNum();
2384
- var_types targetType = treeNode ->TypeGet();
2382
+ const genTreeOps oper = tree ->OperGet();
2383
+ regNumber targetReg = tree ->GetRegNum();
2384
+ var_types targetType = tree ->TypeGet();
2385
2385
emitter* emit = GetEmitter();
2386
2386
2387
- assert(treeNode ->OperIs(GT_ADD, GT_SUB, GT_MUL, GT_DIV, GT_UDIV, GT_AND, GT_AND_NOT, GT_OR, GT_XOR));
2387
+ assert(tree ->OperIs(GT_ADD, GT_SUB, GT_MUL, GT_DIV, GT_UDIV, GT_AND, GT_AND_NOT, GT_OR, GT_XOR));
2388
2388
2389
- GenTree* op1 = treeNode->gtGetOp1();
2390
- GenTree* op2 = treeNode->gtGetOp2();
2391
- instruction ins = genGetInsForOper(treeNode->OperGet(), targetType);
2389
+ GenTree* op1 = tree->gtGetOp1();
2390
+ GenTree* op2 = tree->gtGetOp2();
2392
2391
2393
- if ((treeNode->gtFlags & GTF_SET_FLAGS) != 0)
2392
+ // Handles combined operations: 'madd', 'msub'
2393
+ if (op2->OperIs(GT_MUL) && op2->isContained())
2394
+ {
2395
+ // In the future, we might consider enabling this for floating-point "unsafe" math.
2396
+ assert(varTypeIsIntegral(tree));
2397
+ assert(!(tree->gtFlags & GTF_SET_FLAGS));
2398
+
2399
+ GenTree* a = op1;
2400
+ GenTree* b = op2->gtGetOp1();
2401
+ GenTree* c = op2->gtGetOp2();
2402
+
2403
+ instruction ins;
2404
+ switch (oper)
2405
+ {
2406
+ case GT_ADD:
2407
+ {
2408
+ // d = a + b * c
2409
+ // madd: d, b, c, a
2410
+ ins = INS_madd;
2411
+ break;
2412
+ }
2413
+
2414
+ case GT_SUB:
2415
+ {
2416
+ // d = a - b * c
2417
+ // msub: d, b, c, a
2418
+ ins = INS_msub;
2419
+ break;
2420
+ }
2421
+
2422
+ default:
2423
+ unreached();
2424
+ }
2425
+
2426
+ emit->emitIns_R_R_R_R(ins, emitActualTypeSize(tree), targetReg, b->GetRegNum(), c->GetRegNum(), a->GetRegNum());
2427
+ genProduceReg(tree);
2428
+ return;
2429
+ }
2430
+
2431
+ instruction ins = genGetInsForOper(tree->OperGet(), targetType);
2432
+
2433
+ if ((tree->gtFlags & GTF_SET_FLAGS) != 0)
2394
2434
{
2395
2435
switch (oper)
2396
2436
{
@@ -2414,10 +2454,10 @@ void CodeGen::genCodeForBinary(GenTreeOp* treeNode)
2414
2454
// The arithmetic node must be sitting in a register (since it's not contained)
2415
2455
assert(targetReg != REG_NA);
2416
2456
2417
- regNumber r = emit->emitInsTernary(ins, emitActualTypeSize(treeNode ), treeNode , op1, op2);
2457
+ regNumber r = emit->emitInsTernary(ins, emitActualTypeSize(tree ), tree , op1, op2);
2418
2458
assert(r == targetReg);
2419
2459
2420
- genProduceReg(treeNode );
2460
+ genProduceReg(tree );
2421
2461
}
2422
2462
2423
2463
//------------------------------------------------------------------------
@@ -10062,76 +10102,6 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind)
10062
10102
}
10063
10103
}
10064
10104
10065
- //-----------------------------------------------------------------------------------
10066
- // genCodeForMadd: Emit a madd (Multiply-Add) instruction
10067
- //
10068
- // Arguments:
10069
- // tree - GT_MADD tree where op1 or op2 is GT_ADD
10070
- //
10071
- void CodeGen::genCodeForMadd(GenTreeOp* tree)
10072
- {
10073
- assert(tree->OperIs(GT_MADD) && varTypeIsIntegral(tree) && !(tree->gtFlags & GTF_SET_FLAGS));
10074
- genConsumeOperands(tree);
10075
-
10076
- GenTree* a;
10077
- GenTree* b;
10078
- GenTree* c;
10079
- if (tree->gtGetOp1()->OperIs(GT_MUL) && tree->gtGetOp1()->isContained())
10080
- {
10081
- a = tree->gtGetOp1()->gtGetOp1();
10082
- b = tree->gtGetOp1()->gtGetOp2();
10083
- c = tree->gtGetOp2();
10084
- }
10085
- else
10086
- {
10087
- assert(tree->gtGetOp2()->OperIs(GT_MUL) && tree->gtGetOp2()->isContained());
10088
- a = tree->gtGetOp2()->gtGetOp1();
10089
- b = tree->gtGetOp2()->gtGetOp2();
10090
- c = tree->gtGetOp1();
10091
- }
10092
-
10093
- bool useMsub = false;
10094
- if (a->OperIs(GT_NEG) && a->isContained())
10095
- {
10096
- a = a->gtGetOp1();
10097
- useMsub = true;
10098
- }
10099
- if (b->OperIs(GT_NEG) && b->isContained())
10100
- {
10101
- b = b->gtGetOp1();
10102
- useMsub = !useMsub; // it's either "a * -b" or "-a * -b" which is the same as "a * b"
10103
- }
10104
-
10105
- GetEmitter()->emitIns_R_R_R_R(useMsub ? INS_msub : INS_madd, emitActualTypeSize(tree), tree->GetRegNum(),
10106
- a->GetRegNum(), b->GetRegNum(), c->GetRegNum());
10107
- genProduceReg(tree);
10108
- }
10109
-
10110
- //-----------------------------------------------------------------------------------
10111
- // genCodeForMsub: Emit a msub (Multiply-Subtract) instruction
10112
- //
10113
- // Arguments:
10114
- // tree - GT_MSUB tree where op2 is GT_MUL
10115
- //
10116
- void CodeGen::genCodeForMsub(GenTreeOp* tree)
10117
- {
10118
- assert(tree->OperIs(GT_MSUB) && varTypeIsIntegral(tree) && !(tree->gtFlags & GTF_SET_FLAGS));
10119
- genConsumeOperands(tree);
10120
-
10121
- assert(tree->gtGetOp2()->OperIs(GT_MUL));
10122
- assert(tree->gtGetOp2()->isContained());
10123
-
10124
- GenTree* a = tree->gtGetOp1();
10125
- GenTree* b = tree->gtGetOp2()->gtGetOp1();
10126
- GenTree* c = tree->gtGetOp2()->gtGetOp2();
10127
-
10128
- // d = a - b * c
10129
- // MSUB d, b, c, a
10130
- GetEmitter()->emitIns_R_R_R_R(INS_msub, emitActualTypeSize(tree), tree->GetRegNum(), b->GetRegNum(), c->GetRegNum(),
10131
- a->GetRegNum());
10132
- genProduceReg(tree);
10133
- }
10134
-
10135
10105
//------------------------------------------------------------------------
10136
10106
// genCodeForBfiz: Generates the code sequence for a GenTree node that
10137
10107
// represents a bitfield insert in zero with sign/zero extension.
0 commit comments