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 @@ -3627,6 +3627,41 @@ return nullptr; } +static Value *simplifyICmpLShiftedVScales(CmpInst::Predicate Predicate, + Value *LHS, Value *RHS, + const SimplifyQuery &Q) { + ConstantInt *IntLHS, *IntRHS; + if (!match(LHS, m_Shl(m_VScale(Q.DL), m_ConstantInt(IntLHS))) || + !match(RHS, m_Shl(m_VScale(Q.DL), m_ConstantInt(IntRHS))) || + LHS->getType() != RHS->getType()) + return nullptr; + + switch (Predicate) { + case CmpInst::ICMP_ULT: + case CmpInst::ICMP_SLT: + if (IntLHS < IntRHS) + return getTrue(getCompareTy(LHS)); + return getFalse(getCompareTy(LHS)); + case CmpInst::ICMP_UGT: + case CmpInst::ICMP_SGT: + if (IntLHS > IntRHS) + return getTrue(getCompareTy(LHS)); + return getFalse(getCompareTy(LHS)); + case CmpInst::ICMP_ULE: + case CmpInst::ICMP_SLE: + if (IntLHS <= IntRHS) + return getTrue(getCompareTy(LHS)); + return getFalse(getCompareTy(LHS)); + case CmpInst::ICMP_UGE: + case CmpInst::ICMP_SGE: + if (IntLHS >= IntRHS) + return getTrue(getCompareTy(LHS)); + return getFalse(getCompareTy(LHS)); + default: + return nullptr; + }; +} + static Value *simplifyICmpWithDominatingAssume(CmpInst::Predicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q) { @@ -3940,6 +3975,9 @@ if (Value *V = threadCmpOverPHI(Pred, LHS, RHS, Q, MaxRecurse)) return V; + if (Value *V = simplifyICmpLShiftedVScales(Pred, LHS, RHS, Q)) + return V; + return nullptr; } 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 @@ -2812,6 +2812,107 @@ ret i1 %res } +define i1 @compare_vscales_ult() { +; CHECK-LABEL: @compare_vscales_ult( +; CHECK-NEXT: ret i1 true +; + %vscale = call i64 @llvm.vscale.i64() + %vscalex2 = shl nuw nsw i64 %vscale, 1 + %vscalex4 = shl nuw nsw i64 %vscale, 2 + %cmp = icmp ult i64 %vscalex2, %vscalex4 + ret i1 %cmp +} + +define i1 @compare_vscales_ult2() { +; CHECK-LABEL: @compare_vscales_ult2( +; CHECK-NEXT: ret i1 false +; + %vscale = call i64 @llvm.vscale.i64() + %vscalex2 = shl nuw nsw i64 %vscale, 1 + %vscalex4 = shl nuw nsw i64 %vscale, 2 + %cmp = icmp ult i64 %vscalex4, %vscalex2 + ret i1 %cmp +} + +define i1 @compare_vscales_sgt() { +; CHECK-LABEL: @compare_vscales_sgt( +; CHECK-NEXT: ret i1 false +; + %vscale = call i64 @llvm.vscale.i64() + %vscalex2 = shl nuw nsw i64 %vscale, 1 + %vscalex4 = shl nuw nsw i64 %vscale, 2 + %cmp = icmp sgt i64 %vscalex2, %vscalex4 + ret i1 %cmp +} + +define i1 @compare_vscales_sgt2() { +; CHECK-LABEL: @compare_vscales_sgt2( +; CHECK-NEXT: ret i1 true +; + %vscale = call i64 @llvm.vscale.i64() + %vscalex2 = shl nuw nsw i64 %vscale, 1 + %vscalex4 = shl nuw nsw i64 %vscale, 2 + %cmp = icmp sgt i64 %vscalex4, %vscalex2 + ret i1 %cmp +} + +define i1 @compare_vscales_sgt3() { +; CHECK-LABEL: @compare_vscales_sgt3( +; CHECK-NEXT: ret i1 false +; + %vscale = call i64 @llvm.vscale.i64() + %vscale1 = shl nuw nsw i64 %vscale, 2 + %vscale2 = shl nuw nsw i64 %vscale, 2 + %cmp = icmp sgt i64 %vscale1, %vscale2 + ret i1 %cmp +} + +define i1 @compare_vscales_ule() { +; CHECK-LABEL: @compare_vscales_ule( +; CHECK-NEXT: ret i1 true +; + %vscale = call i64 @llvm.vscale.i64() + %vscalex2 = shl nuw nsw i64 %vscale, 1 + %vscalex4 = shl nuw nsw i64 %vscale, 2 + %cmp = icmp ule i64 %vscalex2, %vscalex4 + ret i1 %cmp +} + +define i1 @compare_vscales_ule2() { +; CHECK-LABEL: @compare_vscales_ule2( +; CHECK-NEXT: ret i1 false +; + %vscale = call i64 @llvm.vscale.i64() + %vscalex2 = shl nuw nsw i64 %vscale, 1 + %vscalex4 = shl nuw nsw i64 %vscale, 2 + %cmp = icmp ule i64 %vscalex4, %vscalex2 + ret i1 %cmp +} + +define i1 @compare_vscales_sge() { +; CHECK-LABEL: @compare_vscales_sge( +; CHECK-NEXT: ret i1 false +; + %vscale = call i64 @llvm.vscale.i64() + %vscalex2 = shl nuw nsw i64 %vscale, 1 + %vscalex4 = shl nuw nsw i64 %vscale, 2 + %cmp = icmp sge i64 %vscalex2, %vscalex4 + ret i1 %cmp +} + +define i1 @compare_vscales_sge2() { +; CHECK-LABEL: @compare_vscales_sge2( +; CHECK-NEXT: ret i1 true +; + %vscale = call i64 @llvm.vscale.i64() + %vscalex2 = shl nuw nsw i64 %vscale, 1 + %vscalex4 = shl nuw nsw i64 %vscale, 2 + %cmp = icmp sge i64 %vscalex4, %vscalex2 + ret i1 %cmp +} + +declare i64 @llvm.vscale.i64() + ; TODO: Add coverage for global aliases, link once, etc..