[llvm] [InstCombine] x mod(c1*c2)/c2 --> (x /c2) mod(c1) (PR #140197)

Kshitij Paranjape via llvm-commits llvm-commits at lists.llvm.org
Thu May 15 23:19:44 PDT 2025


https://github.com/kshitijvp created https://github.com/llvm/llvm-project/pull/140197

None

>From 0bff990289bf82a9fec320cca80f3d43753438cc Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Mon, 27 Jan 2025 21:19:33 +0530
Subject: [PATCH 1/5] [ELFObject] Added dbgs() statement in removeSections()

This patch adds dbgs() statement inside removeSections()
and removeSymbol() function to print the removed sections
and symbols.

Fixes: #123041
---
 llvm/lib/ObjCopy/ELF/ELFObject.cpp    | 26 ++++++++++++++++++++------
 llvm/tools/llvm-objcopy/CommonOpts.td |  2 ++
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index e5de17e093dfd..5c7489e5b941e 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -766,8 +766,14 @@ Error SymbolTableSection::removeSymbols(
     function_ref<bool(const Symbol &)> ToRemove) {
   Symbols.erase(
       std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
-                     [ToRemove](const SymPtr &Sym) { return ToRemove(*Sym); }),
-      std::end(Symbols));
+               [ToRemove](const SymPtr &Sym) {
+                   if (ToRemove(*Sym)) {
+                       dbgs()<<"Symbols Removed:"<<Sym->Name<< "\n";
+                       return true;
+                   }
+                   return false;
+               }));
+
   auto PrevSize = Size;
   Size = Symbols.size() * EntrySize;
   if (Size < PrevSize)
