Skip to content

Commit c4ae8b1

Browse files
authored
[SandboxIR] Implement Instruction flags (#103343)
This patch implements sandboxir::Instruction flags.
1 parent 3287a2e commit c4ae8b1

File tree

5 files changed

+316
-7
lines changed

5 files changed

+316
-7
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,98 @@ class Instruction : public sandboxir::User {
682682
/// For isa/dyn_cast.
683683
static bool classof(const sandboxir::Value *From);
684684

685+
/// Determine whether the no signed wrap flag is set.
686+
bool hasNoUnsignedWrap() const {
687+
return cast<llvm::Instruction>(Val)->hasNoUnsignedWrap();
688+
}
689+
/// Set or clear the nuw flag on this instruction, which must be an operator
690+
/// which supports this flag. See LangRef.html for the meaning of this flag.
691+
void setHasNoUnsignedWrap(bool B = true);
692+
/// Determine whether the no signed wrap flag is set.
693+
bool hasNoSignedWrap() const {
694+
return cast<llvm::Instruction>(Val)->hasNoSignedWrap();
695+
}
696+
/// Set or clear the nsw flag on this instruction, which must be an operator
697+
/// which supports this flag. See LangRef.html for the meaning of this flag.
698+
void setHasNoSignedWrap(bool B = true);
699+
/// Determine whether all fast-math-flags are set.
700+
bool isFast() const { return cast<llvm::Instruction>(Val)->isFast(); }
701+
/// Set or clear all fast-math-flags on this instruction, which must be an
702+
/// operator which supports this flag. See LangRef.html for the meaning of
703+
/// this flag.
704+
void setFast(bool B);
705+
/// Determine whether the allow-reassociation flag is set.
706+
bool hasAllowReassoc() const {
707+
return cast<llvm::Instruction>(Val)->hasAllowReassoc();
708+
}
709+
/// Set or clear the reassociation flag on this instruction, which must be
710+
/// an operator which supports this flag. See LangRef.html for the meaning of
711+
/// this flag.
712+
void setHasAllowReassoc(bool B);
713+
/// Determine whether the exact flag is set.
714+
bool isExact() const { return cast<llvm::Instruction>(Val)->isExact(); }
715+
/// Set or clear the exact flag on this instruction, which must be an operator
716+
/// which supports this flag. See LangRef.html for the meaning of this flag.
717+
void setIsExact(bool B = true);
718+
/// Determine whether the no-NaNs flag is set.
719+
bool hasNoNaNs() const { return cast<llvm::Instruction>(Val)->hasNoNaNs(); }
720+
/// Set or clear the no-nans flag on this instruction, which must be an
721+
/// operator which supports this flag. See LangRef.html for the meaning of
722+
/// this flag.
723+
void setHasNoNaNs(bool B);
724+
/// Determine whether the no-infs flag is set.
725+
bool hasNoInfs() const { return cast<llvm::Instruction>(Val)->hasNoInfs(); }
726+
/// Set or clear the no-infs flag on this instruction, which must be an
727+
/// operator which supports this flag. See LangRef.html for the meaning of
728+
/// this flag.
729+
void setHasNoInfs(bool B);
730+
/// Determine whether the no-signed-zeros flag is set.
731+
bool hasNoSignedZeros() const {
732+
return cast<llvm::Instruction>(Val)->hasNoSignedZeros();
733+
}
734+
/// Set or clear the no-signed-zeros flag on this instruction, which must be
735+
/// an operator which supports this flag. See LangRef.html for the meaning of
736+
/// this flag.
737+
void setHasNoSignedZeros(bool B);
738+
/// Determine whether the allow-reciprocal flag is set.
739+
bool hasAllowReciprocal() const {
740+
return cast<llvm::Instruction>(Val)->hasAllowReciprocal();
741+
}
742+
/// Set or clear the allow-reciprocal flag on this instruction, which must be
743+
/// an operator which supports this flag. See LangRef.html for the meaning of
744+
/// this flag.
745+
void setHasAllowReciprocal(bool B);
746+
/// Determine whether the allow-contract flag is set.
747+
bool hasAllowContract() const {
748+
return cast<llvm::Instruction>(Val)->hasAllowContract();
749+
}
750+
/// Set or clear the allow-contract flag on this instruction, which must be
751+
/// an operator which supports this flag. See LangRef.html for the meaning of
752+
/// this flag.
753+
void setHasAllowContract(bool B);
754+
/// Determine whether the approximate-math-functions flag is set.
755+
bool hasApproxFunc() const {
756+
return cast<llvm::Instruction>(Val)->hasApproxFunc();
757+
}
758+
/// Set or clear the approximate-math-functions flag on this instruction,
759+
/// which must be an operator which supports this flag. See LangRef.html for
760+
/// the meaning of this flag.
761+
void setHasApproxFunc(bool B);
762+
/// Convenience function for getting all the fast-math flags, which must be an
763+
/// operator which supports these flags. See LangRef.html for the meaning of
764+
/// these flags.
765+
FastMathFlags getFastMathFlags() const {
766+
return cast<llvm::Instruction>(Val)->getFastMathFlags();
767+
}
768+
/// Convenience function for setting multiple fast-math flags on this
769+
/// instruction, which must be an operator which supports these flags. See
770+
/// LangRef.html for the meaning of these flags.
771+
void setFastMathFlags(FastMathFlags FMF);
772+
/// Convenience function for transferring all fast-math flag values to this
773+
/// instruction, which must be an operator which supports these flags. See
774+
/// LangRef.html for the meaning of these flags.
775+
void copyFastMathFlags(FastMathFlags FMF);
776+
685777
#ifndef NDEBUG
686778
void dumpOS(raw_ostream &OS) const override;
687779
#endif

llvm/include/llvm/SandboxIR/Tracker.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,13 @@ class RemoveFromParent : public IRChangeBase {
226226
///
227227
template <auto GetterFn, auto SetterFn>
228228
class GenericSetter final : public IRChangeBase {
229-
/// Helper for getting the class type from the getter
230-
template <typename ClassT, typename RetT>
231-
static ClassT getClassTypeFromGetter(RetT (ClassT::*Fn)() const);
232-
template <typename ClassT, typename RetT>
233-
static ClassT getClassTypeFromGetter(RetT (ClassT::*Fn)());
234-
235-
using InstrT = decltype(getClassTypeFromGetter(GetterFn));
229+
/// Traits for getting the class type from GetterFn type.
230+
template <typename> struct GetClassTypeFromGetter;
231+
template <typename RetT, typename ClassT>
232+
struct GetClassTypeFromGetter<RetT (ClassT::*)() const> {
233+
using ClassType = ClassT;
234+
};
235+
using InstrT = typename GetClassTypeFromGetter<decltype(GetterFn)>::ClassType;
236236
using SavedValT = std::invoke_result_t<decltype(GetterFn), InstrT>;
237237
InstrT *I;
238238
SavedValT OrigVal;

llvm/lib/SandboxIR/SandboxIR.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,103 @@ bool Instruction::classof(const sandboxir::Value *From) {
472472
}
473473
}
474474

475+
void Instruction::setHasNoUnsignedWrap(bool B) {
476+
Ctx.getTracker()
477+
.emplaceIfTracking<GenericSetter<&Instruction::hasNoUnsignedWrap,
478+
&Instruction::setHasNoUnsignedWrap>>(
479+
this);
480+
cast<llvm::Instruction>(Val)->setHasNoUnsignedWrap(B);
481+
}
482+
483+
void Instruction::setHasNoSignedWrap(bool B) {
484+
Ctx.getTracker()
485+
.emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedWrap,
486+
&Instruction::setHasNoSignedWrap>>(this);
487+
cast<llvm::Instruction>(Val)->setHasNoSignedWrap(B);
488+
}
489+
490+
void Instruction::setFast(bool B) {
491+
Ctx.getTracker()
492+
.emplaceIfTracking<
493+
GenericSetter<&Instruction::isFast, &Instruction::setFast>>(this);
494+
cast<llvm::Instruction>(Val)->setFast(B);
495+
}
496+
497+
void Instruction::setIsExact(bool B) {
498+
Ctx.getTracker()
499+
.emplaceIfTracking<
500+
GenericSetter<&Instruction::isExact, &Instruction::setIsExact>>(this);
501+
cast<llvm::Instruction>(Val)->setIsExact(B);
502+
}
503+
504+
void Instruction::setHasAllowReassoc(bool B) {
505+
Ctx.getTracker()
506+
.emplaceIfTracking<GenericSetter<&Instruction::hasAllowReassoc,
507+
&Instruction::setHasAllowReassoc>>(this);
508+
cast<llvm::Instruction>(Val)->setHasAllowReassoc(B);
509+
}
510+
511+
void Instruction::setHasNoNaNs(bool B) {
512+
Ctx.getTracker()
513+
.emplaceIfTracking<
514+
GenericSetter<&Instruction::hasNoNaNs, &Instruction::setHasNoNaNs>>(
515+
this);
516+
cast<llvm::Instruction>(Val)->setHasNoNaNs(B);
517+
}
518+
519+
void Instruction::setHasNoInfs(bool B) {
520+
Ctx.getTracker()
521+
.emplaceIfTracking<
522+
GenericSetter<&Instruction::hasNoInfs, &Instruction::setHasNoInfs>>(
523+
this);
524+
cast<llvm::Instruction>(Val)->setHasNoInfs(B);
525+
}
526+
527+
void Instruction::setHasNoSignedZeros(bool B) {
528+
Ctx.getTracker()
529+
.emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedZeros,
530+
&Instruction::setHasNoSignedZeros>>(
531+
this);
532+
cast<llvm::Instruction>(Val)->setHasNoSignedZeros(B);
533+
}
534+
535+
void Instruction::setHasAllowReciprocal(bool B) {
536+
Ctx.getTracker()
537+
.emplaceIfTracking<GenericSetter<&Instruction::hasAllowReciprocal,
538+
&Instruction::setHasAllowReciprocal>>(
539+
this);
540+
cast<llvm::Instruction>(Val)->setHasAllowReciprocal(B);
541+
}
542+
543+
void Instruction::setHasAllowContract(bool B) {
544+
Ctx.getTracker()
545+
.emplaceIfTracking<GenericSetter<&Instruction::hasAllowContract,
546+
&Instruction::setHasAllowContract>>(
547+
this);
548+
cast<llvm::Instruction>(Val)->setHasAllowContract(B);
549+
}
550+
551+
void Instruction::setFastMathFlags(FastMathFlags FMF) {
552+
Ctx.getTracker()
553+
.emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
554+
&Instruction::copyFastMathFlags>>(this);
555+
cast<llvm::Instruction>(Val)->setFastMathFlags(FMF);
556+
}
557+
558+
void Instruction::copyFastMathFlags(FastMathFlags FMF) {
559+
Ctx.getTracker()
560+
.emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags,
561+
&Instruction::copyFastMathFlags>>(this);
562+
cast<llvm::Instruction>(Val)->copyFastMathFlags(FMF);
563+
}
564+
565+
void Instruction::setHasApproxFunc(bool B) {
566+
Ctx.getTracker()
567+
.emplaceIfTracking<GenericSetter<&Instruction::hasApproxFunc,
568+
&Instruction::setHasApproxFunc>>(this);
569+
cast<llvm::Instruction>(Val)->setHasApproxFunc(B);
570+
}
571+
475572
#ifndef NDEBUG
476573
void Instruction::dumpOS(raw_ostream &OS) const {
477574
OS << "Unimplemented! Please override dump().";

llvm/unittests/SandboxIR/SandboxIRTest.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,65 @@ define void @foo(ptr %ptr, <2 x ptr> %ptrs) {
15691569
EXPECT_EQ(NewGEP2->getNextNode(), nullptr);
15701570
}
15711571

1572+
TEST_F(SandboxIRTest, Flags) {
1573+
parseIR(C, R"IR(
1574+
define void @foo(i32 %arg, float %farg) {
1575+
%add = add i32 %arg, %arg
1576+
%fadd = fadd float %farg, %farg
1577+
%udiv = udiv i32 %arg, %arg
1578+
ret void
1579+
}
1580+
)IR");
1581+
Function &LLVMF = *M->getFunction("foo");
1582+
BasicBlock *LLVMBB = &*LLVMF.begin();
1583+
auto LLVMIt = LLVMBB->begin();
1584+
auto *LLVMAdd = &*LLVMIt++;
1585+
auto *LLVMFAdd = &*LLVMIt++;
1586+
auto *LLVMUDiv = &*LLVMIt++;
1587+
1588+
sandboxir::Context Ctx(C);
1589+
auto &F = *Ctx.createFunction(&LLVMF);
1590+
auto *BB = &*F.begin();
1591+
auto It = BB->begin();
1592+
auto *Add = &*It++;
1593+
auto *FAdd = &*It++;
1594+
auto *UDiv = &*It++;
1595+
1596+
#define CHECK_FLAG(I, LLVMI, GETTER, SETTER) \
1597+
{ \
1598+
EXPECT_EQ(I->GETTER(), LLVMI->GETTER()); \
1599+
bool NewFlagVal = !I->GETTER(); \
1600+
I->SETTER(NewFlagVal); \
1601+
EXPECT_EQ(I->GETTER(), NewFlagVal); \
1602+
EXPECT_EQ(I->GETTER(), LLVMI->GETTER()); \
1603+
}
1604+
1605+
CHECK_FLAG(Add, LLVMAdd, hasNoUnsignedWrap, setHasNoUnsignedWrap);
1606+
CHECK_FLAG(Add, LLVMAdd, hasNoSignedWrap, setHasNoSignedWrap);
1607+
CHECK_FLAG(FAdd, LLVMFAdd, isFast, setFast);
1608+
CHECK_FLAG(FAdd, LLVMFAdd, hasAllowReassoc, setHasAllowReassoc);
1609+
CHECK_FLAG(UDiv, LLVMUDiv, isExact, setIsExact);
1610+
CHECK_FLAG(FAdd, LLVMFAdd, hasNoNaNs, setHasNoNaNs);
1611+
CHECK_FLAG(FAdd, LLVMFAdd, hasNoInfs, setHasNoInfs);
1612+
CHECK_FLAG(FAdd, LLVMFAdd, hasNoSignedZeros, setHasNoSignedZeros);
1613+
CHECK_FLAG(FAdd, LLVMFAdd, hasAllowReciprocal, setHasAllowReciprocal);
1614+
CHECK_FLAG(FAdd, LLVMFAdd, hasAllowContract, setHasAllowContract);
1615+
CHECK_FLAG(FAdd, LLVMFAdd, hasApproxFunc, setHasApproxFunc);
1616+
1617+
// Check getFastMathFlags(), copyFastMathFlags().
1618+
FAdd->setFastMathFlags(FastMathFlags::getFast());
1619+
EXPECT_FALSE(FAdd->getFastMathFlags() != LLVMFAdd->getFastMathFlags());
1620+
FastMathFlags OrigFMF = FAdd->getFastMathFlags();
1621+
FastMathFlags NewFMF;
1622+
NewFMF.setAllowReassoc(true);
1623+
EXPECT_TRUE(NewFMF != OrigFMF);
1624+
FAdd->setFastMathFlags(NewFMF);
1625+
EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);
1626+
FAdd->copyFastMathFlags(NewFMF);
1627+
EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);
1628+
EXPECT_FALSE(FAdd->getFastMathFlags() != LLVMFAdd->getFastMathFlags());
1629+
}
1630+
15721631
TEST_F(SandboxIRTest, AtomicCmpXchgInst) {
15731632
parseIR(C, R"IR(
15741633
define void @foo(ptr %ptr, i8 %cmp, i8 %new) {

llvm/unittests/SandboxIR/TrackerTest.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,3 +968,64 @@ define void @foo(ptr %arg0, i8 %val) {
968968
Ctx.revert();
969969
EXPECT_FALSE(Store->isVolatile());
970970
}
971+
972+
TEST_F(TrackerTest, Flags) {
973+
parseIR(C, R"IR(
974+
define void @foo(i32 %arg, float %farg) {
975+
%add = add i32 %arg, %arg
976+
%fadd = fadd float %farg, %farg
977+
%udiv = udiv i32 %arg, %arg
978+
ret void
979+
}
980+
)IR");
981+
Function &LLVMF = *M->getFunction("foo");
982+
sandboxir::Context Ctx(C);
983+
auto &F = *Ctx.createFunction(&LLVMF);
984+
auto *BB = &*F.begin();
985+
auto It = BB->begin();
986+
auto *Add = &*It++;
987+
auto *FAdd = &*It++;
988+
auto *UDiv = &*It++;
989+
990+
#define CHECK_FLAG(I, GETTER, SETTER) \
991+
{ \
992+
Ctx.save(); \
993+
bool OrigFlag = I->GETTER(); \
994+
bool NewFlag = !OrigFlag; \
995+
I->SETTER(NewFlag); \
996+
EXPECT_EQ(I->GETTER(), NewFlag); \
997+
Ctx.revert(); \
998+
EXPECT_EQ(I->GETTER(), OrigFlag); \
999+
}
1000+
1001+
CHECK_FLAG(Add, hasNoUnsignedWrap, setHasNoUnsignedWrap);
1002+
CHECK_FLAG(Add, hasNoSignedWrap, setHasNoSignedWrap);
1003+
CHECK_FLAG(FAdd, isFast, setFast);
1004+
CHECK_FLAG(FAdd, hasAllowReassoc, setHasAllowReassoc);
1005+
CHECK_FLAG(UDiv, isExact, setIsExact);
1006+
CHECK_FLAG(FAdd, hasNoNaNs, setHasNoNaNs);
1007+
CHECK_FLAG(FAdd, hasNoInfs, setHasNoInfs);
1008+
CHECK_FLAG(FAdd, hasNoSignedZeros, setHasNoSignedZeros);
1009+
CHECK_FLAG(FAdd, hasAllowReciprocal, setHasAllowReciprocal);
1010+
CHECK_FLAG(FAdd, hasAllowContract, setHasAllowContract);
1011+
CHECK_FLAG(FAdd, hasApproxFunc, setHasApproxFunc);
1012+
1013+
// Check setFastMathFlags().
1014+
FastMathFlags OrigFMF = FAdd->getFastMathFlags();
1015+
FastMathFlags NewFMF;
1016+
NewFMF.setAllowReassoc(true);
1017+
EXPECT_TRUE(NewFMF != OrigFMF);
1018+
1019+
Ctx.save();
1020+
FAdd->setFastMathFlags(NewFMF);
1021+
EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);
1022+
Ctx.revert();
1023+
EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);
1024+
1025+
// Check copyFastMathFlags().
1026+
Ctx.save();
1027+
FAdd->copyFastMathFlags(NewFMF);
1028+
EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);
1029+
Ctx.revert();
1030+
EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);
1031+
}

0 commit comments

Comments
 (0)