Add BitOr for floating points to B3
authorkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Dec 2016 01:19:55 +0000 (01:19 +0000)
committerkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Dec 2016 01:19:55 +0000 (01:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=166446

Reviewed by Saam Barati.

Source/JavaScriptCore:

This patch does some slight refactoring to the ARM assembler,
which groups all the vector floating point instructions together.

* assembler/ARM64Assembler.h:
(JSC::ARM64Assembler::vand):
(JSC::ARM64Assembler::vorr):
(JSC::ARM64Assembler::vectorDataProcessingLogical):
(JSC::ARM64Assembler::vectorDataProcessing2Source): Deleted.
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::orDouble):
(JSC::MacroAssemblerARM64::orFloat):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::orDouble):
(JSC::MacroAssemblerX86Common::orFloat):
* assembler/X86Assembler.h:
(JSC::X86Assembler::orps_rr):
* b3/B3ConstDoubleValue.cpp:
(JSC::B3::ConstDoubleValue::bitOrConstant):
(JSC::B3::ConstDoubleValue::bitXorConstant):
* b3/B3ConstDoubleValue.h:
* b3/B3ConstFloatValue.cpp:
(JSC::B3::ConstFloatValue::bitOrConstant):
(JSC::B3::ConstFloatValue::bitXorConstant):
* b3/B3ConstFloatValue.h:
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
* b3/B3Validate.cpp:
* b3/air/AirInstInlines.h:
(JSC::B3::Air::Inst::shouldTryAliasingDef):
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::bitOrDouble):
(JSC::B3::testBitOrArgDouble):
(JSC::B3::testBitOrArgsDouble):
(JSC::B3::testBitOrArgImmDouble):
(JSC::B3::testBitOrImmsDouble):
(JSC::B3::bitOrFloat):
(JSC::B3::testBitOrArgFloat):
(JSC::B3::testBitOrArgsFloat):
(JSC::B3::testBitOrArgImmFloat):
(JSC::B3::testBitOrImmsFloat):
(JSC::B3::testBitOrArgsFloatWithUselessDoubleConversion):
(JSC::B3::run):

Websites/webkit.org:

Update docs to indicate it's cool to use bit ops with floating point.

* docs/b3/intermediate-representation.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210124 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/assembler/ARM64Assembler.h
Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
Source/JavaScriptCore/assembler/X86Assembler.h
Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp
Source/JavaScriptCore/b3/B3ConstDoubleValue.h
Source/JavaScriptCore/b3/B3ConstFloatValue.cpp
Source/JavaScriptCore/b3/B3ConstFloatValue.h
Source/JavaScriptCore/b3/B3LowerToAir.cpp
Source/JavaScriptCore/b3/B3Validate.cpp
Source/JavaScriptCore/b3/air/AirInstInlines.h
Source/JavaScriptCore/b3/air/AirOpcode.opcodes
Source/JavaScriptCore/b3/testb3.cpp
Websites/webkit.org/ChangeLog
Websites/webkit.org/docs/b3/intermediate-representation.html

