From af4a82e46ebfb672e17b02ac83f7a4e374b8e4de Mon Sep 17 00:00:00 2001 From: vporpo Date: Mon, 26 Aug 2024 15:31:01 -0700 Subject: [PATCH] [SandboxIR] Implement PossiblyNonNegInst (#106149) This patch implements sandboxir::PossiblyNonNegInst mirroring llvm::PossiblyNonNegInst. --- llvm/include/llvm/SandboxIR/SandboxIR.h | 23 ++++++++++++ llvm/lib/SandboxIR/SandboxIR.cpp | 7 ++++ llvm/unittests/SandboxIR/SandboxIRTest.cpp | 42 ++++++++++++++++++++++ llvm/unittests/SandboxIR/TrackerTest.cpp | 26 ++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h index 6f37f928d7614d..e4c48e39a40015 100644 --- a/llvm/include/llvm/SandboxIR/SandboxIR.h +++ b/llvm/include/llvm/SandboxIR/SandboxIR.h @@ -137,6 +137,7 @@ class CatchReturnInst; class CleanupReturnInst; class GetElementPtrInst; class CastInst; +class PossiblyNonNegInst; class PtrToIntInst; class BitCastInst; class AllocaInst; @@ -2762,6 +2763,28 @@ class CastInst : public UnaryInstruction { Type *getDestTy() const { return cast(Val)->getDestTy(); } }; +/// Instruction that can have a nneg flag (zext/uitofp). +class PossiblyNonNegInst : public CastInst { +public: + bool hasNonNeg() const { + return cast(Val)->hasNonNeg(); + } + void setNonNeg(bool B); + /// For isa/dyn_cast. + static bool classof(const Value *From) { + if (auto *I = dyn_cast(From)) { + switch (I->getOpcode()) { + case Opcode::ZExt: + case Opcode::UIToFP: + return true; + default: + return false; + } + } + return false; + } +}; + // Helper class to simplify stamping out CastInst subclasses. template class CastInstImpl : public CastInst { public: diff --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp index 2195e9f98b53b4..35b642ac7f3a22 100644 --- a/llvm/lib/SandboxIR/SandboxIR.cpp +++ b/llvm/lib/SandboxIR/SandboxIR.cpp @@ -1991,6 +1991,13 @@ bool CastInst::classof(const Value *From) { return From->getSubclassID() == ClassID::Cast; } +void PossiblyNonNegInst::setNonNeg(bool B) { + Ctx.getTracker() + .emplaceIfTracking>(this); + cast(Val)->setNonNeg(B); +} + Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx, Instruction *InsertBefore, Context &Ctx, const Twine &Name) { diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp index 6afd5f9897a829..869e752b23913f 100644 --- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp +++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp @@ -3682,6 +3682,48 @@ define void @foo(i32 %arg, float %farg, double %darg, ptr %ptr) { } } +TEST_F(SandboxIRTest, PossiblyNonNegInst) { + parseIR(C, R"IR( +define void @foo(i32 %arg, float %farg, double %darg, ptr %ptr) { + %zext = zext i32 %arg to i64 + %uitofp = uitofp i32 %arg to float + + %sext = sext i32 %arg to i64 + %fptoui = fptoui float %farg to i32 + %fptosi = fptosi float %farg to i32 + %fpext = fpext float %farg to double + %ptrtoint = ptrtoint ptr %ptr to i32 + %inttoptr = inttoptr i32 %arg to ptr + %sitofp = sitofp i32 %arg to float + %trunc = trunc i32 %arg to i16 + %fptrunc = fptrunc double %darg to float + %bitcast = bitcast i32 %arg to float + %addrspacecast = addrspacecast ptr %ptr to ptr addrspace(1) + ret void +} +)IR"); + Function &LLVMF = *M->getFunction("foo"); + sandboxir::Context Ctx(C); + sandboxir::Function *F = Ctx.createFunction(&LLVMF); + auto *BB = &*F->begin(); + auto It = BB->begin(); + auto *PNNI0 = cast(&*It++); + auto *PNNI1 = cast(&*It++); + for (auto ItE = BB->end(); It != ItE; ++It) + EXPECT_FALSE(isa(&*It++)); + + for (auto *PNNI : {PNNI0, PNNI1}) { + // Check setNonNeg(), hasNonNeg(). + auto OrigNonNeg = PNNI->hasNonNeg(); + auto NewNonNeg = true; + EXPECT_NE(NewNonNeg, OrigNonNeg); + PNNI->setNonNeg(NewNonNeg); + EXPECT_EQ(PNNI->hasNonNeg(), NewNonNeg); + PNNI->setNonNeg(OrigNonNeg); + EXPECT_EQ(PNNI->hasNonNeg(), OrigNonNeg); + } +} + /// CastInst's subclasses are very similar so we can use a common test function /// for them. template diff --git a/llvm/unittests/SandboxIR/TrackerTest.cpp b/llvm/unittests/SandboxIR/TrackerTest.cpp index 1feb04137e129c..ca6effb727bf37 100644 --- a/llvm/unittests/SandboxIR/TrackerTest.cpp +++ b/llvm/unittests/SandboxIR/TrackerTest.cpp @@ -1014,6 +1014,32 @@ define void @foo(i8 %arg0, i8 %arg1) { EXPECT_EQ(PDI->isDisjoint(), OrigIsDisjoint); } +TEST_F(TrackerTest, PossiblyNonNegInstSetters) { + parseIR(C, R"IR( +define void @foo(i32 %arg) { + %zext = zext i32 %arg to i64 + 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 *PNNI = cast(&*It++); + + // Check setNonNeg(). + auto OrigNonNeg = PNNI->hasNonNeg(); + auto NewNonNeg = true; + EXPECT_NE(NewNonNeg, OrigNonNeg); + Ctx.save(); + PNNI->setNonNeg(NewNonNeg); + EXPECT_EQ(PNNI->hasNonNeg(), NewNonNeg); + Ctx.revert(); + EXPECT_EQ(PNNI->hasNonNeg(), OrigNonNeg); +} + TEST_F(TrackerTest, AtomicRMWSetters) { parseIR(C, R"IR( define void @foo(ptr %ptr, i8 %arg) {