Skip to content

Commit 3929817

Browse files
committed
[InstCombine] Try optimizing with knownbits which determined from SelectInst Cond
ICmpInst of SelectInst is not included in the calculation of KnownBits so we are missing the opportunity to optimize the Value of the True or False Condition via ICmpInst with KnownBits. Consider: %or = or i32 %x, %y %or0 = icmp eq i32 %or, 0 %and = and i32 %x, %y %cond = select i1 %or0, i32 %and, i32 %or ret i32 %cond Expect: %or = or i32 %x, %y ret i32 %or We could know what bit was enabled for %x, %y by ICmpInst in SelectInst. This patch is an implementation that calculates the known bits over ICmp and optimizes them where possible. Proof : https://alive2.llvm.org/ce/z/kJ4YBF
1 parent e757950 commit 3929817

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

llvm/include/llvm/Transforms/InstCombine/InstCombiner.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,13 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
438438
return llvm::computeKnownBits(V, Depth, SQ.getWithInstruction(CxtI));
439439
}
440440

441+
void computeKnownBitsFromCond(const Value *V, ICmpInst *Cmp, KnownBits &Known,
442+
unsigned Depth, const Instruction *CxtI,
443+
bool Invert) const {
444+
llvm::computeKnownBitsFromCond(V, Cmp, Known, Depth,
445+
SQ.getWithInstruction(CxtI), Invert);
446+
}
447+
441448
bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero = false,
442449
unsigned Depth = 0,
443450
const Instruction *CxtI = nullptr) {

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,6 +1790,159 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
17901790
return nullptr;
17911791
}
17921792

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

2088+
if (Instruction *NewSel = foldSelectICmpBinOp(SI, ICI, CmpLHS, CmpRHS,
2089+
TrueVal, FalseVal, *this))
2090+
return NewSel;
2091+
19352092
return Changed ? &SI : nullptr;
19362093
}
19372094

0 commit comments

Comments
 (0)