Search in sources :

Example 16 with Label

use of org.graalvm.compiler.asm.Label in project graal by oracle.

the class SPARCControlFlow method emitBranch.

private static boolean emitBranch(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCKind kind, ConditionFlag conditionFlag, LabelRef trueDestination, LabelRef falseDestination, boolean withDelayedNop, double trueDestinationProbability) {
    Label actualTarget;
    ConditionFlag actualConditionFlag;
    boolean needJump;
    BranchPredict predictTaken;
    if (falseDestination != null && crb.isSuccessorEdge(trueDestination)) {
        actualConditionFlag = conditionFlag != null ? conditionFlag.negate() : null;
        actualTarget = falseDestination.label();
        needJump = false;
        predictTaken = trueDestinationProbability < .5d ? PREDICT_TAKEN : PREDICT_NOT_TAKEN;
    } else {
        actualConditionFlag = conditionFlag;
        actualTarget = trueDestination.label();
        needJump = falseDestination != null && !crb.isSuccessorEdge(falseDestination);
        predictTaken = trueDestinationProbability > .5d ? PREDICT_TAKEN : PREDICT_NOT_TAKEN;
    }
    if (!withDelayedNop && needJump) {
        // We cannot make use of the delay slot when we jump in true-case and false-case
        return false;
    }
    if (kind.isFloat()) {
        FBPCC.emit(masm, Fcc0, actualConditionFlag, NOT_ANNUL, predictTaken, actualTarget);
    } else {
        assert kind.isInteger();
        CC cc = kind.equals(WORD) ? Icc : Xcc;
        BPCC.emit(masm, cc, actualConditionFlag, NOT_ANNUL, predictTaken, actualTarget);
    }
    if (withDelayedNop) {
        // delay slot
        masm.nop();
    }
    if (needJump) {
        masm.jmp(falseDestination.label());
    }
    return true;
}
Also used : BPCC(org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC) FBPCC(org.graalvm.compiler.asm.sparc.SPARCAssembler.FBPCC) CC(org.graalvm.compiler.asm.sparc.SPARCAssembler.CC) BranchPredict(org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict) Label(org.graalvm.compiler.asm.Label) ConditionFlag(org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag)

Example 17 with Label

use of org.graalvm.compiler.asm.Label in project graal by oracle.

the class AMD64ControlFlow method floatJcc.

private static void floatJcc(AMD64MacroAssembler masm, ConditionFlag condition, boolean unorderedIsTrue, Label label) {
    Label endLabel = new Label();
    if (unorderedIsTrue && !trueOnUnordered(condition)) {
        masm.jcc(ConditionFlag.Parity, label);
    } else if (!unorderedIsTrue && trueOnUnordered(condition)) {
        masm.jccb(ConditionFlag.Parity, endLabel);
    }
    masm.jcc(condition, label);
    masm.bind(endLabel);
}
Also used : Label(org.graalvm.compiler.asm.Label)

Example 18 with Label

use of org.graalvm.compiler.asm.Label in project graal by oracle.

the class AMD64MacroAssembler method stringIndexofC8.

