[llvm] [SeparateConstOffsetFromGEP] Decompose constant xor operand if possible (PR #135788)
Juan Manuel Martinez CaamaƱo via llvm-commits
llvm-commits at lists.llvm.org
Wed May 14 00:59:12 PDT 2025
================
@@ -1162,6 +1199,165 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
return true;
}
+// Helper function to check if an instruction has at least one GEP user
+bool XorToOrDisjointTransformer::hasGEPUser(const Value *V) const {
+ for (const User *U : V->users()) {
+ if (isa<GetElementPtrInst>(U)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool XorToOrDisjointTransformer::processXorGroup(Value *OriginalBaseVal,
+ XorOpList &XorsInGroup) {
+ bool Changed = false;
+ if (XorsInGroup.size() <= 1)
+ return false;
+
+ // Sort XorsInGroup by the constant offset value in increasing order.
+ llvm::sort(
+ XorsInGroup.begin(), XorsInGroup.end(),
+ [](const auto &A, const auto &B) { return A.second.ult(B.second); });
+
+ // Dominance check
+ // The "base" XOR for dominance purposes is the one with the smallest
+ // constant.
+ BinaryOperator *XorWithSmallConst = XorsInGroup[0].first;
+
+ for (size_t i = 1; i < XorsInGroup.size(); ++i) {
+ BinaryOperator *currentXorToProcess = XorsInGroup[i].first;
+
+ // Check if the XorWithSmallConst dominates currentXorToProcess.
+ // If not, clone and add the instruction.
+ if (!DT.dominates(XorWithSmallConst, currentXorToProcess)) {
+ LLVM_DEBUG(
+ dbgs() << DEBUG_TYPE
+ << ": Cloning and inserting XOR with smallest constant ("
+ << *XorWithSmallConst << ") as it does not dominate "
+ << *currentXorToProcess << " in function " << F.getName()
+ << "\n");
+
+ BinaryOperator *ClonedXor =
+ cast<BinaryOperator>(XorWithSmallConst->clone());
+ ClonedXor->setName(XorWithSmallConst->getName() + ".dom_clone");
+ ClonedXor->insertAfter(dyn_cast<Instruction>(OriginalBaseVal));
+ LLVM_DEBUG(dbgs() << " Cloned Inst: " << *ClonedXor << "\n");
+ Changed = true;
+ XorWithSmallConst = ClonedXor;
+ break;
+ }
+ }
+
+ SmallVector<Instruction *, 8> InstructionsToErase;
+ const APInt SmallestConst =
+ dyn_cast<ConstantInt>(XorWithSmallConst->getOperand(1))->getValue();
+
+ // Main transformation loop: Iterate over the original XORs in the sorted
+ // group.
+ for (const auto &XorEntry : XorsInGroup) {
+ BinaryOperator *XorInst = XorEntry.first; // Original XOR instruction
+ const APInt ConstOffsetVal = XorEntry.second;
+
+ // Do not process the one with smallest constant as it is the base.
+ if (XorInst == XorWithSmallConst)
+ continue;
+
+ // Disjointness Check 1
+ APInt NewConstVal = ConstOffsetVal - SmallestConst;
+ if ((NewConstVal & SmallestConst) != 0) {
+ LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": Cannot transform XOR in function "
+ << F.getName() << ":\n"
+ << " New Const: " << NewConstVal << "\n"
+ << " Smallest Const: " << SmallestConst << "\n"
+ << " are not disjoint \n");
+ continue;
+ }
+
+ // Disjointness Check 2
+ KnownBits KnownBaseBits(
+ XorWithSmallConst->getType()->getScalarSizeInBits());
+ computeKnownBits(XorWithSmallConst, KnownBaseBits, DL, 0, nullptr,
+ XorWithSmallConst, &DT);
+ if ((KnownBaseBits.Zero & NewConstVal) == NewConstVal) {
+ LLVM_DEBUG(dbgs() << DEBUG_TYPE
+ << ": Transforming XOR to OR (disjoint) in function "
+ << F.getName() << ":\n"
+ << " Xor: " << *XorInst << "\n"
+ << " Base Val: " << *XorWithSmallConst << "\n"
+ << " New Const: " << NewConstVal << "\n");
+
+ auto *NewOrInst = BinaryOperator::CreateDisjointOr(
+ XorWithSmallConst,
+ ConstantInt::get(OriginalBaseVal->getType(), NewConstVal),
+ XorInst->getName() + ".or_disjoint", XorInst->getIterator());
+
+ NewOrInst->copyMetadata(*XorInst);
+ XorInst->replaceAllUsesWith(NewOrInst);
+ LLVM_DEBUG(dbgs() << " New Inst: " << *NewOrInst << "\n");
+ InstructionsToErase.push_back(XorInst); // Mark original XOR for deletion
+
+ Changed = true;
+ } else {
+ LLVM_DEBUG(
+ dbgs() << DEBUG_TYPE
+ << ": Cannot transform XOR (not proven disjoint) in function "
+ << F.getName() << ":\n"
+ << " Xor: " << *XorInst << "\n"
+ << " Base Val: " << *XorWithSmallConst << "\n"
+ << " New Const: " << NewConstVal << "\n");
+ }
+ }
+ if (!InstructionsToErase.empty())
+ for (Instruction *I : InstructionsToErase)
+ I->eraseFromParent();
----------------
jmmartinez wrote:
```suggestion
for (Instruction *I : InstructionsToErase)
I->eraseFromParent();
```
https://github.com/llvm/llvm-project/pull/135788
More information about the llvm-commits
mailing list