Bug 877338: Add alias analysis and GVN for global variable loads / stores in asm.js; r=jandem
authorBenjamin Bouvier <bbouvier@mozilla.com>
Wed, 18 Sep 2013 18:41:01 -0700
changeset 161642 6c99d5808529c7eb8f5f2e059d2b6d94a00bfa26
parent 161641 4e62723cac0f97c47d514974c1b5424e43aa530c
child 161643 71f2968c73594f902199b33b6241bbf6d251539a
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs877338
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 877338: Add alias analysis and GVN for global variable loads / stores in asm.js; r=jandem
js/src/jit-test/tests/asm.js/testGlobals.js
js/src/jit/MIR.cpp
js/src/jit/MIR.h
--- a/js/src/jit-test/tests/asm.js/testGlobals.js
+++ b/js/src/jit-test/tests/asm.js/testGlobals.js
@@ -99,8 +99,13 @@ assertEq(asmLink(asmCompile(USE_ASM + "v
 var f1 = asmCompile('global', 'foreign', 'heap', USE_ASM + 'var i32 = new global.Int32Array(heap); function g() { return i32[4]|0 } return g');
 var global = this;
 var ab = new ArrayBuffer(4096);
 var p = new Proxy(global,
                   {has:function(name) { f1(global, null, ab); return true},
                    getOwnPropertyDescriptor:function(name) { return {value:Int32Array}}});
 new Int32Array(ab)[4] = 42;
 assertEq(f1(p, null, ab)(), 42);
+
+// GVN checks
+assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var x = 0; g = 1; x = g; return (x+g)|0 } return f"))(), 2);
+assertEq(asmLink(asmCompile(USE_ASM + "var g=0; function f() { var x = 0; g = 1; x = g; g = 2; return (x+g)|0 } return f"))(), 3);
+assertEq(asmLink(asmCompile(USE_ASM + "var g=0; var h=0; function f() { var x = 0; g = 1; x = g; h = 3; return (x+g)|0 } return f"))(), 2);
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -2428,16 +2428,36 @@ bool
 MLoadFixedSlot::mightAlias(MDefinition *store)
 {
     if (store->isStoreFixedSlot() && store->toStoreFixedSlot()->slot() != slot())
         return false;
     return true;
 }
 
 bool
+MAsmJSLoadGlobalVar::mightAlias(MDefinition *def)
+{
+    if (def->isAsmJSStoreGlobalVar()) {
+        MAsmJSStoreGlobalVar *store = def->toAsmJSStoreGlobalVar();
+        return store->globalDataOffset() == globalDataOffset_;
+    }
+    return true;
+}
+
+bool
+MAsmJSLoadGlobalVar::congruentTo(MDefinition *ins) const
+{
+    if (ins->isAsmJSLoadGlobalVar()) {
+        MAsmJSLoadGlobalVar *load = ins->toAsmJSLoadGlobalVar();
+        return globalDataOffset_ == load->globalDataOffset_;
+    }
+    return false;
+}
+
+bool
 MLoadSlot::mightAlias(MDefinition *store)
 {
     if (store->isStoreSlot() && store->toStoreSlot()->slot() != slot())
         return false;
     return true;
 }
 
 void
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -212,20 +212,21 @@ class AliasSet {
     enum Flag {
         None_             = 0,
         ObjectFields      = 1 << 0, // shape, class, slots, length etc.
         Element           = 1 << 1, // A member of obj->elements.
         DynamicSlot       = 1 << 2, // A member of obj->slots.
         FixedSlot         = 1 << 3, // A member of obj->fixedSlots().
         TypedArrayElement = 1 << 4, // A typed array element.
         DOMProperty       = 1 << 5, // A DOM property
-        Last              = DOMProperty,
+        AsmJSGlobalVar    = 1 << 6, // An asm.js global var
+        Last              = AsmJSGlobalVar,
         Any               = Last | (Last - 1),
 
-        NumCategories     = 6,
+        NumCategories     = 7,
 
         // Indicates load or store.
         Store_            = 1 << 31
     };
     AliasSet(uint32_t flags)
       : flags_(flags)
     {
         JS_STATIC_ASSERT((1 << NumCategories) - 1 == Any);
@@ -8441,38 +8442,38 @@ class MAsmJSStoreHeap : public MBinaryIn
 
 class MAsmJSLoadGlobalVar : public MNullaryInstruction
 {
     MAsmJSLoadGlobalVar(MIRType type, unsigned globalDataOffset, bool isConstant)
       : globalDataOffset_(globalDataOffset), isConstant_(isConstant)
     {
         JS_ASSERT(type == MIRType_Int32 || type == MIRType_Double);
         setResultType(type);
-        if (isConstant)
-            setMovable();
+        setMovable();
     }
 
     unsigned globalDataOffset_;
     bool isConstant_;
 
   public:
     INSTRUCTION_HEADER(AsmJSLoadGlobalVar);
 
     static MAsmJSLoadGlobalVar *New(MIRType type, unsigned globalDataOffset, bool isConstant) {
         return new MAsmJSLoadGlobalVar(type, globalDataOffset, isConstant);
     }
 
     unsigned globalDataOffset() const { return globalDataOffset_; }
 
+    bool congruentTo(MDefinition *ins) const;
+
     AliasSet getAliasSet() const {
-        if (isConstant_)
-            return AliasSet::None();
-        else
-            return AliasSet::Store(AliasSet::Any);
-    }
+        return AliasSet::Load(AliasSet::AsmJSGlobalVar);
+    }
+
+    bool mightAlias(MDefinition *def);
 };
 
 class MAsmJSStoreGlobalVar : public MUnaryInstruction
 {
     MAsmJSStoreGlobalVar(unsigned globalDataOffset, MDefinition *v)
       : MUnaryInstruction(v), globalDataOffset_(globalDataOffset)
     {}
 
@@ -8482,16 +8483,20 @@ class MAsmJSStoreGlobalVar : public MUna
     INSTRUCTION_HEADER(AsmJSStoreGlobalVar);
 
     static MAsmJSStoreGlobalVar *New(unsigned globalDataOffset, MDefinition *v) {
         return new MAsmJSStoreGlobalVar(globalDataOffset, v);
     }
 
     unsigned globalDataOffset() const { return globalDataOffset_; }
     MDefinition *value() const { return getOperand(0); }
+
+    AliasSet getAliasSet() const {
+        return AliasSet::Store(AliasSet::AsmJSGlobalVar);
+    }
 };
 
 class MAsmJSLoadFuncPtr : public MUnaryInstruction
 {
     MAsmJSLoadFuncPtr(unsigned globalDataOffset, MDefinition *index)
       : MUnaryInstruction(index), globalDataOffset_(globalDataOffset)
     {
         setResultType(MIRType_Pointer);