Skip to content

Commit 6ddc237

Browse files
committed
[InstCombine] reduce code for flip of masked bit; NFC
There are 1-2 potential follow-up NFC commits to reduce this further on the way to generalizing this for vectors. The operand replacing path should be dead code because demanded bits handles that more generally (D91415).
1 parent e56103d commit 6ddc237

File tree

4 files changed

+80
-89
lines changed

4 files changed

+80
-89
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -114,47 +114,39 @@ static Value *SimplifyBSwap(BinaryOperator &I,
114114
return Builder.CreateCall(F, BinOp);
115115
}
116116

117-
/// This handles expressions of the form ((val OP C1) & C2). Where
118-
/// the Op parameter is 'OP', OpRHS is 'C1', and AndRHS is 'C2'.
119-
Instruction *InstCombinerImpl::OptAndOp(BinaryOperator *Op, ConstantInt *OpRHS,
120-
ConstantInt *AndRHS,
117+
/// This handles expressions of the form ((X + OpRHS) & AndRHS).
118+
Instruction *InstCombinerImpl::OptAndOp(BinaryOperator *Op, ConstantInt *AndRHS,
121119
BinaryOperator &TheAnd) {
122-
Value *X = Op->getOperand(0);
123-
124-
switch (Op->getOpcode()) {
125-
default: break;
126-
case Instruction::Add:
127-
if (Op->hasOneUse()) {
128-
// Adding a one to a single bit bit-field should be turned into an XOR
129-
// of the bit. First thing to check is to see if this AND is with a
130-
// single bit constant.
131-
const APInt &AndRHSV = AndRHS->getValue();
132-
133-
// If there is only one bit set.
134-
if (AndRHSV.isPowerOf2()) {
135-
// Ok, at this point, we know that we are masking the result of the
136-
// ADD down to exactly one bit. If the constant we are adding has
137-
// no bits set below this bit, then we can eliminate the ADD.
138-
const APInt& AddRHS = OpRHS->getValue();
139-
140-
// Check to see if any bits below the one bit set in AndRHSV are set.
141-
if ((AddRHS & (AndRHSV - 1)).isNullValue()) {
142-
// If not, the only thing that can effect the output of the AND is
143-
// the bit specified by AndRHSV. If that bit is set, the effect of
144-
// the XOR is to toggle the bit. If it is clear, then the ADD has
145-
// no effect.
146-
if ((AddRHS & AndRHSV).isNullValue()) { // Bit is not set, noop
147-
return replaceOperand(TheAnd, 0, X);
148-
} else {
149-
// Pull the XOR out of the AND.
150-
Value *NewAnd = Builder.CreateAnd(X, AndRHS);
151-
NewAnd->takeName(Op);
152-
return BinaryOperator::CreateXor(NewAnd, AndRHS);
153-
}
154-
}
155-
}
120+
Value *X;
121+
const APInt *C;
122+
if (!match(Op, m_OneUse(m_Add(m_Value(X), m_APInt(C)))))
123+
return nullptr;
124+
125+
// Adding a one to a single bit bit-field should be turned into an XOR
126+
// of the bit. First thing to check is to see if this AND is with a
127+
// single bit constant.
128+
const APInt &AndRHSV = AndRHS->getValue();
129+
130+
// If there is only one bit set.
131+
if (AndRHSV.isPowerOf2()) {
132+
// Ok, at this point, we know that we are masking the result of the
133+
// ADD down to exactly one bit. If the constant we are adding has
134+
// no bits set below this bit, then we can eliminate the ADD.
135+
136+
// Check to see if any bits below the one bit set in AndRHSV are set.
137+
if ((*C & (AndRHSV - 1)).isNullValue()) {
138+
// If not, the only thing that can effect the output of the AND is
139+
// the bit specified by AndRHSV. If that bit is set, the effect of
140+
// the XOR is to toggle the bit. If it is clear, then the ADD has
141+
// no effect.
142+
if ((*C & AndRHSV).isNullValue()) // Bit is not set, noop
143+
return replaceOperand(TheAnd, 0, X);
144+
145+
// Pull the XOR out of the AND.
146+
Value *NewAnd = Builder.CreateAnd(X, AndRHS);
147+
NewAnd->takeName(Op);
148+
return BinaryOperator::CreateXor(NewAnd, AndRHS);
156149
}
157-
break;
158150
}
159151
return nullptr;
160152
}
@@ -1868,9 +1860,8 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
18681860
}
18691861
}
18701862

1871-
if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
1872-
if (Instruction *Res = OptAndOp(Op0I, Op0CI, AndRHS, I))
1873-
return Res;
1863+
if (Instruction *Res = OptAndOp(Op0I, AndRHS, I))
1864+
return Res;
18741865
}
18751866
}
18761867

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
711711
Instruction *foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI);
712712
Instruction *foldSelectValueEquivalence(SelectInst &SI, ICmpInst &ICI);
713713

