mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-20 03:23:01 +02:00
[InstCombine] Fold and(shl(zext(x), width(SIGNMASK) - width(%x)), SIGNMASK)
to and(sext(%x), SIGNMASK)
One less instruction and reducing use count of zext. As alive2 confirms, we're fine with all the weird combinations of undef elts in constants, but unless the shift amount was undef for a lane, we must sanitize undef mask to zero, since sign bits are no longer zeros. https://rise4fun.com/Alive/d7r ``` ---------------------------------------- Optimization: zz Precondition: ((C1 == (width(%r) - width(%x))) && isSignBit(C2)) %o0 = zext %x %o1 = shl %o0, C1 %r = and %o1, C2 => %n0 = sext %x %r = and %n0, C2 Done: 2016 Optimization is correct! ```
This commit is contained in:
parent
01b8ffbe23
commit
4f26d69f1c
@ -1846,6 +1846,25 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
|
||||
}
|
||||
}
|
||||
|
||||
if (match(&I, m_And(m_OneUse(m_Shl(m_ZExt(m_Value(X)), m_Value(Y))),
|
||||
m_SignMask())) &&
|
||||
match(Y, m_SpecificInt_ICMP(
|
||||
ICmpInst::Predicate::ICMP_EQ,
|
||||
APInt(Ty->getScalarSizeInBits(),
|
||||
Ty->getScalarSizeInBits() -
|
||||
X->getType()->getScalarSizeInBits())))) {
|
||||
auto *SExt = Builder.CreateSExt(X, Ty, X->getName() + ".signext");
|
||||
auto *SanitizedSignMask = cast<Constant>(Op1);
|
||||
// We must be careful with the undef elements of the sign bit mask, however:
|
||||
// the mask elt can be undef iff the shift amount for that lane was undef,
|
||||
// otherwise we need to sanitize undef masks to zero.
|
||||
SanitizedSignMask = Constant::replaceUndefsWith(
|
||||
SanitizedSignMask, ConstantInt::getNullValue(Ty->getScalarType()));
|
||||
SanitizedSignMask =
|
||||
Constant::mergeUndefsWith(SanitizedSignMask, cast<Constant>(Y));
|
||||
return BinaryOperator::CreateAnd(SExt, SanitizedSignMask);
|
||||
}
|
||||
|
||||
if (Instruction *Z = narrowMaskedBinOp(I))
|
||||
return Z;
|
||||
|
||||
|
@ -12,9 +12,8 @@ declare void @use32(i32)
|
||||
|
||||
define i32 @t0(i16 %x) {
|
||||
; CHECK-LABEL: @t0(
|
||||
; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[I1:%.*]] = shl nuw i32 [[I0]], 16
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -2147483648
|
||||
; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext i16 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[X_SIGNEXT]], -2147483648
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%i0 = zext i16 %x to i32
|
||||
@ -24,9 +23,8 @@ define i32 @t0(i16 %x) {
|
||||
}
|
||||
define i32 @t1(i8 %x) {
|
||||
; CHECK-LABEL: @t1(
|
||||
; CHECK-NEXT: [[I0:%.*]] = zext i8 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[I1:%.*]] = shl nuw i32 [[I0]], 24
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -2147483648
|
||||
; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext i8 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[X_SIGNEXT]], -2147483648
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%i0 = zext i8 %x to i32
|
||||
@ -77,8 +75,8 @@ define i32 @t5(i16 %x) {
|
||||
; CHECK-LABEL: @t5(
|
||||
; CHECK-NEXT: [[I0:%.*]] = zext i16 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: call void @use32(i32 [[I0]])
|
||||
; CHECK-NEXT: [[I1:%.*]] = shl nuw i32 [[I0]], 16
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[I1]], -2147483648
|
||||
; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext i16 [[X]] to i32
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[X_SIGNEXT]], -2147483648
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%i0 = zext i16 %x to i32
|
||||
@ -122,9 +120,8 @@ define i32 @n7(i16 %x) {
|
||||
|
||||
define <2 x i32> @t8(<2 x i16> %x) {
|
||||
; CHECK-LABEL: @t8(
|
||||
; CHECK-NEXT: [[I0:%.*]] = zext <2 x i16> [[X:%.*]] to <2 x i32>
|
||||
; CHECK-NEXT: [[I1:%.*]] = shl nuw <2 x i32> [[I0]], <i32 16, i32 16>
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[I1]], <i32 -2147483648, i32 -2147483648>
|
||||
; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32>
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 -2147483648>
|
||||
; CHECK-NEXT: ret <2 x i32> [[R]]
|
||||
;
|
||||
%i0 = zext <2 x i16> %x to <2 x i32>
|
||||
@ -134,9 +131,8 @@ define <2 x i32> @t8(<2 x i16> %x) {
|
||||
}
|
||||
define <2 x i32> @t9(<2 x i16> %x) {
|
||||
; CHECK-LABEL: @t9(
|
||||
; CHECK-NEXT: [[I0:%.*]] = zext <2 x i16> [[X:%.*]] to <2 x i32>
|
||||
; CHECK-NEXT: [[I1:%.*]] = shl <2 x i32> [[I0]], <i32 16, i32 undef>
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[I1]], <i32 -2147483648, i32 -2147483648>
|
||||
; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32>
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 undef>
|
||||
; CHECK-NEXT: ret <2 x i32> [[R]]
|
||||
;
|
||||
%i0 = zext <2 x i16> %x to <2 x i32>
|
||||
@ -147,9 +143,8 @@ define <2 x i32> @t9(<2 x i16> %x) {
|
||||
}
|
||||
define <2 x i32> @t10(<2 x i16> %x) {
|
||||
; CHECK-LABEL: @t10(
|
||||
; CHECK-NEXT: [[I0:%.*]] = zext <2 x i16> [[X:%.*]] to <2 x i32>
|
||||
; CHECK-NEXT: [[I1:%.*]] = shl nuw <2 x i32> [[I0]], <i32 16, i32 16>
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[I1]], <i32 -2147483648, i32 undef>
|
||||
; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32>
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 0>
|
||||
; CHECK-NEXT: ret <2 x i32> [[R]]
|
||||
;
|
||||
%i0 = zext <2 x i16> %x to <2 x i32>
|
||||
@ -161,9 +156,8 @@ define <2 x i32> @t10(<2 x i16> %x) {
|
||||
}
|
||||
define <2 x i32> @t11(<2 x i16> %x) {
|
||||
; CHECK-LABEL: @t11(
|
||||
; CHECK-NEXT: [[I0:%.*]] = zext <2 x i16> [[X:%.*]] to <2 x i32>
|
||||
; CHECK-NEXT: [[I1:%.*]] = shl <2 x i32> [[I0]], <i32 16, i32 undef>
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[I1]], <i32 -2147483648, i32 undef>
|
||||
; CHECK-NEXT: [[X_SIGNEXT:%.*]] = sext <2 x i16> [[X:%.*]] to <2 x i32>
|
||||
; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[X_SIGNEXT]], <i32 -2147483648, i32 undef>
|
||||
; CHECK-NEXT: ret <2 x i32> [[R]]
|
||||
;
|
||||
%i0 = zext <2 x i16> %x to <2 x i32>
|
||||
|
Loading…
Reference in New Issue
Block a user