return ConstantInt::getTrue(getCompareTy(RHS));
}
- if (MaxRecurse && LBO && RBO && LBO->getOpcode() == RBO->getOpcode() &&
- LBO->getOperand(1) == RBO->getOperand(1)) {
+ if (!MaxRecurse || !LBO || !RBO || LBO->getOpcode() != RBO->getOpcode())
+ return nullptr;
+
+ if (LBO->getOperand(0) == RBO->getOperand(0)) {
+ switch (LBO->getOpcode()) {
+ default:
+ break;
+ case Instruction::Shl:
+ bool NUW = Q.IIQ.hasNoUnsignedWrap(LBO) && Q.IIQ.hasNoUnsignedWrap(RBO);
+ bool NSW = Q.IIQ.hasNoSignedWrap(LBO) && Q.IIQ.hasNoSignedWrap(RBO);
+ if (!NUW || (ICmpInst::isSigned(Pred) && !NSW) ||
+ !isKnownNonZero(LBO->getOperand(0), Q.DL))
+ break;
+ if (Value *V = simplifyICmpInst(Pred, LBO->getOperand(1),
+ RBO->getOperand(1), Q, MaxRecurse - 1))
+ return V;
+ }
+ }
+
+ if (LBO->getOperand(1) == RBO->getOperand(1)) {
switch (LBO->getOpcode()) {
default:
break;
define i1 @icmp_lshr_known_non_zero_ult_true(i8 %x) {
; CHECK-LABEL: @icmp_lshr_known_non_zero_ult_true(
-; CHECK-NEXT: [[OR:%.*]] = or i8 [[X:%.*]], 1
-; CHECK-NEXT: [[X1:%.*]] = shl nuw i8 [[OR]], 1
-; CHECK-NEXT: [[X2:%.*]] = shl nuw i8 [[OR]], 2
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X1]], [[X2]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%or = or i8 %x, 1
%x1 = shl nuw i8 %or, 1
define i1 @icmp_lshr_known_non_zero_ult_false(i8 %x) {
; CHECK-LABEL: @icmp_lshr_known_non_zero_ult_false(
-; CHECK-NEXT: [[OR:%.*]] = or i8 [[X:%.*]], 1
-; CHECK-NEXT: [[X1:%.*]] = shl nuw i8 [[OR]], 1
-; CHECK-NEXT: [[X2:%.*]] = shl nuw i8 [[OR]], 2
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X1]], [[X2]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
;
%or = or i8 %x, 1
%x1 = shl nuw i8 %or, 1
define i1 @icmp_lshr_known_non_zero_slt_true(i8 %x) {
; CHECK-LABEL: @icmp_lshr_known_non_zero_slt_true(
-; CHECK-NEXT: [[OR:%.*]] = or i8 [[X:%.*]], 1
-; CHECK-NEXT: [[X1:%.*]] = shl nuw nsw i8 [[OR]], 1
-; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i8 [[OR]], 2
-; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X1]], [[X2]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%or = or i8 %x, 1
%x1 = shl nuw nsw i8 %or, 1
define i1 @icmp_lshr_known_non_zero_slt_false(i8 %x) {
; CHECK-LABEL: @icmp_lshr_known_non_zero_slt_false(
-; CHECK-NEXT: [[OR:%.*]] = or i8 [[X:%.*]], 1
-; CHECK-NEXT: [[X1:%.*]] = shl nuw nsw i8 [[OR]], 2
-; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i8 [[OR]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X1]], [[X2]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
;
%or = or i8 %x, 1
%x1 = shl nuw nsw i8 %or, 2
ret i1 %cmp
}
+define i1 @neg_icmp_lshr_known_non_zero_ult_no_nuw(i8 %x) {
+; CHECK-LABEL: @neg_icmp_lshr_known_non_zero_ult_no_nuw(
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[X:%.*]], 1
+; CHECK-NEXT: [[X1:%.*]] = shl i8 [[OR]], 1
+; CHECK-NEXT: [[X2:%.*]] = shl i8 [[OR]], 2
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X1]], [[X2]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %or = or i8 %x, 1
+ %x1 = shl i8 %or, 1
+ %x2 = shl i8 %or, 2
+ %cmp = icmp slt i8 %x1, %x2
+ ret i1 %cmp
+}
+
define i1 @neg_icmp_lshr_known_non_zero_slt_no_nuw(i8 %x) {
; CHECK-LABEL: @neg_icmp_lshr_known_non_zero_slt_no_nuw(
; CHECK-NEXT: [[OR:%.*]] = or i8 [[X:%.*]], 1
define i1 @icmp_ult_vscale_true(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_ult_vscale_true(
-; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-; CHECK-NEXT: [[X1:%.*]] = shl nuw nsw i64 [[VSCALE]], 1
-; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i64 [[VSCALE]], 2
-; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[X1]], [[X2]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 true
;
%vscale = call i64 @llvm.vscale.i64()
%x1 = shl nuw nsw i64 %vscale, 1
define i1 @icmp_ult_vscale_false(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_ult_vscale_false(
-; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-; CHECK-NEXT: [[X1:%.*]] = shl nuw nsw i64 [[VSCALE]], 1
-; CHECK-NEXT: [[X2:%.*]] = shl nuw nsw i64 [[VSCALE]], 2
-; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[X1]], [[X2]]
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
;
%vscale = call i64 @llvm.vscale.i64()
%x1 = shl nuw nsw i64 %vscale, 1