FTL should be able to convey branch weights to LLVM
https://bugs.webkit.org/show_bug.cgi?id=129054

Reviewed by Michael Saboff.
        
This introduces a really nice way to convey branch weights to LLVM. The basic class
is Weight, which just wraps a float; NaN is used when you are not sure. You can
pass this alongside a LBasicBlock to branching instructions like condbr and switch.
But for simplicity, you can just pass a WeightedTarget, which is a tuple of the
two. And for even greater simplicity, you can create WeightedTargets from
LBasicBlocks by doing:
        
    usually(b)   => WeightedTarget(b, Weight(1))
    rarely(b)    => WeightedTarget(b, Weight(0))
    unsure(b)    => WeightedTarget(b, Weight()) or WeightedTarget(b, Weight(NaN))
        
This allows for constructs like:
        
    m_out.branch(isCell(value), usually(isCellCase), rarely(slowCase));
        
This was intended to be perf-neutral for now, but it did end up creating a ~1%
speed-up on V8v7 and Octane2.

* JavaScriptCore.xcodeproj/project.pbxproj:
* ftl/FTLAbbreviations.h:
(JSC::FTL::mdNode):
* ftl/FTLCommonValues.cpp:
(JSC::FTL::CommonValues::CommonValues):
* ftl/FTLCommonValues.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::lower):
(JSC::FTL::LowerDFGToLLVM::compileValueToInt32):
(JSC::FTL::LowerDFGToLLVM::compileStoreBarrierWithNullCheck):
(JSC::FTL::LowerDFGToLLVM::compileToThis):
(JSC::FTL::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::LowerDFGToLLVM::compileArithDiv):
(JSC::FTL::LowerDFGToLLVM::compileArithMod):
(JSC::FTL::LowerDFGToLLVM::compileArithMinOrMax):
(JSC::FTL::LowerDFGToLLVM::compileCheckStructure):
(JSC::FTL::LowerDFGToLLVM::compileArrayifyToStructure):
(JSC::FTL::LowerDFGToLLVM::compileGetById):
(JSC::FTL::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
(JSC::FTL::LowerDFGToLLVM::compileGetTypedArrayByteOffset):
(JSC::FTL::LowerDFGToLLVM::compileGetByVal):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::compileArrayPush):
(JSC::FTL::LowerDFGToLLVM::compileArrayPop):
(JSC::FTL::LowerDFGToLLVM::compileNewArrayWithSize):
(JSC::FTL::LowerDFGToLLVM::compileToString):
(JSC::FTL::LowerDFGToLLVM::compileToPrimitive):
(JSC::FTL::LowerDFGToLLVM::compileStringCharAt):
(JSC::FTL::LowerDFGToLLVM::compileStringCharCodeAt):
(JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
(JSC::FTL::LowerDFGToLLVM::compileNotifyWrite):
(JSC::FTL::LowerDFGToLLVM::compileBranch):
(JSC::FTL::LowerDFGToLLVM::compileSwitch):
(JSC::FTL::LowerDFGToLLVM::compareEqObjectOrOtherToObject):
(JSC::FTL::LowerDFGToLLVM::nonSpeculativeCompare):
(JSC::FTL::LowerDFGToLLVM::allocateCell):
(JSC::FTL::LowerDFGToLLVM::allocateBasicStorageAndGetEnd):
(JSC::FTL::LowerDFGToLLVM::boolify):
(JSC::FTL::LowerDFGToLLVM::equalNullOrUndefined):
(JSC::FTL::LowerDFGToLLVM::contiguousPutByValOutOfBounds):
(JSC::FTL::LowerDFGToLLVM::buildSwitch):
(JSC::FTL::LowerDFGToLLVM::doubleToInt32):
(JSC::FTL::LowerDFGToLLVM::sensibleDoubleToInt32):
(JSC::FTL::LowerDFGToLLVM::lowDouble):
(JSC::FTL::LowerDFGToLLVM::strictInt52ToJSValue):
(JSC::FTL::LowerDFGToLLVM::speculateObjectOrOther):
(JSC::FTL::LowerDFGToLLVM::speculateStringOrStringObject):
(JSC::FTL::LowerDFGToLLVM::emitStoreBarrier):
(JSC::FTL::LowerDFGToLLVM::callCheck):
(JSC::FTL::LowerDFGToLLVM::appendOSRExit):
* ftl/FTLOutput.cpp:
(JSC::FTL::Output::initialize):
(JSC::FTL::Output::appendTo):
(JSC::FTL::Output::newBlock):
(JSC::FTL::Output::sensibleDoubleToInt):
(JSC::FTL::Output::load):
(JSC::FTL::Output::store):
(JSC::FTL::Output::baseIndex):
(JSC::FTL::Output::branch):
(JSC::FTL::Output::crashNonTerminal):
* ftl/FTLOutput.h:
(JSC::FTL::Output::branch):
(JSC::FTL::Output::switchInstruction):
* ftl/FTLSwitchCase.h:
(JSC::FTL::SwitchCase::SwitchCase):
(JSC::FTL::SwitchCase::weight):
* ftl/FTLWeight.h: Added.
(JSC::FTL::Weight::Weight):
(JSC::FTL::Weight::isSet):
(JSC::FTL::Weight::operator!):
(JSC::FTL::Weight::value):
(JSC::FTL::Weight::scaleToTotal):
* ftl/FTLWeightedTarget.h: Added.
(JSC::FTL::WeightedTarget::WeightedTarget):
(JSC::FTL::WeightedTarget::target):
(JSC::FTL::WeightedTarget::weight):
(JSC::FTL::usually):
(JSC::FTL::rarely):
(JSC::FTL::unsure):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@164389 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ftl/FTLOutput.cpp b/Source/JavaScriptCore/ftl/FTLOutput.cpp
index fb2fc93..986d374 100644
--- a/Source/JavaScriptCore/ftl/FTLOutput.cpp
+++ b/Source/JavaScriptCore/ftl/FTLOutput.cpp
@@ -45,6 +45,104 @@
     llvm->DisposeBuilder(m_builder);
 }
 
