[llvm] [CodeGen] Represent ISD::ArgFlagsTy flags as a bitmask (NFC) (PR #217548)
Cullen Rhodes via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 00:49:42 PDT 2026
https://github.com/c-rhodes created https://github.com/llvm/llvm-project/pull/217548
ArgFlagsTy's individual bitfields cannot express whole-set queries, such as checking that Pointer is the only flag set. Store them in a mask similar to FastMathFlags and MachineMemOperand while preserving the existing APIs.
Assisted-by: codex
>From c8fda875fe34fdd5e99d17b6f277dc6e8039e790 Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Wed, 19 Aug 2026 08:26:52 +0000
Subject: [PATCH] [CodeGen] Represent ISD::ArgFlagsTy flags as a bitmask (NFC)
ArgFlagsTy's individual bitfields cannot express whole-set queries, such
as checking that Pointer is the only flag set. Store them in a mask
similar to FastMathFlags and MachineMemOperand while preserving the
existing APIs.
Assisted-by: codex
---
llvm/include/llvm/CodeGen/TargetCallingConv.h | 201 ++++++++++--------
1 file changed, 113 insertions(+), 88 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetCallingConv.h b/llvm/include/llvm/CodeGen/TargetCallingConv.h
index f197c7f1645ec..d92979c80db20 100644
--- a/llvm/include/llvm/CodeGen/TargetCallingConv.h
+++ b/llvm/include/llvm/CodeGen/TargetCallingConv.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CODEGEN_TARGETCALLINGCONV_H
#define LLVM_CODEGEN_TARGETCALLINGCONV_H
+#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/Support/Alignment.h"
@@ -25,130 +26,145 @@ namespace llvm {
namespace ISD {
struct ArgFlagsTy {
+ public:
+ /// Flag bits describing an argument.
+ enum Flags : uint32_t {
+ NoFlags = 0,
+ ZExt = 1U << 0, ///< Zero extended
+ SExt = 1U << 1, ///< Sign extended
+ NoExt = 1U << 2, ///< No extension
+ InReg = 1U << 3, ///< Passed in register
+ SRet = 1U << 4, ///< Hidden struct-ret ptr
+ ByVal = 1U << 5, ///< Struct passed by value
+ ByRef = 1U << 6, ///< Passed in memory
+ Nest = 1U << 7, ///< Nested fn static chain
+ Returned = 1U << 8, ///< Always returned
+ Split = 1U << 9,
+ InAlloca = 1U << 10, ///< Passed with inalloca
+ Preallocated = 1U << 11, ///< ByVal without the copy
+ SplitEnd = 1U << 12, ///< Last part of a split
+ SwiftSelf = 1U << 13, ///< Swift self parameter
+ SwiftAsync = 1U << 14, ///< Swift async context parameter
+ SwiftError = 1U << 15, ///< Swift error parameter
+ CFGuardTarget = 1U << 16, ///< Control Flow Guard target
+ Hva = 1U << 17, ///< HVA field
+ HvaStart = 1U << 18, ///< HVA structure start
+ SecArgPass = 1U << 19, ///< Second argument
+ InConsecutiveRegsLast = 1U << 20,
+ InConsecutiveRegs = 1U << 21,
+ CopyElisionCandidate = 1U << 22, ///< Argument copy elision candidate
+ Pointer = 1U << 23,
+ /// Whether this is part of a variable argument list (non-fixed).
+ VarArg = 1U << 24,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ VarArg)
+ };
+
private:
- unsigned IsZExt : 1; ///< Zero extended
- unsigned IsSExt : 1; ///< Sign extended
- unsigned IsNoExt : 1; ///< No extension
- unsigned IsInReg : 1; ///< Passed in register
- unsigned IsSRet : 1; ///< Hidden struct-ret ptr
- unsigned IsByVal : 1; ///< Struct passed by value
- unsigned IsByRef : 1; ///< Passed in memory
- unsigned IsNest : 1; ///< Nested fn static chain
- unsigned IsReturned : 1; ///< Always returned
- unsigned IsSplit : 1;
- unsigned IsInAlloca : 1; ///< Passed with inalloca
- unsigned IsPreallocated : 1; ///< ByVal without the copy
- unsigned IsSplitEnd : 1; ///< Last part of a split
- unsigned IsSwiftSelf : 1; ///< Swift self parameter
- unsigned IsSwiftAsync : 1; ///< Swift async context parameter
- unsigned IsSwiftError : 1; ///< Swift error parameter
- unsigned IsCFGuardTarget : 1; ///< Control Flow Guard target
- unsigned IsHva : 1; ///< HVA field for
- unsigned IsHvaStart : 1; ///< HVA structure start
- unsigned IsSecArgPass : 1; ///< Second argument
- unsigned MemAlign : 6; ///< Log 2 of alignment when arg is passed in memory
- ///< (including byval/byref). The max alignment is
- ///< verified in IR verification.
- unsigned OrigAlign : 5; ///< Log 2 of original alignment
- unsigned IsInConsecutiveRegsLast : 1;
- unsigned IsInConsecutiveRegs : 1;
- unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate
- unsigned IsPointer : 1;
- /// Whether this is part of a variable argument list (non-fixed).
- unsigned IsVarArg : 1;
+ Flags FlagVals = NoFlags;
+ unsigned MemAlign : 6; ///< Log 2 of alignment when arg is passed in memory
+ ///< (including byval/byref). The max alignment is
+ ///< verified in IR verification.
+ unsigned OrigAlign : 5; ///< Log 2 of original alignment
unsigned ByValOrByRefSize = 0; ///< Byval or byref struct size
unsigned PointerAddrSpace = 0; ///< Address space of pointer argument
+ void setFlag(Flags Flag, bool Value = true) {
+ FlagVals = (FlagVals & ~Flag) | (Value ? Flag : NoFlags);
+ }
+
public:
- ArgFlagsTy()
- : IsZExt(0), IsSExt(0), IsNoExt(0), IsInReg(0), IsSRet(0), IsByVal(0),
- IsByRef(0), IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0),
- IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftAsync(0),
- IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), IsHvaStart(0),
- IsSecArgPass(0), MemAlign(0), OrigAlign(0),
- IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
- IsCopyElisionCandidate(0), IsPointer(0), IsVarArg(0) {
+ ArgFlagsTy() : MemAlign(0), OrigAlign(0) {
static_assert(sizeof(*this) == 4 * sizeof(unsigned), "flags are too big");
}
- bool isZExt() const { return IsZExt; }
- void setZExt() { IsZExt = 1; }
+ /// Return the argument's boolean flags.
+ Flags getFlags() const { return FlagVals; }
+
+ bool isZExt() const { return FlagVals & ZExt; }
+ void setZExt() { setFlag(ZExt); }
- bool isSExt() const { return IsSExt; }
- void setSExt() { IsSExt = 1; }
+ bool isSExt() const { return FlagVals & SExt; }
+ void setSExt() { setFlag(SExt); }
- bool isNoExt() const { return IsNoExt; }
- void setNoExt() { IsNoExt = 1; }
+ bool isNoExt() const { return FlagVals & NoExt; }
+ void setNoExt() { setFlag(NoExt); }
- bool isInReg() const { return IsInReg; }
- void setInReg() { IsInReg = 1; }
+ bool isInReg() const { return FlagVals & InReg; }
+ void setInReg() { setFlag(InReg); }
- bool isSRet() const { return IsSRet; }
- void setSRet() { IsSRet = 1; }
+ bool isSRet() const { return FlagVals & SRet; }
+ void setSRet() { setFlag(SRet); }
- bool isByVal() const { return IsByVal; }
- void setByVal() { IsByVal = 1; }
+ bool isByVal() const { return FlagVals & ByVal; }
+ void setByVal() { setFlag(ByVal); }
- bool isByRef() const { return IsByRef; }
- void setByRef() { IsByRef = 1; }
+ bool isByRef() const { return FlagVals & ByRef; }
+ void setByRef() { setFlag(ByRef); }
- bool isInAlloca() const { return IsInAlloca; }
- void setInAlloca() { IsInAlloca = 1; }
+ bool isInAlloca() const { return FlagVals & InAlloca; }
+ void setInAlloca() { setFlag(InAlloca); }
- bool isPreallocated() const { return IsPreallocated; }
- void setPreallocated() { IsPreallocated = 1; }
+ bool isPreallocated() const { return FlagVals & Preallocated; }
+ void setPreallocated() { setFlag(Preallocated); }
- bool isSwiftSelf() const { return IsSwiftSelf; }
- void setSwiftSelf() { IsSwiftSelf = 1; }
+ bool isSwiftSelf() const { return FlagVals & SwiftSelf; }
+ void setSwiftSelf() { setFlag(SwiftSelf); }
- bool isSwiftAsync() const { return IsSwiftAsync; }
- void setSwiftAsync() { IsSwiftAsync = 1; }
+ bool isSwiftAsync() const { return FlagVals & SwiftAsync; }
+ void setSwiftAsync() { setFlag(SwiftAsync); }
- bool isSwiftError() const { return IsSwiftError; }
- void setSwiftError() { IsSwiftError = 1; }
+ bool isSwiftError() const { return FlagVals & SwiftError; }
+ void setSwiftError() { setFlag(SwiftError); }
- bool isCFGuardTarget() const { return IsCFGuardTarget; }
- void setCFGuardTarget() { IsCFGuardTarget = 1; }
+ bool isCFGuardTarget() const { return FlagVals & CFGuardTarget; }
+ void setCFGuardTarget() { setFlag(CFGuardTarget); }
- bool isHva() const { return IsHva; }
- void setHva() { IsHva = 1; }
+ bool isHva() const { return FlagVals & Hva; }
+ void setHva() { setFlag(Hva); }
- bool isHvaStart() const { return IsHvaStart; }
- void setHvaStart() { IsHvaStart = 1; }
+ bool isHvaStart() const { return FlagVals & HvaStart; }
+ void setHvaStart() { setFlag(HvaStart); }
- bool isSecArgPass() const { return IsSecArgPass; }
- void setSecArgPass() { IsSecArgPass = 1; }
+ bool isSecArgPass() const { return FlagVals & SecArgPass; }
+ void setSecArgPass() { setFlag(SecArgPass); }
- bool isNest() const { return IsNest; }
- void setNest() { IsNest = 1; }
+ bool isNest() const { return FlagVals & Nest; }
+ void setNest() { setFlag(Nest); }
- bool isReturned() const { return IsReturned; }
- void setReturned(bool V = true) { IsReturned = V; }
+ bool isReturned() const { return FlagVals & Returned; }
+ void setReturned(bool V = true) { setFlag(Returned, V); }
- bool isInConsecutiveRegs() const { return IsInConsecutiveRegs; }
- void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; }
+ bool isInConsecutiveRegs() const { return FlagVals & InConsecutiveRegs; }
+ void setInConsecutiveRegs(bool Flag = true) {
+ setFlag(InConsecutiveRegs, Flag);
+ }
- bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; }
+ bool isInConsecutiveRegsLast() const {
+ return FlagVals & InConsecutiveRegsLast;
+ }
void setInConsecutiveRegsLast(bool Flag = true) {
- IsInConsecutiveRegsLast = Flag;
+ setFlag(InConsecutiveRegsLast, Flag);
}
- bool isSplit() const { return IsSplit; }
- void setSplit() { IsSplit = 1; }
+ bool isSplit() const { return FlagVals & Split; }
+ void setSplit() { setFlag(Split); }
- bool isSplitEnd() const { return IsSplitEnd; }
- void setSplitEnd() { IsSplitEnd = 1; }
+ bool isSplitEnd() const { return FlagVals & SplitEnd; }
+ void setSplitEnd() { setFlag(SplitEnd); }
- bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; }
- void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; }
+ bool isCopyElisionCandidate() const {
+ return FlagVals & CopyElisionCandidate;
+ }
+ void setCopyElisionCandidate() { setFlag(CopyElisionCandidate); }
- bool isPointer() const { return IsPointer; }
- void setPointer() { IsPointer = 1; }
+ bool isPointer() const { return FlagVals & Pointer; }
+ void setPointer() { setFlag(Pointer); }
- bool isVarArg() const { return IsVarArg; }
- void setVarArg() { IsVarArg = 1; }
+ bool isVarArg() const { return FlagVals & VarArg; }
+ void setVarArg() { setFlag(VarArg); }
Align getNonZeroMemAlign() const {
return decodeMaybeAlign(MemAlign).valueOrOne();
@@ -195,6 +211,15 @@ namespace ISD {
unsigned getPointerAddrSpace() const { return PointerAddrSpace; }
void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; }
+
+ bool operator==(const ArgFlagsTy &Other) const {
+ return FlagVals == Other.FlagVals && MemAlign == Other.MemAlign &&
+ OrigAlign == Other.OrigAlign &&
+ ByValOrByRefSize == Other.ByValOrByRefSize &&
+ PointerAddrSpace == Other.PointerAddrSpace;
+ }
+
+ bool operator!=(const ArgFlagsTy &Other) const { return !(*this == Other); }
};
/// InputArg - This struct carries flags and type information about a
More information about the llvm-commits
mailing list