Skip to content

Commit 1679b20

Browse files
authored
[InstCombine] Fix transforms of two select patterns (#65845)
This patch fixes transforms of `select (~a | c), a, b` and `select (c & b), a, b` as discussed in [D158983](https://reviews.llvm.org/D158983). Alive2: https://alive2.llvm.org/ce/z/ft6TDw
1 parent a054d89 commit 1679b20

File tree

2 files changed

+44
-51
lines changed

2 files changed

+44
-51
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,28 +3099,29 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
30993099
m_c_LogicalOr(m_Deferred(A), m_Deferred(B)))))
31003100
return BinaryOperator::CreateXor(A, B);
31013101

3102-
// select (~a | c), a, b -> and a, (or c, freeze(b))
3103-
if (match(CondVal, m_c_Or(m_Not(m_Specific(TrueVal)), m_Value(C))) &&
3104-
CondVal->hasOneUse()) {
3105-
FalseVal = Builder.CreateFreeze(FalseVal);
3106-
return BinaryOperator::CreateAnd(TrueVal, Builder.CreateOr(C, FalseVal));
3107-
}
3108-
// select (~c & b), a, b -> and b, (or freeze(a), c)
3109-
if (match(CondVal, m_c_And(m_Not(m_Value(C)), m_Specific(FalseVal))) &&
3110-
CondVal->hasOneUse()) {
3111-
TrueVal = Builder.CreateFreeze(TrueVal);
3112-
return BinaryOperator::CreateAnd(FalseVal, Builder.CreateOr(C, TrueVal));
3102+
// select (~a | c), a, b -> select a, (select c, true, b), false
3103+
if (match(CondVal,
3104+
m_OneUse(m_c_Or(m_Not(m_Specific(TrueVal)), m_Value(C))))) {
3105+
Value *OrV = Builder.CreateSelect(C, One, FalseVal);
3106+
return SelectInst::Create(TrueVal, OrV, Zero);
3107+
}
3108+
// select (c & b), a, b -> select b, (select ~c, true, a), false
3109+
if (match(CondVal, m_OneUse(m_c_And(m_Value(C), m_Specific(FalseVal)))) &&
3110+
isFreeToInvert(C, C->hasOneUse())) {
3111+
Value *NotC = Builder.CreateNot(C);
3112+
Value *OrV = Builder.CreateSelect(NotC, One, TrueVal);
3113+
return SelectInst::Create(FalseVal, OrV, Zero);
31133114
}
31143115
// select (a | c), a, b -> select a, true, (select ~c, b, false)
3115-
if (match(CondVal, m_c_Or(m_Specific(TrueVal), m_Value(C))) &&
3116-
CondVal->hasOneUse() && isFreeToInvert(C, C->hasOneUse())) {
3116+
if (match(CondVal, m_OneUse(m_c_Or(m_Specific(TrueVal), m_Value(C)))) &&
3117+
isFreeToInvert(C, C->hasOneUse())) {
31173118
Value *NotC = Builder.CreateNot(C);
31183119
Value *AndV = Builder.CreateSelect(NotC, FalseVal, Zero);
31193120
return SelectInst::Create(TrueVal, One, AndV);
31203121
}
31213122
// select (c & ~b), a, b -> select b, true, (select c, a, false)
3122-
if (match(CondVal, m_c_And(m_Value(C), m_Not(m_Specific(FalseVal)))) &&
3123-
CondVal->hasOneUse()) {
3123+
if (match(CondVal,
3124+
m_OneUse(m_c_And(m_Value(C), m_Not(m_Specific(FalseVal)))))) {
31243125
Value *AndV = Builder.CreateSelect(C, TrueVal, Zero);
31253126
return SelectInst::Create(FalseVal, One, AndV);
31263127
}

llvm/test/Transforms/InstCombine/select-and-or.ll

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,8 @@ define i1 @demorgan_select_infloop2(i1 %L) {
453453

454454
define i1 @and_or1(i1 %a, i1 %b, i1 %c) {
455455
; CHECK-LABEL: @and_or1(
456-
; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]]
457-
; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]]
458-
; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP2]], [[A:%.*]]
456+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[B:%.*]]
457+
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 [[TMP1]], i1 false
459458
; CHECK-NEXT: ret i1 [[R]]
460459
;
461460
%nota = xor i1 %a, true
@@ -466,9 +465,8 @@ define i1 @and_or1(i1 %a, i1 %b, i1 %c) {
466465

467466
define i1 @and_or2(i1 %a, i1 %b, i1 %c) {
468467
; CHECK-LABEL: @and_or2(
469-
; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[A:%.*]]
470-
; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]]
471-
; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP2]], [[B:%.*]]
468+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[A:%.*]]
469+
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false
472470
; CHECK-NEXT: ret i1 [[R]]
473471
;
474472
%notc = xor i1 %c, true
@@ -479,9 +477,8 @@ define i1 @and_or2(i1 %a, i1 %b, i1 %c) {
479477

480478
define i1 @and_or1_commuted(i1 %a, i1 %b, i1 %c) {
481479
; CHECK-LABEL: @and_or1_commuted(
482-
; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[B:%.*]]
483-
; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]]
484-
; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP2]], [[A:%.*]]
480+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[B:%.*]]
481+
; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 [[TMP1]], i1 false
485482
; CHECK-NEXT: ret i1 [[R]]
486483
;
487484
%nota = xor i1 %a, true
@@ -492,9 +489,8 @@ define i1 @and_or1_commuted(i1 %a, i1 %b, i1 %c) {
492489

493490
define i1 @and_or2_commuted(i1 %a, i1 %b, i1 %c) {
494491
; CHECK-LABEL: @and_or2_commuted(
495-
; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[A:%.*]]
496-
; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[C:%.*]]
497-
; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP2]], [[B:%.*]]
492+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[A:%.*]]
493+
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false
498494
; CHECK-NEXT: ret i1 [[R]]
499495
;
500496
%notc = xor i1 %c, true
@@ -536,9 +532,8 @@ define i1 @and_or2_multiuse(i1 %a, i1 %b, i1 %c) {
536532
define <2 x i1> @and_or1_vec(<2 x i1> %a, <2 x i1> %b) {
537533
; CHECK-LABEL: @and_or1_vec(
538534
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
539-
; CHECK-NEXT: [[TMP1:%.*]] = freeze <2 x i1> [[B:%.*]]
540-
; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i1> [[C]], [[TMP1]]
541-
; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[TMP2]], [[A:%.*]]
535+
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[B:%.*]]
536+
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
542537
; CHECK-NEXT: ret <2 x i1> [[R]]
543538
;
544539
%c = call <2 x i1> @gen_v2i1()
@@ -551,9 +546,8 @@ define <2 x i1> @and_or1_vec(<2 x i1> %a, <2 x i1> %b) {
551546
define <2 x i1> @and_or2_vec(<2 x i1> %a, <2 x i1> %b) {
552547
; CHECK-LABEL: @and_or2_vec(
553548
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
554-
; CHECK-NEXT: [[TMP1:%.*]] = freeze <2 x i1> [[A:%.*]]
555-
; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i1> [[C]], [[TMP1]]
556-
; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[TMP2]], [[B:%.*]]
549+
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
550+
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
557551
; CHECK-NEXT: ret <2 x i1> [[R]]
558552
;
559553
%c = call <2 x i1> @gen_v2i1()
@@ -566,9 +560,8 @@ define <2 x i1> @and_or2_vec(<2 x i1> %a, <2 x i1> %b) {
566560
define <2 x i1> @and_or1_vec_commuted(<2 x i1> %a, <2 x i1> %b) {
567561
; CHECK-LABEL: @and_or1_vec_commuted(
568562
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
569-
; CHECK-NEXT: [[TMP1:%.*]] = freeze <2 x i1> [[B:%.*]]
570-
; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i1> [[C]], [[TMP1]]
571-
; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[TMP2]], [[A:%.*]]
563+
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[B:%.*]]
564+
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
572565
; CHECK-NEXT: ret <2 x i1> [[R]]
573566
;
574567
%c = call <2 x i1> @gen_v2i1()
@@ -581,9 +574,8 @@ define <2 x i1> @and_or1_vec_commuted(<2 x i1> %a, <2 x i1> %b) {
581574
define <2 x i1> @and_or2_vec_commuted(<2 x i1> %a, <2 x i1> %b) {
582575
; CHECK-LABEL: @and_or2_vec_commuted(
583576
; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1()
584-
; CHECK-NEXT: [[TMP1:%.*]] = freeze <2 x i1> [[A:%.*]]
585-
; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i1> [[C]], [[TMP1]]
586-
; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[TMP2]], [[B:%.*]]
577+
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
578+
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
587579
; CHECK-NEXT: ret <2 x i1> [[R]]
588580
;
589581
%c = call <2 x i1> @gen_v2i1()
@@ -621,9 +613,9 @@ define i1 @and_or2_wrong_operand(i1 %a, i1 %b, i1 %c, i1 %d) {
621613

622614
define i1 @and_or3(i1 %a, i1 %b, i32 %x, i32 %y) {
623615
; CHECK-LABEL: @and_or3(
624-
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
625-
; CHECK-NEXT: [[COND:%.*]] = and i1 [[C]], [[B:%.*]]
626-
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]]
616+
; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
617+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 true, i1 [[A:%.*]]
618+
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false
627619
; CHECK-NEXT: ret i1 [[R]]
628620
;
629621
%c = icmp eq i32 %x, %y
@@ -634,9 +626,9 @@ define i1 @and_or3(i1 %a, i1 %b, i32 %x, i32 %y) {
634626

635627
define i1 @and_or3_commuted(i1 %a, i1 %b, i32 %x, i32 %y) {
636628
; CHECK-LABEL: @and_or3_commuted(
637-
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
638-
; CHECK-NEXT: [[COND:%.*]] = and i1 [[C]], [[B:%.*]]
639-
; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]]
629+
; CHECK-NEXT: [[C:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
630+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i1 true, i1 [[A:%.*]]
631+
; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 [[TMP1]], i1 false
640632
; CHECK-NEXT: ret i1 [[R]]
641633
;
642634
%c = icmp eq i32 %x, %y
@@ -673,9 +665,9 @@ define i1 @and_or3_multiuse(i1 %a, i1 %b, i32 %x, i32 %y) {
673665

674666
define <2 x i1> @and_or3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
675667
; CHECK-LABEL: @and_or3_vec(
676-
; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[X:%.*]], [[Y:%.*]]
677-
; CHECK-NEXT: [[COND:%.*]] = and <2 x i1> [[C]], [[B:%.*]]
678-
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[COND]], <2 x i1> [[A:%.*]], <2 x i1> [[B]]
668+
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
669+
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
670+
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
679671
; CHECK-NEXT: ret <2 x i1> [[R]]
680672
;
681673
%c = icmp eq <2 x i32> %x, %y
@@ -686,9 +678,9 @@ define <2 x i1> @and_or3_vec(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %
686678

687679
define <2 x i1> @and_or3_vec_commuted(<2 x i1> %a, <2 x i1> %b, <2 x i32> %x, <2 x i32> %y) {
688680
; CHECK-LABEL: @and_or3_vec_commuted(
689-
; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[X:%.*]], [[Y:%.*]]
690-
; CHECK-NEXT: [[COND:%.*]] = and <2 x i1> [[C]], [[B:%.*]]
691-
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[COND]], <2 x i1> [[A:%.*]], <2 x i1> [[B]]
681+
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
682+
; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[A:%.*]]
683+
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
692684
; CHECK-NEXT: ret <2 x i1> [[R]]
693685
;
694686
%c = icmp eq <2 x i32> %x, %y

0 commit comments

Comments
 (0)