Title: [194003] trunk/Source/_javascript_Core
Revision
194003
Author
[email protected]
Date
2015-12-11 22:10:07 -0800 (Fri, 11 Dec 2015)

Log Message

[JSC] Add Floating Point Abs() to B3
https://bugs.webkit.org/show_bug.cgi?id=152176

Patch by Benjamin Poulain <[email protected]> on 2015-12-11
Reviewed by Geoffrey Garen.

This patch adds an Abs() operation for floating point.

On x86, Abs() is implemented by masking the top bit
of the floating point value. On ARM64, there is a builtin
abs opcode.

To account for those differences, B3 use "Abs" as
the cannonical operation. When we are about to lower
to Air, Abs is extended on x86 to get a clean handling
of the mask constants.

This patch has one cool thing related to FTL.
If you do:
   @1 = unboxDouble(@0)
   @2 = abs(@1)
   @3 = boxDouble(@2)

B3ReduceStrength completely eliminate the Double-Integer
conversion.

The strength reduction of Abs is aware that it can do a bit
mask over the bitcast used by unboxing.
If even works if you use floats by forcing fround: reduceDoubleToFloat()
elminiates the useless conversions, followed by ReduceStrength
that removes the switch from GP to FP.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::andDouble):
(JSC::MacroAssemblerX86Common::andFloat):
* assembler/X86Assembler.h:
(JSC::X86Assembler::andps_rr):
* b3/B3ConstDoubleValue.cpp:
(JSC::B3::ConstDoubleValue::bitAndConstant):
(JSC::B3::ConstDoubleValue::absConstant):
* b3/B3ConstDoubleValue.h:
* b3/B3ConstFloatValue.cpp:
(JSC::B3::ConstFloatValue::bitAndConstant):
(JSC::B3::ConstFloatValue::absConstant):
* b3/B3ConstFloatValue.h:
* b3/B3Generate.cpp:
(JSC::B3::generateToAir):
* b3/B3LowerMacrosAfterOptimizations.cpp: Added.
(JSC::B3::lowerMacrosAfterOptimizations):
* b3/B3LowerMacrosAfterOptimizations.h: Added.
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3ReduceDoubleToFloat.cpp:
* b3/B3ReduceStrength.cpp:
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::absConstant):
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::typeFor):
* b3/B3Value.h:
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::bitAndDouble):
(JSC::B3::testBitAndArgDouble):
(JSC::B3::testBitAndArgsDouble):
(JSC::B3::testBitAndArgImmDouble):
(JSC::B3::testBitAndImmsDouble):
(JSC::B3::bitAndFloat):
(JSC::B3::testBitAndArgFloat):
(JSC::B3::testBitAndArgsFloat):
(JSC::B3::testBitAndArgImmFloat):
(JSC::B3::testBitAndImmsFloat):
(JSC::B3::testBitAndArgsFloatWithUselessDoubleConversion):
(JSC::B3::testAbsArg):
(JSC::B3::testAbsImm):
(JSC::B3::testAbsMem):
(JSC::B3::testAbsAbsArg):
(JSC::B3::testAbsBitwiseCastArg):
(JSC::B3::testBitwiseCastAbsBitwiseCastArg):
(JSC::B3::testAbsArgWithUselessDoubleConversion):
(JSC::B3::testAbsArgWithEffectfulDoubleConversion):
(JSC::B3::run):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::doubleAbs):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (194002 => 194003)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2015-12-12 06:10:07 UTC (rev 194003)
@@ -114,6 +114,7 @@
     b3/B3HeapRange.cpp
     b3/B3InsertionSet.cpp
     b3/B3LowerMacros.cpp
+    b3/B3LowerMacrosAfterOptimizations.cpp
     b3/B3LowerToAir.cpp
     b3/B3MathExtras.cpp
     b3/B3MemoryValue.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (194002 => 194003)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-12 06:10:07 UTC (rev 194003)