index edbb66c..b421ed8 100644 (file)
@@ -1,3 +1,54 @@
+2016-12-22  Keith Miller  <keith_miller@apple.com>
+
+        Add BitOr for floating points to B3
+        https://bugs.webkit.org/show_bug.cgi?id=166446
+
+        Reviewed by Saam Barati.
+
+        This patch does some slight refactoring to the ARM assembler,
+        which groups all the vector floating point instructions together.
+
+        * assembler/ARM64Assembler.h:
+        (JSC::ARM64Assembler::vand):
+        (JSC::ARM64Assembler::vorr):
+        (JSC::ARM64Assembler::vectorDataProcessingLogical):
+        (JSC::ARM64Assembler::vectorDataProcessing2Source): Deleted.
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::orDouble):
+        (JSC::MacroAssemblerARM64::orFloat):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::orDouble):
+        (JSC::MacroAssemblerX86Common::orFloat):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::orps_rr):
+        * b3/B3ConstDoubleValue.cpp:
+        (JSC::B3::ConstDoubleValue::bitOrConstant):
+        (JSC::B3::ConstDoubleValue::bitXorConstant):
+        * b3/B3ConstDoubleValue.h:
+        * b3/B3ConstFloatValue.cpp:
+        (JSC::B3::ConstFloatValue::bitOrConstant):
+        (JSC::B3::ConstFloatValue::bitXorConstant):
+        * b3/B3ConstFloatValue.h:
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3Validate.cpp:
+        * b3/air/AirInstInlines.h:
+        (JSC::B3::Air::Inst::shouldTryAliasingDef):
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::bitOrDouble):
+        (JSC::B3::testBitOrArgDouble):
+        (JSC::B3::testBitOrArgsDouble):
+        (JSC::B3::testBitOrArgImmDouble):
+        (JSC::B3::testBitOrImmsDouble):
+        (JSC::B3::bitOrFloat):
+        (JSC::B3::testBitOrArgFloat):
+        (JSC::B3::testBitOrArgsFloat):
+        (JSC::B3::testBitOrArgImmFloat):
+        (JSC::B3::testBitOrImmsFloat):
+        (JSC::B3::testBitOrArgsFloatWithUselessDoubleConversion):
+        (JSC::B3::run):
+
 2016-12-22  Mark Lam  <mark.lam@apple.com>
 
         BytecodeGenerator::m_finallyDepth should be unsigned.
index 1eb2018..d61a508 100644 (file)
@@ -621,7 +621,19 @@ private:
     };
 
     enum SIMD3Same {
-        SIMD_LogicalOp_AND = 0x03
+        SIMD_LogicalOp = 0x03
+    };
+
+    enum SIMD3SameLogical {
+        // This includes both the U bit and the "size" / opc for convience.
+        SIMD_LogicalOp_AND = 0x00,
+        SIMD_LogicalOp_BIC = 0x01,
+        SIMD_LogicalOp_ORR = 0x02,
+        SIMD_LogicalOp_ORN = 0x03,
+        SIMD_LogacalOp_EOR = 0x80,
+        SIMD_LogicalOp_BSL = 0x81,
+        SIMD_LogicalOp_BIT = 0x82,
+        SIMD_LogicalOp_BIF = 0x83,
     };
 
     enum FPIntConvOp {
@@ -2222,7 +2234,14 @@ public:
     ALWAYS_INLINE void vand(FPRegisterID vd, FPRegisterID vn, FPRegisterID vm)
     {
         CHECK_VECTOR_DATASIZE();
-        insn(vectorDataProcessing2Source(SIMD_LogicalOp_AND, vm, vn, vd));
+        insn(vectorDataProcessingLogical(SIMD_LogicalOp_AND, vm, vn, vd));
+    }
+
+    template<int datasize>
+    ALWAYS_INLINE void vorr(FPRegisterID vd, FPRegisterID vn, FPRegisterID vm)
+    {
+        CHECK_VECTOR_DATASIZE();
+        insn(vectorDataProcessingLogical(SIMD_LogicalOp_ORR, vm, vn, vd));
     }
 
     template<int datasize>
@@ -3328,18 +3347,12 @@ private:
         return (0x1e200800 | M << 31 | S << 29 | type << 22 | rm << 16 | opcode << 12 | rn << 5 | rd);
     }
 
-    ALWAYS_INLINE static int vectorDataProcessing2Source(SIMD3Same opcode, unsigned size, FPRegisterID vm, FPRegisterID vn, FPRegisterID vd)
+    ALWAYS_INLINE static int vectorDataProcessingLogical(SIMD3SameLogical uAndSize, FPRegisterID vm, FPRegisterID vn, FPRegisterID vd)
     {
         const int Q = 0;
-        return (0xe201c00 | Q << 30 | size << 22 | vm << 16 | opcode << 11 | vn << 5 | vd);
+        return (0xe200400 | Q << 30 | uAndSize << 22 | vm << 16 | SIMD_LogicalOp << 11 | vn << 5 | vd);
     }
 
