[llvm] [SelectionDAG] Add preliminary plumbing for `samesign` flag (PR #112354)

Antonio Frighetto via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 16 03:23:10 PDT 2024


https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/112354

>From 276ebf5817594de082977bf67f3afa5f0f440ea7 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Tue, 15 Oct 2024 15:08:25 +0200
Subject: [PATCH 1/2] [SelectionDAG] Add preliminary plumbing for `samesign`

Extend recently-added poison-generating IR flag to codegen as well.
---
 llvm/include/llvm/CodeGen/SelectionDAGNodes.h      | 14 +++++++++-----
 .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp   |  4 ++++
 .../CodeGen/SelectionDAG/SelectionDAGDumper.cpp    |  3 +++
 llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp   |  8 +++++++-
 4 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 639e9311977502..bad19173683101 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -382,6 +382,7 @@ struct SDNodeFlags {
   bool NoSignedWrap : 1;
   bool Exact : 1;
   bool Disjoint : 1;
+  bool SameSign : 1;
   bool NonNeg : 1;
   bool NoNaNs : 1;
   bool NoInfs : 1;
@@ -404,10 +405,10 @@ struct SDNodeFlags {
   /// Default constructor turns off all optimization flags.
   SDNodeFlags()
       : NoUnsignedWrap(false), NoSignedWrap(false), Exact(false),
-        Disjoint(false), NonNeg(false), NoNaNs(false), NoInfs(false),
-        NoSignedZeros(false), AllowReciprocal(false), AllowContract(false),
-        ApproximateFuncs(false), AllowReassociation(false), NoFPExcept(false),
-        Unpredictable(false) {}
+        Disjoint(false), SameSign(false), NonNeg(false), NoNaNs(false),
+        NoInfs(false), NoSignedZeros(false), AllowReciprocal(false),
+        AllowContract(false), ApproximateFuncs(false),
+        AllowReassociation(false), NoFPExcept(false), Unpredictable(false) {}
 
   /// Propagate the fast-math-flags from an IR FPMathOperator.
   void copyFMF(const FPMathOperator &FPMO) {
@@ -425,6 +426,7 @@ struct SDNodeFlags {
   void setNoSignedWrap(bool b) { NoSignedWrap = b; }
   void setExact(bool b) { Exact = b; }
   void setDisjoint(bool b) { Disjoint = b; }
+  void setSameSign(bool b) { SameSign = b; }
   void setNonNeg(bool b) { NonNeg = b; }
   void setNoNaNs(bool b) { NoNaNs = b; }
   void setNoInfs(bool b) { NoInfs = b; }
@@ -441,6 +443,7 @@ struct SDNodeFlags {
   bool hasNoSignedWrap() const { return NoSignedWrap; }
   bool hasExact() const { return Exact; }
   bool hasDisjoint() const { return Disjoint; }
+  bool hasSameSign() const { return SameSign; }
   bool hasNonNeg() const { return NonNeg; }
   bool hasNoNaNs() const { return NoNaNs; }
   bool hasNoInfs() const { return NoInfs; }
@@ -473,6 +476,7 @@ struct SDNodeFlags {
     NoSignedWrap &= Flags.NoSignedWrap;
     Exact &= Flags.Exact;
     Disjoint &= Flags.Disjoint;
+    SameSign &= Flags.SameSign;
     NonNeg &= Flags.NonNeg;
     NoNaNs &= Flags.NoNaNs;
     NoInfs &= Flags.NoInfs;
@@ -1032,7 +1036,7 @@ END_TWO_BYTE_PACK()
     SDNodeFlags Flags = getFlags();
     return Flags.hasNoUnsignedWrap() || Flags.hasNoSignedWrap() ||
            Flags.hasExact() || Flags.hasDisjoint() || Flags.hasNonNeg() ||
-           Flags.hasNoNaNs() || Flags.hasNoInfs();
+           Flags.hasNoNaNs() || Flags.hasNoInfs() || Flags.hasSameSign();
   }
 
   void setCFIType(uint32_t Type) { CFIType = Type; }
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 805b8ecf009598..35ea9419f2dd1a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3640,6 +3640,10 @@ void SelectionDAGBuilder::visitICmp(const ICmpInst &I) {
   SDValue Op2 = getValue(I.getOperand(1));
   ISD::CondCode Opcode = getICmpCondCode(predicate);
 
+  SDNodeFlags Flags;
+  Flags.setSameSign(I.hasSameSign());
+  SelectionDAG::FlagInserter FlagsInserter(DAG, Flags);
+
   auto &TLI = DAG.getTargetLoweringInfo();
   EVT MemVT =
       TLI.getMemValueType(DAG.getDataLayout(), I.getOperand(0)->getType());
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 56fc538172f9fc..24fc83b422147f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -651,6 +651,9 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
   if (getFlags().hasDisjoint())
     OS << " disjoint";
 
+  if (getFlags().hasSameSign())
+    OS << " samesign";
+
   if (getFlags().hasNonNeg())
     OS << " nneg";
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 40f030d7b936f7..43e6a43e820b5a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1703,6 +1703,7 @@ bool TargetLowering::SimplifyDemandedBits(
   case ISD::SETCC: {
     SDValue Op0 = Op.getOperand(0);
     SDValue Op1 = Op.getOperand(1);
+    SDNodeFlags Flags = Op.getNode()->getFlags();
     ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
     // If (1) we only need the sign-bit, (2) the setcc operands are the same
     // width as the setcc result, and (3) the result of a setcc conforms to 0 or
@@ -1716,8 +1717,13 @@ bool TargetLowering::SimplifyDemandedBits(
       // if we don't care about FP signed-zero. The use of SETLT with FP means
       // that we don't care about NaNs.
       if (CC == ISD::SETLT && Op1.getValueType().isInteger() &&
-          (isNullConstant(Op1) || ISD::isBuildVectorAllZeros(Op1.getNode())))
+          (isNullConstant(Op1) || ISD::isBuildVectorAllZeros(Op1.getNode()))) {
+        if (Flags.hasSameSign()) {
+          Flags.setSameSign(false);
+          Op->setFlags(Flags);
+        }
         return TLO.CombineTo(Op, Op0);
+      }
 
       // TODO: Should we check for other forms of sign-bit comparisons?
       // Examples: X <= -1, X >= 0

>From a4b4f9d9e751f1a3fba7626f663a512810fef3fb Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Wed, 16 Oct 2024 12:22:08 +0200
Subject: [PATCH 2/2] !fixup extend to operator==, instremitter, mirparser

---
 llvm/include/llvm/CodeGen/MachineInstr.h       | 1 +
 llvm/include/llvm/CodeGen/SelectionDAGNodes.h  | 6 +++---
 llvm/lib/CodeGen/MIRParser/MILexer.cpp         | 1 +
 llvm/lib/CodeGen/MIRParser/MILexer.h           | 1 +
 llvm/lib/CodeGen/MIRParser/MIParser.cpp        | 5 ++++-
 llvm/lib/CodeGen/MIRPrinter.cpp                | 2 ++
 llvm/lib/CodeGen/MachineInstr.cpp              | 8 ++++++++
 llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 3 +++
 8 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 76a7b8662bae66..2dde32a58c016c 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -119,6 +119,7 @@ class MachineInstr
     Disjoint = 1 << 19,      // Each bit is zero in at least one of the inputs.
     NoUSWrap = 1 << 20,      // Instruction supports geps
                              // no unsigned signed wrap.
+    SameSign = 1 << 21,      // Compare instruction has same sign.
   };
 
 private:
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index bad19173683101..bab17d36e8e6b5 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -458,9 +458,9 @@ struct SDNodeFlags {
   bool operator==(const SDNodeFlags &Other) const {
     return NoUnsignedWrap == Other.NoUnsignedWrap &&
            NoSignedWrap == Other.NoSignedWrap && Exact == Other.Exact &&
-           Disjoint == Other.Disjoint && NonNeg == Other.NonNeg &&
-           NoNaNs == Other.NoNaNs && NoInfs == Other.NoInfs &&
-           NoSignedZeros == Other.NoSignedZeros &&
+           Disjoint == Other.Disjoint && SameSign == Other.SameSign &&
+           NonNeg == Other.NonNeg && NoNaNs == Other.NoNaNs &&
+           NoInfs == Other.NoInfs && NoSignedZeros == Other.NoSignedZeros &&
            AllowReciprocal == Other.AllowReciprocal &&
            AllowContract == Other.AllowContract &&
            ApproximateFuncs == Other.ApproximateFuncs &&
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
index 0809f88fde56b1..51c203ae9d9083 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
@@ -216,6 +216,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
       .Case("exact", MIToken::kw_exact)
       .Case("nneg", MIToken::kw_nneg)
       .Case("disjoint", MIToken::kw_disjoint)
+      .Case("samesign", MIToken::kw_samesign)
       .Case("nofpexcept", MIToken::kw_nofpexcept)
       .Case("unpredictable", MIToken::kw_unpredictable)
       .Case("debug-location", MIToken::kw_debug_location)
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h
index 22547483a8a86b..fd24b0b64bf9ed 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.h
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.h
@@ -77,6 +77,7 @@ struct MIToken {
     kw_unpredictable,
     kw_nneg,
     kw_disjoint,
+    kw_samesign,
     kw_debug_location,
     kw_debug_instr_number,
     kw_dbg_instr_ref,
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 7aaa0f409d5ef9..d0184a7387ce47 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1476,7 +1476,8 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) {
          Token.is(MIToken::kw_noconvergent) ||
          Token.is(MIToken::kw_unpredictable) ||
          Token.is(MIToken::kw_nneg) ||
-         Token.is(MIToken::kw_disjoint)) {
+         Token.is(MIToken::kw_disjoint) ||
+         Token.is(MIToken::kw_samesign)) {
     // clang-format on
     // Mine frame and fast math flags
     if (Token.is(MIToken::kw_frame_setup))
@@ -1513,6 +1514,8 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) {
       Flags |= MachineInstr::NonNeg;
     if (Token.is(MIToken::kw_disjoint))
       Flags |= MachineInstr::Disjoint;
+    if (Token.is(MIToken::kw_samesign))
+      Flags |= MachineInstr::SameSign;
 
     lex();
   }
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index a015cd3c2a55f9..658bbe0e577e5c 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -837,6 +837,8 @@ void MIPrinter::print(const MachineInstr &MI) {
     OS << "disjoint ";
   if (MI.getFlag(MachineInstr::NoUSWrap))
     OS << "nusw ";
+  if (MI.getFlag(MachineInstr::SameSign))
+    OS << "samesign ";
 
   OS << TII->getName(MI.getOpcode());
   if (I < E)
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 0d78c2cafbaf63..06e28aee1d9689 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -620,6 +620,12 @@ uint32_t MachineInstr::copyFlagsFromInstruction(const Instruction &I) {
       MIFlags |= MachineInstr::MIFlag::FmReassoc;
   }
 
+  // Copy the samesign flag.
+  if (const auto *ICI = dyn_cast<ICmpInst>(&I)) {
+    if (ICI->hasSameSign())
+      MIFlags |= MachineInstr::MIFlag::SameSign;
+  }
+
   if (I.getMetadata(LLVMContext::MD_unpredictable))
     MIFlags |= MachineInstr::MIFlag::Unpredictable;
 
@@ -1773,6 +1779,8 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
     OS << "nneg ";
   if (getFlag(MachineInstr::Disjoint))
     OS << "disjoint ";
+  if (getFlag(MachineInstr::SameSign))
+    OS << "samesign ";
 
   // Print the opcode name.
   if (TII)
diff --git a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index 281d1578d0173a..9c7085cc7e7a83 100644
--- a/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
@@ -1105,6 +1105,9 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned,
 
     if (Flags.hasDisjoint())
       MI->setFlag(MachineInstr::MIFlag::Disjoint);
+
+    if (Flags.hasSameSign())
+      MI->setFlag(MachineInstr::MIFlag::SameSign);
   }
 
   // Emit all of the actual operands of this instruction, adding them to the



More information about the llvm-commits mailing list