Skip to content

Commit 95e1c2b

Browse files
committed
[MERGE #5252 @rajatd] Fixing obj-ptr copy-prop in prepass. OS 17555305
Merge pull request #5252 from rajatd:ac-master For copy-propping in prepass, it is not sufficient that the two syms are safe to tranfer values. For instance, the copy sym may not be live on back-edge but, may become live on back edge after the copy-prop. In addition to the safe-to-transfer checks, the copy-sym shouldn't be written to if the original sym is live on back edge. If, however, the original sym is not live on back edge, then we can do the copy prop, provided both symbols satisfied the safe-to-transfer checks. Example: s1 = s2 $Loop: s3 = s1 <-- can't copy-prop s2 here even though both s1 and s2 are safe to transfer s2 = s4 Br $Loop
2 parents 16de442 + 71aabbf commit 95e1c2b

File tree

5 files changed

+62
-2
lines changed

5 files changed

+62
-2
lines changed

lib/Backend/GlobOpt.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5560,6 +5560,30 @@ GlobOpt::IsSafeToTransferInPrepass(StackSym * const srcSym, ValueInfo *const src
55605560
!currentBlock->loop->IsSymAssignedToInSelfOrParents(srcSym);
55615561
}
55625562

5563+
bool
5564+
GlobOpt::SafeToCopyPropInPrepass(StackSym * const originalSym, StackSym * const copySym, Value *const value) const
5565+
{
5566+
Assert(this->currentBlock->globOptData.GetCopyPropSym(originalSym, value) == copySym);
5567+
5568+
// In the following example, to copy-prop s2 into s1, it is not enough to check if s1 and s2 are safe to transfer.
5569+
// In fact, both s1 and s2 are safe to transfer, but it is not legal to copy prop s2 into s1.
5570+
//
5571+
// s1 = s2
5572+
// $Loop:
5573+
// s3 = s1
5574+
// s2 = s4
5575+
// Br $Loop
5576+
//
5577+
// In general, requirements for copy-propping in prepass are more restricted than those for transferring values.
5578+
// For copy prop in prepass, if the original sym is live on back-edge, then the copy-prop sym should not be written to
5579+
// in the loop (or its parents)
5580+
5581+
ValueInfo* const valueInfo = value->GetValueInfo();
5582+
return IsSafeToTransferInPrepass(originalSym, valueInfo) &&
5583+
IsSafeToTransferInPrepass(copySym, valueInfo) &&
5584+
(!currentBlock->loop->regAlloc.liveOnBackEdgeSyms->Test(originalSym->m_id) || !currentBlock->loop->IsSymAssignedToInSelfOrParents(copySym));
5585+
}
5586+
55635587
Value *GlobOpt::CreateDstUntransferredIntValue(
55645588
const int32 min,
55655589
const int32 max,

lib/Backend/GlobOpt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ class GlobOpt
565565
bool IsPrepassSrcValueInfoPrecise(IR::Opnd *const src, Value *const srcValue, bool * canTransferValueNumberToDst = nullptr) const;
566566
bool IsPrepassSrcValueInfoPrecise(IR::Instr *const instr, Value *const src1Value, Value *const src2Value, bool * canTransferValueNumberToDst = nullptr) const;
567567
bool IsSafeToTransferInPrepass(StackSym * const sym, ValueInfo *const srcValueInfo) const;
568+
bool SafeToCopyPropInPrepass(StackSym * const originalSym, StackSym * const copySym, Value *const value) const;
568569
Value * CreateDstUntransferredIntValue(const int32 min, const int32 max, IR::Instr *const instr, Value *const src1Value, Value *const src2Value);
569570
Value * CreateDstUntransferredValue(const ValueType desiredValueType, IR::Instr *const instr, Value *const src1Value, Value *const src2Value);
570571
Value * ValueNumberTransferDst(IR::Instr *const instr, Value *src1Val);

lib/Backend/GlobOptFields.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,8 +1710,7 @@ GlobOpt::CopyPropPropertySymObj(IR::SymOpnd *symOpnd, IR::Instr *instr)
17101710
PropertySym *newProp = PropertySym::FindOrCreate(
17111711
copySym->m_id, propertySym->m_propertyId, propertySym->GetPropertyIdIndex(), propertySym->GetInlineCacheIndex(), propertySym->m_fieldKind, this->func);
17121712

1713-
if (!this->IsLoopPrePass() ||
1714-
(IsSafeToTransferInPrepass(objSym, val->GetValueInfo()) && IsSafeToTransferInPrepass(copySym, val->GetValueInfo())))
1713+
if (!this->IsLoopPrePass() || SafeToCopyPropInPrepass(objSym, copySym, val))
17151714
{
17161715
#if DBG_DUMP
17171716
if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::GlobOptPhase, this->func->GetSourceContextId(), this->func->GetLocalFunctionId()))

test/Optimizer/rlexe.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,12 @@
14881488
<files>test150.js</files>
14891489
</default>
14901490
</test>
1491+
<test>
1492+
<default>
1493+
<files>test151.js</files>
1494+
<compile-flags>-off:usefixeddataprops -off:objtypespec</compile-flags>
1495+
</default>
1496+
</test>
14911497
<test>
14921498
<default>
14931499
<files>IsIn_ArrayNoMissingValues.js</files>

test/Optimizer/test151.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
function foo(n, a, o, i) {
7+
8+
var g;
9+
var k = n || i.tmpl;
10+
for(var j = 0; j<a.length; j++)
11+
{
12+
g = o[j];
13+
k.tmpls && g.tmpls;
14+
k.tmpls[0];
15+
n = g.props.tmpl;
16+
}
17+
18+
}
19+
20+
n = {tmpls: [1,2,3,4,5]};
21+
a = [1,2];
22+
o = {};
23+
24+
o[0] = {props: {tmpl: 10}, tmpls: [1,2,3,4,5]};
25+
o[1] = {props: {tmpl: 20}, tmpls: [1,2,3,4,5]};
26+
27+
foo(n, a, o);
28+
foo(n, a, o);
29+
foo(n, a, o);
30+
print("passed");

0 commit comments

Comments
 (0)