Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 47 additions & 18 deletions src/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,6 @@ class CodeGen : public CodeGenInterface
}
}

enum CompareKind
{
CK_SIGNED,
CK_UNSIGNED,
CK_LOGICAL
};
static emitJumpKind genJumpKindForOper(genTreeOps cmp, CompareKind compareKind);

// For a given compare oper tree, returns the conditions to use with jmp/set in 'jmpKind' array.
// The corresponding elements of jmpToTrueLabel indicate whether the target of the jump is to the
// 'true' label or a 'false' label.
//
// 'true' label corresponds to jump target of the current basic block i.e. the target to
// branch to on compare condition being true. 'false' label corresponds to the target to
// branch to on condition being false.
static void genJumpKindsForTree(GenTree* cmpTree, emitJumpKind jmpKind[2], bool jmpToTrueLabel[2]);

static bool genShouldRoundFP();

GenTreeIndir indirForm(var_types type, GenTree* base);
Expand Down Expand Up @@ -1043,6 +1026,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void genCodeForReturnTrap(GenTreeOp* tree);
void genCodeForJcc(GenTreeCC* tree);
void genCodeForSetcc(GenTreeCC* setcc);
void genCodeForSelCC(GenTreeOpCC* selcc);
void genCodeForStoreInd(GenTreeStoreInd* tree);
void genCodeForSwap(GenTreeOp* tree);
void genCodeForCpObj(GenTreeObj* cpObjNode);
Expand Down Expand Up @@ -1134,7 +1118,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
void genCallInstruction(GenTreeCall* call);
void genJmpMethod(GenTree* jmp);
BasicBlock* genCallFinally(BasicBlock* block);
void genCodeForJumpTrue(GenTree* tree);
void genCodeForJumpTrue(GenTreeOp* jtrue);
#ifdef _TARGET_ARM64_
void genCodeForJumpCompare(GenTreeOp* tree);
#endif // _TARGET_ARM64_
Expand Down Expand Up @@ -1354,6 +1338,51 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#ifdef _TARGET_XARCH_
instruction genMapShiftInsToShiftByConstantIns(instruction ins, int shiftByValue);
#endif // _TARGET_XARCH_

// Maps a GenCondition code to a sequence of conditional jumps or other conditional instructions
// such as X86's SETcc. A sequence of instructions rather than just a single one is required for
// certain floating point conditions.
// For example, X86's UCOMISS sets ZF to indicate equality but it also sets it, together with PF,
// to indicate an unordered result. So for GenCondition::FEQ we first need to check if PF is 0
// and then jump if ZF is 1:
// JP fallThroughBlock
// JE jumpDestBlock
// fallThroughBlock:
// ...
// jumpDestBlock:
//
// This is very similar to the way shortcircuit evaluation of bool AND and OR operators works so
// in order to make the GenConditionDesc mapping tables easier to read, a bool expression-like
// pattern is used to encode the above:
// { EJ_jnp, GT_AND, EJ_je }
// { EJ_jp, GT_OR, EJ_jne }
//
// For more details check inst_JCC and inst_SETCC functions.
//
struct GenConditionDesc
{
emitJumpKind jumpKind1;
genTreeOps oper;
emitJumpKind jumpKind2;
char padTo4Bytes;

static const GenConditionDesc& Get(GenCondition condition)
{
assert(condition.GetCode() < _countof(map));
const GenConditionDesc& desc = map[condition.GetCode()];
assert(desc.jumpKind1 != EJ_NONE);
assert((desc.oper == GT_NONE) || (desc.oper == GT_AND) || (desc.oper == GT_OR));
assert((desc.oper == GT_NONE) == (desc.jumpKind2 == EJ_NONE));
return desc;
}

private:
static const GenConditionDesc map[32];
};

void inst_JCC(GenCondition condition, BasicBlock* target);
void inst_SETCC(GenCondition condition, var_types type, regNumber dstReg);
void inst_CMOVCC(GenCondition condition, var_types type, GenTree* op1, GenTree* op2);
};

/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Expand Down
77 changes: 10 additions & 67 deletions src/jit/codegenarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,7 @@ void CodeGen::genLclHeap(GenTree* tree)
genConsumeRegAndCopy(size, regCnt);
endLabel = genCreateTempLabel();
getEmitter()->emitIns_R_R(INS_TEST, easz, regCnt, regCnt);
emitJumpKind jmpEqual = genJumpKindForOper(GT_EQ, CK_SIGNED);
inst_JMP(jmpEqual, endLabel);
inst_JMP(EJ_eq, endLabel);
}

