forked from OSchip/llvm-project
[InstCombine] reorder mask folds for efficiency
This shows narrowing improvements on the logic tests
(transforms recently added with e247b0e5c9
).
This is not a complete fix. That would require adding
folds to visitOr/visitXor. But it enables the expected
transforms for the basic patterns in the affected tests.
This commit is contained in:
parent
30bb659c6f
commit
310adb658c
|
@ -1796,25 +1796,6 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
|
|||
return BinaryOperator::CreateOr(And, ConstantInt::get(Ty, Together));
|
||||
}
|
||||
|
||||
// If the mask is only needed on one incoming arm, push the 'and' op up.
|
||||
if (match(Op0, m_OneUse(m_Xor(m_Value(X), m_Value(Y)))) ||
|
||||
match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
|
||||
APInt NotAndMask(~(*C));
|
||||
BinaryOperator::BinaryOps BinOp = cast<BinaryOperator>(Op0)->getOpcode();
|
||||
if (MaskedValueIsZero(X, NotAndMask, 0, &I)) {
|
||||
// Not masking anything out for the LHS, move mask to RHS.
|
||||
// and ({x}or X, Y), C --> {x}or X, (and Y, C)
|
||||
Value *NewRHS = Builder.CreateAnd(Y, Op1, Y->getName() + ".masked");
|
||||
return BinaryOperator::Create(BinOp, X, NewRHS);
|
||||
}
|
||||
if (!isa<Constant>(Y) && MaskedValueIsZero(Y, NotAndMask, 0, &I)) {
|
||||
// Not masking anything out for the RHS, move mask to LHS.
|
||||
// and ({x}or X, Y), C --> {x}or (and X, C), Y
|
||||
Value *NewLHS = Builder.CreateAnd(X, Op1, X->getName() + ".masked");
|
||||
return BinaryOperator::Create(BinOp, NewLHS, Y);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Width = Ty->getScalarSizeInBits();
|
||||
const APInt *ShiftC;
|
||||
if (match(Op0, m_OneUse(m_SExt(m_AShr(m_Value(X), m_APInt(ShiftC)))))) {
|
||||
|
@ -1912,6 +1893,27 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
|
|||
}
|
||||
}
|
||||
|
||||
// This is intentionally placed after the narrowing transforms for
|
||||
// efficiency (transform directly to the narrow logic op if possible).
|
||||
// If the mask is only needed on one incoming arm, push the 'and' op up.
|
||||
if (match(Op0, m_OneUse(m_Xor(m_Value(X), m_Value(Y)))) ||
|
||||
match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
|
||||
APInt NotAndMask(~(*C));
|
||||
BinaryOperator::BinaryOps BinOp = cast<BinaryOperator>(Op0)->getOpcode();
|
||||
if (MaskedValueIsZero(X, NotAndMask, 0, &I)) {
|
||||
// Not masking anything out for the LHS, move mask to RHS.
|
||||
// and ({x}or X, Y), C --> {x}or X, (and Y, C)
|
||||
Value *NewRHS = Builder.CreateAnd(Y, Op1, Y->getName() + ".masked");
|
||||
return BinaryOperator::Create(BinOp, X, NewRHS);
|
||||
}
|
||||
if (!isa<Constant>(Y) && MaskedValueIsZero(Y, NotAndMask, 0, &I)) {
|
||||
// Not masking anything out for the RHS, move mask to LHS.
|
||||
// and ({x}or X, Y), C --> {x}or (and X, C), Y
|
||||
Value *NewLHS = Builder.CreateAnd(X, Op1, X->getName() + ".masked");
|
||||
return BinaryOperator::Create(BinOp, NewLHS, Y);
|
||||
}
|
||||
}
|
||||
|
||||
Constant *C1, *C2;
|
||||
const APInt *C3 = C;
|
||||
Value *X;
|
||||
|
|
|
@ -862,14 +862,12 @@ define i32 @lowmask_mul_zext(i8 %x, i32 %y) {
|
|||
ret i32 %r
|
||||
}
|
||||
|
||||
; TODO: we could have narrowed the xor
|
||||
|
||||
define i32 @lowmask_xor_zext_commute(i8 %x, i32 %p) {
|
||||
; CHECK-LABEL: @lowmask_xor_zext_commute(
|
||||
; CHECK-NEXT: [[Y:%.*]] = mul i32 [[P:%.*]], [[P]]
|
||||
; CHECK-NEXT: [[ZX:%.*]] = zext i8 [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[Y_MASKED:%.*]] = and i32 [[Y]], 255
|
||||
; CHECK-NEXT: [[R:%.*]] = xor i32 [[Y_MASKED]], [[ZX]]
|
||||
; CHECK-NEXT: [[Y_TR:%.*]] = trunc i32 [[Y]] to i8
|
||||
; CHECK-NEXT: [[BO_NARROW:%.*]] = xor i8 [[Y_TR]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = zext i8 [[BO_NARROW]] to i32
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%y = mul i32 %p, %p ; thwart complexity-based canonicalization
|
||||
|
@ -879,13 +877,11 @@ define i32 @lowmask_xor_zext_commute(i8 %x, i32 %p) {
|
|||
ret i32 %r
|
||||
}
|
||||
|
||||
; TODO: we could have narrowed the or
|
||||
|
||||
define i24 @lowmask_or_zext_commute(i16 %x, i24 %y) {
|
||||
; CHECK-LABEL: @lowmask_or_zext_commute(
|
||||
; CHECK-NEXT: [[ZX:%.*]] = zext i16 [[X:%.*]] to i24
|
||||
; CHECK-NEXT: [[Y_MASKED:%.*]] = and i24 [[Y:%.*]], 65535
|
||||
; CHECK-NEXT: [[R:%.*]] = or i24 [[Y_MASKED]], [[ZX]]
|
||||
; CHECK-NEXT: [[Y_TR:%.*]] = trunc i24 [[Y:%.*]] to i16
|
||||
; CHECK-NEXT: [[BO_NARROW:%.*]] = or i16 [[Y_TR]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = zext i16 [[BO_NARROW]] to i24
|
||||
; CHECK-NEXT: ret i24 [[R]]
|
||||
;
|
||||
%zx = zext i16 %x to i24
|
||||
|
|
Loading…
Reference in New Issue