-    ALWAYS_INLINE static int vectorDataProcessing2Source(SIMD3Same opcode, FPRegisterID vm, FPRegisterID vn, FPRegisterID vd)
-    {
-        return vectorDataProcessing2Source(opcode, 0, vm, vn, vd);
-    }
-
-
     // 'o1' means negate
     ALWAYS_INLINE static int floatingPointDataProcessing3Source(Datasize type, bool o1, FPRegisterID rm, AddOp o2, FPRegisterID ra, FPRegisterID rn, FPRegisterID rd)
     {
index d8d7b69..a278fc7 100644 (file)
@@ -1941,6 +1941,16 @@ public:
         andDouble(op1, op2, dest);
     }
 
+    void orDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        m_assembler.vorr<64>(dest, op1, op2);
+    }
+
+    void orFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        orDouble(op1, op2, dest);
+    }
+
     void negateDouble(FPRegisterID src, FPRegisterID dest)
     {
         m_assembler.fneg<64>(dest, src);
index 7d8493c..8b1c8f5 100644 (file)
@@ -1589,6 +1589,36 @@ public:
         }
     }
 
+    void orDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.orps_rr(src, dst);
+    }
+
+    void orDouble(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
+    {
+        if (src1 == dst)
+            orDouble(src2, dst);
+        else {
+            moveDouble(src2, dst);
+            orDouble(src1, dst);
+        }
+    }
+
+    void orFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.orps_rr(src, dst);
+    }
+
+    void orFloat(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
+    {
+        if (src1 == dst)
+            orFloat(src2, dst);
+        else {
+            moveDouble(src2, dst);
+            orFloat(src1, dst);
+        }
+    }
+
     void xorDouble(FPRegisterID src, FPRegisterID dst)
     {
         m_assembler.xorps_rr(src, dst);
index a65e695..cb2f5e4 100644 (file)
@@ -281,6 +281,7 @@ private:
         OP2_SQRTSD_VsdWsd   = 0x51,
         OP2_ANDPS_VpdWpd    = 0x54,
         OP2_ANDNPD_VpdWpd   = 0x55,
+        OP2_ORPS_VpdWpd     = 0x56,
         OP2_XORPD_VpdWpd    = 0x57,
         OP2_MOVD_VdEd       = 0x6E,
         OP2_MOVD_EdVd       = 0x7E,
@@ -2660,6 +2661,11 @@ public:
         m_formatter.twoByteOp(OP2_ANDPS_VpdWpd, (RegisterID)dst, (RegisterID)src);
     }
 
+    void orps_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.twoByteOp(OP2_ORPS_VpdWpd, (RegisterID)dst, (RegisterID)src);
+    }
+
     void xorps_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         m_formatter.twoByteOp(OP2_XORPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
index 46183f3..0a7d748 100644 (file)
@@ -77,6 +77,23 @@ Value* ConstDoubleValue::bitAndConstant(Procedure& proc, const Value* other) con
     return proc.add<ConstDoubleValue>(origin(), result);
 }
 
+Value* ConstDoubleValue::bitOrConstant(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::bitXorConstant(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));
index 75976f3..fdfaddc 100644 (file)
@@ -47,6 +47,8 @@ public:
     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* bitOrConstant(Procedure&, const Value* other) const override;
+    Value* bitXorConstant(Procedure&, const Value* other) const override;
     Value* bitwiseCastConstant(Procedure&) const override;
     Value* doubleToFloatConstant(Procedure&) const override;
     Value* absConstant(Procedure&) const override;
index 7c1b395..76facae 100644 (file)
@@ -77,6 +77,22 @@ Value* ConstFloatValue::bitAndConstant(Procedure& proc, const Value* other) cons
     return proc.add<ConstFloatValue>(origin(), result);
 }
 
