-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Optimize FMA codegen base on the overwritten #58196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ee2c0b6
46d0011
cce4bda
b825291
f615e39
b698036
7d9c0d6
1344d92
029a9b5
f2a371f
9955389
7c56653
1d51caa
091133e
9a6ae44
ffcff76
5641f8f
b7312ac
a325fe3
0f950dd
33a596d
5da9368
c3a9f07
9e356aa
f8159bc
18bbe4d
2ca2524
17bd967
eed5912
43c5034
5ef70a5
bfa6924
12f260b
5ca658e
ec4ef66
aa93a85
c66a018
ff5a433
a4657c7
75d7a37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2272,48 +2272,93 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) | |
|
|
||
| const bool copiesUpperBits = HWIntrinsicInfo::CopiesUpperBits(intrinsicId); | ||
|
|
||
| // Intrinsics with CopyUpperBits semantics cannot have op1 be contained | ||
| assert(!copiesUpperBits || !op1->isContained()); | ||
| unsigned resultOpNum = 0; | ||
| LIR::Use use; | ||
| GenTree* user = nullptr; | ||
|
|
||
| if (op2->isContained()) | ||
| if (LIR::AsRange(blockSequence[curBBSeqNum]).TryGetUse(intrinsicTree, &use)) | ||
| { | ||
| // 132 form: op1 = (op1 * op3) + [op2] | ||
| user = use.User(); | ||
| } | ||
| resultOpNum = intrinsicTree->GetResultOpNumForFMA(user, op1, op2, op3); | ||
|
|
||
| tgtPrefUse = BuildUse(op1); | ||
| unsigned containedOpNum = 0; | ||
|
|
||
| srcCount += 1; | ||
| srcCount += BuildOperandUses(op2); | ||
| srcCount += BuildDelayFreeUses(op3, op1); | ||
| // containedOpNum remains 0 when no operand is contained or regOptional | ||
| if (op1->isContained() || op1->IsRegOptional()) | ||
| { | ||
| containedOpNum = 1; | ||
| } | ||
| else if (op1->isContained()) | ||
| else if (op2->isContained() || op2->IsRegOptional()) | ||
| { | ||
| // 231 form: op3 = (op2 * op3) + [op1] | ||
|
|
||
| tgtPrefUse = BuildUse(op3); | ||
|
|
||
| srcCount += BuildOperandUses(op1); | ||
| srcCount += BuildDelayFreeUses(op2, op1); | ||
| srcCount += 1; | ||
| containedOpNum = 2; | ||
| } | ||
| else | ||
| else if (op3->isContained() || op3->IsRegOptional()) | ||
| { | ||
| // 213 form: op1 = (op2 * op1) + [op3] | ||
| containedOpNum = 3; | ||
| } | ||
|
|
||
| tgtPrefUse = BuildUse(op1); | ||
| srcCount += 1; | ||
| GenTree* emitOp1 = op1; | ||
| GenTree* emitOp2 = op2; | ||
| GenTree* emitOp3 = op3; | ||
|
|
||
| if (copiesUpperBits) | ||
| // Intrinsics with CopyUpperBits semantics must have op1 as target | ||
| assert(containedOpNum != 1 || !copiesUpperBits); | ||
|
|
||
| if (containedOpNum == 1) | ||
| { | ||
| // https://github.com/dotnet/runtime/issues/62215 | ||
| // resultOpNum might change between lowering and lsra, comment out assertion for now. | ||
| // assert(containedOpNum != resultOpNum); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need to uncomment this assert?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This assertion cannot be uncommented because the last use value could change after lowering step. I left them here for follow up work if necessary.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please create a issue for it and add the link to the issue in the comment here? |
||
| // resultOpNum is 3 or 0: op3/? = ([op1] * op2) + op3 | ||
| std::swap(emitOp1, emitOp3); | ||
|
|
||
| if (resultOpNum == 2) | ||
| { | ||
| srcCount += BuildDelayFreeUses(op2, op1); | ||
| // op2 = ([op1] * op2) + op3 | ||
| std::swap(emitOp2, emitOp3); | ||
| } | ||
| else | ||
| } | ||
| else if (containedOpNum == 3) | ||
| { | ||
| // assert(containedOpNum != resultOpNum); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here? |
||
| if (resultOpNum == 2 && !copiesUpperBits) | ||
| { | ||
| tgtPrefUse2 = BuildUse(op2); | ||
| srcCount += 1; | ||
| // op2 = (op1 * op2) + [op3] | ||
| std::swap(emitOp1, emitOp2); | ||
| } | ||
| // else: op1/? = (op1 * op2) + [op3] | ||
| } | ||
| else if (containedOpNum == 2) | ||
| { | ||
| // assert(containedOpNum != resultOpNum); | ||
|
|
||
| srcCount += op3->isContained() ? BuildOperandUses(op3) : BuildDelayFreeUses(op3, op1); | ||
| // op1/? = (op1 * [op2]) + op3 | ||
| std::swap(emitOp2, emitOp3); | ||
| if (resultOpNum == 3 && !copiesUpperBits) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just capturing a comment, I don't think we need to do anything in this PR. I think the logic around |
||
| { | ||
| // op3 = (op1 * [op2]) + op3 | ||
| std::swap(emitOp1, emitOp2); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| // containedOpNum == 0 | ||
| // no extra work when resultOpNum is 0 or 1 | ||
| if (resultOpNum == 2) | ||
| { | ||
| std::swap(emitOp1, emitOp2); | ||
| } | ||
| else if (resultOpNum == 3) | ||
| { | ||
| std::swap(emitOp1, emitOp3); | ||
| } | ||
| } | ||
| tgtPrefUse = BuildUse(emitOp1); | ||
|
|
||
| srcCount += 1; | ||
| srcCount += BuildDelayFreeUses(emitOp2, emitOp1); | ||
| srcCount += emitOp3->isContained() ? BuildOperandUses(emitOp3) : BuildDelayFreeUses(emitOp3, emitOp1); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a lot smaller and easier to follow now 🎉 |
||
|
|
||
| buildUses = false; | ||
| break; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.