Skip to content
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
42 changes: 33 additions & 9 deletions src/coreclr/jit/codegenriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3188,7 +3188,6 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree)
regOp1 = tmpRegOp1;
}
}

if (tree->OperIs(GT_EQ, GT_NE))
{
if ((imm != 0) || (cmpSize == EA_4BYTE))
Expand Down Expand Up @@ -3353,8 +3352,14 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree)
regNumber tmpRegOp1 = rsGetRsvdReg();
assert(regOp1 != tmpRegOp1);
imm = static_cast<int32_t>(imm);
emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
regOp1 = tmpRegOp1;

// It might be possible to watch the type of op1 to decide the redundancy.
// But due to the safety reason, only a peephole optimization is done now.
if (!(emit->isRedundantSignExtend(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1)))
{
emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
regOp1 = tmpRegOp1;
}
break;
}
case EA_8BYTE:
Expand Down Expand Up @@ -3389,8 +3394,14 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree)
{
regNumber tmpRegOp1 = rsGetRsvdReg();
assert(regOp1 != tmpRegOp1);
emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
regOp1 = tmpRegOp1;

// It might be possible to watch the type of op1 to decide the redundancy.
// But due to the safety reason, only a peephole optimization is done now.
if (!(emit->isRedundantSignExtend(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1)))
{
emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
regOp1 = tmpRegOp1;
}
}
}

Expand Down Expand Up @@ -3438,10 +3449,23 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree)
regNumber tmpRegOp2 = rsGetRsvdReg();
assert(regOp1 != tmpRegOp2);
assert(regOp2 != tmpRegOp2);
emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp2, regOp2);
regOp1 = tmpRegOp1;
regOp2 = tmpRegOp2;

// It might be possible to watch the type of op1 to decide the redundancy.
// But due to the safety reason, only a peephole optimization is done now.
bool signExtOp1 = !(emit->isRedundantSignExtend(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1));
bool signExtOp2 = !(emit->isRedundantSignExtend(INS_sext_w, EA_8BYTE, tmpRegOp2, regOp2));

if (signExtOp1)
{
emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1);
regOp1 = tmpRegOp1;
}

if (signExtOp2)
{
emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp2, regOp2);
regOp2 = tmpRegOp2;
}
}

switch (cond.GetCode())
Expand Down
95 changes: 95 additions & 0 deletions src/coreclr/jit/emitriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,101 @@ void emitter::emitIns_Mov(emitAttr attr, regNumber dstReg, regNumber srcReg, boo
}
}

//------------------------------------------------------------------------
// emitInsIsSignExtend: Determines whether a given instruction sign extends
//
// Arguments:
// ins -- The instruction being checked
//
bool emitter::emitInsIsSignExtend(instruction ins)
{
switch (ins)
{
case INS_sext_w: // R_R
case INS_lui: // R_I

// R_R_I
case INS_lb:
case INS_lh:
case INS_lw:

// R_R_I
case INS_addiw:
case INS_slliw:
case INS_srliw:
case INS_sraiw:

// R_R_R
case INS_addw:
case INS_subw:
case INS_sllw:
case INS_srlw:
case INS_sraw:

// R_R_R
case INS_mulw:
case INS_divw:
case INS_divuw:
case INS_remw:
case INS_remuw:
{
return true;
}
// TODO: Add more sign-extension instructions
default:
{
return false;
}
}
}

//------------------------------------------------------------------------
// isRedundantSignExtend:
// Check if the current 'sext.w' instruction is redundant and can be omitted.
//
// A 'sext.w' instruction is redundant if the previous instruction sign extends
// the source register of current instruction.
//
// Arguments:
// ins -- The instruction being emitted
// attr -- The emit attribute
// dst -- The destination register
// src -- The source register
//
bool emitter::isRedundantSignExtend(instruction ins, emitAttr size, regNumber dst, regNumber src)
{
assert(ins == INS_sext_w);

if (!emitComp->opts.OptimizationEnabled())
{
return false;
}

const bool canOptimize = emitCanPeepholeLastIns();

if (!canOptimize)
{
return false;
}

regNumber prevDst = emitLastIns->idReg1();
regNumber prevSrc = emitLastIns->idReg2();
emitAttr prevSize = emitLastIns->idOpSize();

bool isPrevInsSignExtend = emitInsIsSignExtend(emitLastIns->idIns());

if (isPrevInsSignExtend && (prevDst == src))
{
JITDUMP("\n -- suppressing 'sext.w reg%u, reg%u' as previous instruction already sign-extended "
"the register reg%u.\n",
dst, src, prevDst);

return true;
}

return false;
}

/*****************************************************************************
*
* Add an instruction referencing two registers
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/jit/emitriscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ struct CnsVal
bool cnsReloc;
};

bool isRedundantSignExtend(instruction ins, emitAttr size, regNumber dst, regNumber src);

#ifdef DEBUG

/************************************************************************/
Expand Down Expand Up @@ -61,6 +63,7 @@ instrDesc* emitNewInstrCallInd(int argCnt,
bool emitInsIsLoad(instruction ins);
bool emitInsIsStore(instruction ins);
bool emitInsIsLoadOrStore(instruction ins);
bool emitInsIsSignExtend(instruction ins);

void emitDispInsName(
code_t code, const BYTE* addr, bool doffs, unsigned insOffset, const instrDesc* id, const insGroup* ig);
Expand Down
Loading