[llvm] [IR] Store fast-math flags in subclasses of Instruction (PR #191190)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 13 02:33:23 PDT 2026
https://github.com/paperchalice updated https://github.com/llvm/llvm-project/pull/191190
>From 56bc3157dbd28be13a7e789da71a6feea68f0a76 Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Fri, 10 Apr 2026 19:16:37 +0800
Subject: [PATCH 1/2] [IR] Store fast-math flags in subclasses of Instruction
---
llvm/include/llvm/IR/InstVisitor.h | 1 +
llvm/include/llvm/IR/InstrTypes.h | 83 ++++++++++++++++++++++---
llvm/include/llvm/IR/Instruction.def | 10 ++--
llvm/include/llvm/IR/Instruction.h | 3 +-
llvm/include/llvm/IR/Instructions.h | 14 +++--
llvm/include/llvm/IR/Operator.h | 90 ++++++++++++++++------------
llvm/lib/IR/Instruction.cpp | 11 ++--
llvm/lib/IR/Instructions.cpp | 61 +++++++++++++++----
llvm/lib/IR/Operator.cpp | 48 +++++++++++++++
9 files changed, 248 insertions(+), 73 deletions(-)
diff --git a/llvm/include/llvm/IR/InstVisitor.h b/llvm/include/llvm/IR/InstVisitor.h
index 4d5dd00b744b9..ff2b999b271a0 100644
--- a/llvm/include/llvm/IR/InstVisitor.h
+++ b/llvm/include/llvm/IR/InstVisitor.h
@@ -264,6 +264,7 @@ class InstVisitor {
RetTy visitCastInst(CastInst &I) { DELEGATE(UnaryInstruction);}
RetTy visitUnaryOperator(UnaryOperator &I) { DELEGATE(UnaryInstruction);}
RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction);}
+ RetTy visitFPBinaryOperator(FPBinaryOperator &I) { DELEGATE(BinaryOperator); }
RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction);}
RetTy visitUnaryInstruction(UnaryInstruction &I){ DELEGATE(Instruction);}
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 61dc5ebef1b1d..c8fac25d0e032 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -51,6 +51,15 @@ namespace Intrinsic {
typedef unsigned ID;
}
+/// Provide fast-math flags storage, instructions that support fast-math flags
+/// should inherit from this class.
+class FastMathFlagsStorage {
+ friend class FPMathOperator;
+
+protected:
+ unsigned short FMFValue = 0;
+};
+
//===----------------------------------------------------------------------===//
// UnaryInstruction Class
//===----------------------------------------------------------------------===//
@@ -98,7 +107,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value)
// UnaryOperator Class
//===----------------------------------------------------------------------===//
-class UnaryOperator : public UnaryInstruction {
+class UnaryOperator : public UnaryInstruction, public FastMathFlagsStorage {
void AssertOK();
protected:
@@ -203,16 +212,12 @@ class BinaryOperator : public Instruction {
/// statically know what type of instruction you're going to create. These
/// helpers just save some typing.
#define HANDLE_BINARY_INST(N, OPC, CLASS) \
- static BinaryOperator *Create##OPC(Value *V1, Value *V2, \
- const Twine &Name = "") { \
- return Create(Instruction::OPC, V1, V2, Name); \
- }
+ static inline BinaryOperator *Create##OPC(Value *V1, Value *V2, \
+ const Twine &Name = "");
#include "llvm/IR/Instruction.def"
#define HANDLE_BINARY_INST(N, OPC, CLASS) \
- static BinaryOperator *Create##OPC(Value *V1, Value *V2, const Twine &Name, \
- InsertPosition InsertBefore) { \
- return Create(Instruction::OPC, V1, V2, Name, InsertBefore); \
- }
+ static inline BinaryOperator *Create##OPC( \
+ Value *V1, Value *V2, const Twine &Name, InsertPosition InsertBefore);
#include "llvm/IR/Instruction.def"
static BinaryOperator *
@@ -435,6 +440,66 @@ BinaryOperator *BinaryOperator::CreateDisjoint(BinaryOps Opc, Value *V1,
return BO;
}
+/// Binary operators support fast-math flags, users should not use this
+/// class directly, BinaryOperator can automatic create instructions with
+/// correct type.
+class FPBinaryOperator : public BinaryOperator, public FastMathFlagsStorage {
+ friend class Instruction;
+ friend class BinaryOperator;
+ LLVM_ABI FPBinaryOperator *cloneImpl() const;
+ using BinaryOperator::BinaryOperator;
+
+ LLVM_ABI static FPBinaryOperator *
+ Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name = Twine(),
+ InsertPosition InsertBefore = nullptr);
+
+public:
+ static bool classof(const Instruction *I) {
+ switch (I->getOpcode()) {
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FMul:
+ case Instruction::FDiv:
+ case Instruction::FRem:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ static bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+};
+
+#define HANDLE_BINARY_INST(N, OPC, CLASS) \
+ BinaryOperator *BinaryOperator::Create##OPC(Value *V1, Value *V2, \
+ const Twine &Name) { \
+ if constexpr (Instruction::OPC == Instruction::FAdd || \
+ Instruction::OPC == Instruction::FSub || \
+ Instruction::OPC == Instruction::FMul || \
+ Instruction::OPC == Instruction::FDiv || \
+ Instruction::OPC == Instruction::FRem) \
+ return FPBinaryOperator::Create(Instruction::OPC, V1, V2, Name); \
+ else \
+ return Create(Instruction::OPC, V1, V2, Name); \
+ }
+#include "llvm/IR/Instruction.def"
+#define HANDLE_BINARY_INST(N, OPC, CLASS) \
+ BinaryOperator *BinaryOperator::Create##OPC( \
+ Value *V1, Value *V2, const Twine &Name, InsertPosition InsertBefore) { \
+ if constexpr (Instruction::OPC == Instruction::FAdd || \
+ Instruction::OPC == Instruction::FSub || \
+ Instruction::OPC == Instruction::FMul || \
+ Instruction::OPC == Instruction::FDiv || \
+ Instruction::OPC == Instruction::FRem) \
+ return FPBinaryOperator::Create(Instruction::OPC, V1, V2, Name, \
+ InsertBefore); \
+ else \
+ return Create(Instruction::OPC, V1, V2, Name, InsertBefore); \
+ }
+#include "llvm/IR/Instruction.def"
+
//===----------------------------------------------------------------------===//
// CastInst Class
//===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/IR/Instruction.def b/llvm/include/llvm/IR/Instruction.def
index 89d214868e16b..c1c008d634616 100644
--- a/llvm/include/llvm/IR/Instruction.def
+++ b/llvm/include/llvm/IR/Instruction.def
@@ -146,17 +146,17 @@ HANDLE_UNARY_INST(13, FNeg , UnaryOperator)
// Standard binary operators...
FIRST_BINARY_INST(14)
HANDLE_BINARY_INST(14, Add , BinaryOperator)
-HANDLE_BINARY_INST(15, FAdd , BinaryOperator)
+HANDLE_BINARY_INST(15, FAdd , FPBinaryOperator)
HANDLE_BINARY_INST(16, Sub , BinaryOperator)
-HANDLE_BINARY_INST(17, FSub , BinaryOperator)
+HANDLE_BINARY_INST(17, FSub , FPBinaryOperator)
HANDLE_BINARY_INST(18, Mul , BinaryOperator)
-HANDLE_BINARY_INST(19, FMul , BinaryOperator)
+HANDLE_BINARY_INST(19, FMul , FPBinaryOperator)
HANDLE_BINARY_INST(20, UDiv , BinaryOperator)
HANDLE_BINARY_INST(21, SDiv , BinaryOperator)
-HANDLE_BINARY_INST(22, FDiv , BinaryOperator)
+HANDLE_BINARY_INST(22, FDiv , FPBinaryOperator)
HANDLE_BINARY_INST(23, URem , BinaryOperator)
HANDLE_BINARY_INST(24, SRem , BinaryOperator)
-HANDLE_BINARY_INST(25, FRem , BinaryOperator)
+HANDLE_BINARY_INST(25, FRem , FPBinaryOperator)
// Logical operators (integer operands)
HANDLE_BINARY_INST(26, Shl , BinaryOperator) // Shift left (logical)
diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index 0b57ad4d0a379..379eca2fd43a6 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -712,7 +712,8 @@ class Instruction : public User,
/// Convenience method to copy supported exact, fast-math, and (optionally)
/// wrapping flags from V to this instruction.
- LLVM_ABI void copyIRFlags(const Value *V, bool IncludeWrapFlags = true);
+ LLVM_ABI void copyIRFlags(const Value *V, bool IncludeWrapFlags = true,
+ bool IncludeFastMathFlags = true);
/// Logical 'and' of any supported wrapping, exact, and fast-math flags of
/// V and this instruction.
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index f4fa59ada9d05..2fa49b6fc4e28 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -1418,7 +1418,7 @@ class ICmpInst: public CmpInst {
/// to the constructor. It only operates on floating point values or packed
/// vectors of floating point values. The operands must be identical types.
/// Represents a floating point comparison operator.
-class FCmpInst: public CmpInst {
+class FCmpInst : public CmpInst, public FastMathFlagsStorage {
void AssertOK() {
assert(isFPPredicate() && "Invalid FCmp predicate value");
assert(getOperand(0)->getType() == getOperand(1)->getType() &&
@@ -1456,6 +1456,8 @@ class FCmpInst: public CmpInst {
Instruction *FlagsSource = nullptr)
: CmpInst(makeCmpResultType(LHS->getType()), Instruction::FCmp, Pred, LHS,
RHS, NameStr, nullptr, FlagsSource) {
+ if (FlagsSource)
+ copyFastMathFlags(FlagsSource);
AssertOK();
}
@@ -1518,7 +1520,7 @@ class FCmpInst: public CmpInst {
/// field to indicate whether or not this is a tail call. The rest of the bits
/// hold the calling convention of the call.
///
-class CallInst : public CallBase {
+class CallInst : public CallBase, public FastMathFlagsStorage {
CallInst(const CallInst &CI, AllocInfo AllocInfo);
/// Construct a CallInst from a range of arguments
@@ -1697,7 +1699,7 @@ CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args,
/// This class represents the LLVM 'select' instruction.
///
-class SelectInst : public Instruction {
+class SelectInst : public Instruction, public FastMathFlagsStorage {
constexpr static IntrusiveOperandsAllocMarker AllocMarker{3};
SelectInst(Value *C, Value *S1, Value *S2, const Twine &NameStr,
@@ -2648,7 +2650,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value)
// node, that can not exist in nature, but can be synthesized in a computer
// scientist's overactive imagination.
//
-class PHINode : public Instruction {
+class PHINode : public Instruction, public FastMathFlagsStorage {
constexpr static HungOffOperandsAllocMarker AllocMarker{};
/// The number of operands actually allocated. NumOperands is
@@ -4878,7 +4880,7 @@ class SExtInst : public CastInst {
//===----------------------------------------------------------------------===//
/// This class represents a truncation of floating point types.
-class FPTruncInst : public CastInst {
+class FPTruncInst : public CastInst, public FastMathFlagsStorage {
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
@@ -4909,7 +4911,7 @@ class FPTruncInst : public CastInst {
//===----------------------------------------------------------------------===//
/// This class represents an extension of floating point types.
-class FPExtInst : public CastInst {
+class FPExtInst : public CastInst, public FastMathFlagsStorage {
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h
index 2e0e71cbbf315..89f6b1f5ea1c6 100644
--- a/llvm/include/llvm/IR/Operator.h
+++ b/llvm/include/llvm/IR/Operator.h
@@ -201,6 +201,9 @@ class FPMathOperator : public Operator {
private:
friend class Instruction;
+ unsigned short &getFMFValue();
+ unsigned short getFMFValue() const;
+
/// 'Fast' means all bits are set.
void setFast(bool B) {
setHasAllowReassoc(B);
@@ -213,57 +216,59 @@ class FPMathOperator : public Operator {
}
void setHasAllowReassoc(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::AllowReassoc) |
- (B * FastMathFlags::AllowReassoc);
+ unsigned short &FMFValue = getFMFValue();
+ FMFValue = (FMFValue & ~FastMathFlags::AllowReassoc) |
+ (B * FastMathFlags::AllowReassoc);
}
void setHasNoNaNs(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::NoNaNs) |
- (B * FastMathFlags::NoNaNs);
+ unsigned short &FMFValue = getFMFValue();
+ FMFValue =
+ (FMFValue & ~FastMathFlags::NoNaNs) | (B * FastMathFlags::NoNaNs);
}
void setHasNoInfs(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::NoInfs) |
- (B * FastMathFlags::NoInfs);
+ unsigned short &FMFValue = getFMFValue();
+ FMFValue =
+ (FMFValue & ~FastMathFlags::NoInfs) | (B * FastMathFlags::NoInfs);
}
void setHasNoSignedZeros(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) |
- (B * FastMathFlags::NoSignedZeros);
+ unsigned short &FMFValue = getFMFValue();
+ FMFValue = (FMFValue & ~FastMathFlags::NoSignedZeros) |
+ (B * FastMathFlags::NoSignedZeros);
}
void setHasAllowReciprocal(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) |
- (B * FastMathFlags::AllowReciprocal);
+ unsigned short &FMFValue = getFMFValue();
+ FMFValue = (FMFValue & ~FastMathFlags::AllowReciprocal) |
+ (B * FastMathFlags::AllowReciprocal);
}
void setHasAllowContract(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::AllowContract) |
- (B * FastMathFlags::AllowContract);
+ unsigned short &FMFValue = getFMFValue();
+ FMFValue = (FMFValue & ~FastMathFlags::AllowContract) |
+ (B * FastMathFlags::AllowContract);
}
void setHasApproxFunc(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::ApproxFunc) |
- (B * FastMathFlags::ApproxFunc);
+ unsigned short &FMFValue = getFMFValue();
+ FMFValue = (FMFValue & ~FastMathFlags::ApproxFunc) |
+ (B * FastMathFlags::ApproxFunc);
}
/// Convenience function for setting multiple fast-math flags.
/// FMF is a mask of the bits to set.
void setFastMathFlags(FastMathFlags FMF) {
- SubclassOptionalData |= FMF.Flags;
+ unsigned short &FMFValue = getFMFValue();
+ FMFValue |= FMF.Flags;
}
/// Convenience function for copying all fast-math flags.
/// All values in FMF are transferred to this operator.
void copyFastMathFlags(FastMathFlags FMF) {
- SubclassOptionalData = FMF.Flags;
+ unsigned short &FMFValue = getFMFValue();
+ FMFValue = FMF.Flags;
}
/// Returns true if `Ty` is composed of a single kind of float-poing type
@@ -284,54 +289,63 @@ class FPMathOperator : public Operator {
public:
/// Test if this operation allows all non-strict floating-point transforms.
bool isFast() const {
- return ((SubclassOptionalData & FastMathFlags::AllowReassoc) != 0 &&
- (SubclassOptionalData & FastMathFlags::NoNaNs) != 0 &&
- (SubclassOptionalData & FastMathFlags::NoInfs) != 0 &&
- (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0 &&
- (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0 &&
- (SubclassOptionalData & FastMathFlags::AllowContract) != 0 &&
- (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0);
+ unsigned short FMFValue = getFMFValue();
+ return ((FMFValue & FastMathFlags::AllowReassoc) != 0 &&
+ (FMFValue & FastMathFlags::NoNaNs) != 0 &&
+ (FMFValue & FastMathFlags::NoInfs) != 0 &&
+ (FMFValue & FastMathFlags::NoSignedZeros) != 0 &&
+ (FMFValue & FastMathFlags::AllowReciprocal) != 0 &&
+ (FMFValue & FastMathFlags::AllowContract) != 0 &&
+ (FMFValue & FastMathFlags::ApproxFunc) != 0);
}
/// Test if this operation may be simplified with reassociative transforms.
bool hasAllowReassoc() const {
- return (SubclassOptionalData & FastMathFlags::AllowReassoc) != 0;
+ unsigned short FMFValue = getFMFValue();
+ return (FMFValue & FastMathFlags::AllowReassoc) != 0;
}
/// Test if this operation's arguments and results are assumed not-NaN.
bool hasNoNaNs() const {
- return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0;
+ unsigned short FMFValue = getFMFValue();
+ return (FMFValue & FastMathFlags::NoNaNs) != 0;
}
/// Test if this operation's arguments and results are assumed not-infinite.
bool hasNoInfs() const {
- return (SubclassOptionalData & FastMathFlags::NoInfs) != 0;
+ unsigned short FMFValue = getFMFValue();
+ return (FMFValue & FastMathFlags::NoInfs) != 0;
}
/// Test if this operation can ignore the sign of zero.
bool hasNoSignedZeros() const {
- return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0;
+ unsigned short FMFValue = getFMFValue();
+ return (FMFValue & FastMathFlags::NoSignedZeros) != 0;
}
/// Test if this operation can use reciprocal multiply instead of division.
bool hasAllowReciprocal() const {
- return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0;
+ unsigned short FMFValue = getFMFValue();
+ return (FMFValue & FastMathFlags::AllowReciprocal) != 0;
}
/// Test if this operation can be floating-point contracted (FMA).
bool hasAllowContract() const {
- return (SubclassOptionalData & FastMathFlags::AllowContract) != 0;
+ unsigned short FMFValue = getFMFValue();
+ return (FMFValue & FastMathFlags::AllowContract) != 0;
}
/// Test if this operation allows approximations of math library functions or
/// intrinsics.
bool hasApproxFunc() const {
- return (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0;
+ unsigned short FMFValue = getFMFValue();
+ return (FMFValue & FastMathFlags::ApproxFunc) != 0;
}
/// Convenience function for getting all the fast-math flags
FastMathFlags getFastMathFlags() const {
- return FastMathFlags(SubclassOptionalData);
+ unsigned short FMFValue = getFMFValue();
+ return FastMathFlags(FMFValue);
}
/// Get the maximum error permitted by this operation in ULPs. An accuracy of
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index 8aa19a436a157..1974634dffbcb 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -708,7 +708,8 @@ void Instruction::copyFastMathFlags(const Instruction *I) {
copyFastMathFlags(I->getFastMathFlags());
}
-void Instruction::copyIRFlags(const Value *V, bool IncludeWrapFlags) {
+void Instruction::copyIRFlags(const Value *V, bool IncludeWrapFlags,
+ bool IncludeFastMathFlags) {
// Copy the wrapping flags.
if (IncludeWrapFlags && isa<OverflowingBinaryOperator>(this)) {
if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
@@ -734,9 +735,11 @@ void Instruction::copyIRFlags(const Value *V, bool IncludeWrapFlags) {
DestPD->setIsDisjoint(SrcPD->isDisjoint());
// Copy the fast-math flags.
- if (auto *FP = dyn_cast<FPMathOperator>(V))
- if (isa<FPMathOperator>(this))
- copyFastMathFlags(FP->getFastMathFlags());
+ if (IncludeFastMathFlags) {
+ if (auto *FP = dyn_cast<FPMathOperator>(V))
+ if (isa<FPMathOperator>(this))
+ copyFastMathFlags(FP->getFastMathFlags());
+ }
if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(V))
if (auto *DestGEP = dyn_cast<GetElementPtrInst>(this))
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 8a220c48acac8..2fd8758698b88 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -802,6 +802,7 @@ CallInst::CallInst(const CallInst &CI, AllocInfo AllocInfo)
std::copy(CI.bundle_op_info_begin(), CI.bundle_op_info_end(),
bundle_op_info_begin());
SubclassOptionalData = CI.SubclassOptionalData;
+ FMFValue = CI.FMFValue;
}
CallInst *CallInst::Create(CallInst *CI, ArrayRef<OperandBundleDef> OpB,
@@ -813,6 +814,7 @@ CallInst *CallInst::Create(CallInst *CI, ArrayRef<OperandBundleDef> OpB,
NewCI->setTailCallKind(CI->getTailCallKind());
NewCI->setCallingConv(CI->getCallingConv());
NewCI->SubclassOptionalData = CI->SubclassOptionalData;
+ NewCI->FMFValue = CI->FMFValue;
NewCI->setAttributes(CI->getAttributes());
NewCI->setDebugLoc(CI->getDebugLoc());
return NewCI;
@@ -2717,7 +2719,11 @@ BinaryOperator *BinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
InsertPosition InsertBefore) {
assert(S1->getType() == S2->getType() &&
"Cannot create binary operator with two operands of differing type!");
- return new BinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
+ return FPMathOperator::isSupportedFloatingPointType(S1->getType())
+ ? new FPBinaryOperator(Op, S1, S2, S1->getType(), Name,
+ InsertBefore)
+ : new BinaryOperator(Op, S1, S2, S1->getType(), Name,
+ InsertBefore);
}
BinaryOperator *BinaryOperator::CreateNeg(Value *Op, const Twine &Name,
@@ -2750,6 +2756,14 @@ bool BinaryOperator::swapOperands() {
return false;
}
+FPBinaryOperator *FPBinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
+ const Twine &Name,
+ InsertPosition InsertBefore) {
+ assert(S1->getType() == S2->getType() &&
+ "Cannot create binary operator with two operands of differing type!");
+ return new FPBinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
+}
+
//===----------------------------------------------------------------------===//
// FPMathOperator Class
//===----------------------------------------------------------------------===//
@@ -3532,7 +3546,8 @@ CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS,
setPredicate(predicate);
setName(Name);
if (FlagsSource)
- copyIRFlags(FlagsSource);
+ copyIRFlags(FlagsSource, /*IncludeWrapFlags=*/true,
+ /*IncludeFastMathFlags=*/false);
}
CmpInst *CmpInst::Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2,
@@ -4346,15 +4361,27 @@ GetElementPtrInst *GetElementPtrInst::cloneImpl() const {
}
UnaryOperator *UnaryOperator::cloneImpl() const {
- return Create(getOpcode(), Op<0>());
+ auto *I = Create(getOpcode(), Op<0>());
+ I->FMFValue = FMFValue;
+ return I;
}
BinaryOperator *BinaryOperator::cloneImpl() const {
+ if (auto *I = dyn_cast<FPBinaryOperator>(this))
+ return I->cloneImpl();
return Create(getOpcode(), Op<0>(), Op<1>());
}
+FPBinaryOperator *FPBinaryOperator::cloneImpl() const {
+ FPBinaryOperator *I = Create(getOpcode(), Op<0>(), Op<1>());
+ I->FMFValue = FMFValue;
+ return I;
+}
+
FCmpInst *FCmpInst::cloneImpl() const {
- return new FCmpInst(getPredicate(), Op<0>(), Op<1>());
+ auto *I = new FCmpInst(getPredicate(), Op<0>(), Op<1>());
+ I->FMFValue = FMFValue;
+ return I;
}
ICmpInst *ICmpInst::cloneImpl() const {
@@ -4421,11 +4448,15 @@ SExtInst *SExtInst::cloneImpl() const {
}
FPTruncInst *FPTruncInst::cloneImpl() const {
- return new FPTruncInst(getOperand(0), getType());
+ auto *I = new FPTruncInst(getOperand(0), getType());
+ I->FMFValue = FMFValue;
+ return I;
}
FPExtInst *FPExtInst::cloneImpl() const {
- return new FPExtInst(getOperand(0), getType());
+ auto *I = new FPExtInst(getOperand(0), getType());
+ I->FMFValue = FMFValue;
+ return I;
}
UIToFPInst *UIToFPInst::cloneImpl() const {
@@ -4469,14 +4500,20 @@ CallInst *CallInst::cloneImpl() const {
IntrusiveOperandsAndDescriptorAllocMarker AllocMarker{
getNumOperands(),
getNumOperandBundles() * unsigned(sizeof(BundleOpInfo))};
- return new (AllocMarker) CallInst(*this, AllocMarker);
+ auto *I = new (AllocMarker) CallInst(*this, AllocMarker);
+ I->FMFValue = FMFValue;
+ return I;
}
IntrusiveOperandsAllocMarker AllocMarker{getNumOperands()};
- return new (AllocMarker) CallInst(*this, AllocMarker);
+ auto *I = new (AllocMarker) CallInst(*this, AllocMarker);
+ I->FMFValue = FMFValue;
+ return I;
}
SelectInst *SelectInst::cloneImpl() const {
- return SelectInst::Create(getOperand(0), getOperand(1), getOperand(2));
+ auto *I = SelectInst::Create(getOperand(0), getOperand(1), getOperand(2));
+ I->FMFValue = FMFValue;
+ return I;
}
VAArgInst *VAArgInst::cloneImpl() const {
@@ -4495,7 +4532,11 @@ ShuffleVectorInst *ShuffleVectorInst::cloneImpl() const {
return new ShuffleVectorInst(getOperand(0), getOperand(1), getShuffleMask());
}
-PHINode *PHINode::cloneImpl() const { return new (AllocMarker) PHINode(*this); }
+PHINode *PHINode::cloneImpl() const {
+ auto *I = new (AllocMarker) PHINode(*this);
+ I->FMFValue = FMFValue;
+ return I;
+}
LandingPadInst *LandingPadInst::cloneImpl() const {
return new LandingPadInst(*this);
diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp
index bd92a32142ebc..67ced0c2714eb 100644
--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -300,3 +300,51 @@ void FastMathFlags::print(raw_ostream &O) const {
O << " afn";
}
}
+
+unsigned short &FPMathOperator::getFMFValue() {
+ auto *V = static_cast<Value *>(this);
+ auto *I = dyn_cast<Instruction>(V);
+
+ if (FastMathFlagsStorage *Op = dyn_cast<UnaryOperator>(I))
+ return Op->FMFValue;
+ if (FastMathFlagsStorage *Op = dyn_cast<FPBinaryOperator>(I))
+ return Op->FMFValue;
+ if (FastMathFlagsStorage *Op = dyn_cast<FPTruncInst>(I))
+ return Op->FMFValue;
+ if (FastMathFlagsStorage *Op = dyn_cast<FPExtInst>(I))
+ return Op->FMFValue;
+ if (FastMathFlagsStorage *Op = dyn_cast<FCmpInst>(I))
+ return Op->FMFValue;
+ if (FastMathFlagsStorage *Op = dyn_cast<PHINode>(I))
+ return Op->FMFValue;
+ if (FastMathFlagsStorage *Op = dyn_cast<SelectInst>(I))
+ return Op->FMFValue;
+ if (FastMathFlagsStorage *Op = dyn_cast<CallInst>(I))
+ return Op->FMFValue;
+
+ llvm_unreachable("Unknown FPMathOperator!");
+}
+
+unsigned short FPMathOperator::getFMFValue() const {
+ const auto *V = static_cast<const Value *>(this);
+ const auto *I = dyn_cast<Instruction>(V);
+
+ if (const FastMathFlagsStorage *Op = dyn_cast<UnaryOperator>(I))
+ return Op->FMFValue;
+ if (const FastMathFlagsStorage *Op = dyn_cast<FPBinaryOperator>(I))
+ return Op->FMFValue;
+ if (const FastMathFlagsStorage *Op = dyn_cast<FPTruncInst>(I))
+ return Op->FMFValue;
+ if (const FastMathFlagsStorage *Op = dyn_cast<FPExtInst>(I))
+ return Op->FMFValue;
+ if (const FastMathFlagsStorage *Op = dyn_cast<FCmpInst>(I))
+ return Op->FMFValue;
+ if (const FastMathFlagsStorage *Op = dyn_cast<PHINode>(I))
+ return Op->FMFValue;
+ if (const FastMathFlagsStorage *Op = dyn_cast<SelectInst>(I))
+ return Op->FMFValue;
+ if (const FastMathFlagsStorage *Op = dyn_cast<CallInst>(I))
+ return Op->FMFValue;
+
+ llvm_unreachable("Unknown FPMathOperator!");
+}
\ No newline at end of file
>From 6bd72d7537d8d1c0bcec267cecc05ab50a29e034 Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Mon, 13 Apr 2026 17:33:04 +0800
Subject: [PATCH 2/2] address some comments * add FPUnaryOperator * Use
BinaryOperator::Create only * add missing newline
---
llvm/include/llvm/IR/InstVisitor.h | 1 +
llvm/include/llvm/IR/InstrTypes.h | 73 ++++++++++++++--------------
llvm/include/llvm/IR/Instruction.def | 2 +-
llvm/lib/IR/Instructions.cpp | 43 +++++++++-------
llvm/lib/IR/Operator.cpp | 14 +++---
5 files changed, 70 insertions(+), 63 deletions(-)
diff --git a/llvm/include/llvm/IR/InstVisitor.h b/llvm/include/llvm/IR/InstVisitor.h
index ff2b999b271a0..45b2e59510b67 100644
--- a/llvm/include/llvm/IR/InstVisitor.h
+++ b/llvm/include/llvm/IR/InstVisitor.h
@@ -263,6 +263,7 @@ class InstVisitor {
//
RetTy visitCastInst(CastInst &I) { DELEGATE(UnaryInstruction);}
RetTy visitUnaryOperator(UnaryOperator &I) { DELEGATE(UnaryInstruction);}
+ RetTy visitFPUnaryOperator(FPUnaryOperator &I) { DELEGATE(UnaryOperator); }
RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction);}
RetTy visitFPBinaryOperator(FPBinaryOperator &I) { DELEGATE(BinaryOperator); }
RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction);}
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index c8fac25d0e032..39fc4765b452d 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -107,7 +107,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value)
// UnaryOperator Class
//===----------------------------------------------------------------------===//
-class UnaryOperator : public UnaryInstruction, public FastMathFlagsStorage {
+class UnaryOperator : public UnaryInstruction {
void AssertOK();
protected:
@@ -173,6 +173,32 @@ class UnaryOperator : public UnaryInstruction, public FastMathFlagsStorage {
}
};
+/// Unary operators support fast-math flags, users should not use this
+/// class directly, Unary can automatic create instructions with
+/// correct type.
+class FPUnaryOperator : public UnaryOperator, public FastMathFlagsStorage {
+ // Note: Instruction needs to be a friend here to call cloneImpl.
+ friend class Instruction;
+ friend class UnaryOperator;
+ using UnaryOperator::UnaryOperator;
+
+ LLVM_ABI FPUnaryOperator *cloneImpl() const;
+
+public:
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static bool classof(const Instruction *I) {
+ switch (I->getOpcode()) {
+ case Instruction::FNeg:
+ return true;
+ default:
+ return false;
+ }
+ }
+ static bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+};
+
//===----------------------------------------------------------------------===//
// BinaryOperator Class
//===----------------------------------------------------------------------===//
@@ -212,12 +238,16 @@ class BinaryOperator : public Instruction {
/// statically know what type of instruction you're going to create. These
/// helpers just save some typing.
#define HANDLE_BINARY_INST(N, OPC, CLASS) \
- static inline BinaryOperator *Create##OPC(Value *V1, Value *V2, \
- const Twine &Name = "");
+ static BinaryOperator *Create##OPC(Value *V1, Value *V2, \
+ const Twine &Name = "") { \
+ return Create(Instruction::OPC, V1, V2, Name); \
+ }
#include "llvm/IR/Instruction.def"
#define HANDLE_BINARY_INST(N, OPC, CLASS) \
- static inline BinaryOperator *Create##OPC( \
- Value *V1, Value *V2, const Twine &Name, InsertPosition InsertBefore);
+ static BinaryOperator *Create##OPC(Value *V1, Value *V2, const Twine &Name, \
+ InsertPosition InsertBefore) { \
+ return Create(Instruction::OPC, V1, V2, Name, InsertBefore); \
+ }
#include "llvm/IR/Instruction.def"
static BinaryOperator *
@@ -444,15 +474,12 @@ BinaryOperator *BinaryOperator::CreateDisjoint(BinaryOps Opc, Value *V1,
/// class directly, BinaryOperator can automatic create instructions with
/// correct type.
class FPBinaryOperator : public BinaryOperator, public FastMathFlagsStorage {
+ // Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
friend class BinaryOperator;
LLVM_ABI FPBinaryOperator *cloneImpl() const;
using BinaryOperator::BinaryOperator;
- LLVM_ABI static FPBinaryOperator *
- Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name = Twine(),
- InsertPosition InsertBefore = nullptr);
-
public:
static bool classof(const Instruction *I) {
switch (I->getOpcode()) {
@@ -472,34 +499,6 @@ class FPBinaryOperator : public BinaryOperator, public FastMathFlagsStorage {
}
};
-#define HANDLE_BINARY_INST(N, OPC, CLASS) \
- BinaryOperator *BinaryOperator::Create##OPC(Value *V1, Value *V2, \
- const Twine &Name) { \
- if constexpr (Instruction::OPC == Instruction::FAdd || \
- Instruction::OPC == Instruction::FSub || \
- Instruction::OPC == Instruction::FMul || \
- Instruction::OPC == Instruction::FDiv || \
- Instruction::OPC == Instruction::FRem) \
- return FPBinaryOperator::Create(Instruction::OPC, V1, V2, Name); \
- else \
- return Create(Instruction::OPC, V1, V2, Name); \
- }
-#include "llvm/IR/Instruction.def"
-#define HANDLE_BINARY_INST(N, OPC, CLASS) \
- BinaryOperator *BinaryOperator::Create##OPC( \
- Value *V1, Value *V2, const Twine &Name, InsertPosition InsertBefore) { \
- if constexpr (Instruction::OPC == Instruction::FAdd || \
- Instruction::OPC == Instruction::FSub || \
- Instruction::OPC == Instruction::FMul || \
- Instruction::OPC == Instruction::FDiv || \
- Instruction::OPC == Instruction::FRem) \
- return FPBinaryOperator::Create(Instruction::OPC, V1, V2, Name, \
- InsertBefore); \
- else \
- return Create(Instruction::OPC, V1, V2, Name, InsertBefore); \
- }
-#include "llvm/IR/Instruction.def"
-
//===----------------------------------------------------------------------===//
// CastInst Class
//===----------------------------------------------------------------------===//
diff --git a/llvm/include/llvm/IR/Instruction.def b/llvm/include/llvm/IR/Instruction.def
index c1c008d634616..949a9d0beecb4 100644
--- a/llvm/include/llvm/IR/Instruction.def
+++ b/llvm/include/llvm/IR/Instruction.def
@@ -140,7 +140,7 @@ HANDLE_TERM_INST (12, CallBr , CallBrInst) // A call-site terminator
// Standard unary operators...
FIRST_UNARY_INST(13)
-HANDLE_UNARY_INST(13, FNeg , UnaryOperator)
+HANDLE_UNARY_INST(13, FNeg , FPUnaryOperator)
LAST_UNARY_INST(13)
// Standard binary operators...
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 2fd8758698b88..5d2d5bcaa64cb 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -2613,7 +2613,12 @@ UnaryOperator::UnaryOperator(UnaryOps iType, Value *S, Type *Ty,
UnaryOperator *UnaryOperator::Create(UnaryOps Op, Value *S, const Twine &Name,
InsertPosition InsertBefore) {
- return new UnaryOperator(Op, S, S->getType(), Name, InsertBefore);
+ switch (Op) {
+ case UnaryOps::FNeg:
+ return new FPUnaryOperator(Op, S, S->getType(), Name, InsertBefore);
+ default:
+ return new UnaryOperator(Op, S, S->getType(), Name, InsertBefore);
+ }
}
void UnaryOperator::AssertOK() {
@@ -2719,11 +2724,16 @@ BinaryOperator *BinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
InsertPosition InsertBefore) {
assert(S1->getType() == S2->getType() &&
"Cannot create binary operator with two operands of differing type!");
- return FPMathOperator::isSupportedFloatingPointType(S1->getType())
- ? new FPBinaryOperator(Op, S1, S2, S1->getType(), Name,
- InsertBefore)
- : new BinaryOperator(Op, S1, S2, S1->getType(), Name,
- InsertBefore);
+ switch (Op) {
+ case BinaryOps::FAdd:
+ case BinaryOps::FSub:
+ case BinaryOps::FMul:
+ case BinaryOps::FDiv:
+ case BinaryOps::FRem:
+ return new FPBinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
+ default:
+ return new BinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
+ }
}
BinaryOperator *BinaryOperator::CreateNeg(Value *Op, const Twine &Name,
@@ -2756,14 +2766,6 @@ bool BinaryOperator::swapOperands() {
return false;
}
-FPBinaryOperator *FPBinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
- const Twine &Name,
- InsertPosition InsertBefore) {
- assert(S1->getType() == S2->getType() &&
- "Cannot create binary operator with two operands of differing type!");
- return new FPBinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
-}
-
//===----------------------------------------------------------------------===//
// FPMathOperator Class
//===----------------------------------------------------------------------===//
@@ -4361,19 +4363,24 @@ GetElementPtrInst *GetElementPtrInst::cloneImpl() const {
}
UnaryOperator *UnaryOperator::cloneImpl() const {
- auto *I = Create(getOpcode(), Op<0>());
+ return Create(getOpcode(), Op<0>());
+}
+
+FPUnaryOperator *FPUnaryOperator::cloneImpl() const {
+ auto *I = static_cast<FPUnaryOperator *>(Create(getOpcode(), Op<0>()));
I->FMFValue = FMFValue;
return I;
}
BinaryOperator *BinaryOperator::cloneImpl() const {
- if (auto *I = dyn_cast<FPBinaryOperator>(this))
- return I->cloneImpl();
+ assert(!isa<FPBinaryOperator>(this) &&
+ "Should call FPBinaryOperator::cloneImpl!");
return Create(getOpcode(), Op<0>(), Op<1>());
}
FPBinaryOperator *FPBinaryOperator::cloneImpl() const {
- FPBinaryOperator *I = Create(getOpcode(), Op<0>(), Op<1>());
+ auto *I =
+ static_cast<FPBinaryOperator *>(Create(getOpcode(), Op<0>(), Op<1>()));
I->FMFValue = FMFValue;
return I;
}
diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp
index 67ced0c2714eb..b232cdc7eb583 100644
--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -302,10 +302,10 @@ void FastMathFlags::print(raw_ostream &O) const {
}
unsigned short &FPMathOperator::getFMFValue() {
- auto *V = static_cast<Value *>(this);
- auto *I = dyn_cast<Instruction>(V);
+ Value *V = this;
+ auto *I = cast<Instruction>(V);
- if (FastMathFlagsStorage *Op = dyn_cast<UnaryOperator>(I))
+ if (FastMathFlagsStorage *Op = dyn_cast<FPUnaryOperator>(I))
return Op->FMFValue;
if (FastMathFlagsStorage *Op = dyn_cast<FPBinaryOperator>(I))
return Op->FMFValue;
@@ -326,10 +326,10 @@ unsigned short &FPMathOperator::getFMFValue() {
}
unsigned short FPMathOperator::getFMFValue() const {
- const auto *V = static_cast<const Value *>(this);
- const auto *I = dyn_cast<Instruction>(V);
+ const Value *V = this;
+ const auto *I = cast<Instruction>(V);
- if (const FastMathFlagsStorage *Op = dyn_cast<UnaryOperator>(I))
+ if (const FastMathFlagsStorage *Op = dyn_cast<FPUnaryOperator>(I))
return Op->FMFValue;
if (const FastMathFlagsStorage *Op = dyn_cast<FPBinaryOperator>(I))
return Op->FMFValue;
@@ -347,4 +347,4 @@ unsigned short FPMathOperator::getFMFValue() const {
return Op->FMFValue;
llvm_unreachable("Unknown FPMathOperator!");
-}
\ No newline at end of file
+}
More information about the llvm-commits
mailing list