Skip to content

Commit 9a44f5d

Browse files
committed
[InstCombine] Support and/or in getFreelyInvertedImpl using DeMorgan's Law
1 parent 5b09b6a commit 9a44f5d

File tree

4 files changed

+59
-41
lines changed

4 files changed

+59
-41
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2596,6 +2596,32 @@ Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
25962596
return nullptr;
25972597
}
25982598

2599+
// De Morgan's Laws:
2600+
// (~(A | B)) -> (~A & ~B)
2601+
// (~(A & B)) -> (~A | ~B)
2602+
auto TryInvertAndOrUsingDeMorgan = [&](Instruction::BinaryOps Opcode,
2603+
Value *A, Value *B) -> Value * {
2604+
bool LocalDoesConsume = DoesConsume;
2605+
if (!getFreelyInvertedImpl(B, B->hasOneUse(), /*Builder=*/nullptr,
2606+
LocalDoesConsume, Depth))
2607+
return nullptr;
2608+
if (auto *NotA = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
2609+
LocalDoesConsume, Depth)) {
2610+
auto *NotB = getFreelyInvertedImpl(B, B->hasOneUse(), Builder,
2611+
LocalDoesConsume, Depth);
2612+
DoesConsume = LocalDoesConsume;
2613+
return Builder ? Builder->CreateBinOp(Opcode, NotA, NotB) : NonNull;
2614+
}
2615+
2616+
return nullptr;
2617+
};
2618+
2619+
if (match(V, m_Or(m_Value(A), m_Value(B))))
2620+
return TryInvertAndOrUsingDeMorgan(Instruction::And, A, B);
2621+
2622+
if (match(V, m_And(m_Value(A), m_Value(B))))
2623+
return TryInvertAndOrUsingDeMorgan(Instruction::Or, A, B);
2624+
25992625
return nullptr;
26002626
}
26012627

llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,11 @@ define i1 @src_is_mask_shl_lshr(i8 %x_in, i8 %y, i1 %cond) {
226226

227227
define i1 @src_is_mask_shl_lshr_fail_not_allones(i8 %x_in, i8 %y, i1 %cond) {
228228
; CHECK-LABEL: @src_is_mask_shl_lshr_fail_not_allones(
229-
; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
230229
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[Y:%.*]]
231230
; CHECK-NEXT: [[MASK:%.*]] = and i8 [[TMP1]], -2
232-
; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[MASK]], -1
233-
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]]
234-
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0
231+
; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[X_IN:%.*]], -124
232+
; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[TMP2]], [[MASK]]
233+
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1
235234
; CHECK-NEXT: ret i1 [[R]]
236235
;
237236
%x = xor i8 %x_in, 123
@@ -572,11 +571,10 @@ define i1 @src_is_notmask_neg_p2(i8 %x_in, i8 %y) {
572571

573572
define i1 @src_is_notmask_neg_p2_fail_not_invertable(i8 %x_in, i8 %y) {
574573
; CHECK-LABEL: @src_is_notmask_neg_p2_fail_not_invertable(
575-
; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123
576-
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1
577-
; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y]], -1
578-
; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP1]], [[TMP2]]
579-
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[TMP3]]
574+
; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X_IN:%.*]], -124
575+
; CHECK-NEXT: [[TMP2:%.*]] = sub i8 0, [[Y:%.*]]
576+
; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[TMP2]], [[Y]]
577+
; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[TMP1]], [[TMP3]]
580578
; CHECK-NEXT: ret i1 [[R]]
581579
;
582580
%x = xor i8 %x_in, 123