@@ -2249,10 +2255,18 @@ Error Object::removeSections(
 
   // Transfer removed sections into the Object RemovedSections container for use
   // later.
-  std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
-  // Now finally get rid of them all together.
-  Sections.erase(Iter, std::end(Sections));
-  return Error::success();
+  for(auto &KeepSec : make_range(std::begin(Sections) , Iter))
+  {
+    
+    if (Error E = KeepSec->removeSectionReferences(
+            AllowBrokenLinks, [&RemoveSections](const SectionBase *Sec) {
+              return RemoveSections.find(Sec) != RemoveSections.end();
+            }))
+      std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
+      dbgs()<<"Sections Removed:"<<KeepSec->Name<<'\n';
+      Sections.erase(Iter, std::end(Sections));
+      return Error::success();
+  }
 }
 
 Error Object::replaceSections(
diff --git a/llvm/tools/llvm-objcopy/CommonOpts.td b/llvm/tools/llvm-objcopy/CommonOpts.td
index c247c93f6e0f2..5b15191f54605 100644
--- a/llvm/tools/llvm-objcopy/CommonOpts.td
+++ b/llvm/tools/llvm-objcopy/CommonOpts.td
@@ -117,6 +117,8 @@ def regex
 
 def version : Flag<["--"], "version">,
               HelpText<"Print the version and exit.">;
+def verbose : Flag<["--"], "verbose">,
+              HelpText<"Prints the removed symbols and sections">;
 def V : Flag<["-"], "V">,
         Alias<version>,
         HelpText<"Alias for --version">;

>From 4d7d96927cb8485c713b071dc729c340fb0d636f Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 8 Feb 2025 14:59:42 +0530
Subject: [PATCH 2/5] Made Changes

---
 llvm/include/llvm/ObjCopy/CommonConfig.h   |  1 +
 llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp        |  1 +
 llvm/lib/ObjCopy/ELF/ELFObject.cpp         | 27 +++++++++++-----------
 llvm/lib/ObjCopy/ELF/ELFObject.h           |  1 +
 llvm/tools/llvm-objcopy/ObjcopyOptions.cpp |  2 ++
 5 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h
index aea9cd6f9a9c7..83ad4590d9c72 100644
--- a/llvm/include/llvm/ObjCopy/CommonConfig.h
+++ b/llvm/include/llvm/ObjCopy/CommonConfig.h
@@ -274,6 +274,7 @@ struct CommonConfig {
   bool StripNonAlloc = false;
   bool StripSections = false;
   bool StripUnneeded = false;
+  bool Verbose = false;
   bool Weaken = false;
   bool DecompressDebugSections = false;
 
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index f810bbf639300..fe9efc95b3bd6 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -783,6 +783,7 @@ static Error verifyNoteSection(StringRef Name, endianness Endianness,
 // system. The only priority is that keeps/copies overrule removes.
 static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
                         ElfType OutputElfType, Object &Obj) {
+  Obj.isVerboseEnabled = Config.Verbose;
   if (Config.OutputArch) {
     Obj.Machine = Config.OutputArch->EMachine;
     Obj.OSABI = Config.OutputArch->OSABI;
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index 5c7489e5b941e..ab4e246896ed5 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -768,7 +768,7 @@ Error SymbolTableSection::removeSymbols(
       std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
                [ToRemove](const SymPtr &Sym) {
                    if (ToRemove(*Sym)) {
-                       dbgs()<<"Symbols Removed:"<<Sym->Name<< "\n";
+                       llvm::outs() << "Symbols Removed:" << Sym->Name<< "\n";
                        return true;
                    }
                    return false;
@@ -2236,6 +2236,9 @@ Error Object::removeSections(
   for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
     for (auto &Segment : Segments)
       Segment->removeSection(RemoveSec.get());
+    if (isVerboseEnabled) {
+      llvm::outs() << "Removed Section: " << (RemoveSec.get()->Name);
+    }
     RemoveSec->onRemove();
     RemoveSections.insert(RemoveSec.get());
   }
@@ -2255,18 +2258,10 @@ Error Object::removeSections(
 
   // Transfer removed sections into the Object RemovedSections container for use
   // later.
-  for(auto &KeepSec : make_range(std::begin(Sections) , Iter))
-  {
-    
-    if (Error E = KeepSec->removeSectionReferences(
-            AllowBrokenLinks, [&RemoveSections](const SectionBase *Sec) {
-              return RemoveSections.find(Sec) != RemoveSections.end();
-            }))
-      std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
-      dbgs()<<"Sections Removed:"<<KeepSec->Name<<'\n';
-      Sections.erase(Iter, std::end(Sections));
-      return Error::success();
-  }
+  std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
+  // Now finally get rid of them all together.
+  Sections.erase(Iter, std::end(Sections));
+  return Error::success();
 }
 
 Error Object::replaceSections(
@@ -2296,8 +2291,12 @@ Error Object::replaceSections(
 Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
   if (SymbolTable)
     for (const SecPtr &Sec : Sections)
-      if (Error E = Sec->removeSymbols(ToRemove))
+      if (Error E = Sec->removeSymbols(ToRemove)){
+        if (isVerboseEnabled){
+          llvm::outs() << "Removed Symbols:" << Sec->Name;
+        }
         return E;
+      }
   return Error::success();
 }
 
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index d8f79a4b1a3cc..4ec1f7188ef88 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -1195,6 +1195,7 @@ class Object {
   uint32_t Flags;
 
   bool HadShdrs = true;
+  bool isVerboseEnabled = true;
   bool MustBeRelocatable = false;
   StringTableSection *SectionNames = nullptr;
   SymbolTableSection *SymbolTable = nullptr;
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 0d209590655ef..7a0d719756081 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -1103,6 +1103,7 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
       OBJCOPY_verify_note_sections, OBJCOPY_no_verify_note_sections, true);
 
   Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
+  Config.Verbose = InputArgs.hasArg(OBJCOPY_verbose);
   ELFConfig.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
   MachOConfig.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
   Config.DecompressDebugSections =
@@ -1586,6 +1587,7 @@ objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
   Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu);
   MachOConfig.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
   Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
+  Config.Verbose = InputArgs.hasArg(STRIP_verbose);
   ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
   MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
 

>From 0d5343e87e86f2d761b6aebe653f0fe5cf50a5e7 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Tue, 11 Mar 2025 12:29:29 +0530
Subject: [PATCH 3/5] Made Changes

---
 llvm/docs/CommandGuide/llvm-objcopy.rst |  4 +++
 llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp     |  6 ++---
 llvm/lib/ObjCopy/ELF/ELFObject.cpp      | 33 ++++++++++++-------------
 llvm/lib/ObjCopy/ELF/ELFObject.h        |  7 ++++--
 4 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index 96f3247780b3b..84ff1cea757e0 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -179,6 +179,10 @@ multiple file formats.
  specified ``<flag>`` values. Can be specified multiple times to update multiple
  sections.
 
+.. option:: --verbose
+
+  List all object files modified.
+
  Supported flag names are `alloc`, `load`, `noload`, `readonly`, `exclude`,
  `debug`, `code`, `data`, `rom`, `share`, `contents`, `merge`, `strings`, and
  `large`. Not all flags are meaningful for all object file formats or target
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index fe9efc95b3bd6..6eec21216aca3 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -547,7 +547,7 @@ static Error replaceAndRemoveSections(const CommonConfig &Config,
     };
   }
 
-  if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred))
+  if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred, Config.Verbose))
     return E;
 
   if (Error E = Obj.compressOrDecompressSections(Config))
@@ -783,7 +783,7 @@ static Error verifyNoteSection(StringRef Name, endianness Endianness,
 // system. The only priority is that keeps/copies overrule removes.
 static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
                         ElfType OutputElfType, Object &Obj) {
-  Obj.isVerboseEnabled = Config.Verbose;
+  Obj.VerboseOutput = Config.Verbose;
   if (Config.OutputArch) {
     Obj.Machine = Config.OutputArch->EMachine;
     Obj.OSABI = Config.OutputArch->OSABI;
@@ -792,7 +792,7 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
   if (!Config.SplitDWO.empty() && Config.ExtractDWO) {
     return Obj.removeSections(
         ELFConfig.AllowBrokenLinks,
-        [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); });
+        [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); }, Config.Verbose);
   }
 
   // Dump sections before add/remove for compatibility with GNU objcopy.
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index ab4e246896ed5..fece7a88b2aa5 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -766,10 +766,11 @@ Error SymbolTableSection::removeSymbols(
     function_ref<bool(const Symbol &)> ToRemove) {
   Symbols.erase(
       std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
-               [ToRemove](const SymPtr &Sym) {
+               [&](const SymPtr &Sym) {
                    if (ToRemove(*Sym)) {
-                       llvm::outs() << "Symbols Removed:" << Sym->Name<< "\n";
-                       return true;
+                    if(VerboseOutput)
+                      outs() << "Symbols Removed:" << Sym->Name<< "\n";
+                    return true;
                    }
                    return false;
                }));
@@ -779,7 +780,6 @@ Error SymbolTableSection::removeSymbols(
   if (Size < PrevSize)
     IndicesChanged = true;
   assignIndices();
-  return Error::success();
 }
 
 void SymbolTableSection::replaceSectionReferences(
@@ -2201,7 +2201,7 @@ Error Object::updateSectionData(SectionBase &S, ArrayRef<uint8_t> Data) {
 }
 
 Error Object::removeSections(
-    bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove) {
+    bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove, bool VerboseOutput) {
 
   auto Iter = std::stable_partition(
       std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
@@ -2236,8 +2236,8 @@ Error Object::removeSections(
   for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
     for (auto &Segment : Segments)
       Segment->removeSection(RemoveSec.get());
-    if (isVerboseEnabled) {
-      llvm::outs() << "Removed Section: " << (RemoveSec.get()->Name);
+    if (VerboseOutput) {
+      outs() << "removed section: " << (RemoveSec.get()->Name);
     }
     RemoveSec->onRemove();
     RemoveSections.insert(RemoveSec.get());
@@ -2282,21 +2282,20 @@ Error Object::replaceSections(
 
   if (Error E = removeSections(
           /*AllowBrokenLinks=*/false,
-          [=](const SectionBase &Sec) { return FromTo.count(&Sec) > 0; }))
+          [=](const SectionBase &Sec) { return FromTo.count(&Sec) > 0; }, false))
     return E;
   llvm::sort(Sections, SectionIndexLess);
   return Error::success();
 }
 
 Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
-  if (SymbolTable)
-    for (const SecPtr &Sec : Sections)
-      if (Error E = Sec->removeSymbols(ToRemove)){
-        if (isVerboseEnabled){
-          llvm::outs() << "Removed Symbols:" << Sec->Name;
-        }
+  if (SymbolTable){
+    for (const SecPtr &Sec : Sections){
+      if (Error E = Sec->removeSymbols(ToRemove))
         return E;
-      }
+      outs() << "removed symbols:" << Sec->Name;
+    }
+  }
   return Error::success();
 }
 
@@ -2583,7 +2582,7 @@ static Error removeUnneededSections(Object &Obj) {
                      : Obj.SymbolTable->getStrTab();
   return Obj.removeSections(false, [&](const SectionBase &Sec) {
     return &Sec == Obj.SymbolTable || &Sec == StrTab;
-  });
+  }, false);
 }
 
 template <class ELFT> Error ELFWriter<ELFT>::finalize() {
@@ -2637,7 +2636,7 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
       if (Error E = Obj.removeSections(false /*AllowBrokenLinks*/,
                                        [this](const SectionBase &Sec) {
                                          return &Sec == Obj.SectionIndexTable;
-                                       }))
+                                       }, false))
         return E;
     }
   }
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 4ec1f7188ef88..bcda100343813 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -814,6 +814,8 @@ class SymbolTableSection : public SectionBase {
   void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
   void assignIndices();
 
+private:
+  bool VerboseOutput;
 protected:
   std::vector<std::unique_ptr<Symbol>> Symbols;
   StringTableSection *SymbolNames = nullptr;
@@ -856,6 +858,7 @@ class SymbolTableSection : public SectionBase {
   static bool classof(const SectionBase *S) {
     return S->OriginalType == ELF::SHT_SYMTAB;
   }
+  bool getVerboseOutput() { return VerboseOutput; }
 };
 
 struct Relocation {
@@ -1195,7 +1198,7 @@ class Object {
   uint32_t Flags;
 
   bool HadShdrs = true;
-  bool isVerboseEnabled = true;
+  bool VerboseOutput;
   bool MustBeRelocatable = false;
   StringTableSection *SectionNames = nullptr;
   SymbolTableSection *SymbolTable = nullptr;
@@ -1225,7 +1228,7 @@ class Object {
   ConstRange<Segment> segments() const { return make_pointee_range(Segments); }
 
   Error removeSections(bool AllowBrokenLinks,
-                       std::function<bool(const SectionBase &)> ToRemove);
+                       std::function<bool(const SectionBase &)> ToRemove, bool VerboseOutput);
   Error compressOrDecompressSections(const CommonConfig &Config);
   Error replaceSections(const DenseMap<SectionBase *, SectionBase *> &FromTo);
   Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);

>From 76f64dad00430eb43eed49e5a6e443a2cfb7073f Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Sat, 12 Apr 2025 23:18:56 +0530
Subject: [PATCH 4/5] Informal Change(Testing)

---
 .../InstCombine/InstCombineAndOrXor.cpp       | 28 ++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 508aef63a3128..3e245532d1f5a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2871,7 +2871,33 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
           simplifyAndOrWithOpReplaced(Op1, Op0, Constant::getAllOnesValue(Ty),
                                       /*SimplifyOnly*/ false, *this))
     return BinaryOperator::CreateAnd(Op0, V);
-
+  // I is the 'and' instruction
+if (auto *Add = dyn_cast<BinaryOperator>(I.getOperand(0))) {
+  if (Add->getOpcode() == Instruction::Add) {
+      Value *LHS = Add->getOperand(0); // should be shl
+      ConstantInt *AddConst = dyn_cast<ConstantInt>(Add->getOperand(1));
+      ConstantInt *AndConst = dyn_cast<ConstantInt>(I.getOperand(1));
+      if (AddConst && AndConst) {
+          // check if AddConst is 47 and AndConst is -32
+          if (AddConst->equalsInt(47) && AndConst->getSExtValue() == -32) {
+              // Check if LHS is shl i64 %a, 5
+              if (auto *Shl = dyn_cast<BinaryOperator>(LHS)) {
+                  if (Shl->getOpcode() == Instruction::Shl) {
+                      ConstantInt *ShlConst = dyn_cast<ConstantInt>(Shl->getOperand(1));
+                      if (ShlConst && ShlConst->equalsInt(5)) {
+                          // You've matched the pattern!
+                          // Replace with: shl i64 (add i64 %a, 1), 5
+                          IRBuilder<> Builder(&I);
+                          Value *NewAdd = Builder.CreateAdd(Shl->getOperand(0), ConstantInt::get(I.getType(), 1));
+                          Value *NewShl = Builder.CreateShl(NewAdd, ShlConst);
+                          I.replaceAllUsesWith(NewShl);
+                      }
+                  }
+              }
+          }
+      }
+  }
+}
   return nullptr;
 }
 

