Index: llvm/include/llvm/Analysis/LogicCombine.h =================================================================== --- llvm/include/llvm/Analysis/LogicCombine.h +++ llvm/include/llvm/Analysis/LogicCombine.h @@ -49,7 +49,8 @@ class LogicCombiner { public: - LogicCombiner() : LogicalOpNodes(), LeafValues(), LeafsMayPoison() {} + LogicCombiner() + : LogicalOpNodes(), LeafValues(), LeafsMayPoison(), ConstantLeafs() {} ~LogicCombiner() { clear(); } Value *simplify(Value *Root); @@ -61,6 +62,9 @@ SmallDenseMap LogicalOpNodes; SmallSetVector LeafValues; uint64_t LeafsMayPoison; + uint64_t ConstantLeafs; + Constant *ConstAllOne; + Constant *ConstZero; void clear(); @@ -68,6 +72,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/LogicCombine.cpp =================================================================== --- llvm/lib/Analysis/LogicCombine.cpp +++ llvm/lib/Analysis/LogicCombine.cpp @@ -99,6 +99,7 @@ void LogicCombiner::clear() { LeafsMayPoison = 0; + ConstantLeafs = 0; LogicalOpNodes.clear(); LeafValues.clear(); } @@ -121,6 +122,8 @@ if (ExprVal != LogicalExpr::ExprAllOne && ExprVal != 0) { if (!isGuaranteedNotToBeUndefOrPoison(Val)) LeafsMayPoison |= ExprVal; + if (isa(Val)) + ConstantLeafs |= ExprVal; LeafValues.insert(Val); } LogicalOpNode *Node = new (Alloc.Allocate()) @@ -155,6 +158,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(); @@ -187,6 +191,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 = @@ -228,6 +234,64 @@ return LogicalOpNodes[Val]; } +void LogicCombiner::foldConstForExpr(LogicalExpr &Expr) { + uint64_t ConstLeafBits = Expr.getLeafMask() & ConstantLeafs; + if (popcount(ConstLeafBits) <= 1) + return; + + bool Changed = false; + ExprAddChain NewAddChain; + Constant *ConstXor = nullptr; + for (auto BitSet : Expr) { + ConstLeafBits = BitSet & ConstantLeafs; + int ConstLeafCnt = popcount(ConstLeafBits); + if (ConstLeafCnt > 1) { + Constant *AndChain = ConstAllOne; + unsigned LeafIdx; + uint64_t LeafIterBits = ConstLeafBits; + for (int I = 0; I < ConstLeafCnt; I++) { + LeafIdx = 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; + if (NewConstNode->getExpr().size() == 0) { + BitSet = 0; + continue; + } else { + BitSet ^= ConstLeafBits; + BitSet |= *NewConstNode->getExpr().begin(); + } + } + } + + ConstLeafBits = BitSet & ConstantLeafs; + if (ConstLeafBits == BitSet && popcount(BitSet) == 1) { + unsigned LeafIdx = countr_zero(BitSet); + Constant *ConstVal = cast(LeafValues[LeafIdx]); + if (!ConstXor) + ConstXor = ConstVal; + else + ConstXor = ConstantExpr::getXor(ConstXor, ConstVal); + } else + NewAddChain.insert(BitSet); + } + + if (ConstXor && !ConstXor->isNullValue()) { + if (auto *NewConstNode = getLogicalOpNode(ConstXor, 1)) { + Changed = true; + NewAddChain.insert(*NewConstNode->getExpr().begin()); + } + } + + if (Changed) + Expr = LogicalExpr(NewAddChain); +} + Value *LogicCombiner::logicalOpToValue(LogicalOpNode *Node) { const LogicalExpr &Expr = Node->getExpr(); // Empty when all leaf bits are erased from the set because a ^ a = 0. @@ -281,11 +345,11 @@ Value *LogicCombiner::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 = popcount(LeafBits); if (LeafCnt == 1) @@ -305,6 +369,10 @@ Value *LogicCombiner::simplify(Value *Root) { assert(MaxLogicOpLeafsToScan <= 63 && "Logical leaf node can't be 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/logic-combine.ll =================================================================== --- llvm/test/Transforms/AggressiveInstCombine/logic-combine.ll +++ llvm/test/Transforms/AggressiveInstCombine/logic-combine.ll @@ -43,6 +43,26 @@ ret i8 %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 i8 @leaf2_xor(i8 %a, i8 %b) { ; CHECK-LABEL: @leaf2_xor( ; CHECK-NEXT: ret i8 [[B:%.*]] @@ -117,6 +137,21 @@ ret i16 %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 i8 @leaf3_complex_ret_const_false(i8 %a, i8 %b, i8 %c) { ; CHECK-LABEL: @leaf3_complex_ret_const_false( ; CHECK-NEXT: ret i8 0