Skip to content

Commit

Permalink
[InstCombine] allow vector splats for add+and with high-mask
Browse files Browse the repository at this point in the history
There might be a better way to specify the pre-conditions,
but this is hopefully clearer than the way it was written:
https://rise4fun.com/Alive/Jhk3

  Pre: C2 < 0 && isShiftedMask(C2) && (C1 == C1 & C2)
  %a = and %x, C2
  %r = add %a, C1
  =>
  %a2 = add %x, C1
  %r = and %a2, C2
  • Loading branch information
rotateright committed Oct 9, 2020
1 parent ccf1260 commit 080e6bc
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 32 deletions.
37 changes: 9 additions & 28 deletions llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,15 @@ Instruction *InstCombinerImpl::foldAddWithConstant(BinaryOperator &Add) {
}
}

// If all bits affected by the add are included in a high-bit-mask, do the
// add before the mask op:
// (X & 0xFF00) + xx00 --> (X + xx00) & 0xFF00
if (match(Op0, m_OneUse(m_And(m_Value(X), m_APInt(C2)))) &&
C2->isNegative() && C2->isShiftedMask() && *C == (*C & *C2)) {
Value *NewAdd = Builder.CreateAdd(X, ConstantInt::get(Ty, *C));
return BinaryOperator::CreateAnd(NewAdd, ConstantInt::get(Ty, *C2));
}

return nullptr;
}

Expand Down Expand Up @@ -1370,34 +1379,6 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT))
return BinaryOperator::CreateOr(LHS, RHS);

// FIXME: We already did a check for ConstantInt RHS above this.
// FIXME: Is this pattern covered by another fold? No regression tests fail on
// removal.
if (ConstantInt *CRHS = dyn_cast<ConstantInt>(RHS)) {
// (X & FF00) + xx00 -> (X+xx00) & FF00
Value *X;
ConstantInt *C2;
if (LHS->hasOneUse() &&
match(LHS, m_And(m_Value(X), m_ConstantInt(C2))) &&
CRHS->getValue() == (CRHS->getValue() & C2->getValue())) {
// See if all bits from the first bit set in the Add RHS up are included
// in the mask. First, get the rightmost bit.
const APInt &AddRHSV = CRHS->getValue();

// Form a mask of all bits from the lowest bit added through the top.
APInt AddRHSHighBits(~((AddRHSV & -AddRHSV)-1));

// See if the and mask includes all of these bits.
APInt AddRHSHighBitsAnd(AddRHSHighBits & C2->getValue());

if (AddRHSHighBits == AddRHSHighBitsAnd) {
// Okay, the xform is safe. Insert the new add pronto.
Value *NewAdd = Builder.CreateAdd(X, CRHS, LHS->getName());
return BinaryOperator::CreateAnd(NewAdd, C2);
}
}
}

// add (select X 0 (sub n A)) A --> select X A n
{
SelectInst *SI = dyn_cast<SelectInst>(LHS);
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Transforms/InstCombine/add.ll
Original file line number Diff line number Diff line change
Expand Up @@ -740,8 +740,8 @@ define i8 @test34(i8 %A) {

define i8 @masked_add(i8 %x) {
; CHECK-LABEL: @masked_add(
; CHECK-NEXT: [[AND1:%.*]] = add i8 [[X:%.*]], 96
; CHECK-NEXT: [[R:%.*]] = and i8 [[AND1]], -16
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X:%.*]], 96
; CHECK-NEXT: [[R:%.*]] = and i8 [[TMP1]], -16
; CHECK-NEXT: ret i8 [[R]]
;
%and = and i8 %x, 240 ; 0xf0
Expand All @@ -751,8 +751,8 @@ define i8 @masked_add(i8 %x) {

define <2 x i8> @masked_add_splat(<2 x i8> %x) {
; CHECK-LABEL: @masked_add_splat(
; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X:%.*]], <i8 -64, i8 -64>
; CHECK-NEXT: [[R:%.*]] = add <2 x i8> [[AND]], <i8 64, i8 64>
; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 64, i8 64>
; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[TMP1]], <i8 -64, i8 -64>
; CHECK-NEXT: ret <2 x i8> [[R]]
;
%and = and <2 x i8> %x, <i8 192, i8 192> ; 0xc0
Expand Down

0 comments on commit 080e6bc

Please sign in to comment.