// IndexOf for constant substrings with size >= 8 chars
// which don't need to be loaded through stack.
public void stringIndexofC8(Register str1, Register str2, Register cnt1, Register cnt2, int intCnt2, Register result, Register vec, Register tmp) {
    // rcx - matched index in string
    assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
    Label reloadSubstr = new Label();
    Label scanToSubstr = new Label();
    Label scanSubstr = new Label();
    Label retFound = new Label();
    Label retNotFound = new Label();
    Label exit = new Label();
    Label foundSubstr = new Label();
    Label matchSubstrHead = new Label();
    Label reloadStr = new Label();
    Label foundCandidate = new Label();
    // if (substr.count == 0) return 0;
    assert intCnt2 >= 8 : "this code isused only for cnt2 >= 8 chars";
    // Load substring.
    movdqu(vec, new AMD64Address(str2, 0));
    movl(cnt2, intCnt2);
    // string addr
    movq(result, str1);
    if (intCnt2 > 8) {
        jmpb(scanToSubstr);
        // Reload substr for rescan, this code
        // is executed only for large substrings (> 8 chars)
        bind(reloadSubstr);
        movdqu(vec, new AMD64Address(str2, 0));
        // Jumped here with negative cnt2, convert to positive
        negq(cnt2);
        bind(reloadStr);
        // We came here after the beginning of the substring was
        // matched but the rest of it was not so we need to search
        // again. Start from the next element after the previous match.
        // cnt2 is number of substring reminding elements and
        // cnt1 is number of string reminding elements when cmp failed.
        // Restored cnt1 = cnt1 - cnt2 + int_cnt2
        subl(cnt1, cnt2);
        addl(cnt1, intCnt2);
        // Now restore cnt2
        movl(cnt2, intCnt2);
        // Shift to next element
        decrementl(cnt1, 1);
        cmpl(cnt1, cnt2);
        // Left less then substring
        jccb(ConditionFlag.Negative, retNotFound);
        addq(result, 2);
    }
    // (int_cnt2 > 8)
    // Scan string for start of substr in 16-byte vectors
    bind(scanToSubstr);
    pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
    // CF == 1
    jccb(ConditionFlag.Below, foundCandidate);
    subl(cnt1, 8);
    // Scanned full string
    jccb(ConditionFlag.LessEqual, retNotFound);
    cmpl(cnt1, cnt2);
    // Left less then substring
    jccb(ConditionFlag.Negative, retNotFound);
    addq(result, 16);
    jmpb(scanToSubstr);
    // Found a potential substr
    bind(foundCandidate);
    // Matched whole vector if first element matched (tmp(rcx) == 0).
    if (intCnt2 == 8) {
        // OF == 1
        jccb(ConditionFlag.Overflow, retFound);
    } else {
        // int_cnt2 > 8
        jccb(ConditionFlag.Overflow, foundSubstr);
    }
    // After pcmpestri tmp(rcx) contains matched element index
    // Compute start addr of substr
    leaq(result, new AMD64Address(result, tmp, Scale.Times2, 0));
    // Make sure string is still long enough
    subl(cnt1, tmp);
    cmpl(cnt1, cnt2);
    if (intCnt2 == 8) {
        jccb(ConditionFlag.GreaterEqual, scanToSubstr);
    } else {
        // int_cnt2 > 8
        jccb(ConditionFlag.GreaterEqual, matchSubstrHead);
    }
    // Left less then substring.
    bind(retNotFound);
    movl(result, -1);
    jmpb(exit);
    if (intCnt2 > 8) {
        // This code is optimized for the case when whole substring
        // is matched if its head is matched.
        bind(matchSubstrHead);
        pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
        // Reload only string if does not match
        // OF == 0
        jccb(ConditionFlag.NoOverflow, reloadStr);
        Label contScanSubstr = new Label();
        // Compare the rest of substring (> 8 chars).
        bind(foundSubstr);
        // First 8 chars are already matched.
        negq(cnt2);
        addq(cnt2, 8);
        bind(scanSubstr);
        subl(cnt1, 8);
        // Do not read beyond substring
        cmpl(cnt2, -8);
        jccb(ConditionFlag.LessEqual, contScanSubstr);
        // Back-up strings to avoid reading beyond substring:
        // cnt1 = cnt1 - cnt2 + 8
        // cnt2 is negative
        addl(cnt1, cnt2);
        addl(cnt1, 8);
        movl(cnt2, 8);
        negq(cnt2);
        bind(contScanSubstr);
        if (intCnt2 < 1024 * 1024 * 1024) {
            movdqu(vec, new AMD64Address(str2, cnt2, Scale.Times2, intCnt2 * 2));
            pcmpestri(vec, new AMD64Address(result, cnt2, Scale.Times2, intCnt2 * 2), 0x0d);
        } else {
            // calculate index in register to avoid integer overflow (int_cnt2*2)
            movl(tmp, intCnt2);
            addq(tmp, cnt2);
            movdqu(vec, new AMD64Address(str2, tmp, Scale.Times2, 0));
            pcmpestri(vec, new AMD64Address(result, tmp, Scale.Times2, 0), 0x0d);
        }
        // Need to reload strings pointers if not matched whole vector
        // OF == 0
        jcc(ConditionFlag.NoOverflow, reloadSubstr);
        addq(cnt2, 8);
        jcc(ConditionFlag.Negative, scanSubstr);
    // Fall through if found full substring
    }
    // (int_cnt2 > 8)
    bind(retFound);
    // Found result if we matched full small substring.
    // Compute substr offset
    subq(result, str1);
    // index
    shrl(result, 1);
    bind(exit);
}
Also used : Label(org.graalvm.compiler.asm.Label)

