Value *NotOp1 = nullptr;
Value **OpToInvert = nullptr;
if (match(Op0, m_Not(m_Value(NotOp0))) &&
- InstCombiner::isFreeToInvert(Op1, Op1->hasOneUse())) {
+ InstCombiner::isFreeToInvert(Op1, /*WillInvertAllUses=*/true) &&
+ InstCombiner::canFreelyInvertAllUsersOf(Op1, /*IgnoredUser=*/&I)) {
Op0 = NotOp0;
OpToInvert = &Op1;
} else if (match(Op1, m_Not(m_Value(NotOp1))) &&
- InstCombiner::isFreeToInvert(Op0, Op0->hasOneUse())) {
+ InstCombiner::isFreeToInvert(Op0, /*WillInvertAllUses=*/true) &&
+ InstCombiner::canFreelyInvertAllUsersOf(Op0, /*IgnoredUser=*/&I)) {
Op1 = NotOp1;
OpToInvert = &Op0;
} else
if (!InstCombiner::canFreelyInvertAllUsersOf(&I, /*IgnoredUser=*/nullptr))
return false;
- *OpToInvert =
+ Builder.SetInsertPoint(
+ &*cast<Instruction>(*OpToInvert)->getInsertionPointAfterDef());
+ Value *NotOpToInvert =
Builder.CreateNot(*OpToInvert, (*OpToInvert)->getName() + ".not");
+ (*OpToInvert)->replaceUsesWithIf(NotOpToInvert, [NotOpToInvert](Use &U) {
+ return U.getUser() != NotOpToInvert;
+ });
+ freelyInvertAllUsersOf(NotOpToInvert, /*IgnoredUser=*/&I);
+ *OpToInvert = NotOpToInvert;
+
Value *NewBinOp;
if (IsBinaryOp)
NewBinOp = Builder.CreateBinOp(NewOpc, Op0, Op1, I.getName() + ".not");
; CHECK-LABEL: @t1(
; CHECK-NEXT: [[I0:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V2:%.*]], [[V3:%.*]]
-; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I3_NOT:%.*]] = or i1 [[I1]], [[I0]]
+; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I4]]
;
; Extra uses are invertible
define i8 @t4(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
; CHECK-LABEL: @t4(
-; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
-; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V2:%.*]], i8 [[V3:%.*]]
+; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]]
+; CHECK-NEXT: [[I4_NOT:%.*]] = or i1 [[I1]], [[I0:%.*]]
+; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]]
; CHECK-NEXT: call void @use8(i8 [[I2]])
-; CHECK-NEXT: [[I3:%.*]] = xor i1 [[I0:%.*]], true
-; CHECK-NEXT: [[I4:%.*]] = and i1 [[I1]], [[I3]]
-; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4]], i8 [[V4:%.*]], i8 [[V5:%.*]]
+; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I5]]
;
%i1 = icmp eq i8 %v0, %v1 ; has extra invertible use
}
define i8 @t4_commutative(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
; CHECK-LABEL: @t4_commutative(
-; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
-; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V2:%.*]], i8 [[V3:%.*]]
+; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]]
+; CHECK-NEXT: [[I4_NOT:%.*]] = or i1 [[I1]], [[I0:%.*]]
+; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]]
; CHECK-NEXT: call void @use8(i8 [[I2]])
-; CHECK-NEXT: [[I3:%.*]] = xor i1 [[I0:%.*]], true
-; CHECK-NEXT: [[I4:%.*]] = and i1 [[I1]], [[I3]]
-; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4]], i8 [[V4:%.*]], i8 [[V5:%.*]]
+; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I5]]
;
%i1 = icmp eq i8 %v0, %v1 ; has extra invertible use
; CHECK-LABEL: @t1(
; CHECK-NEXT: [[I0:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V2:%.*]], [[V3:%.*]]
-; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I0]], i1 true, i1 [[I1]]
+; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I4]]
;
; CHECK-LABEL: @t1_commutative(
; CHECK-NEXT: [[I0:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V2:%.*]], [[V3:%.*]]
-; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I1]], i1 true, i1 [[I0]]
+; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I4]]
;
; Extra uses are invertible
define i8 @t4(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
; CHECK-LABEL: @t4(
-; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
-; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V2:%.*]], i8 [[V3:%.*]]
+; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]]
+; CHECK-NEXT: [[I4_NOT:%.*]] = select i1 [[I0:%.*]], i1 true, i1 [[I1]]
+; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]]
; CHECK-NEXT: call void @use8(i8 [[I2]])
-; CHECK-NEXT: [[I3:%.*]] = xor i1 [[I0:%.*]], true
-; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3]], i1 [[I1]], i1 false
-; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4]], i8 [[V4:%.*]], i8 [[V5:%.*]]
+; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I5]]
;
%i1 = icmp eq i8 %v0, %v1 ; has extra invertible use
}
define i8 @t4_commutative(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
; CHECK-LABEL: @t4_commutative(
-; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
-; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V2:%.*]], i8 [[V3:%.*]]
+; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]]
+; CHECK-NEXT: [[I4_NOT:%.*]] = select i1 [[I1]], i1 true, i1 [[I0:%.*]]
+; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]]
; CHECK-NEXT: call void @use8(i8 [[I2]])
-; CHECK-NEXT: [[I3:%.*]] = xor i1 [[I0:%.*]], true
-; CHECK-NEXT: [[I4:%.*]] = select i1 [[I1]], i1 [[I3]], i1 false
-; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4]], i8 [[V4:%.*]], i8 [[V5:%.*]]
+; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I5]]
;
%i1 = icmp eq i8 %v0, %v1 ; has extra invertible use
; CHECK-LABEL: @t1(
; CHECK-NEXT: [[I0:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V2:%.*]], [[V3:%.*]]
-; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I0]], i1 [[I1]], i1 false
+; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I4]]
;
; CHECK-LABEL: @t1_commutative(
; CHECK-NEXT: [[I0:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V2:%.*]], [[V3:%.*]]
-; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I1]], i1 [[I0]], i1 false
+; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I4]]
;
; Extra uses are invertible
define i8 @t4(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
; CHECK-LABEL: @t4(
-; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
-; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V2:%.*]], i8 [[V3:%.*]]
+; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]]
+; CHECK-NEXT: [[I4_NOT:%.*]] = select i1 [[I0:%.*]], i1 [[I1]], i1 false
+; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]]
; CHECK-NEXT: call void @use8(i8 [[I2]])
-; CHECK-NEXT: [[I3:%.*]] = xor i1 [[I0:%.*]], true
-; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3]], i1 true, i1 [[I1]]
-; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4]], i8 [[V4:%.*]], i8 [[V5:%.*]]
+; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I5]]
;
%i1 = icmp eq i8 %v0, %v1 ; has extra invertible use
}
define i8 @t4_commutative(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
; CHECK-LABEL: @t4_commutative(
-; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
-; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V2:%.*]], i8 [[V3:%.*]]
+; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]]
+; CHECK-NEXT: [[I4_NOT:%.*]] = select i1 [[I1]], i1 [[I0:%.*]], i1 false
+; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]]
; CHECK-NEXT: call void @use8(i8 [[I2]])
-; CHECK-NEXT: [[I3:%.*]] = xor i1 [[I0:%.*]], true
-; CHECK-NEXT: [[I4:%.*]] = select i1 [[I1]], i1 true, i1 [[I3]]
-; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4]], i8 [[V4:%.*]], i8 [[V5:%.*]]
+; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I5]]
;
%i1 = icmp eq i8 %v0, %v1 ; has extra invertible use
; CHECK-LABEL: @t1(
; CHECK-NEXT: [[I0:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V2:%.*]], [[V3:%.*]]
-; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I3_NOT:%.*]] = and i1 [[I1]], [[I0]]
+; CHECK-NEXT: call void @use1(i1 [[I0]])
; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I4]]
;
; Extra uses are invertible
define i8 @t4(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
; CHECK-LABEL: @t4(
-; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
-; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V2:%.*]], i8 [[V3:%.*]]
+; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]]
+; CHECK-NEXT: [[I4_NOT:%.*]] = and i1 [[I1]], [[I0:%.*]]
+; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]]
; CHECK-NEXT: call void @use8(i8 [[I2]])
-; CHECK-NEXT: [[I3:%.*]] = xor i1 [[I0:%.*]], true
-; CHECK-NEXT: [[I4:%.*]] = or i1 [[I1]], [[I3]]
-; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4]], i8 [[V4:%.*]], i8 [[V5:%.*]]
+; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I5]]
;
%i1 = icmp eq i8 %v0, %v1 ; has extra invertible use
}
define i8 @t4_commutative(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
; CHECK-LABEL: @t4_commutative(
-; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]]
-; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V2:%.*]], i8 [[V3:%.*]]
+; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]]
+; CHECK-NEXT: [[I4_NOT:%.*]] = and i1 [[I1]], [[I0:%.*]]
+; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]]
; CHECK-NEXT: call void @use8(i8 [[I2]])
-; CHECK-NEXT: [[I3:%.*]] = xor i1 [[I0:%.*]], true
-; CHECK-NEXT: [[I4:%.*]] = or i1 [[I1]], [[I3]]
-; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4]], i8 [[V4:%.*]], i8 [[V5:%.*]]
+; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]]
; CHECK-NEXT: ret i8 [[I5]]
;
%i1 = icmp eq i8 %v0, %v1 ; has extra invertible use