Index: llvm/include/llvm/Analysis/ComplexLogicCombine.h =================================================================== --- llvm/include/llvm/Analysis/ComplexLogicCombine.h +++ llvm/include/llvm/Analysis/ComplexLogicCombine.h @@ -52,7 +52,8 @@ class LogicalOpsHelper { public: LogicalOpsHelper() - : LogicalOpNodes(), LeafSet(), LeafValues(), LeafsMayPoison() {} + : LogicalOpNodes(), LeafSet(), LeafValues(), LeafsMayPoison(), + ConstantLeafs() {} ~LogicalOpsHelper() { clear(); } Value *simplify(Value *Root); @@ -64,6 +65,9 @@ SmallPtrSet LeafSet; SmallVector LeafValues; uint64_t LeafsMayPoison; + uint64_t ConstantLeafs; + Constant *ConstAllOne; + Constant *ConstZero; void clear(); @@ -71,6 +75,8 @@ LogicalOpNode *visitBinOp(BinaryOperator *BO, unsigned Depth); LogicalOpNode *visitSelect(SelectInst *SI, unsigned Depth); LogicalOpNode *getLogicalOpNode(Value *Val, unsigned Depth = 0); + void foldConstForExpr(LogicalExpr &Expr); + Value *logicalOpToValue(LogicalOpNode *Node); Value *buildAndChain(IRBuilder<> &Builder, Type *Ty, uint64_t LeafBits); }; Index: llvm/lib/Analysis/ComplexLogicCombine.cpp =================================================================== --- llvm/lib/Analysis/ComplexLogicCombine.cpp +++ llvm/lib/Analysis/ComplexLogicCombine.cpp @@ -107,6 +107,7 @@ for (auto node : LogicalOpNodes) delete node.second; LeafsMayPoison = 0; + ConstantLeafs = 0; LogicalOpNodes.clear(); LeafSet.clear(); LeafValues.clear(); @@ -131,6 +132,8 @@ LeafSet.insert(Val).second) { if (!isGuaranteedNotToBeUndefOrPoison(Val)) LeafsMayPoison |= ExprVal; + if (isa(Val)) + ConstantLeafs |= ExprVal; LeafValues.push_back(Val); } LogicalOpNode *Node = @@ -154,7 +157,7 @@ if (RHS == nullptr) return nullptr; - // TODO: We can reduce the weight if th node can be simplified even if + // TODO: We can reduce the weight if the node can be simplified even if // it is not the root node. unsigned Weight = LHS->getWeight() + RHS->getWeight() + 1; unsigned OneUseWeight = Weight; @@ -168,6 +171,7 @@ NewExpr = LHS->getExpr() | RHS->getExpr(); else NewExpr = LHS->getExpr() ^ RHS->getExpr(); + foldConstForExpr(NewExpr); uint64_t PoisonMaskSI = 0; uint64_t LPI = LHS->getExpr().getLeafMask() ^ LHS->getPoisonMaskSI(); @@ -200,6 +204,8 @@ LogicalExpr NewExpr = (Cond->getExpr() & TrueVal->getExpr()) ^ ((~Cond->getExpr()) & FalseVal->getExpr()); + foldConstForExpr(NewExpr); + // TODO: We can reduce the weight if th node can be simplified even if // it is not the root node. unsigned Weight = @@ -241,6 +247,59 @@ return LogicalOpNodes[Val]; } +void LogicalOpsHelper::foldConstForExpr(LogicalExpr &Expr) { + uint64_t ConstLeafBits = Expr.getLeafMask() & ConstantLeafs; + if (llvm::popcount(ConstLeafBits) <= 1) + return; + + bool Changed = false; + ExprAddChain NewAddChain; + Constant *ConstXor = nullptr; + for (auto BitSet : Expr) { + ConstLeafBits = BitSet & ConstantLeafs; + int ConstLeafCnt = llvm::popcount(ConstLeafBits); + if (ConstLeafCnt > 1) { + Constant *AndChain = ConstAllOne; + unsigned LeafIdx; + uint64_t LeafIterBits = ConstLeafBits; + for (int I = 0; I < ConstLeafCnt; I++) { + LeafIdx = llvm::countr_zero(LeafIterBits); + Value *LeafVal = LeafValues[LeafIdx]; + if (auto *ConstVal = dyn_cast(LeafVal)) + AndChain = ConstantExpr::getAnd(ConstVal, AndChain); + LeafIterBits -= (1ULL << LeafIdx); + } + + if (auto *NewConstNode = getLogicalOpNode(AndChain, 1)) { + Changed = true; + BitSet ^= ConstLeafBits; + BitSet |= *NewConstNode->getExpr().begin(); + } + } + + ConstLeafBits = BitSet & ConstantLeafs; + if (ConstLeafBits == BitSet && llvm::popcount(BitSet) == 1) { + unsigned LeafIdx = llvm::countr_zero(BitSet); + Constant *ConstVal = cast(LeafValues[LeafIdx]); + if (!ConstXor) + ConstXor = ConstVal; + else + ConstXor = ConstantExpr::getXor(ConstXor, ConstVal); + } else + NewAddChain.insert(BitSet); + } + + if (ConstXor) { + if (auto *NewConstNode = getLogicalOpNode(ConstXor, 1)) { + Changed = true; + NewAddChain.insert(*NewConstNode->getExpr().begin()); + } + } + + if (Changed) + Expr = LogicalExpr(NewAddChain); +} + Value *LogicalOpsHelper::logicalOpToValue(LogicalOpNode *Node) { const LogicalExpr &Expr = Node->getExpr(); // Empty when all leaf bits are earsed from the set because a ^ a = 0. @@ -294,11 +353,11 @@ Value *LogicalOpsHelper::buildAndChain(IRBuilder<> &Builder, Type *Ty, uint64_t LeafBits) { if (LeafBits == 0) - return Constant::getNullValue(Ty); + return ConstZero; // ExprAllOne is not in the LeafValues if (LeafBits == LogicalExpr::ExprAllOne) - return Constant::getAllOnesValue(Ty); + return ConstAllOne; unsigned LeafCnt = llvm::popcount(LeafBits); if (LeafCnt == 1) @@ -318,6 +377,10 @@ Value *LogicalOpsHelper::simplify(Value *Root) { assert(MaxLogicOpLeafsToScan <= 63 && "Logical leaf node can't larger than 63."); + + ConstAllOne = Constant::getAllOnesValue(Root->getType()); + ConstZero = Constant::getNullValue(Root->getType()); + LogicalOpNode *RootNode = getLogicalOpNode(Root); if (RootNode == nullptr) return nullptr; Index: llvm/test/Transforms/AggressiveInstCombine/complex-logic.ll =================================================================== --- llvm/test/Transforms/AggressiveInstCombine/complex-logic.ll +++ llvm/test/Transforms/AggressiveInstCombine/complex-logic.ll @@ -43,6 +43,27 @@ ret i1 %or } +define i8 @leaf1_and_const_fold(i8 %a) { +; CHECK-LABEL: @leaf1_and_const_fold( +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], 15 +; CHECK-NEXT: ret i8 [[TMP1]] +; + %and1 = and i8 %a, 111 + %and2 = and i8 %and1, 31 + ret i8 %and2 +} + +define i8 @leaf1_xor_const_fold(i8 %a) { +; CHECK-LABEL: @leaf1_xor_const_fold( +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 112, [[A:%.*]] +; CHECK-NEXT: ret i8 [[TMP1]] +; + %xor1 = xor i8 %a, 111 + %xor2 = xor i8 %xor1, 31 + ret i8 %xor2 +} + + define i1 @leaf2_xor(i1 %a, i1 %b) { ; CHECK-LABEL: @leaf2_xor( ; CHECK-NEXT: ret i1 [[B:%.*]] @@ -117,6 +138,21 @@ ret i1 %xor } +define i8 @leaf2_ret_const_fold(i8 %a, i8 %b) { +; CHECK-LABEL: @leaf2_ret_const_fold( +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[A:%.*]], 18 +; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret i8 [[TMP3]] +; + %and1 = and i8 %a, 122 + %or = or i8 %and1, %b + %and2 = and i8 %or, 23 + %and3 = and i8 %b, 23 + %r = xor i8 %and2, %and3 + ret i8 %r +} + define i1 @leaf3_complex_ret_const_false(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @leaf3_complex_ret_const_false( ; CHECK-NEXT: ret i1 false