@@ -1,3 +1,95 @@
+2015-12-11  Benjamin Poulain  <[email protected]>
+
+        [JSC] Add Floating Point Abs() to B3
+        https://bugs.webkit.org/show_bug.cgi?id=152176
+
+        Reviewed by Geoffrey Garen.
+
+        This patch adds an Abs() operation for floating point.
+
+        On x86, Abs() is implemented by masking the top bit
+        of the floating point value. On ARM64, there is a builtin
+        abs opcode.
+
+        To account for those differences, B3 use "Abs" as
+        the cannonical operation. When we are about to lower
+        to Air, Abs is extended on x86 to get a clean handling
+        of the mask constants.
+
+        This patch has one cool thing related to FTL.
+        If you do:
+           @1 = unboxDouble(@0)
+           @2 = abs(@1)
+           @3 = boxDouble(@2)
+
+        B3ReduceStrength completely eliminate the Double-Integer
+        conversion.
+
+        The strength reduction of Abs is aware that it can do a bit
+        mask over the bitcast used by unboxing.
+        If even works if you use floats by forcing fround: reduceDoubleToFloat()
+        elminiates the useless conversions, followed by ReduceStrength
+        that removes the switch from GP to FP.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::andDouble):
+        (JSC::MacroAssemblerX86Common::andFloat):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::andps_rr):
+        * b3/B3ConstDoubleValue.cpp:
+        (JSC::B3::ConstDoubleValue::bitAndConstant):
+        (JSC::B3::ConstDoubleValue::absConstant):
+        * b3/B3ConstDoubleValue.h:
+        * b3/B3ConstFloatValue.cpp:
+        (JSC::B3::ConstFloatValue::bitAndConstant):
+        (JSC::B3::ConstFloatValue::absConstant):
+        * b3/B3ConstFloatValue.h:
+        * b3/B3Generate.cpp:
+        (JSC::B3::generateToAir):
+        * b3/B3LowerMacrosAfterOptimizations.cpp: Added.
+        (JSC::B3::lowerMacrosAfterOptimizations):
+        * b3/B3LowerMacrosAfterOptimizations.h: Added.
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3ReduceDoubleToFloat.cpp:
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::absConstant):
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::typeFor):
+        * b3/B3Value.h:
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::bitAndDouble):
+        (JSC::B3::testBitAndArgDouble):
+        (JSC::B3::testBitAndArgsDouble):
+        (JSC::B3::testBitAndArgImmDouble):
+        (JSC::B3::testBitAndImmsDouble):
+        (JSC::B3::bitAndFloat):
+        (JSC::B3::testBitAndArgFloat):
+        (JSC::B3::testBitAndArgsFloat):
+        (JSC::B3::testBitAndArgImmFloat):
+        (JSC::B3::testBitAndImmsFloat):
+        (JSC::B3::testBitAndArgsFloatWithUselessDoubleConversion):
+        (JSC::B3::testAbsArg):
+        (JSC::B3::testAbsImm):
+        (JSC::B3::testAbsMem):
+        (JSC::B3::testAbsAbsArg):
+        (JSC::B3::testAbsBitwiseCastArg):
+        (JSC::B3::testBitwiseCastAbsBitwiseCastArg):
+        (JSC::B3::testAbsArgWithUselessDoubleConversion):
+        (JSC::B3::testAbsArgWithEffectfulDoubleConversion):
+        (JSC::B3::run):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::doubleAbs):
+
 2015-12-11  Mark Lam  <[email protected]>
 
         Removed some dead code, and simplified some code in the baseline JIT.

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (194002 => 194003)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-12-12 06:10:07 UTC (rev 194003)
@@ -1129,6 +1129,8 @@
 		371D842D17C98B6E00ECF994 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 371D842C17C98B6E00ECF994 /* libz.dylib */; };
 		41359CF30FDD89AD00206180 /* DateConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateConversion.h */; };
 		41DEA1321B9F3163006D65DD /* BuiltinUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DEA1311B9F3154006D65DD /* BuiltinUtils.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		4319DA031C1BE40A001D260B /* B3LowerMacrosAfterOptimizations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4319DA011C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.cpp */; };
+		4319DA041C1BE40D001D260B /* B3LowerMacrosAfterOptimizations.h in Headers */ = {isa = PBXBuildFile; fileRef = 4319DA021C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.h */; };
 		4340A4841A9051AF00D73CCA /* MathCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4340A4821A9051AF00D73CCA /* MathCommon.cpp */; };
 		4340A4851A9051AF00D73CCA /* MathCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 4340A4831A9051AF00D73CCA /* MathCommon.h */; };
 		43422A621C158E6A00E2EB98 /* B3ConstFloatValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43422A601C15871B00E2EB98 /* B3ConstFloatValue.cpp */; };
@@ -3207,6 +3209,8 @@
 		2AF7382B18BBBF92008A5A37 /* StructureIDTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureIDTable.h; sourceTree = "<group>"; };
 		371D842C17C98B6E00ECF994 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
 		41DEA1311B9F3154006D65DD /* BuiltinUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltinUtils.h; sourceTree = "<group>"; };
+		4319DA011C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3LowerMacrosAfterOptimizations.cpp; path = b3/B3LowerMacrosAfterOptimizations.cpp; sourceTree = "<group>"; };
+		4319DA021C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3LowerMacrosAfterOptimizations.h; path = b3/B3LowerMacrosAfterOptimizations.h; sourceTree = "<group>"; };
 		4340A4821A9051AF00D73CCA /* MathCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathCommon.cpp; sourceTree = "<group>"; };
 		4340A4831A9051AF00D73CCA /* MathCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathCommon.h; sourceTree = "<group>"; };
 		43422A601C15871B00E2EB98 /* B3ConstFloatValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ConstFloatValue.cpp; path = b3/B3ConstFloatValue.cpp; sourceTree = "<group>"; };
@@ -4619,8 +4623,6 @@
 				0F338E011BF0276C0013C88F /* B3DataSection.cpp */,
 				0F338E021BF0276C0013C88F /* B3DataSection.h */,
 				0F33FCFA1C1625BE00323F67 /* B3Dominators.h */,