714-
Instruction *OptAndOp(BinaryOperator *Op, ConstantInt *OpRHS,
715-
ConstantInt *AndRHS, BinaryOperator &TheAnd);
714+
Instruction *OptAndOp(BinaryOperator *Op, ConstantInt *AndRHS,
715+
BinaryOperator &TheAnd);
716716

717717
Value *insertRangeTest(Value *V, const APInt &Lo, const APInt &Hi,
718718
bool isSigned, bool Inside);

llvm/test/Transforms/InstCombine/add.ll

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -336,51 +336,6 @@ define i8 @test15(i8 %A) {
336336
ret i8 %C
337337
}
338338

339-
; Only one bit set
340-
define i8 @test16(i8 %A) {
341-
; CHECK-LABEL: @test16(
342-
; CHECK-NEXT: [[B:%.*]] = and i8 [[A:%.*]], 16
343-
; CHECK-NEXT: [[C:%.*]] = xor i8 [[B]], 16
344-
; CHECK-NEXT: ret i8 [[C]]
345-
;
346-
%B = add i8 %A, 16
347-
%C = and i8 %B, 16
348-
ret i8 %C
349-
}
350-
351-
define <2 x i8> @test16_uniform(<2 x i8> %A) {
352-
; CHECK-LABEL: @test16_uniform(
353-
; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 16>
354-
; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 16>
355-
; CHECK-NEXT: ret <2 x i8> [[C]]
356-
;
357-
%B = add <2 x i8> %A, <i8 16, i8 16>
358-
%C = and <2 x i8> %B, <i8 16, i8 16>
359-
ret <2 x i8> %C
360-
}
361-
362-
define <2 x i8> @test16_undef(<2 x i8> %A) {
363-
; CHECK-LABEL: @test16_undef(
364-
; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 undef>
365-
; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 undef>
366-
; CHECK-NEXT: ret <2 x i8> [[C]]
367-
;
368-
%B = add <2 x i8> %A, <i8 16, i8 undef>
369-
%C = and <2 x i8> %B, <i8 16, i8 undef>
370-
ret <2 x i8> %C
371-
}
372-
373-
define <2 x i8> @test16_nonuniform(<2 x i8> %A) {
374-
; CHECK-LABEL: @test16_nonuniform(
375-
; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 4>
376-
; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 4>
377-
; CHECK-NEXT: ret <2 x i8> [[C]]
378-
;
379-
%B = add <2 x i8> %A, <i8 16, i8 4>
380-
%C = and <2 x i8> %B, <i8 16, i8 4>
381-
ret <2 x i8> %C
382-
}
383-
384339
define i32 @test17(i32 %A) {
385340
; CHECK-LABEL: @test17(
386341
; CHECK-NEXT: [[C:%.*]] = sub i32 0, [[A:%.*]]

llvm/test/Transforms/InstCombine/and.ll

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,3 +1134,48 @@ define <2 x i8> @lowmask_add_vec(<2 x i8> %x, <2 x i8>* %p) {
11341134
%r = and <2 x i8> %a, <i8 16, i8 32> ; 0x10, 0x20
11351135
ret <2 x i8> %r
11361136
}
1137+
1138+
; Only one bit set
1139+
define i8 @flip_masked_bit(i8 %A) {
1140+
; CHECK-LABEL: @flip_masked_bit(
1141+
; CHECK-NEXT: [[B:%.*]] = and i8 [[A:%.*]], 16
1142+
; CHECK-NEXT: [[C:%.*]] = xor i8 [[B]], 16
1143+
; CHECK-NEXT: ret i8 [[C]]
1144+
;
1145+
%B = add i8 %A, 16
1146+
%C = and i8 %B, 16
1147+
ret i8 %C
1148+
}
1149+
1150+
define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
1151+
; CHECK-LABEL: @flip_masked_bit_uniform(
1152+
; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 16>
1153+
; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 16>
1154+
; CHECK-NEXT: ret <2 x i8> [[C]]
1155+
;
1156+
%B = add <2 x i8> %A, <i8 16, i8 16>
1157+
%C = and <2 x i8> %B, <i8 16, i8 16>
1158+
ret <2 x i8> %C
1159+
}
1160+
1161+
define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
1162+
; CHECK-LABEL: @flip_masked_bit_undef(
1163+
; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 undef>
1164+
; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 undef>
1165+
; CHECK-NEXT: ret <2 x i8> [[C]]
1166+
;
1167+
%B = add <2 x i8> %A, <i8 16, i8 undef>
1168+
%C = and <2 x i8> %B, <i8 16, i8 undef>
1169+
ret <2 x i8> %C
1170+
}
1171+
1172+
define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) {
1173+
; CHECK-LABEL: @flip_masked_bit_nonuniform(
1174+
; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 4>
1175+
; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 4>
1176+
; CHECK-NEXT: ret <2 x i8> [[C]]
1177+
;
1178+
%B = add <2 x i8> %A, <i8 16, i8 4>
1179+
%C = and <2 x i8> %B, <i8 16, i8 4>
1180+
ret <2 x i8> %C
1181+
}

0 commit comments

Comments
 (0)