forked from OSchip/llvm-project
[LegalizeIntegerTypes][RISCV] Teach PromoteSetCCOperands to check sign bits of unsigned compares.
Unsigned compares work with either zero extended or sign extended inputs just like equality comparisons. I didn't allow this when I refactored the code in D116421 due to lack of tests. But I've since found a simple C test case that demonstrates when this can be useful. Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D116617
This commit is contained in:
parent
9b63fff3db
commit
a04b532505
|
@ -1747,18 +1747,16 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDValue &LHS, SDValue &RHS,
|
|||
|
||||
// Prefer to promote the comparison operand with zero extension.
|
||||
|
||||
// If this is an equality comparison and the width of OpL/OpR excluding the
|
||||
// duplicated sign bits is no greater than the width of LHS/RHS, we can avoid
|
||||
// inserting a zext_inreg operation that we might not be able to remove.
|
||||
if (ISD::isIntEqualitySetCC(CCCode)) {
|
||||
unsigned OpLEffectiveBits = DAG.ComputeMaxSignificantBits(OpL);
|
||||
unsigned OpREffectiveBits = DAG.ComputeMaxSignificantBits(OpR);
|
||||
if (OpLEffectiveBits <= LHS.getScalarValueSizeInBits() &&
|
||||
OpREffectiveBits <= RHS.getScalarValueSizeInBits()) {
|
||||
LHS = OpL;
|
||||
RHS = OpR;
|
||||
return;
|
||||
}
|
||||
// If the width of OpL/OpR excluding the duplicated sign bits is no greater
|
||||
// than the width of LHS/RHS, we can avoid/ inserting a zext_inreg operation
|
||||
// that we might not be able to remove.
|
||||
unsigned OpLEffectiveBits = DAG.ComputeMaxSignificantBits(OpL);
|
||||
unsigned OpREffectiveBits = DAG.ComputeMaxSignificantBits(OpR);
|
||||
if (OpLEffectiveBits <= LHS.getScalarValueSizeInBits() &&
|
||||
OpREffectiveBits <= RHS.getScalarValueSizeInBits()) {
|
||||
LHS = OpL;
|
||||
RHS = OpR;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, use zext_inreg.
|
||||
|
|
|
@ -62,6 +62,24 @@ define i16 @sltiu(i16 %a) nounwind {
|
|||
ret i16 %2
|
||||
}
|
||||
|
||||
; Make sure we avoid an AND, if the input of an unsigned compare is known
|
||||
; to be sign extended. This can occur due to InstCombine canonicalizing
|
||||
; x s>= 0 && x s< 10 to x u< 10.
|
||||
define i16 @sltiu_signext(i16 signext %a) nounwind {
|
||||
; RV32I-LABEL: sltiu_signext:
|
||||
; RV32I: # %bb.0:
|
||||
; RV32I-NEXT: sltiu a0, a0, 10
|
||||
; RV32I-NEXT: ret
|
||||
;
|
||||
; RV64I-LABEL: sltiu_signext:
|
||||
; RV64I: # %bb.0:
|
||||
; RV64I-NEXT: sltiu a0, a0, 10
|
||||
; RV64I-NEXT: ret
|
||||
%1 = icmp ult i16 %a, 10
|
||||
%2 = zext i1 %1 to i16
|
||||
ret i16 %2
|
||||
}
|
||||
|
||||
define i16 @xori(i16 %a) nounwind {
|
||||
; RV32I-LABEL: xori:
|
||||
; RV32I: # %bb.0:
|
||||
|
|
|
@ -58,6 +58,24 @@ define i8 @sltiu(i8 %a) nounwind {
|
|||
ret i8 %2
|
||||
}
|
||||
|
||||
; Make sure we avoid an AND, if the input of an unsigned compare is known
|
||||
; to be sign extended. This can occur due to InstCombine canonicalizing
|
||||
; x s>= 0 && x s< 10 to x u< 10.
|
||||
define i8 @sltiu_signext(i8 signext %a) nounwind {
|
||||
; RV32I-LABEL: sltiu_signext:
|
||||
; RV32I: # %bb.0:
|
||||
; RV32I-NEXT: sltiu a0, a0, 10
|
||||
; RV32I-NEXT: ret
|
||||
;
|
||||
; RV64I-LABEL: sltiu_signext:
|
||||
; RV64I: # %bb.0:
|
||||
; RV64I-NEXT: sltiu a0, a0, 10
|
||||
; RV64I-NEXT: ret
|
||||
%1 = icmp ult i8 %a, 10
|
||||
%2 = zext i1 %1 to i8
|
||||
ret i8 %2
|
||||
}
|
||||
|
||||
define i8 @xori(i8 %a) nounwind {
|
||||
; RV32I-LABEL: xori:
|
||||
; RV32I: # %bb.0:
|
||||
|
|
Loading…
Reference in New Issue