-
Notifications
You must be signed in to change notification settings - Fork 14.8k
Closed
Closed
Copy link
Labels
good first issuehttps://github.com/llvm/llvm-project/contributehttps://github.com/llvm/llvm-project/contributellvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passesCovers the InstCombine, InstSimplify and AggressiveInstCombine passesllvm:support
Description
At the very least ComputeNumSignBitsImpl should be able to report that if we bitcast from a wider scalar/vector type to a narrow vector element type, and the original wide type was all sign bits then the destination narrow type elements will be all sign bits as well.
SelectionDAG already does this (and quite a bit more, but the "fast case" would be enough):
llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Lines 4425 to 4469 in 5ad320a
case ISD::BITCAST: { | |
if (VT.isScalableVector()) | |
break; | |
SDValue N0 = Op.getOperand(0); | |
EVT SrcVT = N0.getValueType(); | |
unsigned SrcBits = SrcVT.getScalarSizeInBits(); | |
// Ignore bitcasts from unsupported types.. | |
if (!(SrcVT.isInteger() || SrcVT.isFloatingPoint())) | |
break; | |
// Fast handling of 'identity' bitcasts. | |
if (VTBits == SrcBits) | |
return ComputeNumSignBits(N0, DemandedElts, Depth + 1); | |
bool IsLE = getDataLayout().isLittleEndian(); | |
// Bitcast 'large element' scalar/vector to 'small element' vector. | |
if ((SrcBits % VTBits) == 0) { | |
assert(VT.isVector() && "Expected bitcast to vector"); | |
unsigned Scale = SrcBits / VTBits; | |
APInt SrcDemandedElts = | |
APIntOps::ScaleBitMask(DemandedElts, NumElts / Scale); | |
// Fast case - sign splat can be simply split across the small elements. | |
Tmp = ComputeNumSignBits(N0, SrcDemandedElts, Depth + 1); | |
if (Tmp == SrcBits) | |
return VTBits; | |
// Slow case - determine how far the sign extends into each sub-element. | |
Tmp2 = VTBits; | |
for (unsigned i = 0; i != NumElts; ++i) | |
if (DemandedElts[i]) { | |
unsigned SubOffset = i % Scale; | |
SubOffset = (IsLE ? ((Scale - 1) - SubOffset) : SubOffset); | |
SubOffset = SubOffset * VTBits; | |
if (Tmp <= SubOffset) | |
return 1; | |
Tmp2 = std::min(Tmp2, Tmp - SubOffset); | |
} | |
return Tmp2; | |
} | |
break; | |
} |
Encountered while fighting bitcasts between SSE intrinsics.
https://alive2.llvm.org/ce/z/NvZpPa
----------------------------------------
define <4 x i2> @src(<1 x i8> %a0, <1 x i8> %a1) {
#0:
%cmp = icmp sgt <1 x i8> %a0, %a1
%ext = sext <1 x i1> %cmp to <1 x i8>
%sub = bitcast <1 x i8> %ext to <4 x i2>
%sra = ashr <4 x i2> %sub, { 1, 1, 1, 1 }
ret <4 x i2> %sra
}
=>
define <4 x i2> @tgt(<1 x i8> %a0, <1 x i8> %a1) {
#0:
%cmp = icmp sgt <1 x i8> %a0, %a1
%ext = sext <1 x i1> %cmp to <1 x i8>
%sub = bitcast <1 x i8> %ext to <4 x i2>
ret <4 x i2> %sub
}
Transformation seems to be correct!
Metadata
Metadata
Assignees
Labels
good first issuehttps://github.com/llvm/llvm-project/contributehttps://github.com/llvm/llvm-project/contributellvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passesCovers the InstCombine, InstSimplify and AggressiveInstCombine passesllvm:support