[llvm] [SandboxIR] Implement Instruction flags (PR #103343)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 13 10:36:49 PDT 2024


https://github.com/vporpo created https://github.com/llvm/llvm-project/pull/103343

This patch implements sandboxir::Instruction flags.

>From 6c902e97be5746d7bbe72357c245b9470d58eedd Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Thu, 8 Aug 2024 14:14:05 -0700
Subject: [PATCH] [SandboxIR] Implement Instruction flags

This patch implements sandboxir::Instruction flags.
---
 llvm/include/llvm/SandboxIR/SandboxIR.h    | 100 +++++++++++++++++++++
 llvm/lib/SandboxIR/SandboxIR.cpp           |  97 ++++++++++++++++++++
 llvm/unittests/SandboxIR/SandboxIRTest.cpp |  59 ++++++++++++
 llvm/unittests/SandboxIR/TrackerTest.cpp   |  61 +++++++++++++
 4 files changed, 317 insertions(+)

diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index a6adb448ff0b1..612a7dee1c28c 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -682,6 +682,106 @@ class Instruction : public sandboxir::User {
   /// For isa/dyn_cast.
   static bool classof(const sandboxir::Value *From);
 
+  /// Determine whether the no signed wrap flag is set.
+  bool hasNoUnsignedWrap() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->hasNoUnsignedWrap();
+  }
+  /// Set or clear the nuw flag on this instruction, which must be an operator
+  /// which supports this flag. See LangRef.html for the meaning of this flag.
+  void setHasNoUnsignedWrap(bool B = true);
+  /// Determine whether the no signed wrap flag is set.
+  bool hasNoSignedWrap() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->hasNoSignedWrap();
+  }
+  /// Set or clear the nsw flag on this instruction, which must be an operator
+  /// which supports this flag. See LangRef.html for the meaning of this flag.
+  void setHasNoSignedWrap(bool B = true);
+  /// Determine whether all fast-math-flags are set.
+  bool isFast() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->isFast();
+  }
+  /// Set or clear all fast-math-flags on this instruction, which must be an
+  /// operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setFast(bool B);
+  /// Determine whether the allow-reassociation flag is set.
+  bool hasAllowReassoc() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->hasAllowReassoc();
+  }
+  /// Set or clear the reassociation flag on this instruction, which must be
+  /// an operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasAllowReassoc(bool B);
+  /// Determine whether the exact flag is set.
+  bool isExact() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->isExact();
+  }
+  /// Set or clear the exact flag on this instruction, which must be an operator
+  /// which supports this flag. See LangRef.html for the meaning of this flag.
+  void setIsExact(bool B = true);
+  /// Determine whether the no-NaNs flag is set.
+  bool hasNoNaNs() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->hasNoNaNs();
+  }
+  /// Set or clear the no-nans flag on this instruction, which must be an
+  /// operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasNoNaNs(bool B);
+  /// Determine whether the no-infs flag is set.
+  bool hasNoInfs() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->hasNoInfs();
+  }
+  /// Set or clear the no-infs flag on this instruction, which must be an
+  /// operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasNoInfs(bool B);
+  /// Determine whether the no-signed-zeros flag is set.
+  bool hasNoSignedZeros() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->hasNoSignedZeros();
+  }
+  /// Set or clear the no-signed-zeros flag on this instruction, which must be
+  /// an operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasNoSignedZeros(bool B);
+  /// Determine whether the allow-reciprocal flag is set.
+  bool hasAllowReciprocal() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->hasAllowReciprocal();
+  }
+  /// Set or clear the allow-reciprocal flag on this instruction, which must be
+  /// an operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasAllowReciprocal(bool B);
+  /// Determine whether the allow-contract flag is set.
+  bool hasAllowContract() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->hasAllowContract();
+  }
+  /// Set or clear the allow-contract flag on this instruction, which must be
+  /// an operator which supports this flag. See LangRef.html for the meaning of
+  /// this flag.
+  void setHasAllowContract(bool B);
+  /// Determine whether the approximate-math-functions flag is set.
+  bool hasApproxFunc() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->hasApproxFunc();
+  }
+  /// Set or clear the approximate-math-functions flag on this instruction,
+  /// which must be an operator which supports this flag. See LangRef.html for
+  /// the meaning of this flag.
+  void setHasApproxFunc(bool B);
+  /// Convenience function for getting all the fast-math flags, which must be an
+  /// operator which supports these flags. See LangRef.html for the meaning of
+  /// these flags.
+  FastMathFlags getFastMathFlags() const LLVM_READONLY {
+    return cast<llvm::Instruction>(Val)->getFastMathFlags();
+  }
+  /// Convenience function for setting multiple fast-math flags on this
+  /// instruction, which must be an operator which supports these flags. See
+  /// LangRef.html for the meaning of these flags.
+  void setFastMathFlags(FastMathFlags FMF);
+  /// Convenience function for transferring all fast-math flag values to this
+  /// instruction, which must be an operator which supports these flags. See
+  /// LangRef.html for the meaning of these flags.
+  void copyFastMathFlags(FastMathFlags FMF);
+
 #ifndef NDEBUG
   void dumpOS(raw_ostream &OS) const override;
 #endif
diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 80809b23e34b2..3c7dbb70c9f4b 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -472,6 +472,103 @@ bool Instruction::classof(const sandboxir::Value *From) {
   }
 }
 
+void Instruction::setHasNoUnsignedWrap(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&Instruction::hasNoUnsignedWrap,
+                                       &Instruction::setHasNoUnsignedWrap>>(
+          this);
+  cast<llvm::Instruction>(Val)->setHasNoUnsignedWrap(B);
+}
+
+void Instruction::setHasNoSignedWrap(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedWrap,
+                                       &Instruction::setHasNoSignedWrap>>(this);
+  cast<llvm::Instruction>(Val)->setHasNoSignedWrap(B);
+}
+
+void Instruction::setFast(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&Instruction::isFast, &Instruction::setFast>>(this);
+  cast<llvm::Instruction>(Val)->setFast(B);
+}
+
+void Instruction::setIsExact(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&Instruction::isExact, &Instruction::setIsExact>>(this);
+  cast<llvm::Instruction>(Val)->setIsExact(B);
+}
+
+void Instruction::setHasAllowReassoc(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&Instruction::hasAllowReassoc,
+                                       &Instruction::setHasAllowReassoc>>(this);
+  cast<llvm::Instruction>(Val)->setHasAllowReassoc(B);
+}
+
+void Instruction::setHasNoNaNs(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&Instruction::hasNoNaNs, &Instruction::setHasNoNaNs>>(
+          this);
+  cast<llvm::Instruction>(Val)->setHasNoNaNs(B);
+}
+
+void Instruction::setHasNoInfs(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<
+          GenericSetter<&Instruction::hasNoInfs, &Instruction::setHasNoInfs>>(
+          this);
+  cast<llvm::Instruction>(Val)->setHasNoInfs(B);
+}
+
+void Instruction::setHasNoSignedZeros(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedZeros,
+                                       &Instruction::setHasNoSignedZeros>>(
+          this);
+  cast<llvm::Instruction>(Val)->setHasNoSignedZeros(B);
+}
+
+void Instruction::setHasAllowReciprocal(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&Instruction::hasAllowReciprocal,
+                                       &Instruction::setHasAllowReciprocal>>(
+          this);
+  cast<llvm::Instruction>(Val)->setHasAllowReciprocal(B);
+}
+
+void Instruction::setHasAllowContract(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&Instruction::hasAllowContract,
+                                       &Instruction::setHasAllowContract>>(
+          this);
+  cast<llvm::Instruction>(Val)->setHasAllowContract(B);
+}
+
+void Instruction::setFastMathFlags(FastMathFlags FMF) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
+                                       &Instruction::copyFastMathFlags>>(this);
+  cast<llvm::Instruction>(Val)->setFastMathFlags(FMF);
+}
+
+void Instruction::copyFastMathFlags(FastMathFlags FMF) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
+                                       &Instruction::copyFastMathFlags>>(this);
+  cast<llvm::Instruction>(Val)->copyFastMathFlags(FMF);
+}
+
+void Instruction::setHasApproxFunc(bool B) {
+  Ctx.getTracker()
+      .emplaceIfTracking<GenericSetter<&Instruction::hasApproxFunc,
+                                       &Instruction::setHasApproxFunc>>(this);
+  cast<llvm::Instruction>(Val)->setHasApproxFunc(B);
+}
+
 #ifndef NDEBUG
 void Instruction::dumpOS(raw_ostream &OS) const {
   OS << "Unimplemented! Please override dump().";
diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
index caf306922847e..1e4679ed6e802 100644
--- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp
+++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp
@@ -1569,6 +1569,65 @@ define void @foo(ptr %ptr, <2 x ptr> %ptrs) {
   EXPECT_EQ(NewGEP2->getNextNode(), nullptr);
 }
 
+TEST_F(SandboxIRTest, Flags) {
+  parseIR(C, R"IR(
+define void @foo(i32 %arg, float %farg) {
+  %add = add i32 %arg, %arg
+  %fadd = fadd float %farg, %farg
+  %udiv = udiv i32 %arg, %arg
+  ret void
+}
+)IR");
+  Function &LLVMF = *M->getFunction("foo");
+  BasicBlock *LLVMBB = &*LLVMF.begin();
+  auto LLVMIt = LLVMBB->begin();
+  auto *LLVMAdd = &*LLVMIt++;
+  auto *LLVMFAdd = &*LLVMIt++;
+  auto *LLVMUDiv = &*LLVMIt++;
+
+  sandboxir::Context Ctx(C);
+  auto &F = *Ctx.createFunction(&LLVMF);
+  auto *BB = &*F.begin();
+  auto It = BB->begin();
+  auto *Add = &*It++;
+  auto *FAdd = &*It++;
+  auto *UDiv = &*It++;
+
+#define CHECK_FLAG(I, LLVMI, GETTER, SETTER)                                   \
+  {                                                                            \
+    EXPECT_EQ(I->GETTER(), LLVMI->GETTER());                                   \
+    bool NewFlagVal = !I->GETTER();                                            \
+    I->SETTER(NewFlagVal);                                                     \
+    EXPECT_EQ(I->GETTER(), NewFlagVal);                                        \
+    EXPECT_EQ(I->GETTER(), LLVMI->GETTER());                                   \
+  }
+
+  CHECK_FLAG(Add, LLVMAdd, hasNoUnsignedWrap, setHasNoUnsignedWrap);
+  CHECK_FLAG(Add, LLVMAdd, hasNoSignedWrap, setHasNoSignedWrap);
+  CHECK_FLAG(FAdd, LLVMFAdd, isFast, setFast);
+  CHECK_FLAG(FAdd, LLVMFAdd, hasAllowReassoc, setHasAllowReassoc);
+  CHECK_FLAG(UDiv, LLVMUDiv, isExact, setIsExact);
+  CHECK_FLAG(FAdd, LLVMFAdd, hasNoNaNs, setHasNoNaNs);
+  CHECK_FLAG(FAdd, LLVMFAdd, hasNoInfs, setHasNoInfs);
+  CHECK_FLAG(FAdd, LLVMFAdd, hasNoSignedZeros, setHasNoSignedZeros);
+  CHECK_FLAG(FAdd, LLVMFAdd, hasAllowReciprocal, setHasAllowReciprocal);
+  CHECK_FLAG(FAdd, LLVMFAdd, hasAllowContract, setHasAllowContract);
+  CHECK_FLAG(FAdd, LLVMFAdd, hasApproxFunc, setHasApproxFunc);
+
+  // Check getFastMathFlags(), copyFastMathFlags().
+  FAdd->setFastMathFlags(FastMathFlags::getFast());
+  EXPECT_FALSE(FAdd->getFastMathFlags() != LLVMFAdd->getFastMathFlags());
+  FastMathFlags OrigFMF = FAdd->getFastMathFlags();
+  FastMathFlags NewFMF;
+  NewFMF.setAllowReassoc(true);
+  EXPECT_TRUE(NewFMF != OrigFMF);
+  FAdd->setFastMathFlags(NewFMF);
+  EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);
+  FAdd->copyFastMathFlags(NewFMF);
+  EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);
+  EXPECT_FALSE(FAdd->getFastMathFlags() != LLVMFAdd->getFastMathFlags());
+}
+
 TEST_F(SandboxIRTest, AtomicCmpXchgInst) {
   parseIR(C, R"IR(
 define void @foo(ptr %ptr, i8 %cmp, i8 %new) {
diff --git a/llvm/unittests/SandboxIR/TrackerTest.cpp b/llvm/unittests/SandboxIR/TrackerTest.cpp
index ba1d16de7d212..c1f23c95cbfae 100644
--- a/llvm/unittests/SandboxIR/TrackerTest.cpp
+++ b/llvm/unittests/SandboxIR/TrackerTest.cpp
@@ -968,3 +968,64 @@ define void @foo(ptr %arg0, i8 %val) {
   Ctx.revert();
   EXPECT_FALSE(Store->isVolatile());
 }
+
+TEST_F(TrackerTest, Flags) {
+  parseIR(C, R"IR(
+define void @foo(i32 %arg, float %farg) {
+  %add = add i32 %arg, %arg
+  %fadd = fadd float %farg, %farg
+  %udiv = udiv i32 %arg, %arg
+  ret void
+}
+)IR");
+  Function &LLVMF = *M->getFunction("foo");
+  sandboxir::Context Ctx(C);
+  auto &F = *Ctx.createFunction(&LLVMF);
+  auto *BB = &*F.begin();
+  auto It = BB->begin();
+  auto *Add = &*It++;
+  auto *FAdd = &*It++;
+  auto *UDiv = &*It++;
+
+#define CHECK_FLAG(I, GETTER, SETTER)                                          \
+  {                                                                            \
+    Ctx.save();                                                                \
+    bool OrigFlag = I->GETTER();                                               \
+    bool NewFlag = !OrigFlag;                                                  \
+    I->SETTER(NewFlag);                                                        \
+    EXPECT_EQ(I->GETTER(), NewFlag);                                           \
+    Ctx.revert();                                                              \
+    EXPECT_EQ(I->GETTER(), OrigFlag);                                          \
+  }
+
+  CHECK_FLAG(Add, hasNoUnsignedWrap, setHasNoUnsignedWrap);
+  CHECK_FLAG(Add, hasNoSignedWrap, setHasNoSignedWrap);
+  CHECK_FLAG(FAdd, isFast, setFast);
+  CHECK_FLAG(FAdd, hasAllowReassoc, setHasAllowReassoc);
+  CHECK_FLAG(UDiv, isExact, setIsExact);
+  CHECK_FLAG(FAdd, hasNoNaNs, setHasNoNaNs);
+  CHECK_FLAG(FAdd, hasNoInfs, setHasNoInfs);
+  CHECK_FLAG(FAdd, hasNoSignedZeros, setHasNoSignedZeros);
+  CHECK_FLAG(FAdd, hasAllowReciprocal, setHasAllowReciprocal);
+  CHECK_FLAG(FAdd, hasAllowContract, setHasAllowContract);
+  CHECK_FLAG(FAdd, hasApproxFunc, setHasApproxFunc);
+
+  // Check setFastMathFlags().
+  FastMathFlags OrigFMF = FAdd->getFastMathFlags();
+  FastMathFlags NewFMF;
+  NewFMF.setAllowReassoc(true);
+  EXPECT_TRUE(NewFMF != OrigFMF);
+
+  Ctx.save();
+  FAdd->setFastMathFlags(NewFMF);
+  EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);
+  Ctx.revert();
+  EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);
+
+  // Check copyFastMathFlags().
+  Ctx.save();
+  FAdd->copyFastMathFlags(NewFMF);
+  EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);
+  Ctx.revert();
+  EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);
+}



More information about the llvm-commits mailing list