Skip to content

Commit 71aabbf

Browse files
committed
Fixing obj-ptr copy-prop in prepass
1 parent 16de442 commit 71aabbf

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)