switch (Op->getOpcode()) {
default: break;
- case Instruction::Or:
- if (Op->hasOneUse()){
- ConstantInt *TogetherCI = dyn_cast<ConstantInt>(Together);
- if (TogetherCI && !TogetherCI->isZero()){
- // (X | C1) & C2 --> (X & (C2^(C1&C2))) | C1
- // NOTE: This reduces the number of bits set in the & mask, which
- // can expose opportunities for store narrowing.
- Together = ConstantExpr::getXor(AndRHS, Together);
- Value *And = Builder.CreateAnd(X, Together);
- And->takeName(Op);
- return BinaryOperator::CreateOr(And, OpRHS);
- }
- }
-
- break;
case Instruction::Add:
if (Op->hasOneUse()) {
// Adding a one to a single bit bit-field should be turned into an XOR
return BinaryOperator::CreateXor(And, NewC);
}
+ const APInt *OrC;
+ if (match(Op0, m_OneUse(m_Or(m_Value(X), m_APInt(OrC))))) {
+ // (X | C1) & C2 --> (X & C2^(C1&C2)) | (C1&C2)
+ // NOTE: This reduces the number of bits set in the & mask, which
+ // can expose opportunities for store narrowing for scalars.
+ // NOTE: SimplifyDemandedBits should have already removed bits from C1
+ // that aren't set in C2. Meaning we can replace (C1&C2) with C1 in
+ // above, but this feels safer.
+ APInt Together = *C & *OrC;
+ Value *And = Builder.CreateAnd(X, ConstantInt::get(I.getType(),
+ Together ^ *C));
+ And->takeName(Op0);
+ return BinaryOperator::CreateOr(And, ConstantInt::get(I.getType(),
+ 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))))) {
ret i32 %E
}
+define <2 x i32> @test30vec(<2 x i32> %A) {
+; CHECK-LABEL: @test30vec(
+; CHECK-NEXT: [[C:%.*]] = and <2 x i32> [[A:%.*]], <i32 -65536, i32 -65536>
+; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[A]], <i32 7224, i32 7224>
+; CHECK-NEXT: [[D:%.*]] = or <2 x i32> [[B]], <i32 32962, i32 32962>
+; CHECK-NEXT: [[E:%.*]] = or <2 x i32> [[D]], [[C]]
+; CHECK-NEXT: ret <2 x i32> [[E]]
+;
+ %B = or <2 x i32> %A, <i32 32962, i32 32962>
+ %C = and <2 x i32> %A, <i32 -65536, i32 -65536>
+ %D = and <2 x i32> %B, <i32 40186, i32 40186>
+ %E = or <2 x i32> %D, %C
+ ret <2 x i32> %E
+}
+
; PR4216
define i64 @test31(i64 %A) {
; CHECK-LABEL: @test31(
ret i64 %F
}
+define <2 x i64> @test31vec(<2 x i64> %A) {
+; CHECK-LABEL: @test31vec(
+; CHECK-NEXT: [[E:%.*]] = and <2 x i64> [[A:%.*]], <i64 4294908984, i64 4294908984>
+; CHECK-NEXT: [[F:%.*]] = or <2 x i64> [[E]], <i64 32962, i64 32962>
+; CHECK-NEXT: ret <2 x i64> [[F]]
+;
+ %B = or <2 x i64> %A, <i64 194, i64 194>
+ %D = and <2 x i64> %B, <i64 250, i64 250>
+
+ %C = or <2 x i64> %A, <i64 32768, i64 32768>
+ %E = and <2 x i64> %C, <i64 4294941696, i64 4294941696>
+
+ %F = or <2 x i64> %D, %E
+ ret <2 x i64> %F
+}
+
; codegen is mature enough to handle vector selects.
define <4 x i32> @test32(<4 x i1> %and.i1352, <4 x i32> %vecinit6.i176, <4 x i32> %vecinit6.i191) {
; CHECK-LABEL: @test32(