diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2946,6 +2946,31 @@ return getTrue(ITy); } + // If x is nonzero: + // x >> C true for C > 0. + // x udiv C true for C > 1. + // TODO: allow non-constant shift amount/divisor + const APInt *C; + if ((match(LBO, m_LShr(m_Specific(RHS), m_APInt(C))) && C->ugt(0)) || + (match(LBO, m_UDiv(m_Specific(RHS), m_APInt(C))) && C->ugt(1))) { + if (isKnownNonZero(RHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT)) { + switch (Pred) { + default: + break; + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_UGE: + return getFalse(ITy); + case ICmpInst::ICMP_NE: + case ICmpInst::ICMP_ULT: + return getTrue(ITy); + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_ULE: + // UGT/ULE are handled by the more general case just above + llvm_unreachable("Unexpected UGT/ULE, should have been handled"); + } + } + } + // (x*C1)/C2 <= x for C1 <= C2. // This holds even if the multiplication overflows: Assume that x != 0 and // arithmetic is modulo M. For overflow to occur we must have C1 >= M/x and diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll --- a/llvm/test/Transforms/InstSimplify/compare.ll +++ b/llvm/test/Transforms/InstSimplify/compare.ll @@ -582,9 +582,7 @@ ; CHECK-LABEL: @lshr_nonzero1( ; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NE_0]]) -; CHECK-NEXT: [[LHS:%.*]] = lshr i32 [[X]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[LHS]], [[X]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %x_ne_0 = icmp ne i32 %x, 0 call void @llvm.assume(i1 %x_ne_0) @@ -597,9 +595,7 @@ ; CHECK-LABEL: @lshr_nonzero2( ; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NE_0]]) -; CHECK-NEXT: [[LHS:%.*]] = lshr i32 [[X]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[LHS]], [[X]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %x_ne_0 = icmp ne i32 %x, 0 call void @llvm.assume(i1 %x_ne_0) @@ -612,9 +608,7 @@ ; CHECK-LABEL: @lshr_nonzero3( ; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NE_0]]) -; CHECK-NEXT: [[LHS:%.*]] = lshr i32 [[X]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[LHS]], [[X]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %x_ne_0 = icmp ne i32 %x, 0 call void @llvm.assume(i1 %x_ne_0) @@ -627,9 +621,7 @@ ; CHECK-LABEL: @lshr_nonzero4( ; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NE_0]]) -; CHECK-NEXT: [[LHS:%.*]] = lshr i32 [[X]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[LHS]], [[X]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %x_ne_0 = icmp ne i32 %x, 0 call void @llvm.assume(i1 %x_ne_0) @@ -982,9 +974,7 @@ ; CHECK-LABEL: @udiv_nonzero1( ; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NE_0]]) -; CHECK-NEXT: [[LHS:%.*]] = udiv i32 [[X]], 3 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[LHS]], [[X]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %x_ne_0 = icmp ne i32 %x, 0 call void @llvm.assume(i1 %x_ne_0) @@ -997,9 +987,7 @@ ; CHECK-LABEL: @udiv_nonzero2( ; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NE_0]]) -; CHECK-NEXT: [[LHS:%.*]] = udiv i32 [[X]], 3 -; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[LHS]], [[X]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %x_ne_0 = icmp ne i32 %x, 0 call void @llvm.assume(i1 %x_ne_0) @@ -1012,9 +1000,7 @@ ; CHECK-LABEL: @udiv_nonzero3( ; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NE_0]]) -; CHECK-NEXT: [[LHS:%.*]] = udiv i32 [[X]], 3 -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[LHS]], [[X]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %x_ne_0 = icmp ne i32 %x, 0 call void @llvm.assume(i1 %x_ne_0) @@ -1027,9 +1013,7 @@ ; CHECK-LABEL: @udiv_nonzero4( ; CHECK-NEXT: [[X_NE_0:%.*]] = icmp ne i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_NE_0]]) -; CHECK-NEXT: [[LHS:%.*]] = udiv i32 [[X]], 3 -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[LHS]], [[X]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %x_ne_0 = icmp ne i32 %x, 0 call void @llvm.assume(i1 %x_ne_0)