+void Output::initialize(LModule module, LValue function, AbstractHeapRepository& heaps)
+{
+    IntrinsicRepository::initialize(module);
+    m_function = function;
+    m_heaps = &heaps;
+}
+
+LBasicBlock Output::appendTo(LBasicBlock block, LBasicBlock nextBlock)
+{
+    appendTo(block);
+    return insertNewBlocksBefore(nextBlock);
+}
+
+void Output::appendTo(LBasicBlock block)
+{
+    m_block = block;
+    
+    llvm->PositionBuilderAtEnd(m_builder, block);
+}
+
+LBasicBlock Output::newBlock(const char* name)
+{
+    if (!m_nextBlock)
+        return appendBasicBlock(m_context, m_function, name);
+    return insertBasicBlock(m_context, m_nextBlock, name);
+}
+
+LValue Output::sensibleDoubleToInt(LValue value)
+{
+    RELEASE_ASSERT(isX86());
+    return call(
+        x86SSE2CvtTSD2SIIntrinsic(),
+        insertElement(
+            insertElement(getUndef(vectorType(doubleType, 2)), value, int32Zero),
+            doubleZero, int32One));
+}
+
+LValue Output::load(TypedPointer pointer, LType refType)
+{
+    LValue result = get(intToPtr(pointer.value(), refType));
+    pointer.heap().decorateInstruction(result, *m_heaps);
+    return result;
+}
+
+void Output::store(LValue value, TypedPointer pointer, LType refType)
+{
+    LValue result = set(value, intToPtr(pointer.value(), refType));
+    pointer.heap().decorateInstruction(result, *m_heaps);
+}
+
+LValue Output::baseIndex(LValue base, LValue index, Scale scale, ptrdiff_t offset)
+{
+    LValue accumulatedOffset;
+        
+    switch (scale) {
+    case ScaleOne:
+        accumulatedOffset = index;
+        break;
+    case ScaleTwo:
+        accumulatedOffset = shl(index, intPtrOne);
+        break;
+    case ScaleFour:
+        accumulatedOffset = shl(index, intPtrTwo);
+        break;
+    case ScaleEight:
+    case ScalePtr:
+        accumulatedOffset = shl(index, intPtrThree);
+        break;
+    }
+        
+    if (offset)
+        accumulatedOffset = add(accumulatedOffset, constIntPtr(offset));
+        
+    return add(base, accumulatedOffset);
+}
+
+void Output::branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight)
+{
+    LValue branch = buildCondBr(m_builder, condition, taken, notTaken);
+    
+    if (!takenWeight || !notTakenWeight)
+        return;
+    
+    double total = takenWeight.value() + notTakenWeight.value();
+    
+    setMetadata(
+        branch, profKind,
+        mdNode(
+            m_context, branchWeights,
+            constInt32(takenWeight.scaleToTotal(total)),
+            constInt32(notTakenWeight.scaleToTotal(total))));
+}
+
+void Output::crashNonTerminal()
+{
+    call(intToPtr(constIntPtr(abort), pointerType(functionType(voidType))));
+}
+
 } } // namespace JSC::FTL
 
 #endif // ENABLE(FTL_JIT)