Known.One = std::move(IKnownOne);
break;
}
- case Instruction::Select:
- // If this is a select as part of a min/max pattern, don't simplify any
- // further in case we break the structure.
+ case Instruction::Select: {
Value *LHS, *RHS;
- if (matchSelectPattern(I, LHS, RHS).Flavor != SPF_UNKNOWN)
+ SelectPatternFlavor SPF = matchSelectPattern(I, LHS, RHS).Flavor;
+ if (SPF == SPF_UMAX) {
+ // UMax(A, C) == A if ...
+ // The lowest non-zero bit of DemandMask is higher than the highest
+ // non-zero bit of C.
+ const APInt *C;
+ unsigned CTZ = DemandedMask.countTrailingZeros();
+ if (match(RHS, m_APInt(C)) && CTZ >= C->getActiveBits())
+ return LHS;
+ }
+
+ // If this is a select as part of any other min/max pattern, don't simplify
+ // any further in case we break the structure.
+ if (SPF != SPF_UNKNOWN)
return nullptr;
if (SimplifyDemandedBits(I, 2, DemandedMask, RHSKnown, Depth + 1) ||
Known.One = RHSKnown.One & LHSKnown.One;
Known.Zero = RHSKnown.Zero & LHSKnown.Zero;
break;
+ }
case Instruction::ZExt:
case Instruction::Trunc: {
unsigned SrcBitWidth = I->getOperand(0)->getType()->getScalarSizeInBits();
define i32 @and_umax_less(i32 %A) {
; CHECK-LABEL: @and_umax_less(
-; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], 31
-; CHECK-NEXT: [[L1:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 31
-; CHECK-NEXT: [[X:%.*]] = and i32 [[L1]], -32
+; CHECK-NEXT: [[X:%.*]] = and i32 [[A:%.*]], -32
; CHECK-NEXT: ret i32 [[X]]
;
%l0 = icmp ugt i32 31, %A
define i32 @and_umax_muchless(i32 %A) {
; CHECK-LABEL: @and_umax_muchless(
-; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], 12
-; CHECK-NEXT: [[L1:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 12
-; CHECK-NEXT: [[X:%.*]] = and i32 [[L1]], -32
+; CHECK-NEXT: [[X:%.*]] = and i32 [[A:%.*]], -32
; CHECK-NEXT: ret i32 [[X]]
;
%l0 = icmp ugt i32 12, %A
define i32 @shr_umax(i32 %A) {
; CHECK-LABEL: @shr_umax(
-; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], 15
-; CHECK-NEXT: [[L1:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 15
-; CHECK-NEXT: [[X:%.*]] = lshr i32 [[L1]], 4
+; CHECK-NEXT: [[X:%.*]] = lshr i32 [[A:%.*]], 4
; CHECK-NEXT: ret i32 [[X]]
;
%l0 = icmp ugt i32 15, %A
define i8 @t_1_10(i8 %A) {
; CHECK-LABEL: @t_1_10(
-; CHECK-NEXT: [[L2:%.*]] = icmp ugt i8 [[A:%.*]], 1
-; CHECK-NEXT: [[L1:%.*]] = select i1 [[L2]], i8 [[A]], i8 1
-; CHECK-NEXT: [[X:%.*]] = and i8 [[L1]], 10
+; CHECK-NEXT: [[X:%.*]] = and i8 [[A:%.*]], 10
; CHECK-NEXT: ret i8 [[X]]
;
%l2 = icmp ugt i8 %A, 1
define i8 @t_2_4(i8 %A) {
; CHECK-LABEL: @t_2_4(
-; CHECK-NEXT: [[L2:%.*]] = icmp ugt i8 [[A:%.*]], 2
-; CHECK-NEXT: [[L1:%.*]] = select i1 [[L2]], i8 [[A]], i8 2
-; CHECK-NEXT: [[X:%.*]] = and i8 [[L1]], 4
+; CHECK-NEXT: [[X:%.*]] = and i8 [[A:%.*]], 4
; CHECK-NEXT: ret i8 [[X]]
;
%l2 = icmp ugt i8 %A, 2
define i8 @t_2_192(i8 %A) {
; CHECK-LABEL: @t_2_192(
-; CHECK-NEXT: [[L2:%.*]] = icmp ugt i8 [[A:%.*]], 2
-; CHECK-NEXT: [[L1:%.*]] = select i1 [[L2]], i8 [[A]], i8 2
-; CHECK-NEXT: [[X:%.*]] = and i8 [[L1]], -64
+; CHECK-NEXT: [[X:%.*]] = and i8 [[A:%.*]], -64
; CHECK-NEXT: ret i8 [[X]]
;
%l2 = icmp ugt i8 %A, 2
define i8 @t_2_63_or(i8 %A) {
; CHECK-LABEL: @t_2_63_or(
-; CHECK-NEXT: [[L2:%.*]] = icmp ugt i8 [[A:%.*]], 2
-; CHECK-NEXT: [[L1:%.*]] = select i1 [[L2]], i8 [[A]], i8 2
-; CHECK-NEXT: [[X:%.*]] = or i8 [[L1]], 63
+; CHECK-NEXT: [[X:%.*]] = or i8 [[A:%.*]], 63
; CHECK-NEXT: ret i8 [[X]]
;
%l2 = icmp ugt i8 %A, 2