[TargetLowering][RISCV] Introduce isSExtCheaperThanZExt hook and implement for RISC-V

DAGTypeLegalizer::PromoteSetCCOperands currently prefers to zero-extend 
operands when it is able to do so. For some targets this is more expensive 
than a sign-extension, which is also a valid choice. Introduce the 
isSExtCheaperThanZExt hook and use it in the new SExtOrZExtPromotedInteger 
helper. On RISC-V, we prefer sign-extension for FromTy == MVT::i32 and ToTy == 
MVT::i64, as it can be performed using a single instruction.

Differential Revision: https://reviews.llvm.org/D52978

llvm-svn: 347977
This commit is contained in:
Alex Bradbury 2018-11-30 09:56:54 +00:00
parent deaa3e2068
commit e0e62e97df
6 changed files with 36 additions and 16 deletions

View File

@ -2220,6 +2220,12 @@ public:
return false;
}
/// Return true if sign-extension from FromTy to ToTy is cheaper than
/// zero-extension.
virtual bool isSExtCheaperThanZExt(EVT FromTy, EVT ToTy) const {
return false;
}
/// Return true if the target supplies and combines to a paired load
/// two loaded values of type LoadedType next to each other in memory.
/// RequiredAlignment gives the minimal alignment constraints that must be met

View File

@ -1063,9 +1063,10 @@ bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) {
/// shared among BR_CC, SELECT_CC, and SETCC handlers.
void DAGTypeLegalizer::PromoteSetCCOperands(SDValue &NewLHS,SDValue &NewRHS,
ISD::CondCode CCCode) {
// We have to insert explicit sign or zero extends. Note that we could
// insert sign extends for ALL conditions, but zero extend is cheaper on
// many machines (an AND instead of two shifts), so prefer it.
// We have to insert explicit sign or zero extends. Note that we could
// insert sign extends for ALL conditions. For those operations where either
// zero or sign extension would be valid, use SExtOrZExtPromotedInteger
// which will choose the cheapest for the target.
switch (CCCode) {
default: llvm_unreachable("Unknown integer comparison!");
case ISD::SETEQ:
@ -1086,8 +1087,8 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDValue &NewLHS,SDValue &NewRHS,
NewLHS = OpL;
NewRHS = OpR;
} else {
NewLHS = ZExtPromotedInteger(NewLHS);
NewRHS = ZExtPromotedInteger(NewRHS);
NewLHS = SExtOrZExtPromotedInteger(NewLHS);
NewRHS = SExtOrZExtPromotedInteger(NewRHS);
}
break;
}
@ -1095,11 +1096,8 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDValue &NewLHS,SDValue &NewRHS,
case ISD::SETUGT:
case ISD::SETULE:
case ISD::SETULT:
// ALL of these operations will work if we either sign or zero extend
// the operands (including the unsigned comparisons!). Zero extend is
// usually a simpler/cheaper operation, so prefer it.
NewLHS = ZExtPromotedInteger(NewLHS);
NewRHS = ZExtPromotedInteger(NewRHS);
NewLHS = SExtOrZExtPromotedInteger(NewLHS);
NewRHS = SExtOrZExtPromotedInteger(NewRHS);
break;
case ISD::SETGE:
case ISD::SETGT:

View File

@ -281,6 +281,20 @@ private:
return DAG.getZeroExtendInReg(Op, dl, OldVT.getScalarType());
}
// Get a promoted operand and sign or zero extend it to the final size
// (depending on TargetLoweringInfo::isSExtCheaperThanZExt). For a given
// subtarget and type, the choice of sign or zero-extension will be
// consistent.
SDValue SExtOrZExtPromotedInteger(SDValue Op) {
EVT OldVT = Op.getValueType();
SDLoc DL(Op);
Op = GetPromotedInteger(Op);
if (TLI.isSExtCheaperThanZExt(OldVT, Op.getValueType()))
return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Op.getValueType(), Op,
DAG.getValueType(OldVT));
return DAG.getZeroExtendInReg(Op, DL, OldVT.getScalarType());
}
// Integer Result Promotion.
void PromoteIntegerResult(SDNode *N, unsigned ResNo);
SDValue PromoteIntRes_MERGE_VALUES(SDNode *N, unsigned ResNo);

View File

@ -267,6 +267,10 @@ bool RISCVTargetLowering::isZExtFree(SDValue Val, EVT VT2) const {
return TargetLowering::isZExtFree(Val, VT2);
}
bool RISCVTargetLowering::isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const {
return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64;
}
// Changes the condition code and swaps operands if necessary, so the SetCC
// operation matches one of the comparisons supported directly in the RISC-V
// ISA.

View File

@ -54,6 +54,7 @@ public:
bool isTruncateFree(Type *SrcTy, Type *DstTy) const override;
bool isTruncateFree(EVT SrcVT, EVT DstVT) const override;
bool isZExtFree(SDValue Val, EVT VT2) const override;
bool isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const override;
// Provide custom lowering hooks for some operations.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;

View File

@ -51,8 +51,7 @@ define i32 @sltiu(i32 %a) nounwind {
;
; RV64I-LABEL: sltiu:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: sltiu a0, a0, 3
; RV64I-NEXT: ret
%1 = icmp ult i32 %a, 3
@ -213,10 +212,8 @@ define i32 @sltu(i32 %a, i32 %b) nounwind {
;
; RV64I-LABEL: sltu:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a1, a1, 32
; RV64I-NEXT: srli a1, a1, 32
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: sext.w a1, a1
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: sltu a0, a0, a1
; RV64I-NEXT: ret
%1 = icmp ult i32 %a, %b