llvm/test/Transforms/InstCombine/not.ll

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -864,11 +864,10 @@ define i32 @test_zext(i32 %a, i32 %b){
864864
define void @test_invert_demorgan_or(i32 %a, i32 %b, i1 %cond) {
865865
; CHECK-LABEL: @test_invert_demorgan_or(
866866
; CHECK-NEXT: entry:
867-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
868867
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0
869-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
870-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true
871-
; CHECK-NEXT: [[MERGE:%.*]] = or i1 [[OR]], [[NOT]]
868+
; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[B1:%.*]], 0
869+
; CHECK-NEXT: [[OR_NOT1:%.*]] = and i1 [[CMP2]], [[CMP3]]
870+
; CHECK-NEXT: [[MERGE:%.*]] = and i1 [[OR_NOT1]], [[COND:%.*]]
872871
; CHECK-NEXT: br i1 [[MERGE]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
873872
; CHECK: if.then:
874873
; CHECK-NEXT: call void @f1()
@@ -894,12 +893,11 @@ if.else:
894893

895894
define i1 @test_invert_demorgan_or2(i64 %a, i64 %b, i64 %c) {
896895
; CHECK-LABEL: @test_invert_demorgan_or2(
897-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[A:%.*]], 23
898-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i64 [[B:%.*]], 59
899-
; CHECK-NEXT: [[OR1:%.*]] = or i1 [[CMP1]], [[CMP2]]
900-
; CHECK-NEXT: [[CMP3:%.*]] = icmp ugt i64 [[C:%.*]], 59
901-
; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[CMP3]]
902-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OR2]], true
896+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[A:%.*]], 24
897+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[B:%.*]], 60
898+
; CHECK-NEXT: [[OR1_NOT1:%.*]] = and i1 [[CMP1]], [[CMP2]]
899+
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i64 [[C:%.*]], 60
900+
; CHECK-NEXT: [[NOT:%.*]] = and i1 [[OR1_NOT1]], [[CMP3]]
903901
; CHECK-NEXT: ret i1 [[NOT]]
904902
;
905903
%cmp1 = icmp ugt i64 %a, 23
@@ -913,17 +911,16 @@ define i1 @test_invert_demorgan_or2(i64 %a, i64 %b, i64 %c) {
913911

914912
define i1 @test_invert_demorgan_or3(i32 %a, i32 %b) {
915913
; CHECK-LABEL: @test_invert_demorgan_or3(
916-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 178206
917-
; CHECK-NEXT: [[V1:%.*]] = add i32 [[B:%.*]], -195102
918-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[V1]], 1506
919-
; CHECK-NEXT: [[V2:%.*]] = add i32 [[B]], -201547
920-
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[V2]], 716213
921-
; CHECK-NEXT: [[V3:%.*]] = add i32 [[B]], -918000
922-
; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[V3]], 196112
923-
; CHECK-NEXT: [[OR1:%.*]] = or i1 [[CMP1]], [[CMP2]]
924-
; CHECK-NEXT: [[OR2:%.*]] = or i1 [[OR1]], [[CMP3]]
925-
; CHECK-NEXT: [[OR3:%.*]] = or i1 [[OR2]], [[CMP4]]
926-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[OR3]], true
914+
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 178206
915+
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[B:%.*]], -196608
916+
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[TMP1]], -1506
917+
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[B]], -917760
918+
; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[TMP2]], -716213
919+
; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[B]], -1114112
920+
; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[TMP3]], -196112
921+
; CHECK-NEXT: [[OR1_NOT2:%.*]] = and i1 [[CMP1]], [[CMP2]]
922+
; CHECK-NEXT: [[OR2_NOT1:%.*]] = and i1 [[OR1_NOT2]], [[CMP3]]
923+
; CHECK-NEXT: [[NOT:%.*]] = and i1 [[OR2_NOT1]], [[CMP4]]
927924
; CHECK-NEXT: ret i1 [[NOT]]
928925
;
929926
%cmp1 = icmp eq i32 %a, 178206
@@ -943,11 +940,10 @@ define i1 @test_invert_demorgan_or3(i32 %a, i32 %b) {
943940
define i1 @test_invert_demorgan_and(i32 %a, i32 %b, i1 %cond) {
944941
; CHECK-LABEL: @test_invert_demorgan_and(
945942
; CHECK-NEXT: entry:
946-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
947943
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0
948-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
949-
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true
950-
; CHECK-NEXT: [[MERGE:%.*]] = and i1 [[AND]], [[NOT]]
944+
; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[B1:%.*]], 0
945+
; CHECK-NEXT: [[AND_NOT1:%.*]] = or i1 [[CMP2]], [[CMP3]]
946+
; CHECK-NEXT: [[MERGE:%.*]] = or i1 [[AND_NOT1]], [[COND:%.*]]
951947
; CHECK-NEXT: br i1 [[MERGE]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
952948
; CHECK: if.then:
953949
; CHECK-NEXT: call void @f1()
@@ -973,9 +969,8 @@ if.else:
973969

974970
define i64 @test_invert_demorgan_and2(i64 %x) {
975971
; CHECK-LABEL: @test_invert_demorgan_and2(
976-
; CHECK-NEXT: [[ADD:%.*]] = add i64 [[X:%.*]], 9223372036854775807
977-
; CHECK-NEXT: [[AND:%.*]] = and i64 [[ADD]], 9223372036854775807
978-
; CHECK-NEXT: [[SUB:%.*]] = xor i64 [[AND]], -1
972+
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[X:%.*]]
973+
; CHECK-NEXT: [[SUB:%.*]] = or i64 [[TMP1]], -9223372036854775808
979974
; CHECK-NEXT: ret i64 [[SUB]]
980975
;
981976
%add = add i64 %x, 9223372036854775807
@@ -986,10 +981,9 @@ define i64 @test_invert_demorgan_and2(i64 %x) {
986981

987982
define i1 @test_invert_demorgan_and3(i32 %a, i32 %b) {
988983
; CHECK-LABEL: @test_invert_demorgan_and3(
989-
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1
990-
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NOT]], [[B:%.*]]
984+
; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
991985
; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], 4095
992-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
986+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 4095
993987
; CHECK-NEXT: ret i1 [[CMP]]
994988
;
995989
%not = xor i32 %a, -1

llvm/test/Transforms/InstCombine/pr63791.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ define void @y() {
1515
; CHECK-NEXT: store i1 true, ptr poison, align 1
1616
; CHECK-NEXT: br i1 poison, label [[FOR_COND_I]], label [[FOR_COND5_PREHEADER_I]]
1717
; CHECK: for.cond5.preheader.i:
18-
; CHECK-NEXT: br i1 false, label [[FOR_INC19_I:%.*]], label [[FOR_COND1_LOOPEXIT_I:%.*]]
18+
; CHECK-NEXT: br i1 true, label [[FOR_COND1_LOOPEXIT_I:%.*]], label [[FOR_INC19_I:%.*]]
1919
; CHECK: for.inc19.i:
2020
; CHECK-NEXT: br i1 poison, label [[FOR_INC19_I]], label [[FOR_COND1_LOOPEXIT_I]]
2121
;

0 commit comments

Comments
 (0)