return BinaryOperator::CreateSub(ConstantExpr::getNeg(AddOne(C)), X);
}
+ // Use DeMorgan and reassociation to eliminate a 'not' op.
+ Constant *C1;
+ if (match(Op1, m_Constant(C1))) {
+ Constant *C2;
+ if (match(Op0, m_OneUse(m_Or(m_Not(m_Value(X)), m_Constant(C2))))) {
+ // (~X | C2) ^ C1 --> ((X & ~C2) ^ -1) ^ C1 --> (X & ~C2) ^ ~C1
+ Value *And = Builder.CreateAnd(X, ConstantExpr::getNot(C2));
+ return BinaryOperator::CreateXor(And, ConstantExpr::getNot(C1));
+ }
+ if (match(Op0, m_OneUse(m_And(m_Not(m_Value(X)), m_Constant(C2))))) {
+ // (~X & C2) ^ C1 --> ((X | ~C2) ^ -1) ^ C1 --> (X | ~C2) ^ ~C1
+ Value *Or = Builder.CreateOr(X, ConstantExpr::getNot(C2));
+ return BinaryOperator::CreateXor(Or, ConstantExpr::getNot(C1));
+ }
+ }
+
// not (cmp A, B) = !cmp A, B
CmpInst::Predicate Pred;
if (match(&I, m_Not(m_OneUse(m_Cmp(Pred, m_Value(), m_Value()))))) {
ret i32 %r
}
-; TODO: (~X | C2) ^ C1 --> ((X & ~C2) ^ -1) ^ C1 --> (X & ~C2) ^ ~C1
+; (~X | C2) ^ C1 --> ((X & ~C2) ^ -1) ^ C1 --> (X & ~C2) ^ ~C1
; The extra use (store) is here because the simpler case
; may be transformed using demanded bits.
; CHECK-LABEL: @xor_or_not(
; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
; CHECK-NEXT: store i8 [[NX]], i8* [[P:%.*]], align 1
-; CHECK-NEXT: [[OR:%.*]] = or i8 [[NX]], 7
-; CHECK-NEXT: [[R:%.*]] = xor i8 [[OR]], 12
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], -8
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[TMP1]], -13
; CHECK-NEXT: ret i8 [[R]]
;
%nx = xor i8 %x, -1
ret i8 %r
}
-; TODO: (~X & C2) ^ C1 --> ((X | ~C2) ^ -1) ^ C1 --> (X | ~C2) ^ ~C1
+; (~X & C2) ^ C1 --> ((X | ~C2) ^ -1) ^ C1 --> (X | ~C2) ^ ~C1
; The extra use (store) is here because the simpler case
; may be transformed using demanded bits.
; CHECK-LABEL: @xor_and_not(
; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1
; CHECK-NEXT: store i8 [[NX]], i8* [[P:%.*]], align 1
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[NX]], 42
-; CHECK-NEXT: [[R:%.*]] = xor i8 [[AND]], 31
+; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X]], -43
+; CHECK-NEXT: [[R:%.*]] = xor i8 [[TMP1]], -32
; CHECK-NEXT: ret i8 [[R]]
;
%nx = xor i8 %x, -1