@@ -1809,6 +1809,156 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
1809
1809
return nullptr ;
1810
1810
}
1811
1811
1812
+ // ICmpInst of SelectInst is not included in the calculation of KnownBits
1813
+ // so we are missing the opportunity to optimize the Value of the True or
1814
+ // False Condition via ICmpInst with KnownBits.
1815
+ //
1816
+ // Consider:
1817
+ // %or = or i32 %x, %y
1818
+ // %or0 = icmp eq i32 %or, 0
1819
+ // %and = and i32 %x, %y
1820
+ // %cond = select i1 %or0, i32 %and, i32 %or
1821
+ // ret i32 %cond
1822
+ //
1823
+ // Expect:
1824
+ // %or = or i32 %x, %y
1825
+ // ret i32 %or
1826
+ //
1827
+ // We could know what bit was enabled for %x, %y by ICmpInst in SelectInst.
1828
+ static Instruction *foldSelectICmpBinOp (SelectInst &SI, ICmpInst *ICI,
1829
+ Value *CmpLHS, Value *CmpRHS,
1830
+ Value *TVal, Value *FVal,
1831
+ InstCombinerImpl &IC) {
1832
+ Value *X, *Y;
1833
+ const APInt *C;
1834
+
1835
+ if (!((match (CmpLHS, m_BinOp (m_Value (X), m_Value (Y))) &&
1836
+ match (CmpRHS, m_APInt (C))) &&
1837
+ (match (TVal, m_c_BinOp (m_Specific (X), m_Value ())) ||
1838
+ match (TVal, m_c_BinOp (m_Specific (Y), m_Value ())))))
1839
+ return nullptr ;
1840
+
1841
+ enum SpecialKnownBits {
1842
+ NothingSpecial = 0 ,
1843
+ NoCommonBits = 1 << 1 ,
1844
+ AllCommonBits = 1 << 2 ,
1845
+ AllBitsEnabled = 1 << 3 ,
1846
+ };
1847
+
1848
+ // We cannot know exactly what bits is known in X Y.
1849
+ // Instead, we just know what relationship exist for.
1850
+ auto isSpecialKnownBitsFor = [&](const Instruction *CmpLHS,
1851
+ const APInt *CmpRHS) -> unsigned {
1852
+ unsigned Opc = CmpLHS->getOpcode ();
1853
+ if (Opc == Instruction::And) {
1854
+ if (CmpRHS->isZero ())
1855
+ return NoCommonBits;
1856
+ } else if (Opc == Instruction::Xor) {
1857
+ if (CmpRHS->isAllOnes ())
1858
+ return NoCommonBits | AllBitsEnabled;
1859
+ if (CmpRHS->isZero ())
1860
+ return AllCommonBits;
1861
+ }
1862
+
1863
+ return NothingSpecial;
1864
+ };
1865
+
1866
+ auto hasOperandAt = [&](Instruction *I, Value *Op) -> int {
1867
+ for (unsigned Idx = 0 ; Idx < I->getNumOperands (); Idx++) {
1868
+ if (I->getOperand (Idx) == Op)
1869
+ return Idx + 1 ;
1870
+ }
1871
+ return 0 ;
1872
+ };
1873
+
1874
+ Type *TValTy = TVal->getType ();
1875
+ unsigned BitWidth = TVal->getType ()->getScalarSizeInBits ();
1876
+ auto TValBop = cast<BinaryOperator>(TVal);
1877
+ auto CmpLHSBop = cast<BinaryOperator>(CmpLHS);
1878
+ unsigned XOrder = hasOperandAt (TValBop, X);
1879
+ unsigned YOrder = hasOperandAt (TValBop, Y);
1880
+ unsigned SKB = isSpecialKnownBitsFor (CmpLHSBop, C);
1881
+
1882
+ KnownBits Known;
1883
+ if (TValBop->isBitwiseLogicOp ()) {
1884
+ if (SKB != SpecialKnownBits::NothingSpecial && XOrder && YOrder) {
1885
+ if (SKB & SpecialKnownBits::NoCommonBits) {
1886
+ if (SKB & (SpecialKnownBits::AllBitsEnabled)) {
1887
+ if (TValBop->getOpcode () == Instruction::Xor)
1888
+ Known = KnownBits::makeConstant (APInt (BitWidth, -1 ));
1889
+ }
1890
+ if (TValBop->getOpcode () == Instruction::And)
1891
+ Known = KnownBits::makeConstant (APInt (BitWidth, 0 ));
1892
+ else if ((match (TVal, m_c_Or (m_Specific (X), m_Specific (Y))) &&
1893
+ match (FVal, m_c_Xor (m_Specific (X), m_Specific (Y)))) ||
1894
+ (match (TVal, m_c_Xor (m_Specific (X), m_Specific (Y))) &&
1895
+ match (FVal, m_c_Or (m_Specific (X), m_Specific (Y)))))
1896
+ return IC.replaceInstUsesWith (SI, FVal);
1897
+ } else if (SKB & SpecialKnownBits::AllCommonBits) {
1898
+ if (TValBop->getOpcode () == Instruction::And ||
1899
+ TValBop->getOpcode () == Instruction::Or)
1900
+ if (TValBop->hasOneUse ())
1901
+ return IC.replaceOperand (SI, 1 , X);
1902
+ } else if (SKB & SpecialKnownBits::AllBitsEnabled) {
1903
+ if (TValBop->getOpcode () == Instruction::Or)
1904
+ Known = KnownBits::makeConstant (APInt (BitWidth, -1 ));
1905
+ }
1906
+ } else {
1907
+ KnownBits XKnown, YKnown, Temp;
1908
+ KnownBits TValBop0KB, TValBop1KB;
1909
+ XKnown = IC.computeKnownBits (X, 0 , &SI);
1910
+ IC.computeKnownBitsFromCond (X, ICI, XKnown, 0 , &SI, false );
1911
+ YKnown = IC.computeKnownBits (Y, 0 , &SI);
1912
+ IC.computeKnownBitsFromCond (Y, ICI, YKnown, 0 , &SI, false );
1913
+ CmpInst::Predicate Pred = ICI->getPredicate ();
1914
+ if (Pred == ICmpInst::ICMP_EQ) {
1915
+ if (CmpLHSBop->getOpcode () == Instruction::And) {
1916
+ XKnown.Zero |= ~*C & YKnown.One ;
1917
+ YKnown.Zero |= ~*C & XKnown.One ;
1918
+ }
1919
+ if (CmpLHSBop->getOpcode () == Instruction::Or) {
1920
+ XKnown.One |= *C & YKnown.Zero ;
1921
+ YKnown.One |= *C & XKnown.Zero ;
1922
+ }
1923
+ if (CmpLHSBop->getOpcode () == Instruction::Xor) {
1924
+ XKnown.One |= *C & YKnown.Zero ;
1925
+ XKnown.Zero |= *C & YKnown.One ;
1926
+ YKnown.One |= *C & XKnown.Zero ;
1927
+ YKnown.Zero |= *C & XKnown.One ;
1928
+ XKnown.Zero |= ~*C & YKnown.Zero ;
1929
+ XKnown.One |= ~*C & YKnown.One ;
1930
+ YKnown.Zero |= ~*C & XKnown.Zero ;
1931
+ YKnown.One |= ~*C & XKnown.One ;
1932
+ }
1933
+ }
1934
+
1935
+ auto getTValBopKB = [&](unsigned OpNum) -> KnownBits {
1936
+ unsigned Order = OpNum + 1 ;
1937
+ if (Order == XOrder)
1938
+ return XKnown;
1939
+ else if (Order == YOrder)
1940
+ return YKnown;
1941
+
1942
+ Value *V = TValBop->getOperand (OpNum);
1943
+ KnownBits Known = IC.computeKnownBits (V, 0 , &SI);
1944
+ return Known;
1945
+ };
1946
+ TValBop0KB = getTValBopKB (0 );
1947
+ TValBop1KB = getTValBopKB (1 );
1948
+ Known = analyzeKnownBitsFromAndXorOr (
1949
+ cast<Operator>(TValBop), TValBop0KB, TValBop1KB, 0 ,
1950
+ IC.getSimplifyQuery ().getWithInstruction (&SI));
1951
+ }
1952
+ }
1953
+
1954
+ if (Known.isConstant ()) {
1955
+ auto Const = ConstantInt::get (TValTy, Known.getConstant ());
1956
+ return IC.replaceOperand (SI, 1 , Const);
1957
+ }
1958
+
1959
+ return nullptr ;
1960
+ }
1961
+
1812
1962
// / Visit a SelectInst that has an ICmpInst as its first operand.
1813
1963
Instruction *InstCombinerImpl::foldSelectInstWithICmp (SelectInst &SI,
1814
1964
ICmpInst *ICI) {
@@ -1951,6 +2101,10 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
1951
2101
if (Value *V = foldAbsDiff (ICI, TrueVal, FalseVal, Builder))
1952
2102
return replaceInstUsesWith (SI, V);
1953
2103
2104
+ if (Instruction *NewSel = foldSelectICmpBinOp (SI, ICI, CmpLHS, CmpRHS,
2105
+ TrueVal, FalseVal, *this ))
2106
+ return NewSel;
2107
+
1954
2108
return Changed ? &SI : nullptr ;
1955
2109
}
1956
2110
0 commit comments