stackAdjustment = 0;
Expand Down Expand Up @@ -383,8 +382,7 @@ void CodeGen::genLclHeap(GenTree* tree)
// Note that regCnt is the number of bytes to stack allocate.
assert(genIsValidIntReg(regCnt));
getEmitter()->emitIns_R_I(INS_sub, EA_PTRSIZE, regCnt, STACK_ALIGN, INS_FLAGS_SET);
emitJumpKind jmpNotEqual = genJumpKindForOper(GT_NE, CK_SIGNED);
inst_JMP(jmpNotEqual, loop);
inst_JMP(EJ_ne, loop);
}
else
{
Expand Down Expand Up @@ -442,8 +440,7 @@ void CodeGen::genLclHeap(GenTree* tree)
getEmitter()->emitIns_R_R_I(INS_sub, EA_PTRSIZE, regTmp, REG_SPBASE, compiler->eeGetPageSize());

getEmitter()->emitIns_R_R(INS_cmp, EA_PTRSIZE, regTmp, regCnt);
emitJumpKind jmpLTU = genJumpKindForOper(GT_LT, CK_UNSIGNED);
inst_JMP(jmpLTU, done);
inst_JMP(EJ_lo, done);

// Update SP to be at the next page of stack that we will tickle
getEmitter()->emitIns_R_R(INS_mov, EA_PTRSIZE, REG_SPBASE, regTmp);
Expand Down Expand Up @@ -1137,7 +1134,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree)
// Are we evaluating this into a register?
if (targetReg != REG_NA)
{
genSetRegToCond(targetReg, tree);
inst_SETCC(GenCondition::FromRelop(tree), tree->TypeGet(), targetReg);
genProduceReg(tree);
}
}
Expand All @@ -1163,8 +1160,7 @@ void CodeGen::genCodeForReturnTrap(GenTreeOp* tree)

BasicBlock* skipLabel = genCreateTempLabel();

emitJumpKind jmpEqual = genJumpKindForOper(GT_EQ, CK_SIGNED);
inst_JMP(jmpEqual, skipLabel);
inst_JMP(EJ_eq, skipLabel);

// emit the call to the EE-helper that stops for GC (or other reasons)

Expand Down Expand Up @@ -1237,54 +1233,6 @@ void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree)
}
}

//------------------------------------------------------------------------
// genSetRegToCond: Generate code to materialize a condition into a register.
//
// Arguments:
// dstReg - The target register to set to 1 or 0
// tree - The GenTree Relop node that was used to set the Condition codes
//
// Return Value: none
//
// Preconditions:
// The condition codes must already have been appropriately set.
//
void CodeGen::genSetRegToCond(regNumber dstReg, GenTree* tree)
{
// Emit code like that:
// ...
// beq True
// bvs True ; this second branch is typically absent
// movs rD, #0
// b Next
// True:
// movs rD, #1
// Next:
// ...

emitJumpKind jumpKind[2];
bool branchToTrueLabel[2];
genJumpKindsForTree(tree, jumpKind, branchToTrueLabel);

BasicBlock* labelTrue = genCreateTempLabel();
getEmitter()->emitIns_J(emitter::emitJumpKindToIns(jumpKind[0]), labelTrue);

if (jumpKind[1] != EJ_NONE)
{
getEmitter()->emitIns_J(emitter::emitJumpKindToIns(jumpKind[1]), labelTrue);
}

getEmitter()->emitIns_R_I(INS_mov, emitActualTypeSize(tree->gtType), dstReg, 0);

BasicBlock* labelNext = genCreateTempLabel();
getEmitter()->emitIns_J(INS_b, labelNext);

genDefineTempLabel(labelTrue);
getEmitter()->emitIns_R_I(INS_mov, emitActualTypeSize(tree->gtType), dstReg, 1);
genDefineTempLabel(labelNext);
}

//------------------------------------------------------------------------
// genLongToIntCast: Generate code for long to int casts.
//
// Arguments:
Expand Down Expand Up @@ -1336,17 +1284,14 @@ void CodeGen::genLongToIntCast(GenTree* cast)
BasicBlock* success = genCreateTempLabel();

inst_RV_RV(INS_tst, loSrcReg, loSrcReg, TYP_INT, EA_4BYTE);
emitJumpKind JmpNegative = genJumpKindForOper(GT_LT, CK_LOGICAL);
inst_JMP(JmpNegative, allOne);
inst_JMP(EJ_mi, allOne);
inst_RV_RV(INS_tst, hiSrcReg, hiSrcReg, TYP_INT, EA_4BYTE);
emitJumpKind jmpNotEqualL = genJumpKindForOper(GT_NE, CK_LOGICAL);
genJumpToThrowHlpBlk(jmpNotEqualL, SCK_OVERFLOW);
genJumpToThrowHlpBlk(EJ_ne, SCK_OVERFLOW);
inst_JMP(EJ_jmp, success);

genDefineTempLabel(allOne);
inst_RV_IV(INS_cmp, hiSrcReg, -1, EA_4BYTE);
emitJumpKind jmpNotEqualS = genJumpKindForOper(GT_NE, CK_SIGNED);
genJumpToThrowHlpBlk(jmpNotEqualS, SCK_OVERFLOW);
genJumpToThrowHlpBlk(EJ_ne, SCK_OVERFLOW);

genDefineTempLabel(success);
}
Expand All @@ -1355,13 +1300,11 @@ void CodeGen::genLongToIntCast(GenTree* cast)
if ((srcType == TYP_ULONG) && (dstType == TYP_INT))
{
inst_RV_RV(INS_tst, loSrcReg, loSrcReg, TYP_INT, EA_4BYTE);
emitJumpKind JmpNegative = genJumpKindForOper(GT_LT, CK_LOGICAL);
genJumpToThrowHlpBlk(JmpNegative, SCK_OVERFLOW);
genJumpToThrowHlpBlk(EJ_mi, SCK_OVERFLOW);
}

inst_RV_RV(INS_tst, hiSrcReg, hiSrcReg, TYP_INT, EA_4BYTE);
emitJumpKind jmpNotEqual = genJumpKindForOper(GT_NE, CK_LOGICAL);
genJumpToThrowHlpBlk(jmpNotEqual, SCK_OVERFLOW);
genJumpToThrowHlpBlk(EJ_ne, SCK_OVERFLOW);
}
}

Expand Down
Loading