Example 19 with Label

use of org.graalvm.compiler.asm.Label in project graal by oracle.

the class AMD64MacroAssembler method stringIndexOf.

// string_indexofC8
// Small strings are loaded through stack if they cross page boundary.
public void stringIndexOf(Register str1, Register str2, Register cnt1, Register cnt2, int intCnt2, Register result, Register vec, Register tmp, int vmPageSize) {
    // 
    assert intCnt2 == -1 || (0 < intCnt2 && intCnt2 < 8) : "should be != 0";
    // rcx - matched index in string
    assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
    Label reloadSubstr = new Label();
    Label scanToSubstr = new Label();
    Label scanSubstr = new Label();
    Label adjustStr = new Label();
    Label retFound = new Label();
    Label retNotFound = new Label();
    Label cleanup = new Label();
    Label foundSubstr = new Label();
    Label foundCandidate = new Label();
    int wordSize = 8;
    // We don't know where these strings are located
    // and we can't read beyond them. Load them through stack.
    Label bigStrings = new Label();
    Label checkStr = new Label();
    Label copySubstr = new Label();
    Label copyStr = new Label();
    // save old SP
    movq(tmp, rsp);
    if (intCnt2 > 0) {
        // small (< 8 chars) constant substring
        if (intCnt2 == 1) {
            // One char
            movzwl(result, new AMD64Address(str2, 0));
            // move 32 bits
            movdl(vec, result);
        } else if (intCnt2 == 2) {
            // Two chars
            // move 32 bits
            movdl(vec, new AMD64Address(str2, 0));
        } else if (intCnt2 == 4) {
            // Four chars
            // move 64 bits
            movq(vec, new AMD64Address(str2, 0));
        } else {
            // cnt2 = { 3, 5, 6, 7 }
            // Array header size is 12 bytes in 32-bit VM
            // + 6 bytes for 3 chars == 18 bytes,
            // enough space to load vec and shift.
            movdqu(vec, new AMD64Address(str2, (intCnt2 * 2) - 16));
            psrldq(vec, 16 - (intCnt2 * 2));
        }
    } else {
        // not constant substring
        cmpl(cnt2, 8);
        // Both strings are big enough
        jccb(ConditionFlag.AboveEqual, bigStrings);
        // since heaps are aligned and mapped by pages.
        assert vmPageSize < 1024 * 1024 * 1024 : "default page should be small";
        // We need only low 32 bits
        movl(result, str2);
        andl(result, (vmPageSize - 1));
        cmpl(result, (vmPageSize - 16));
        jccb(ConditionFlag.BelowEqual, checkStr);
        // Move small strings to stack to allow load 16 bytes into vec.
        subq(rsp, 16);
        int stackOffset = wordSize - 2;
        push(cnt2);
        bind(copySubstr);
        movzwl(result, new AMD64Address(str2, cnt2, Scale.Times2, -2));
        movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result);
        decrementl(cnt2, 1);
        jccb(ConditionFlag.NotZero, copySubstr);
        pop(cnt2);
        // New substring address
        movq(str2, rsp);
    }
    // non constant
    bind(checkStr);
    cmpl(cnt1, 8);
    jccb(ConditionFlag.AboveEqual, bigStrings);
    // Check cross page boundary.
    // We need only low 32 bits
    movl(result, str1);
    andl(result, (vmPageSize - 1));
    cmpl(result, (vmPageSize - 16));
    jccb(ConditionFlag.BelowEqual, bigStrings);
    subq(rsp, 16);
    int stackOffset = -2;
    if (intCnt2 < 0) {
        // not constant
        push(cnt2);
        stackOffset += wordSize;
    }
    movl(cnt2, cnt1);
    bind(copyStr);
    movzwl(result, new AMD64Address(str1, cnt2, Scale.Times2, -2));
    movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result);
    decrementl(cnt2, 1);
    jccb(ConditionFlag.NotZero, copyStr);
    if (intCnt2 < 0) {
        // not constant
        pop(cnt2);
    }
    // New string address
    movq(str1, rsp);
    bind(bigStrings);
    // Load substring.
    if (intCnt2 < 0) {
        // -1
        movdqu(vec, new AMD64Address(str2, 0));
        // substr count
        push(cnt2);
        // substr addr
        push(str2);
        // string addr
        push(str1);
    } else {
        // Small (< 8 chars) constant substrings are loaded already.
        movl(cnt2, intCnt2);
    }
    // original SP
    push(tmp);
    // Finished loading
    // ========================================================
    // Start search
    // 
    // string addr
    movq(result, str1);
    if (intCnt2 < 0) {
        // Only for non constant substring
        jmpb(scanToSubstr);
        // SP saved at sp+0
        // String saved at sp+1*wordSize
        // Substr saved at sp+2*wordSize
        // Substr count saved at sp+3*wordSize
        // Reload substr for rescan, this code
        // is executed only for large substrings (> 8 chars)
        bind(reloadSubstr);
        movq(str2, new AMD64Address(rsp, 2 * wordSize));
        movl(cnt2, new AMD64Address(rsp, 3 * wordSize));
        movdqu(vec, new AMD64Address(str2, 0));
        // We came here after the beginning of the substring was
        // matched but the rest of it was not so we need to search
        // again. Start from the next element after the previous match.
        // Restore counter
        subq(str1, result);
        shrl(str1, 1);
        addl(cnt1, str1);
        // Shift to next element
        decrementl(cnt1);
        cmpl(cnt1, cnt2);
        // Left less then substring
        jccb(ConditionFlag.Negative, retNotFound);
        addq(result, 2);
    }
    // non constant
    // Scan string for start of substr in 16-byte vectors
    bind(scanToSubstr);
    assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
    pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
    // CF == 1
    jccb(ConditionFlag.Below, foundCandidate);
    subl(cnt1, 8);
    // Scanned full string
    jccb(ConditionFlag.LessEqual, retNotFound);
    cmpl(cnt1, cnt2);
    // Left less then substring
    jccb(ConditionFlag.Negative, retNotFound);
    addq(result, 16);
    bind(adjustStr);
    // Do not read beyond string
    cmpl(cnt1, 8);
    jccb(ConditionFlag.GreaterEqual, scanToSubstr);
    // Back-up string to avoid reading beyond string.
    leaq(result, new AMD64Address(result, cnt1, Scale.Times2, -16));
    movl(cnt1, 8);
    jmpb(scanToSubstr);
    // Found a potential substr
    bind(foundCandidate);
    // After pcmpestri tmp(rcx) contains matched element index
    // Make sure string is still long enough
    subl(cnt1, tmp);
    cmpl(cnt1, cnt2);
    jccb(ConditionFlag.GreaterEqual, foundSubstr);
    // Left less then substring.
    bind(retNotFound);
    movl(result, -1);
    jmpb(cleanup);
    bind(foundSubstr);
    // Compute start addr of substr
    leaq(result, new AMD64Address(result, tmp, Scale.Times2));
    if (intCnt2 > 0) {
        // Constant substring
        // Repeat search for small substring (< 8 chars)
        // from new point without reloading substring.
        // Have to check that we don't read beyond string.
        cmpl(tmp, 8 - intCnt2);
        jccb(ConditionFlag.Greater, adjustStr);
    // Fall through if matched whole substring.
    } else {
        // non constant
        assert intCnt2 == -1 : "should be != 0";
        addl(tmp, cnt2);
        // Found result if we matched whole substring.
        cmpl(tmp, 8);
        jccb(ConditionFlag.LessEqual, retFound);
        // Repeat search for small substring (<= 8 chars)
        // from new point 'str1' without reloading substring.
        cmpl(cnt2, 8);
        // Have to check that we don't read beyond string.
        jccb(ConditionFlag.LessEqual, adjustStr);
        Label checkNext = new Label();
        Label contScanSubstr = new Label();
        Label retFoundLong = new Label();
        // Compare the rest of substring (> 8 chars).
        movq(str1, result);
        cmpl(tmp, cnt2);
        // First 8 chars are already matched.
        jccb(ConditionFlag.Equal, checkNext);
        bind(scanSubstr);
        pcmpestri(vec, new AMD64Address(str1, 0), 0x0d);
        // Need to reload strings pointers if not matched whole vector
        // OF == 0
        jcc(ConditionFlag.NoOverflow, reloadSubstr);
        bind(checkNext);
        subl(cnt2, 8);
        // Found full substring
        jccb(ConditionFlag.LessEqual, retFoundLong);
        addq(str1, 16);
        addq(str2, 16);
        subl(cnt1, 8);
        // Do not read beyond substring
        cmpl(cnt2, 8);
        jccb(ConditionFlag.GreaterEqual, contScanSubstr);
        // Back-up strings to avoid reading beyond substring.
        leaq(str2, new AMD64Address(str2, cnt2, Scale.Times2, -16));
        leaq(str1, new AMD64Address(str1, cnt2, Scale.Times2, -16));
        subl(cnt1, cnt2);
        movl(cnt2, 8);
        addl(cnt1, 8);
        bind(contScanSubstr);
        movdqu(vec, new AMD64Address(str2, 0));
        jmpb(scanSubstr);
        bind(retFoundLong);
        movq(str1, new AMD64Address(rsp, wordSize));
    }
    // non constant
    bind(retFound);
    // Compute substr offset
    subq(result, str1);
    // index
    shrl(result, 1);
    bind(cleanup);
    // restore SP
    pop(rsp);
}
Also used : Label(org.graalvm.compiler.asm.Label)

