mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[SelectionDAG] Add FSHL/FSHR support to computeKnownBits
Also exposes an issue in DAGCombiner::visitFunnelShift where we were assuming the shift amount had the result type (after legalization it'll have the targets shift amount type). llvm-svn: 349298
This commit is contained in:
parent
3c38377cf1
commit
a3996e5f78
@ -6966,8 +6966,10 @@ SDValue DAGCombiner::visitFunnelShift(SDNode *N) {
|
||||
|
||||
// fold (fshl N0, N1, 0) -> N0
|
||||
// fold (fshr N0, N1, 0) -> N1
|
||||
if (DAG.MaskedValueIsZero(N2, APInt::getAllOnesValue(BitWidth)))
|
||||
return IsFSHL ? N0 : N1;
|
||||
if (isPowerOf2_32(BitWidth))
|
||||
if (DAG.MaskedValueIsZero(
|
||||
N2, APInt(N2.getScalarValueSizeInBits(), BitWidth - 1)))
|
||||
return IsFSHL ? N0 : N1;
|
||||
|
||||
// fold (fsh* N0, N1, c) -> (fsh* N0, N1, c % BitWidth)
|
||||
if (ConstantSDNode *Cst = isConstOrConstSplat(N2)) {
|
||||
|
@ -2679,6 +2679,39 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
|
||||
Known.One.ashrInPlace(Shift);
|
||||
}
|
||||
break;
|
||||
case ISD::FSHL:
|
||||
case ISD::FSHR:
|
||||
if (ConstantSDNode *C =
|
||||
isConstOrDemandedConstSplat(Op.getOperand(2), DemandedElts)) {
|
||||
unsigned Amt = C->getAPIntValue().urem(BitWidth);
|
||||
|
||||
// For fshl, 0-shift returns the 1st arg.
|
||||
// For fshr, 0-shift returns the 2nd arg.
|
||||
if (Amt == 0) {
|
||||
Known = computeKnownBits(Op.getOperand(Opcode == ISD::FSHL ? 0 : 1),
|
||||
DemandedElts, Depth + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
// fshl: (X << (Z % BW)) | (Y >> (BW - (Z % BW)))
|
||||
// fshr: (X << (BW - (Z % BW))) | (Y >> (Z % BW))
|
||||
Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
|
||||
Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
|
||||
if (Opcode == ISD::FSHL) {
|
||||
Known.One <<= Amt;
|
||||
Known.Zero <<= Amt;
|
||||
Known2.One.lshrInPlace(BitWidth - Amt);
|
||||
Known2.Zero.lshrInPlace(BitWidth - Amt);
|
||||
} else {
|
||||
Known.One <<= BitWidth - Amt;
|
||||
Known.Zero <<= BitWidth - Amt;
|
||||
Known2.One.lshrInPlace(Amt);
|
||||
Known2.Zero.lshrInPlace(Amt);
|
||||
}
|
||||
Known.One |= Known2.One;
|
||||
Known.Zero |= Known2.Zero;
|
||||
}
|
||||
break;
|
||||
case ISD::SIGN_EXTEND_INREG: {
|
||||
EVT EVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
|
||||
unsigned EBits = EVT.getScalarSizeInBits();
|
||||
|
@ -302,17 +302,12 @@ declare {i64, i1} @llvm.ssub.with.overflow.i64(i64, i64) nounwind readnone
|
||||
define i32 @knownbits_fshl(i32 %a0) nounwind {
|
||||
; X32-LABEL: knownbits_fshl:
|
||||
; X32: # %bb.0:
|
||||
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||||
; X32-NEXT: movl $-1, %eax
|
||||
; X32-NEXT: shrdl $27, %ecx, %eax
|
||||
; X32-NEXT: andl $3, %eax
|
||||
; X32-NEXT: movl $3, %eax
|
||||
; X32-NEXT: retl
|
||||
;
|
||||
; X64-LABEL: knownbits_fshl:
|
||||
; X64: # %bb.0:
|
||||
; X64-NEXT: movl $-1, %eax
|
||||
; X64-NEXT: shrdl $27, %edi, %eax
|
||||
; X64-NEXT: andl $3, %eax
|
||||
; X64-NEXT: movl $3, %eax
|
||||
; X64-NEXT: retq
|
||||
%1 = tail call i32 @llvm.fshl.i32(i32 %a0, i32 -1, i32 5)
|
||||
%2 = and i32 %1, 3
|
||||
@ -322,17 +317,12 @@ define i32 @knownbits_fshl(i32 %a0) nounwind {
|
||||
define i32 @knownbits_fshr(i32 %a0) nounwind {
|
||||
; X32-LABEL: knownbits_fshr:
|
||||
; X32: # %bb.0:
|
||||
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||||
; X32-NEXT: movl $-1, %eax
|
||||
; X32-NEXT: shrdl $5, %ecx, %eax
|
||||
; X32-NEXT: andl $3, %eax
|
||||
; X32-NEXT: movl $3, %eax
|
||||
; X32-NEXT: retl
|
||||
;
|
||||
; X64-LABEL: knownbits_fshr:
|
||||
; X64: # %bb.0:
|
||||
; X64-NEXT: movl $-1, %eax
|
||||
; X64-NEXT: shrdl $5, %edi, %eax
|
||||
; X64-NEXT: andl $3, %eax
|
||||
; X64-NEXT: movl $3, %eax
|
||||
; X64-NEXT: retq
|
||||
%1 = tail call i32 @llvm.fshr.i32(i32 %a0, i32 -1, i32 5)
|
||||
%2 = and i32 %1, 3
|
||||
|
Loading…
Reference in New Issue
Block a user