>From 9a3efc254400f9b7da3f56b654cfa398de8954bb Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Fri, 16 May 2025 11:16:38 +0530
Subject: [PATCH 5/5] [InstCombine] (x mod (C1 * C2) / C2) vs. ((x / C2) mod
 C1) Made Changes in InstCombineMulDivRem.cpp to identify the pattern of the
 form x mod(C1*C2) and replace it with (X/C2) mod C1

Fixes#122442
---
 .../InstCombine/InstCombineMulDivRem.cpp      | 42 ++++++-------------
 1 file changed, 13 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index c7023eb79b04e..c488f0c16f2e1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -255,33 +255,6 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
     }
   }
 
-  // mul (shr exact X, N), (2^N + 1) -> add (X, shr exact (X, N))
-  {
-    Value *NewOp;
-    const APInt *ShiftC;
-    const APInt *MulAP;
-    if (BitWidth > 2 &&
-        match(&I, m_Mul(m_Exact(m_Shr(m_Value(NewOp), m_APInt(ShiftC))),
-                        m_APInt(MulAP))) &&
-        (*MulAP - 1).isPowerOf2() && *ShiftC == MulAP->logBase2()) {
-      Value *BinOp = Op0;
-      BinaryOperator *OpBO = cast<BinaryOperator>(Op0);
-
-      // mul nuw (ashr exact X, N) -> add nuw (X, lshr exact (X, N))
-      if (HasNUW && OpBO->getOpcode() == Instruction::AShr && OpBO->hasOneUse())
-        BinOp = Builder.CreateLShr(NewOp, ConstantInt::get(Ty, *ShiftC), "",
-                                   /*isExact=*/true);
-
-      auto *NewAdd = BinaryOperator::CreateAdd(NewOp, BinOp);
-      if (HasNSW && (HasNUW || OpBO->getOpcode() == Instruction::LShr ||
-                     ShiftC->getZExtValue() < BitWidth - 1))
-        NewAdd->setHasNoSignedWrap(true);
-
-      NewAdd->setHasNoUnsignedWrap(HasNUW);
-      return NewAdd;
-    }
-  }
-
   if (Op0->hasOneUse() && match(Op1, m_NegatedPower2())) {
     // Interpret  X * (-1<<C)  as  (-X) * (1<<C)  and try to sink the negation.
     // The "* (1<<C)" thus becomes a potential shifting opportunity.
@@ -1257,8 +1230,10 @@ static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
 
 /// Common integer divide/remainder transforms
 Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
+  const APInt *C1, *C2;
   assert(I.isIntDivRem() && "Unexpected instruction");
-  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+  Value *X;
+  Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *Op2 = I.getOperand(2);
 
   // If any element of a constant divisor fixed width vector is zero or undef
   // the behavior is undefined and we can fold the whole op to poison.
@@ -1296,6 +1271,15 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
       return R;
   }
 
+  if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::smul_fix>(m_APInt(C1), m_APInt(C2)))) &&
+    match(Op1, m_OneUse(m_URem(m_Value(X), Op0))) &&
+    match(Op2, m_OneUse(m_UDiv(Op1, m_APInt(C2))))) {
+    
+    Value *XDivC2 = Builder.CreateUDiv(X, ConstantInt::get(X->getType(), *C2));
+    Value *Result = Builder.CreateURem(XDivC2, ConstantInt::get(X->getType(), *C1));
+    return replaceInstUsesWith(I, Result);
+}
+
   return nullptr;
 }
 
@@ -2071,7 +2055,7 @@ convertFSqrtDivIntoFMul(CallInst *CI, Instruction *X,
   // instructions in R2 and get the most common fpmath metadata and fast-math
   // flags on it.
   auto *FSqrt = cast<CallInst>(CI->clone());
-  FSqrt->insertBefore(CI->getIterator());
+  FSqrt->insertBefore(CI);
   auto *R2FPMathMDNode = (*R2.begin())->getMetadata(LLVMContext::MD_fpmath);
   FastMathFlags R2FMF = (*R2.begin())->getFastMathFlags(); // Common FMF
   for (Instruction *I : R2) {



More information about the llvm-commits mailing list