From: Mike Danes Date: Wed, 24 May 2017 16:58:28 +0000 (+0300) Subject: Delete long compare support from ARM32 codegen X-Git-Tag: accepted/tizen/base/20180629.140029~1083^2~550^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cc6286cc7f6d065ee823379a8afdfba25e603ed5;p=platform%2Fupstream%2Fcoreclr.git Delete long compare support from ARM32 codegen --- diff --git a/src/jit/codegenarm.cpp b/src/jit/codegenarm.cpp index 8c42bf8..438453b 100644 --- a/src/jit/codegenarm.cpp +++ b/src/jit/codegenarm.cpp @@ -1289,52 +1289,35 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) var_types op1Type = op1->TypeGet(); var_types op2Type = op2->TypeGet(); - if (varTypeIsLong(op1Type)) - { -#ifdef DEBUG - // The result of an unlowered long compare on a 32-bit target must either be - // a) materialized into a register, or - // b) unused. - // - // A long compare that has a result that is used but not materialized into a register should - // have been handled by Lowering::LowerCompare. + assert(!varTypeIsLong(op1Type)); + assert(!varTypeIsLong(op2Type)); - LIR::Use use; - assert((tree->gtRegNum != REG_NA) || !LIR::AsRange(compiler->compCurBB).TryGetUse(tree, &use)); -#endif - genCompareLong(tree); + regNumber targetReg = tree->gtRegNum; + emitter* emit = getEmitter(); + + genConsumeIfReg(op1); + genConsumeIfReg(op2); + + if (varTypeIsFloating(op1Type)) + { + assert(op1Type == op2Type); + assert(!tree->OperIs(GT_CMP)); + emit->emitInsBinary(INS_vcmp, emitTypeSize(op1Type), op1, op2); + // vmrs with register 0xf has special meaning of transferring flags + emit->emitIns_R(INS_vmrs, EA_4BYTE, REG_R15); } else { - assert(!varTypeIsLong(op2Type)); - - regNumber targetReg = tree->gtRegNum; - emitter* emit = getEmitter(); - - genConsumeIfReg(op1); - genConsumeIfReg(op2); - - if (varTypeIsFloating(op1Type)) - { - assert(op1Type == op2Type); - assert(!tree->OperIs(GT_CMP)); - emit->emitInsBinary(INS_vcmp, emitTypeSize(op1Type), op1, op2); - // vmrs with register 0xf has special meaning of transferring flags - emit->emitIns_R(INS_vmrs, EA_4BYTE, REG_R15); - } - else - { - assert(!varTypeIsFloating(op2Type)); - var_types cmpType = (op1Type == op2Type) ? op1Type : TYP_INT; - emit->emitInsBinary(INS_cmp, emitTypeSize(cmpType), op1, op2); - } + assert(!varTypeIsFloating(op2Type)); + var_types cmpType = (op1Type == op2Type) ? op1Type : TYP_INT; + emit->emitInsBinary(INS_cmp, emitTypeSize(cmpType), op1, op2); + } - // Are we evaluating this into a register? - if (targetReg != REG_NA) - { - genSetRegToCond(targetReg, tree); - genProduceReg(tree); - } + // Are we evaluating this into a register? + if (targetReg != REG_NA) + { + genSetRegToCond(targetReg, tree); + genProduceReg(tree); } } @@ -1431,158 +1414,6 @@ void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree) } //------------------------------------------------------------------------ -// genCompareLong: Generate code for comparing two longs when the result of the compare -// is manifested in a register. -// -// Arguments: -// treeNode - the compare tree -// -// Return Value: -// None. -// -// Comments: -// For long compares, we need to compare the high parts of operands first, then the low parts. -// If the high compare is false, we do not need to compare the low parts. For less than and -// greater than, if the high compare is true, we can assume the entire compare is true. -// -void CodeGen::genCompareLong(GenTreePtr treeNode) -{ - assert(treeNode->OperIsCompare()); - - GenTreeOp* tree = treeNode->AsOp(); - GenTreePtr op1 = tree->gtOp1; - GenTreePtr op2 = tree->gtOp2; - - assert(varTypeIsLong(op1->TypeGet())); - assert(varTypeIsLong(op2->TypeGet())); - - regNumber targetReg = treeNode->gtRegNum; - - genConsumeOperands(tree); - - GenTreePtr loOp1 = op1->gtGetOp1(); - GenTreePtr hiOp1 = op1->gtGetOp2(); - GenTreePtr loOp2 = op2->gtGetOp1(); - GenTreePtr hiOp2 = op2->gtGetOp2(); - - // Create compare for the high parts - instruction ins = INS_cmp; - var_types cmpType = TYP_INT; - emitAttr cmpAttr = emitTypeSize(cmpType); - - // Emit the compare instruction - getEmitter()->emitInsBinary(ins, cmpAttr, hiOp1, hiOp2); - - // If the result is not being materialized in a register, we're done. - if (targetReg == REG_NA) - { - return; - } - - BasicBlock* labelTrue = genCreateTempLabel(); - BasicBlock* labelFalse = genCreateTempLabel(); - BasicBlock* labelNext = genCreateTempLabel(); - - genJccLongHi(tree->gtOper, labelTrue, labelFalse, tree->IsUnsigned()); - getEmitter()->emitInsBinary(ins, cmpAttr, loOp1, loOp2); - genJccLongLo(tree->gtOper, labelTrue, labelFalse); - - genDefineTempLabel(labelFalse); - getEmitter()->emitIns_R_I(INS_mov, emitActualTypeSize(tree->gtType), tree->gtRegNum, 0); - getEmitter()->emitIns_J(INS_b, labelNext); - - genDefineTempLabel(labelTrue); - getEmitter()->emitIns_R_I(INS_mov, emitActualTypeSize(tree->gtType), tree->gtRegNum, 1); - - genDefineTempLabel(labelNext); - - genProduceReg(tree); -} - -void CodeGen::genJccLongHi(genTreeOps cmp, BasicBlock* jumpTrue, BasicBlock* jumpFalse, bool isUnsigned) -{ - if (cmp != GT_NE) - { - jumpFalse->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL; - } - - switch (cmp) - { - case GT_EQ: - inst_JMP(EJ_ne, jumpFalse); - break; - - case GT_NE: - inst_JMP(EJ_ne, jumpTrue); - break; - - case GT_LT: - case GT_LE: - if (isUnsigned) - { - inst_JMP(EJ_hi, jumpFalse); - inst_JMP(EJ_lo, jumpTrue); - } - else - { - inst_JMP(EJ_gt, jumpFalse); - inst_JMP(EJ_lt, jumpTrue); - } - break; - - case GT_GE: - case GT_GT: - if (isUnsigned) - { - inst_JMP(EJ_lo, jumpFalse); - inst_JMP(EJ_hi, jumpTrue); - } - else - { - inst_JMP(EJ_lt, jumpFalse); - inst_JMP(EJ_gt, jumpTrue); - } - break; - - default: - noway_assert(!"expected a comparison operator"); - } -} - -void CodeGen::genJccLongLo(genTreeOps cmp, BasicBlock* jumpTrue, BasicBlock* jumpFalse) -{ - switch (cmp) - { - case GT_EQ: - inst_JMP(EJ_eq, jumpTrue); - break; - - case GT_NE: - inst_JMP(EJ_ne, jumpTrue); - break; - - case GT_LT: - inst_JMP(EJ_lo, jumpTrue); - break; - - case GT_LE: - inst_JMP(EJ_ls, jumpTrue); - break; - - case GT_GE: - inst_JMP(EJ_hs, jumpTrue); - break; - - case GT_GT: - inst_JMP(EJ_hi, jumpTrue); - break; - - default: - noway_assert(!"expected comparison"); - } -} - -//------------------------------------------------------------------------ // genSetRegToCond: Generate code to materialize a condition into a register. // // Arguments: diff --git a/src/jit/codegenlinear.h b/src/jit/codegenlinear.h index 59763bc..54c6db1 100644 --- a/src/jit/codegenlinear.h +++ b/src/jit/codegenlinear.h @@ -53,12 +53,6 @@ unsigned getFirstArgWithStackSlot(); void genCompareFloat(GenTreePtr treeNode); void genCompareInt(GenTreePtr treeNode); -#if defined(_TARGET_ARM_) -void genCompareLong(GenTreePtr treeNode); -void genJccLongHi(genTreeOps cmp, BasicBlock* jumpTrue, BasicBlock* jumpFalse, bool isUnsigned = false); -void genJccLongLo(genTreeOps cmp, BasicBlock* jumpTrue, BasicBlock* jumpFalse); -#endif // defined(_TARGET_ARM_) - #ifdef FEATURE_SIMD enum SIMDScalarMoveType { diff --git a/src/jit/lsraarmarch.cpp b/src/jit/lsraarmarch.cpp index ac1c126..e862047 100644 --- a/src/jit/lsraarmarch.cpp +++ b/src/jit/lsraarmarch.cpp @@ -81,27 +81,6 @@ void Lowering::TreeNodeInfoInitCmp(GenTreePtr tree) info->srcCount = 2; info->dstCount = tree->OperIs(GT_CMP) ? 0 : 1; -#ifdef _TARGET_ARM_ - - GenTreePtr op1 = tree->gtOp.gtOp1; - GenTreePtr op2 = tree->gtOp.gtOp2; - var_types op1Type = op1->TypeGet(); - var_types op2Type = op2->TypeGet(); - - // Long compares will consume GT_LONG nodes, each of which produces two results. - // Thus for each long operand there will be an additional source. - // TODO-ARM-CQ: Mark hiOp2 and loOp2 as contained if it is a constant. - if (varTypeIsLong(op1Type)) - { - info->srcCount++; - } - if (varTypeIsLong(op2Type)) - { - info->srcCount++; - } - -#endif // _TARGET_ARM_ - CheckImmedAndMakeContained(tree, tree->gtOp.gtOp2); }