+Value* ConstFloatValue::bitOrConstant(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::bitXorConstant(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));
index 1974f8c..185583c 100644 (file)
@@ -46,6 +46,8 @@ public:
     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* bitOrConstant(Procedure&, const Value* other) const override;
+    Value* bitXorConstant(Procedure&, const Value* other) const override;
     Value* bitwiseCastConstant(Procedure&) const override;
     Value* floatToDoubleConstant(Procedure&) const override;
     Value* absConstant(Procedure&) const override;
index 1b2585f..29a4379 100644 (file)
@@ -2153,7 +2153,7 @@ private:
         }
 
         case BitOr: {
-            appendBinOp<Or32, Or64, Commutative>(
+            appendBinOp<Or32, Or64, OrDouble, OrFloat, Commutative>(
                 m_value->child(0), m_value->child(1));
             return;
         }
index f7224cf..8df8ace 100644 (file)
@@ -194,6 +194,7 @@ public:
             case Mod:
             case UMod:
             case BitAnd:
+            case BitOr:
             case BitXor:
                 VALIDATE(!value->kind().traps(), ("At ", *value));
                 switch (value->opcode()) {
@@ -219,13 +220,6 @@ public:
                 VALIDATE(value->type() == value->child(0)->type(), ("At ", *value));
                 VALIDATE(value->type() != Void, ("At ", *value));
                 break;
-            case BitOr:
-                VALIDATE(!value->kind().hasExtraBits(), ("At ", *value));
-                VALIDATE(value->numChildren() == 2, ("At ", *value));
-                VALIDATE(value->type() == value->child(0)->type(), ("At ", *value));
-                VALIDATE(value->type() == value->child(1)->type(), ("At ", *value));
-                VALIDATE(isInt(value->type()), ("At ", *value));
-                break;
             case Shl:
             case SShr:
             case ZShr:
index b753921..2d3da62 100644 (file)
@@ -129,6 +129,8 @@ inline std::optional<unsigned> Inst::shouldTryAliasingDef()
     case Xor64:
     case AndFloat:
     case AndDouble:
+    case OrFloat:
+    case OrDouble:
     case XorDouble:
     case XorFloat:
         if (args.size() == 3)
index 4170f74..e82c9f5 100644 (file)
@@ -353,6 +353,18 @@ AndFloat U:F:32, U:F:32, D:F:32
 x86: AndFloat U:F:32, UD:F:32
     Tmp, Tmp
 
+OrDouble U:F:64, U:F:64, D:F:64
+    Tmp, Tmp, Tmp
+
+x86: OrDouble U:F:64, UD:F:64
+    Tmp, Tmp
+
+OrFloat U:F:32, U:F:32, D:F:32
+    Tmp, Tmp, Tmp
+
+x86: OrFloat U:F:32, UD:F:32
+    Tmp, Tmp
+
 x86: XorDouble U:F:64, U:F:64, D:F:64
     Tmp, Tmp, Tmp
 
index b76a985..fc33c6f 100644 (file)
@@ -2978,6 +2978,140 @@ void testBitOrImmBitOrArgImm32(int a, int b, int c)
     CHECK(compileAndRun<int>(proc, b) == (a | (b | c)));
 }
 
+double bitOrDouble(double a, double b)
+{
+    return bitwise_cast<double>(bitwise_cast<uint64_t>(a) | bitwise_cast<uint64_t>(b));
+}
+
+void testBitOrArgDouble(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+    Value* result = root->appendNew<Value>(proc, BitOr, Origin(), argument, argument);
+    root->appendNewControlValue(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a), bitOrDouble(a, a)));
+}
+
+void testBitOrArgsDouble(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, BitOr, Origin(), argumentA, argumentB);
+    root->appendNewControlValue(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b)));
+}
+
+void testBitOrArgImmDouble(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, BitOr, Origin(), argumentA, argumentB);
+    root->appendNewControlValue(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a, b), bitOrDouble(a, b)));
+}
+
+void testBitOrImmsDouble(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, BitOr, Origin(), argumentA, argumentB);
+    root->appendNewControlValue(proc, Return, Origin(), result);
+    
+    CHECK(isIdentical(compileAndRun<double>(proc), bitOrDouble(a, b)));
+}
+
+float bitOrFloat(float a, float b)
+{
+    return bitwise_cast<float>(bitwise_cast<uint32_t>(a) | bitwise_cast<uint32_t>(b));
+}
+
+void testBitOrArgFloat(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, BitOr, Origin(), argument, argument);
+    root->appendNewControlValue(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), bitOrFloat(a, a)));
+}
+
+void testBitOrArgsFloat(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, BitOr, Origin(), argumentA, argumentB);
+    root->appendNewControlValue(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b)));
+}
+
+void testBitOrArgImmFloat(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, BitOr, Origin(), argumentA, argumentB);
+    root->appendNewControlValue(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitOrFloat(a, b)));
+}
+
+void testBitOrImmsFloat(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, BitOr, Origin(), argumentA, argumentB);
+    root->appendNewControlValue(proc, Return, Origin(), result);
+
+    CHECK(isIdentical(compileAndRun<float>(proc), bitOrFloat(a, b)));
+}
+
+void testBitOrArgsFloatWithUselessDoubleConversion(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, BitOr, Origin(), argumentAasDouble, argumentBasDouble);
+    Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), doubleResult);
+    root->appendNewControlValue(proc, Return, Origin(), floatResult);
+    
+    double doubleA = a;
+    double doubleB = b;
+    float expected = static_cast<float>(bitOrDouble(doubleA, doubleB));
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), expected));
+}
+
 void testBitXorArgs(int64_t a, int64_t b)
 {
     Procedure proc;
@@ -14447,6 +14581,15 @@ void run(const char* filter)
     RUN(testBitOrImmBitOrArgImm32(7, 2, 3));
     RUN(testBitOrImmBitOrArgImm32(6, 1, 6));
     RUN(testBitOrImmBitOrArgImm32(24, 0xffff, 7));
+    RUN_UNARY(testBitOrArgDouble, floatingPointOperands<double>());
+    RUN_BINARY(testBitOrArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_BINARY(testBitOrArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_BINARY(testBitOrImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+    RUN_UNARY(testBitOrArgFloat, floatingPointOperands<float>());
+    RUN_BINARY(testBitOrArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBitOrArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBitOrImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+    RUN_BINARY(testBitOrArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
 
     RUN_BINARY(testBitXorArgs, int64Operands(), int64Operands());
     RUN_UNARY(testBitXorSameArg, int64Operands());
index c77eea6..bf87b9d 100644 (file)
@@ -1,3 +1,14 @@
+2016-12-22  Keith Miller  <keith_miller@apple.com>
+
+        Add BitOr for floating points to B3
+        https://bugs.webkit.org/show_bug.cgi?id=166446
+
+        Reviewed by Saam Barati.
+
+        Update docs to indicate it's cool to use bit ops with floating point.
+
+        * docs/b3/intermediate-representation.html:
+
 2016-12-07  Dean Jackson  <dino@apple.com>
 
         Remove runtime toggle for pointer-lock
index cfc3b82..68c7d95 100644 (file)
         spec.</dd>
 
       <dt>T BitAnd(T, T)</dt>
-      <dd>Bitwise and.  Valid for Int32 and Int64.</dd>
+      <dd>Bitwise and.  Valid for any type except Void.</dd>
 
       <dt>T BitOr(T, T)</dt>
-      <dd>Bitwise or.  Valid for Int32 and Int64.</dd>
+      <dd>Bitwise or.  Valid for any type except Void.</dd>
 
       <dt>T BitXor(T, T)</dt>
-      <dd>Bitwise xor.  Valid for Int32 and Int64.</dd>
+      <dd>Bitwise xor.  Valid for any type except Void.</dd>
 
       <dt>T Shl(T, Int32)</dt>
       <dd>Shift left.  Valid for Int32 and Int64.  The shift amount is always Int32.  Only the