diff --git a/llvm/include/llvm/IR/InlineAsm.h b/llvm/include/llvm/IR/InlineAsm.h index 36ff7deb6864e..0c0389871fc2f 100644 --- a/llvm/include/llvm/IR/InlineAsm.h +++ b/llvm/include/llvm/IR/InlineAsm.h @@ -272,48 +272,45 @@ class InlineAsm final : public Value { Max = ZT, }; - // These are helper methods for dealing with flags in the INLINEASM SDNode - // in the backend. + // This class is intentionally packed into a 32b value as it is used as a + // MVT::i32 ConstantSDNode SDValue for SelectionDAG and as immediate operands + // on INLINEASM and INLINEASM_BR MachineInstr's. // // The encoding of Flag is currently: - // Bits 2-0 - A Kind::* value indicating the kind of the operand. - // Bits 15-3 - The number of SDNode operands associated with this inline - // assembly operand. + // Bits 2-0 - A Kind::* value indicating the kind of the operand. (KindField) + // Bits 15-3 - The number of SDNode operands associated with + // this inline assembly operand. (NumOperands) + // Bit 31 - determines if this is a matched operand. (IsMatched) // If bit 31 is set: - // Bit 30-16 - The operand number that this operand must match. - // When bits 2-0 are Kind::Mem, the Constraint_* value must be - // obtained from the flags for this operand number. + // Bits 30-16 - The operand number that this operand must match. (MatchedOperandNo) // Else if bits 2-0 are Kind::Mem: - // Bit 30-16 - A Constraint_* value indicating the original constraint - // code. + // Bits 30-16 - A ConstraintCode:: value indicating the original constraint code. (MemConstraintCode) // Else: - // Bit 30-16 - The register class ID to use for the operand. + // Bits 30-16 - The register class ID to use for the operand. (RegClass) // - // Bits 30-16 are called "Data" for lack of a better name. The getter is - // intentionally private; the public methods that rely on that private method - // should be used to check invariants first before accessing Data. + // As such, MatchedOperandNo, MemConstraintCode, and RegClass are views of + // the same slice of bits, but are mutually exclusive depending on the + // fields IsMatched then KindField. class Flag { uint32_t Storage; using KindField = Bitfield::Element; using NumOperands = Bitfield::Element; - using Data = Bitfield::Element; + using MatchedOperandNo = Bitfield::Element; + using MemConstraintCode = Bitfield::Element; + using RegClass = Bitfield::Element; using IsMatched = Bitfield::Element; - unsigned getData() const { return Bitfield::get(Storage); } + + unsigned getMatchedOperandNo() const { return Bitfield::get(Storage); } + unsigned getRegClass() const { return Bitfield::get(Storage); } bool isMatched() const { return Bitfield::get(Storage); } - void setKind(Kind K) { Bitfield::set(Storage, K); } - void setNumOperands(unsigned N) { Bitfield::set(Storage, N); } - void setData(unsigned D) { Bitfield::set(Storage, D); } - void setIsMatched(bool B) { Bitfield::set(Storage, B); } public: Flag() : Storage(0) {} explicit Flag(uint32_t F) : Storage(F) {} - Flag(enum Kind K, unsigned NumOps) { - setKind(K); - setNumOperands(NumOps); - setData(0); - setIsMatched(false); + Flag(enum Kind K, unsigned NumOps) : Storage(0) { + Bitfield::set(Storage, K); + Bitfield::set(Storage, NumOps); } operator uint32_t() { return Storage; } Kind getKind() const { return Bitfield::get(Storage); } @@ -356,7 +353,7 @@ class InlineAsm final : public Value { bool isUseOperandTiedToDef(unsigned &Idx) const { if (!isMatched()) return false; - Idx = getData(); + Idx = getMatchedOperandNo(); return true; } @@ -367,28 +364,24 @@ class InlineAsm final : public Value { return false; // setRegClass() uses 0 to mean no register class, and otherwise stores // RC + 1. - if (!getData()) + if (!getRegClass()) return false; - RC = getData() - 1; + RC = getRegClass() - 1; return true; } ConstraintCode getMemoryConstraintID() const { assert((isMemKind() || isFuncKind()) && "Not expected mem or function flag!"); - uint32_t D = getData(); - assert(D <= static_cast(ConstraintCode::Max) && - D >= static_cast(ConstraintCode::Unknown) && - "unexpected value for memory constraint"); - return static_cast(D); + return Bitfield::get(Storage); } /// setMatchingOp - Augment an existing flag with information indicating /// that this input operand is tied to a previous output operand. - void setMatchingOp(unsigned MatchedOperandNo) { - assert(getData() == 0 && "Matching operand already set"); - setData(MatchedOperandNo); - setIsMatched(true); + void setMatchingOp(unsigned OperandNo) { + assert(getMatchedOperandNo() == 0 && "Matching operand already set"); + Bitfield::set(Storage, OperandNo); + Bitfield::set(Storage, true); } /// setRegClass - Augment an existing flag with the required register class @@ -397,25 +390,23 @@ class InlineAsm final : public Value { void setRegClass(unsigned RC) { assert(!isImmKind() && "Immediates cannot have a register class"); assert(!isMemKind() && "Memory operand cannot have a register class"); - assert(getData() == 0 && "Register class already set"); + assert(getRegClass() == 0 && "Register class already set"); // Store RC + 1, reserve the value 0 to mean 'no register class'. - setData(RC + 1); + Bitfield::set(Storage, RC + 1); } /// setMemConstraint - Augment an existing flag with the constraint code for /// a memory constraint. void setMemConstraint(ConstraintCode C) { - assert((isMemKind() || isFuncKind()) && - "Flag is not a memory or function constraint!"); - assert(getData() == 0 && "Mem constraint already set"); - setData(static_cast(C)); + assert(getMemoryConstraintID() == ConstraintCode::Unknown && "Mem constraint already set"); + Bitfield::set(Storage, C); } /// clearMemConstraint - Similar to setMemConstraint(0), but without the /// assertion checking that the constraint has not been set previously. void clearMemConstraint() { assert((isMemKind() || isFuncKind()) && "Flag is not a memory or function constraint!"); - setData(0); + Bitfield::set(Storage, ConstraintCode::Unknown); } };