if (TrueVal == FalseVal)
return TrueVal;
+ if (Cond == TrueVal) {
+ // select i1 X, i1 X, i1 false --> X (logical-and)
+ if (match(FalseVal, m_ZeroInt()))
+ return Cond;
+ // select i1 X, i1 X, i1 true --> true
+ if (match(FalseVal, m_One()))
+ return ConstantInt::getTrue(Cond->getType());
+ }
+ if (Cond == FalseVal) {
+ // select i1 X, i1 true, i1 X --> X (logical-or)
+ if (match(TrueVal, m_One()))
+ return Cond;
+ // select i1 X, i1 false, i1 X --> false
+ if (match(TrueVal, m_ZeroInt()))
+ return ConstantInt::getFalse(Cond->getType());
+ }
+
// If the true or false value is poison, we can fold to the other value.
// If the true or false value is undef, we can fold to the other value as
// long as the other value isn't poison.
define i1 @and_same_op(i1 %x) {
; CHECK-LABEL: @and_same_op(
-; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 [[X]], i1 false
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 [[X:%.*]]
;
%r = select i1 %x, i1 %x, i1 false
ret i1 %r
define <2 x i1> @or_same_op(<2 x i1> %x) {
; CHECK-LABEL: @or_same_op(
-; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[X:%.*]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[X]]
-; CHECK-NEXT: ret <2 x i1> [[R]]
+; CHECK-NEXT: ret <2 x i1> [[X:%.*]]
;
%r = select <2 x i1> %x, <2 x i1> <i1 true, i1 true>, <2 x i1> %x
ret <2 x i1> %r
define <2 x i1> @always_true_same_op(<2 x i1> %x) {
; CHECK-LABEL: @always_true_same_op(
-; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[X:%.*]], <2 x i1> [[X]], <2 x i1> <i1 poison, i1 true>
-; CHECK-NEXT: ret <2 x i1> [[R]]
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%r = select <2 x i1> %x, <2 x i1> %x, <2 x i1> <i1 poison, i1 true>
ret <2 x i1> %r
define i1 @always_false_same_op(i1 %x) {
; CHECK-LABEL: @always_false_same_op(
-; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 false, i1 [[X]]
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%r = select i1 %x, i1 false, i1 %x
ret i1 %r