|
35 | 35 | #include "llvm/Analysis/TargetLibraryInfo.h"
|
36 | 36 | #include "llvm/Analysis/ValueTracking.h"
|
37 | 37 | #include "llvm/Analysis/VectorUtils.h"
|
| 38 | +#include "llvm/IR/ConstantFPRange.h" |
38 | 39 | #include "llvm/IR/ConstantRange.h"
|
39 | 40 | #include "llvm/IR/DataLayout.h"
|
40 | 41 | #include "llvm/IR/Dominators.h"
|
@@ -1812,6 +1813,46 @@ static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1,
|
1812 | 1813 | return nullptr;
|
1813 | 1814 | }
|
1814 | 1815 |
|
| 1816 | +/// Test if a pair of compares with a shared operand and 2 constants has an |
| 1817 | +/// empty set intersection, full set union, or if one compare is a superset of |
| 1818 | +/// the other. |
| 1819 | +static Value *simplifyAndOrOfFCmpsWithConstants(FCmpInst *Cmp0, FCmpInst *Cmp1, |
| 1820 | + bool IsAnd) { |
| 1821 | + // Look for this pattern: {and/or} (fcmp X, C0), (fcmp X, C1)). |
| 1822 | + if (Cmp0->getOperand(0) != Cmp1->getOperand(0)) |
| 1823 | + return nullptr; |
| 1824 | + |
| 1825 | + const APFloat *C0, *C1; |
| 1826 | + if (!match(Cmp0->getOperand(1), m_APFloat(C0)) || |
| 1827 | + !match(Cmp1->getOperand(1), m_APFloat(C1))) |
| 1828 | + return nullptr; |
| 1829 | + |
| 1830 | + auto Range0 = ConstantFPRange::makeExactFCmpRegion( |
| 1831 | + IsAnd ? Cmp0->getPredicate() : Cmp0->getInversePredicate(), *C0); |
| 1832 | + auto Range1 = ConstantFPRange::makeExactFCmpRegion( |
| 1833 | + IsAnd ? Cmp1->getPredicate() : Cmp1->getInversePredicate(), *C1); |
| 1834 | + |
| 1835 | + if (!Range0 || !Range1) |
| 1836 | + return nullptr; |
| 1837 | + |
| 1838 | + // For and-of-compares, check if the intersection is empty: |
| 1839 | + // (fcmp X, C0) && (fcmp X, C1) --> empty set --> false |
| 1840 | + if (Range0->intersectWith(*Range1).isEmptySet()) |
| 1841 | + return ConstantInt::getBool(Cmp0->getType(), !IsAnd); |
| 1842 | + |
| 1843 | + // Is one range a superset of the other? |
| 1844 | + // If this is and-of-compares, take the smaller set: |
| 1845 | + // (fcmp ogt X, 4) && (fcmp ogt X, 42) --> fcmp ogt X, 42 |
| 1846 | + // If this is or-of-compares, take the larger set: |
| 1847 | + // (fcmp ogt X, 4) || (fcmp ogt X, 42) --> fcmp ogt X, 4 |
| 1848 | + if (Range0->contains(*Range1)) |
| 1849 | + return Cmp1; |
| 1850 | + if (Range1->contains(*Range0)) |
| 1851 | + return Cmp0; |
| 1852 | + |
| 1853 | + return nullptr; |
| 1854 | +} |
| 1855 | + |
1815 | 1856 | static Value *simplifyAndOrOfFCmps(const SimplifyQuery &Q, FCmpInst *LHS,
|
1816 | 1857 | FCmpInst *RHS, bool IsAnd) {
|
1817 | 1858 | Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
|
@@ -1850,34 +1891,8 @@ static Value *simplifyAndOrOfFCmps(const SimplifyQuery &Q, FCmpInst *LHS,
|
1850 | 1891 | : ConstantInt::getBool(LHS->getType(), !IsAnd);
|
1851 | 1892 | }
|
1852 | 1893 |
|
1853 |
| - Value *V0; |
1854 |
| - const APFloat *V0Op1, *V1Op1; |
1855 |
| - // (fcmp olt V0, V0Op1) || (fcmp olt V0, V1Op1) |
1856 |
| - // --> fcmp olt V0, max(V0Op1, V1Op1) |
1857 |
| - // (fcmp ogt V0, V0Op1) || (fcmp ogt V0, V1Op1) |
1858 |
| - // --> fcmp ogt V0, max(V0Op1, V1Op1) |
1859 |
| - // |
1860 |
| - // (fcmp olt V0, V0Op1) && (fcmp olt V0, V1Op1) |
1861 |
| - // --> fcmp olt V0, min(V0Op1, V1Op1) |
1862 |
| - // (fcmp ogt V0, V0Op1) && (fcmp ogt V0, V1Op1) |
1863 |
| - // --> fcmp ogt V0, min(V0Op1, V1Op1) |
1864 |
| - if (match(LHS, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Value(V0), |
1865 |
| - m_APFloat(V0Op1))) && |
1866 |
| - match(RHS, m_SpecificFCmp(FCmpInst::FCMP_OLT, m_Specific(V0), |
1867 |
| - m_APFloat(V1Op1)))) { |
1868 |
| - if (*V0Op1 > *V1Op1) |
1869 |
| - return IsAnd ? RHS : LHS; |
1870 |
| - if (*V1Op1 > *V0Op1) |
1871 |
| - return IsAnd ? LHS : RHS; |
1872 |
| - } else if (match(LHS, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Value(V0), |
1873 |
| - m_APFloat(V0Op1))) && |
1874 |
| - match(RHS, m_SpecificFCmp(FCmpInst::FCMP_OGT, m_Specific(V0), |
1875 |
| - m_APFloat(V1Op1)))) { |
1876 |
| - if (*V0Op1 < *V1Op1) |
1877 |
| - return IsAnd ? RHS : LHS; |
1878 |
| - if (*V1Op1 < *V0Op1) |
1879 |
| - return IsAnd ? LHS : RHS; |
1880 |
| - } |
| 1894 | + if (auto *V = simplifyAndOrOfFCmpsWithConstants(LHS, RHS, IsAnd)) |
| 1895 | + return V; |
1881 | 1896 |
|
1882 | 1897 | return nullptr;
|
1883 | 1898 | }
|
|
0 commit comments