-				43422A641C16221E00E2EB98 /* B3ReduceDoubleToFloat.cpp */,
-				43422A651C16221E00E2EB98 /* B3ReduceDoubleToFloat.h */,
 				0FEC85C41BE16F5A0080FF74 /* B3Effects.cpp */,
 				0FEC85BE1BE167A00080FF74 /* B3Effects.h */,
 				0FEC84CB1BDACDAC0080FF74 /* B3FrequencyClass.cpp */,
@@ -4638,6 +4640,8 @@
 				0FEC85B61BE1462F0080FF74 /* B3InsertionSetInlines.h */,
 				0F338E191BF286EA0013C88F /* B3LowerMacros.cpp */,
 				0F338E1A1BF286EA0013C88F /* B3LowerMacros.h */,
+				4319DA011C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.cpp */,
+				4319DA021C1BE3C1001D260B /* B3LowerMacrosAfterOptimizations.h */,
 				0FEC84D31BDACDAC0080FF74 /* B3LowerToAir.cpp */,
 				0FEC84D41BDACDAC0080FF74 /* B3LowerToAir.h */,
 				43AB26C41C1A52F700D82AE6 /* B3MathExtras.cpp */,
@@ -4664,6 +4668,8 @@
 				0FEC84E11BDACDAC0080FF74 /* B3Procedure.cpp */,
 				0FEC84E21BDACDAC0080FF74 /* B3Procedure.h */,
 				0FEC84E31BDACDAC0080FF74 /* B3ProcedureInlines.h */,
+				43422A641C16221E00E2EB98 /* B3ReduceDoubleToFloat.cpp */,
+				43422A651C16221E00E2EB98 /* B3ReduceDoubleToFloat.h */,
 				0FEC85B71BE1462F0080FF74 /* B3ReduceStrength.cpp */,
 				0FEC85B81BE1462F0080FF74 /* B3ReduceStrength.h */,
 				0F33FCF51C136E2500323F67 /* B3StackmapGenerationParams.cpp */,
@@ -7730,6 +7736,7 @@
 				0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */,
 				FE3A06B21C10CB8900390FDD /* JITBitAndGenerator.h in Headers */,
 				0FD3E40E1B618B6600C80E1E /* PropertyCondition.h in Headers */,
+				4319DA041C1BE40D001D260B /* B3LowerMacrosAfterOptimizations.h in Headers */,
 				A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */,
 				BC95437D0EBA70FD0072B6D3 /* PropertyMapHashTable.h in Headers */,
 				86158AB3155C8B4000B45C9C /* PropertyName.h in Headers */,
@@ -8788,6 +8795,7 @@
 				0F338DF11BE93AD10013C88F /* B3StackmapValue.cpp in Sources */,
 				0F25F1B3181635F300522F39 /* FTLSlowPathCallKey.cpp in Sources */,
 				0F9D339A1803ADB70073C2BC /* FTLStackMaps.cpp in Sources */,
