From 662c69d8c2803055253639f6f1f5076330942958 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Tue, 10 Nov 2015 23:56:20 +0000 Subject: [PATCH] [ValueTracking] Teach isImpliedCondition a new bitwise trick Summary: This change teaches isImpliedCondition to prove things like (A | 15) < L ==> (A | 14) < L if the low 4 bits of A are known to be zero. Depends on D14391 Reviewers: majnemer, reames, hfinkel Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D14392 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252673 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ValueTracking.cpp | 30 ++++++++++ test/Transforms/InstSimplify/implies.ll | 78 +++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index e4cbdb9249f..f851892d3d3 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -4136,6 +4136,36 @@ static bool isTruePredicate(CmpInst::Predicate Pred, Value *LHS, Value *RHS, return C->isMinValue(); return true; } + + // Match A to (X +_{nuw} CA) and B to (X +_{nuw} CB) + auto MatchNUWAddsToSameValue = [&](Value *A, Value *B, Value *&X, + const APInt *&CA, const APInt *&CB) { + if (match(A, m_NUWAdd(m_Value(X), m_APInt(CA))) && + match(B, m_NUWAdd(m_Specific(X), m_APInt(CB)))) + return true; + + // If X & C == 0 then (X | C) == X +_{nuw} C + if (match(A, m_Or(m_Value(X), m_APInt(CA))) && + match(B, m_Or(m_Specific(X), m_APInt(CB)))) { + unsigned BitWidth = CA->getBitWidth(); + APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + computeKnownBits(X, KnownZero, KnownOne, DL, Depth + 1, AC, CxtI, DT); + + if ((KnownZero & *CA) == *CA && (KnownZero & *CB) == *CB) + return true; + } + + return false; + }; + + Value *X; + const APInt *CLHS, *CRHS; + if (MatchNUWAddsToSameValue(LHS, RHS, X, CLHS, CRHS)) { + if (Pred == CmpInst::ICMP_ULE) + return CLHS->ule(*CRHS); + return CLHS->ult(*CRHS); + } + return false; } } diff --git a/test/Transforms/InstSimplify/implies.ll b/test/Transforms/InstSimplify/implies.ll index eb8db4224fa..2e3c9591b07 100644 --- a/test/Transforms/InstSimplify/implies.ll +++ b/test/Transforms/InstSimplify/implies.ll @@ -127,6 +127,84 @@ define i1 @test9(i32 %length.i, i32 %i) { ret i1 %res } +define i1 @test10(i32 %length.i, i32 %x.full) { +; CHECK-LABEL: @test10( +; CHECK: ret i1 true + + %x = and i32 %x.full, 4294901760 ;; 4294901760 == 0xffff0000 + %large = or i32 %x, 100 + %small = or i32 %x, 90 + %known = icmp ult i32 %large, %length.i + %to.prove = icmp ult i32 %small, %length.i + %res = icmp ule i1 %known, %to.prove + ret i1 %res +} + +define i1 @test11(i32 %length.i, i32 %x) { +; CHECK-LABEL: @test11( +; CHECK: %res = icmp ule i1 %known, %to.prove +; CHECK: ret i1 %res + + %large = or i32 %x, 100 + %small = or i32 %x, 90 + %known = icmp ult i32 %large, %length.i + %to.prove = icmp ult i32 %small, %length.i + %res = icmp ule i1 %known, %to.prove + ret i1 %res +} + +define i1 @test12(i32 %length.i, i32 %x.full) { +; CHECK-LABEL: @test12( +; CHECK: %res = icmp ule i1 %known, %to.prove +; CHECK: ret i1 %res + + %x = and i32 %x.full, 4294901760 ;; 4294901760 == 0xffff0000 + %large = or i32 %x, 65536 ;; 65536 == 0x00010000 + %small = or i32 %x, 90 + %known = icmp ult i32 %large, %length.i + %to.prove = icmp ult i32 %small, %length.i + %res = icmp ule i1 %known, %to.prove + ret i1 %res +} + +define i1 @test13(i32 %length.i, i32 %x) { +; CHECK-LABEL: @test13( +; CHECK: ret i1 true + + %large = add nuw i32 %x, 100 + %small = add nuw i32 %x, 90 + %known = icmp ult i32 %large, %length.i + %to.prove = icmp ult i32 %small, %length.i + %res = icmp ule i1 %known, %to.prove + ret i1 %res +} + +define i1 @test14(i32 %length.i, i32 %x.full) { +; CHECK-LABEL: @test14( +; CHECK: ret i1 true + + %x = and i32 %x.full, 4294905615 ;; 4294905615 == 0xffff0f0f + %large = or i32 %x, 8224 ;; == 0x2020 + %small = or i32 %x, 4112 ;; == 0x1010 + %known = icmp ult i32 %large, %length.i + %to.prove = icmp ult i32 %small, %length.i + %res = icmp ule i1 %known, %to.prove + ret i1 %res +} + +define i1 @test15(i32 %length.i, i32 %x) { +; CHECK-LABEL: @test15( +; CHECK: %res = icmp ule i1 %known, %to.prove +; CHECK: ret i1 %res + + %large = add nuw i32 %x, 100 + %small = add nuw i32 %x, 110 + %known = icmp ult i32 %large, %length.i + %to.prove = icmp ult i32 %small, %length.i + %res = icmp ule i1 %known, %to.prove + ret i1 %res +} + ; X >=(s) Y == X ==> Y (i1 1 becomes -1 for reasoning) define i1 @test_sge(i32 %length.i, i32 %i) { ; CHECK-LABEL: @test_sge -- 2.34.1