Example 20 with Label

use of org.graalvm.compiler.asm.Label in project graal by oracle.

the class SPARCAssemblerTest method doTestControlTransferOp.

/**
 * Assembles the control transfer op and then verifies the expected disp value against the disp
 * field provided by the disassembler.
 */
public void doTestControlTransferOp(Consumer<Label> opCreator, int minDisp, int maxDisp) {
    Label lBack = new Label();
    Label lForward = new Label();
    masm.bind(lBack);
    for (int i = 0; i < -minDisp; i++) {
        masm.nop();
    }
    int backPos = masm.position();
    opCreator.accept(lBack);
    // Nop required to separate the two control transfer instructions
    masm.nop();
    int forwardPos = masm.position();
    opCreator.accept(lForward);
    for (int i = 0; i < maxDisp - 1; i++) {
        masm.nop();
    }
    masm.bind(lForward);
    int condBack = masm.getInt(backPos);
    SPARCOp backOp = SPARCAssembler.getSPARCOp(condBack);
    int dispBack = ((ControlTransferOp) backOp).getDisp(condBack);
    Assert.assertEquals(minDisp, dispBack);
    int condFwd = masm.getInt(forwardPos);
    SPARCOp fwdOp = SPARCAssembler.getSPARCOp(condFwd);
    int dispFwd = ((ControlTransferOp) fwdOp).getDisp(condFwd);
    Assert.assertEquals(maxDisp, dispFwd);
}
Also used : SPARCOp(org.graalvm.compiler.asm.sparc.SPARCAssembler.SPARCOp) Label(org.graalvm.compiler.asm.Label) ControlTransferOp(org.graalvm.compiler.asm.sparc.SPARCAssembler.ControlTransferOp)

