@@ -517,6 +517,9 @@ class XorToOrDisjointTransformer {
517517 // / Checks if the given value has at least one GetElementPtr user
518518 static bool hasGEPUser (const Value *V);
519519
520+ // / Helper function to check if BaseXor dominates all XORs in the group
521+ bool dominatesAllXors (BinaryOperator *BaseXor, const XorOpList &XorsInGroup);
522+
520523 // / Processes a group of XOR instructions that share the same non-constant
521524 // / base operand. Returns true if this group's processing modified the
522525 // / function.
@@ -1209,6 +1212,17 @@ bool XorToOrDisjointTransformer::hasGEPUser(const Value *V) {
12091212 return false ;
12101213}
12111214
1215+ bool XorToOrDisjointTransformer::dominatesAllXors (
1216+ BinaryOperator *BaseXor, const XorOpList &XorsInGroup) {
1217+ for (const auto &XorEntry : XorsInGroup) {
1218+ BinaryOperator *XorInst = XorEntry.first ;
1219+ if (XorInst != BaseXor && !DT.dominates (BaseXor, XorInst)) {
1220+ return false ;
1221+ }
1222+ }
1223+ return true ;
1224+ }
1225+
12121226bool XorToOrDisjointTransformer::processXorGroup (Instruction *OriginalBaseInst,
12131227 XorOpList &XorsInGroup) {
12141228 bool Changed = false ;
@@ -1225,28 +1239,20 @@ bool XorToOrDisjointTransformer::processXorGroup(Instruction *OriginalBaseInst,
12251239 // constant.
12261240 BinaryOperator *XorWithSmallConst = XorsInGroup[0 ].first ;
12271241
1228- for (size_t i = 1 ; i < XorsInGroup.size (); ++i) {
1229- BinaryOperator *currentXorToProcess = XorsInGroup[i].first ;
1230-
1231- // Check if the XorWithSmallConst dominates currentXorToProcess.
1232- // If not, clone and add the instruction.
1233- if (!DT.dominates (XorWithSmallConst, currentXorToProcess)) {
1234- LLVM_DEBUG (
1235- dbgs () << DEBUG_TYPE
1236- << " : Cloning and inserting XOR with smallest constant ("
1237- << *XorWithSmallConst << " ) as it does not dominate "
1238- << *currentXorToProcess << " in function " << F.getName ()
1239- << " \n " );
1240-
1241- BinaryOperator *ClonedXor =
1242- cast<BinaryOperator>(XorWithSmallConst->clone ());
1243- ClonedXor->setName (XorWithSmallConst->getName () + " .dom_clone" );
1244- ClonedXor->insertAfter (OriginalBaseInst);
1245- LLVM_DEBUG (dbgs () << " Cloned Inst: " << *ClonedXor << " \n " );
1246- Changed = true ;
1247- XorWithSmallConst = ClonedXor;
1248- break ;
1249- }
1242+ if (!dominatesAllXors (XorWithSmallConst, XorsInGroup)) {
1243+ LLVM_DEBUG (dbgs () << DEBUG_TYPE
1244+ << " : Cloning and inserting XOR with smallest constant ("
1245+ << *XorWithSmallConst
1246+ << " ) as it does not dominate all other XORs"
1247+ << " in function " << F.getName () << " \n " );
1248+
1249+ BinaryOperator *ClonedXor =
1250+ cast<BinaryOperator>(XorWithSmallConst->clone ());
1251+ ClonedXor->setName (XorWithSmallConst->getName () + " .dom_clone" );
1252+ ClonedXor->insertAfter (OriginalBaseInst);
1253+ LLVM_DEBUG (dbgs () << " Cloned Inst: " << *ClonedXor << " \n " );
1254+ Changed = true ;
1255+ XorWithSmallConst = ClonedXor;
12501256 }
12511257
12521258 SmallVector<Instruction *, 8 > InstructionsToErase;
@@ -1330,28 +1336,23 @@ bool XorToOrDisjointTransformer::run() {
13301336
13311337 // Collect all candidate XORs
13321338 for (Instruction &I : instructions (F)) {
1333- if (auto *XorOp = dyn_cast<BinaryOperator>(&I)) {
1334- if (XorOp->getOpcode () == Instruction::Xor) {
1335- Value *Op0 = XorOp->getOperand (0 );
1336- ConstantInt *C1 = nullptr ;
1337- // Match: xor Op0, Constant
1338- if (isa<Instruction>(Op0) &&
1339- match (XorOp->getOperand (1 ), m_ConstantInt (C1))) {
1340- if (hasGEPUser (XorOp)) {
1341- Instruction *InstOp0 = cast<Instruction>(Op0);
1342- XorGroups[InstOp0].push_back ({XorOp, C1->getValue ()});
1343- }
1344- }
1345- }
1346- }
1339+ Instruction *Op0 = nullptr ;
1340+ ConstantInt *C1 = nullptr ;
1341+ BinaryOperator *MatchedXorOp = nullptr ;
1342+
1343+ // Attempt to match the instruction 'I' as XOR operation.
1344+ if (match (&I, m_CombineAnd (m_Xor (m_Instruction (Op0), m_ConstantInt (C1)),
1345+ m_BinOp (MatchedXorOp))) &&
1346+ hasGEPUser (MatchedXorOp))
1347+ XorGroups[Op0].push_back ({MatchedXorOp, C1->getValue ()});
13471348 }
13481349
13491350 if (XorGroups.empty ())
13501351 return false ;
13511352
13521353 // Process each group of XORs
13531354 for (auto &GroupPair : XorGroups) {
1354- Instruction *OriginalBaseInst = cast<Instruction>( GroupPair.first ) ;
1355+ Instruction *OriginalBaseInst = GroupPair.first ;
13551356 XorOpList &XorsInGroup = GroupPair.second ;
13561357 if (processXorGroup (OriginalBaseInst, XorsInGroup))
13571358 Changed = true ;
0 commit comments