+				4319DA031C1BE40A001D260B /* B3LowerMacrosAfterOptimizations.cpp in Sources */,
 				0FEA0A161706BB9000BB722C /* FTLState.cpp in Sources */,
 				0F235BE117178E1C00690C7F /* FTLThunks.cpp in Sources */,
 				0F6B1CC51862C47800845D97 /* FTLUnwindInfo.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (194002 => 194003)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2015-12-12 06:10:07 UTC (rev 194003)
@@ -1013,6 +1013,17 @@
         m_assembler.mulss_mr(src.offset, src.base, dest);
     }
 
+    void andDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        // ANDPS is defined on 128bits and is shorter than ANDPD.
+        m_assembler.andps_rr(src, dst);
+    }
+
+    void andFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.andps_rr(src, dst);
+    }
+
     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (194002 => 194003)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2015-12-12 06:10:07 UTC (rev 194003)
@@ -273,6 +273,7 @@
         OP2_DIVSD_VsdWsd    = 0x5E,
         OP2_MOVMSKPD_VdEd   = 0x50,
         OP2_SQRTSD_VsdWsd   = 0x51,
+        OP2_ANDPS_VpdWpd    = 0x54,
         OP2_ANDNPD_VpdWpd   = 0x55,
         OP2_XORPD_VpdWpd    = 0x57,
         OP2_MOVD_VdEd       = 0x6E,
@@ -2283,6 +2284,11 @@
         m_formatter.twoByteOp(OP2_DIVSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
+    void andps_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_ANDPS_VpdWpd, (RegisterID)dst, (RegisterID)src);
+    }
+
     void xorps_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);

Modified: trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -69,6 +69,14 @@
     return proc.add<ConstDoubleValue>(origin(), m_value * other->asDouble());
 }
 
+Value* ConstDoubleValue::bitAndConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasDouble())
+        return nullptr;
+    double result = bitwise_cast<double>(bitwise_cast<uint64_t>(m_value) & bitwise_cast<uint64_t>(other->asDouble()));
+    return proc.add<ConstDoubleValue>(origin(), result);
+}
+
 Value* ConstDoubleValue::bitwiseCastConstant(Procedure& proc) const
 {
     return proc.add<Const64Value>(origin(), bitwise_cast<int64_t>(m_value));
@@ -79,6 +87,11 @@
     return proc.add<ConstFloatValue>(origin(), static_cast<float>(m_value));
 }
 
+Value* ConstDoubleValue::absConstant(Procedure& proc) const
+{
+    return proc.add<ConstDoubleValue>(origin(), fabs(m_value));
+}
+
 Value* ConstDoubleValue::sqrtConstant(Procedure& proc) const
 {
     return proc.add<ConstDoubleValue>(origin(), sqrt(m_value));

Modified: trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h	2015-12-12 06:10:07 UTC (rev 194003)
@@ -47,8 +47,10 @@
     Value* divConstant(Procedure&, const Value* other) const override;
     Value* modConstant(Procedure&, const Value* other) const override;
     Value* mulConstant(Procedure&, const Value* other) const override;
+    Value* bitAndConstant(Procedure&, const Value* other) const override;
     Value* bitwiseCastConstant(Procedure&) const override;
     Value* doubleToFloatConstant(Procedure&) const override;
+    Value* absConstant(Procedure&) const override;
     Value* sqrtConstant(Procedure&) const override;
 
     TriState equalConstant(const Value* other) const override;

Modified: trunk/Source/_javascript_Core/b3/B3ConstFloatValue.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3ConstFloatValue.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3ConstFloatValue.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -69,6 +69,14 @@
     return proc.add<ConstFloatValue>(origin(), m_value * other->asFloat());
 }
 
+Value* ConstFloatValue::bitAndConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasFloat())
+        return nullptr;
+    float result = bitwise_cast<float>(bitwise_cast<uint32_t>(m_value) & bitwise_cast<uint32_t>(other->asFloat()));
+    return proc.add<ConstFloatValue>(origin(), result);
+}
+
 Value* ConstFloatValue::bitwiseCastConstant(Procedure& proc) const
 {
     return proc.add<Const32Value>(origin(), bitwise_cast<int32_t>(m_value));
@@ -79,6 +87,11 @@
     return proc.add<ConstDoubleValue>(origin(), static_cast<double>(m_value));
 }
 
+Value* ConstFloatValue::absConstant(Procedure& proc) const
+{
+    return proc.add<ConstFloatValue>(origin(), static_cast<float>(fabs(m_value)));
+}
+
 Value* ConstFloatValue::sqrtConstant(Procedure& proc) const
 {
     return proc.add<ConstFloatValue>(origin(), static_cast<float>(sqrt(m_value)));

Modified: trunk/Source/_javascript_Core/b3/B3ConstFloatValue.h (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3ConstFloatValue.h	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3ConstFloatValue.h	2015-12-12 06:10:07 UTC (rev 194003)
@@ -46,8 +46,10 @@
     Value* subConstant(Procedure&, const Value* other) const override;
     Value* divConstant(Procedure&, const Value* other) const override;
     Value* mulConstant(Procedure&, const Value* other) const override;
+    Value* bitAndConstant(Procedure&, const Value* other) const override;
     Value* bitwiseCastConstant(Procedure&) const override;
     Value* floatToDoubleConstant(Procedure&) const override;
+    Value* absConstant(Procedure&) const override;
     Value* sqrtConstant(Procedure&) const override;
 
     TriState equalConstant(const Value* other) const override;

Modified: trunk/Source/_javascript_Core/b3/B3Generate.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3Generate.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3Generate.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -33,6 +33,7 @@
 #include "AirInstInlines.h"
 #include "B3Common.h"
 #include "B3LowerMacros.h"
+#include "B3LowerMacrosAfterOptimizations.h"
 #include "B3LowerToAir.h"
 #include "B3MoveConstants.h"
 #include "B3Procedure.h"
@@ -82,6 +83,8 @@
         // https://bugs.webkit.org/show_bug.cgi?id=150507
     }
 
+    lowerMacrosAfterOptimizations(procedure);
+
     moveConstants(procedure);
 
     if (shouldValidateIR())

Added: trunk/Source/_javascript_Core/b3/B3LowerMacrosAfterOptimizations.cpp (0 => 194003)


--- trunk/Source/_javascript_Core/b3/B3LowerMacrosAfterOptimizations.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3LowerMacrosAfterOptimizations.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "B3LowerMacrosAfterOptimizations.h"
+
+#if ENABLE(B3_JIT)
+
+#include "B3BasicBlockInlines.h"
+#include "B3BlockInsertionSet.h"
+#include "B3ConstDoubleValue.h"
+#include "B3ConstFloatValue.h"
+#include "B3InsertionSetInlines.h"
+#include "B3PhaseScope.h"
+
+namespace JSC { namespace B3 {
+
+namespace {
+
+class LowerMacros {
+public:
+    LowerMacros(Procedure& proc)
+        : m_proc(proc)
+        , m_blockInsertionSet(proc)
+        , m_insertionSet(proc)
+    {
+    }
+
+    bool run()
+    {
+        for (BasicBlock* block : m_proc) {
+            m_block = block;
+            processCurrentBlock();
+        }
+        m_changed |= m_blockInsertionSet.execute();
+        if (m_changed) {
+            m_proc.resetReachability();
+            m_proc.invalidateCFG();
+        }
+        return m_changed;
+    }
+    
+private:
+    void processCurrentBlock()
+    {
+        for (m_index = 0; m_index < m_block->size(); ++m_index) {
+            m_value = m_block->at(m_index);
+            m_origin = m_value->origin();
+            switch (m_value->opcode()) {
+            case Abs: {
+                // ARM supports this instruction natively.
+                if (isARM64())
+                    break;
+
+                Value* mask = nullptr;
+                if (m_value->type() == Double)
+                    mask = m_insertionSet.insert<ConstDoubleValue>(m_index, m_origin, bitwise_cast<double>(~(1l << 63)));
+                else if (m_value->type() == Float)
+                    mask = m_insertionSet.insert<ConstFloatValue>(m_index, m_origin, bitwise_cast<float>(~(1 << 31)));
+                else
+                    RELEASE_ASSERT_NOT_REACHED();
+                Value* result = m_insertionSet.insert<Value>(m_index, BitAnd, m_origin, m_value->child(0), mask);
+                m_value->replaceWithIdentity(result);
+                break;
+            }
+            default:
+                break;
+            }
+        }
+        m_insertionSet.execute(m_block);
+    }
+    
+    Procedure& m_proc;
+    BlockInsertionSet m_blockInsertionSet;
+    InsertionSet m_insertionSet;
+    BasicBlock* m_block;
+    unsigned m_index;
+    Value* m_value;
+    Origin m_origin;
+    bool m_changed { false };
+};
+
+bool lowerMacrosImpl(Procedure& proc)
+{
+    LowerMacros lowerMacros(proc);
+    return lowerMacros.run();
+}
+
+} // anonymous namespace
+
+bool lowerMacrosAfterOptimizations(Procedure& proc)
+{
+    PhaseScope phaseScope(proc, "lowerMacrosAfterOptimizations");
+    bool result = lowerMacrosImpl(proc);
+    if (shouldValidateIR())
+        RELEASE_ASSERT(!lowerMacrosImpl(proc));
+    return result;
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+

Added: trunk/Source/_javascript_Core/b3/B3LowerMacrosAfterOptimizations.h (0 => 194003)


--- trunk/Source/_javascript_Core/b3/B3LowerMacrosAfterOptimizations.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3LowerMacrosAfterOptimizations.h	2015-12-12 06:10:07 UTC (rev 194003)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef B3LowerMacrosAfterOptimizations_h
+#define B3LowerMacrosAfterOptimizations_h
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 {
+
+class Procedure;
+
+// Lower certain high level opcodes to lower-level opcode to help code generation.
+
+bool lowerMacrosAfterOptimizations(Procedure&);
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3LowerMacrosAfterOptimizations_h
+

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -1459,7 +1459,7 @@
         }
 
         case BitAnd: {
-            appendBinOp<And32, And64, Commutative>(
+            appendBinOp<And32, And64, AndDouble, AndFloat, Commutative>(
                 m_value->child(0), m_value->child(1));
             return;
         }

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -146,6 +146,9 @@
     case Clz:
         out.print("Clz");
         return;
+    case Abs:
+        out.print("Abs");
+        return;
     case Sqrt:
         out.print("Sqrt");
         return;

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.h (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3Opcode.h	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.h	2015-12-12 06:10:07 UTC (rev 194003)
@@ -84,7 +84,8 @@
     ZShr, // Logical Shift.
     Clz, // Count leading zeros.
 
-    // Double math.
+    // Floating point math.
+    Abs,
     Sqrt,
 
     // Casts and such.

Modified: trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -48,6 +48,7 @@
             candidate->setType(Float);
         }
         break;
+    case Abs:
     case Sqrt:
         if (candidate->child(0)->opcode() == FloatToDouble) {
             candidate->child(0) = candidate->child(0)->child(0);

Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -505,6 +505,39 @@
 
             break;
 
+        case Abs:
+            // Turn this: Abs(constant)
+            // Into this: fabs<value->type()>(constant)
+            if (Value* constant = m_value->child(0)->absConstant(m_proc)) {
+                replaceWithNewValue(constant);
+                break;
+            }
+
+            // Turn this: Abs(Abs(value))
+            // Into this: Abs(value)
+            if (m_value->child(0)->opcode() == Abs) {
+                m_value->replaceWithIdentity(m_value->child(0));
+                break;
+            }
+
+            // Turn this: Abs(BitwiseCast(value))
+            // Into this: BitwiseCast(And(value, mask-top-bit))
+            if (m_value->child(0)->opcode() == BitwiseCast) {
+                Value* mask;
+                if (m_value->type() == Double)
+                    mask = m_insertionSet.insert<Const64Value>(m_index, m_value->origin(), ~(1l << 63));
+                else
+                    mask = m_insertionSet.insert<Const32Value>(m_index, m_value->origin(), ~(1l << 31));
+
+                Value* bitAnd = m_insertionSet.insert<Value>(m_index, BitAnd, m_value->origin(),
+                    m_value->child(0)->child(0),
+                    mask);
+                Value* cast = m_insertionSet.insert<Value>(m_index, BitwiseCast, m_value->origin(), bitAnd);
+                m_value->replaceWithIdentity(cast);
+                break;
+            }
+            break;
+
         case Sqrt:
             // Turn this: Sqrt(constant)
             // Into this: sqrt<value->type()>(constant)

Modified: trunk/Source/_javascript_Core/b3/B3Validate.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3Validate.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3Validate.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -154,6 +154,7 @@
             case Mul:
             case Div:
             case Mod:
+            case BitAnd:
                 VALIDATE(value->numChildren() == 2, ("At ", *value));
                 VALIDATE(value->type() == value->child(0)->type(), ("At ", *value));
                 VALIDATE(value->type() == value->child(1)->type(), ("At ", *value));
@@ -161,7 +162,6 @@
                 break;
             case ChillDiv:
             case ChillMod:
-            case BitAnd:
             case BitOr:
             case BitXor:
                 VALIDATE(value->numChildren() == 2, ("At ", *value));
@@ -209,6 +209,7 @@
                 VALIDATE(value->child(0)->type() == Int64, ("At ", *value));
                 VALIDATE(value->type() == Int32, ("At ", *value));
                 break;
+            case Abs:
             case Sqrt:
                 VALIDATE(value->numChildren() == 1, ("At ", *value));
                 VALIDATE(isFloat(value->child(0)->type()), ("At ", *value));

Modified: trunk/Source/_javascript_Core/b3/B3Value.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3Value.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3Value.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -221,6 +221,11 @@
     return nullptr;
 }
 
+Value* Value::absConstant(Procedure&) const
+{
+    return nullptr;
+}
+
 Value* Value::sqrtConstant(Procedure&) const
 {
     return nullptr;
@@ -357,6 +362,7 @@
     case SShr:
     case ZShr:
     case Clz:
+    case Abs:
     case Sqrt:
     case BitwiseCast:
     case SExt8:
@@ -433,6 +439,7 @@
     case FramePointer:
         return ValueKey(opcode(), type());
     case Identity:
+    case Abs:
     case Sqrt:
     case SExt8:
     case SExt16:
@@ -539,6 +546,7 @@
     case SShr:
     case ZShr:
     case Clz:
+    case Abs:
     case Sqrt:
     case CheckAdd:
     case CheckSub:

Modified: trunk/Source/_javascript_Core/b3/B3Value.h (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/B3Value.h	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/B3Value.h	2015-12-12 06:10:07 UTC (rev 194003)
@@ -131,6 +131,7 @@
     virtual Value* bitwiseCastConstant(Procedure&) const;
     virtual Value* doubleToFloatConstant(Procedure&) const;
     virtual Value* floatToDoubleConstant(Procedure&) const;
+    virtual Value* absConstant(Procedure&) const;
     virtual Value* sqrtConstant(Procedure&) const;
 
     virtual TriState equalConstant(const Value* other) const;

Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2015-12-12 06:10:07 UTC (rev 194003)
@@ -170,6 +170,12 @@
     Tmp, Tmp
     Imm, Tmp
 
+AndDouble U:F, UD:F
+    Tmp, Tmp
+
+AndFloat U:F, UD:F
+    Tmp, Tmp
+
 Lshift32 U:G, UD:G
     Tmp*, Tmp
     Imm, Tmp

Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (194002 => 194003)


--- trunk/Source/_javascript_Core/b3/testb3.cpp	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp	2015-12-12 06:10:07 UTC (rev 194003)
@@ -1942,6 +1942,140 @@
     CHECK(compileAndRun<int64_t>(proc, a, b) == expected);
 }
 
+double bitAndDouble(double a, double b)
+{
+    return bitwise_cast<double>(bitwise_cast<uint64_t>(a) & bitwise_cast<uint64_t>(b));
+}
+
+void testBitAndArgDouble(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a), bitAndDouble(a, a)));
+}
+
+void testBitAndArgsDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* argumentB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
+    Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
+}
+
+void testBitAndArgImmDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
+    Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitAndDouble(a, b)));
+}
+
+void testBitAndImmsDouble(double a, double b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
+    Value* argumentB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
+    Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<double>(proc), bitAndDouble(a, b)));
+}
+
+float bitAndFloat(float a, float b)
+{
+    return bitwise_cast<float>(bitwise_cast<uint32_t>(a) & bitwise_cast<uint32_t>(b));
+}
+
+void testBitAndArgFloat(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(),
+        root->appendNew<Value>(proc, Trunc, Origin(),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
+    Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argument, argument);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitAndFloat(a, a)));
+}
+
+void testBitAndArgsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
+        root->appendNew<Value>(proc, Trunc, Origin(),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
+    Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
+        root->appendNew<Value>(proc, Trunc, Origin(),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
+    Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
+}
+
+void testBitAndArgImmFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
+        root->appendNew<Value>(proc, Trunc, Origin(),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
+    Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
+    Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitAndFloat(a, b)));
+}
+
+void testBitAndImmsFloat(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root->appendNew<ConstFloatValue>(proc, Origin(), a);
+    Value* argumentB = root->appendNew<ConstFloatValue>(proc, Origin(), b);
+    Value* result = root->appendNew<Value>(proc, BitAnd, Origin(), argumentA, argumentB);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<float>(proc), bitAndFloat(a, b)));
+}
+
+void testBitAndArgsFloatWithUselessDoubleConversion(float a, float b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentA = root->appendNew<Value>(proc, BitwiseCast, Origin(),
+        root->appendNew<Value>(proc, Trunc, Origin(),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)));
+    Value* argumentB = root->appendNew<Value>(proc, BitwiseCast, Origin(),
+        root->appendNew<Value>(proc, Trunc, Origin(),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
+    Value* argumentAasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentA);
+    Value* argumentBasDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), argumentB);
+    Value* doubleResult = root->appendNew<Value>(proc, BitAnd, Origin(), argumentAasDouble, argumentBasDouble);
+    Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
+    root->appendNew<ControlValue>(proc, Return, Origin(), floatResult);
+
+    double doubleA = a;
+    double doubleB = b;
+    float expected = static_cast<float>(bitAndDouble(doubleA, doubleB));
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
+}
+
 void testBitOrArgs(int64_t a, int64_t b)
 {
     Procedure proc;
@@ -2897,6 +3031,202 @@
     CHECK(compileAndRun<unsigned>(proc, &a) == countLeadingZero(a));
 }
 
+void testAbsArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(
+            proc, Abs, Origin(),
+                root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(a)));
+}
+
+void testAbsImm(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(proc, Abs, Origin(), argument));
+
+    CHECK(isIdentical(compileAndRun<double>(proc), fabs(a)));
+}
+
+void testAbsMem(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(proc, Abs, Origin(), loadDouble));
+
+    CHECK(isIdentical(compileAndRun<double>(proc, &a), fabs(a)));
+}
+
+void testAbsAbsArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
+    Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs);
+    root->appendNew<ControlValue>(proc, Return, Origin(), secondAbs);
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a), fabs(a)));
+}
+
+void testAbsBitwiseCastArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64);
+    Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble);
+    root->appendNew<ControlValue>(proc, Return, Origin(), absValue);
+
+    CHECK(isIdentical(compileAndRun<double>(proc, bitwise_cast<int64_t>(a)), fabs(a)));
+}
+
+void testBitwiseCastAbsBitwiseCastArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentAsInt64 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* argumentAsDouble = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt64);
+    Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsDouble);
+    Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue);
+
+    root->appendNew<ControlValue>(proc, Return, Origin(), resultAsInt64);
+
+    int64_t expectedResult = bitwise_cast<int64_t>(fabs(a));
+    CHECK(isIdentical(compileAndRun<int64_t>(proc, bitwise_cast<int64_t>(a)), expectedResult));
+}
+
+void testAbsArg(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+    Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
+}
+
+void testAbsImm(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
+    Value* result = root->appendNew<Value>(proc, Abs, Origin(), argument);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
+}
+
+void testAbsMem(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
+    Value* result = root->appendNew<Value>(proc, Abs, Origin(), loadFloat);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
+}
+
+void testAbsAbsArg(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+    Value* firstAbs = root->appendNew<Value>(proc, Abs, Origin(), argument);
+    Value* secondAbs = root->appendNew<Value>(proc, Abs, Origin(), firstAbs);
+    root->appendNew<ControlValue>(proc, Return, Origin(), secondAbs);
+
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(a))));
+}
+
+void testAbsBitwiseCastArg(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32);
+    Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat);
+    root->appendNew<ControlValue>(proc, Return, Origin(), absValue);
+
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), static_cast<float>(fabs(a))));
+}
+
+void testBitwiseCastAbsBitwiseCastArg(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argumentAsInt32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argumentAsfloat = root->appendNew<Value>(proc, BitwiseCast, Origin(), argumentAsInt32);
+    Value* absValue = root->appendNew<Value>(proc, Abs, Origin(), argumentAsfloat);
+    Value* resultAsInt64 = root->appendNew<Value>(proc, BitwiseCast, Origin(), absValue);
+
+    root->appendNew<ControlValue>(proc, Return, Origin(), resultAsInt64);
+
+    int32_t expectedResult = bitwise_cast<int32_t>(static_cast<float>(fabs(a)));
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), expectedResult));
+}
+
+void testAbsArgWithUselessDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+    Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble);
+    Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
+}
+
+void testAbsArgWithEffectfulDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+    Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root->appendNew<Value>(proc, Abs, Origin(), asDouble);
+    Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
+    Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+    root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    double effect = 0;
+    int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
+    CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(static_cast<float>(fabs(a)))));
+    CHECK(isIdentical(effect, fabs(a)));
+}
+
 void testSqrtArg(double a)
 {
     Procedure proc;
@@ -7515,6 +7845,15 @@
     RUN(testBitAndImmBitAndArgImm32(6, 1, 6));
     RUN(testBitAndImmBitAndArgImm32(24, 0xffff, 7));
     RUN_BINARY(testBitAndWithMaskReturnsBooleans, int64Operands(), int64Operands());
+    RUN_UNARY(testBitAndArgDouble, floatingPointOperands<double>());
+    RUN_BINARY(testBitAndArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_BINARY(testBitAndArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_BINARY(testBitAndImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_UNARY(testBitAndArgFloat, floatingPointOperands<float>());
+    RUN_BINARY(testBitAndArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBitAndArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBitAndImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBitAndArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
 
     RUN(testBitOrArgs(43, 43));
     RUN(testBitOrArgs(43, 0));
@@ -7746,6 +8085,21 @@
     RUN_UNARY(testClzArg32, int32Operands());
     RUN_UNARY(testClzMem32, int64Operands());
 
+    RUN_UNARY(testAbsArg, floatingPointOperands<double>());
+    RUN_UNARY(testAbsImm, floatingPointOperands<double>());
+    RUN_UNARY(testAbsMem, floatingPointOperands<double>());
+    RUN_UNARY(testAbsAbsArg, floatingPointOperands<double>());
+    RUN_UNARY(testAbsBitwiseCastArg, floatingPointOperands<double>());
+    RUN_UNARY(testBitwiseCastAbsBitwiseCastArg, floatingPointOperands<double>());
+    RUN_UNARY(testAbsArg, floatingPointOperands<float>());
+    RUN_UNARY(testAbsImm, floatingPointOperands<float>());
+    RUN_UNARY(testAbsMem, floatingPointOperands<float>());
+    RUN_UNARY(testAbsAbsArg, floatingPointOperands<float>());
+    RUN_UNARY(testAbsBitwiseCastArg, floatingPointOperands<float>());
+    RUN_UNARY(testBitwiseCastAbsBitwiseCastArg, floatingPointOperands<float>());
+    RUN_UNARY(testAbsArgWithUselessDoubleConversion, floatingPointOperands<float>());
+    RUN_UNARY(testAbsArgWithEffectfulDoubleConversion, floatingPointOperands<float>());
+
     RUN_UNARY(testSqrtArg, floatingPointOperands<double>());
     RUN_UNARY(testSqrtImm, floatingPointOperands<double>());
     RUN_UNARY(testSqrtMem, floatingPointOperands<double>());

Modified: trunk/Source/_javascript_Core/ftl/FTLB3Output.h (194002 => 194003)


--- trunk/Source/_javascript_Core/ftl/FTLB3Output.h	2015-12-12 03:26:36 UTC (rev 194002)
+++ trunk/Source/_javascript_Core/ftl/FTLB3Output.h	2015-12-12 06:10:07 UTC (rev 194003)
@@ -162,7 +162,7 @@
     LValue addWithOverflow64(LValue left, LValue right) { CRASH(); }
     LValue subWithOverflow64(LValue left, LValue right) { CRASH(); }
     LValue mulWithOverflow64(LValue left, LValue right) { CRASH(); }
-    LValue doubleAbs(LValue value) { CRASH(); }
+    LValue doubleAbs(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::Abs, origin(), value); }
 
     LValue doubleSin(LValue value) { return callWithoutSideEffects(B3::Double, sin, value); }
     LValue doubleCos(LValue value) { return callWithoutSideEffects(B3::Double, cos, value); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to