Aggregations

Label (org.graalvm.compiler.asm.Label)34 Register (jdk.vm.ci.code.Register)27 ValueUtil.asRegister (jdk.vm.ci.code.ValueUtil.asRegister)23 AMD64Address (org.graalvm.compiler.asm.amd64.AMD64Address)15 ArrayDataPointerConstant (org.graalvm.compiler.lir.asm.ArrayDataPointerConstant)7 ScratchRegister (org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister)5 SPARCAddress (org.graalvm.compiler.asm.sparc.SPARCAddress)4 RegisterConfig (jdk.vm.ci.code.RegisterConfig)3 CompressEncoding (org.graalvm.compiler.core.common.CompressEncoding)3 FrameMap (org.graalvm.compiler.lir.framemap.FrameMap)3 TruffleCallBoundaryInstrumentation (org.graalvm.compiler.truffle.compiler.hotspot.TruffleCallBoundaryInstrumentation)3 AArch64MacroAssembler (org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler)2 AMD64MacroAssembler (org.graalvm.compiler.asm.amd64.AMD64MacroAssembler)2 SPARCMacroAssembler (org.graalvm.compiler.asm.sparc.SPARCMacroAssembler)2 ScratchRegister (org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister)2 CallingConvention (jdk.vm.ci.code.CallingConvention)1 ValueUtil.isRegister (jdk.vm.ci.code.ValueUtil.isRegister)1 AArch64HotSpotRegisterConfig (jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig)1 AArch64Address (org.graalvm.compiler.asm.aarch64.AArch64Address)1 Scale (org.graalvm.compiler.asm.amd64.AMD64Address.Scale)1