diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h --- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -26,6 +26,7 @@ #include "llvm/CodeGen/MachineInstrBundle.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/ErrorHandling.h" @@ -186,7 +187,9 @@ } const MachineInstrBuilder &addRegMask(const uint32_t *Mask) const { - MI->addOperand(*MF, MachineOperand::CreateRegMask(Mask)); + uint32_t NumRegs = MF->getSubtarget().getRegisterInfo()->getNumRegs(); + uint32_t Words = MachineOperand::getRegMaskSize(NumRegs); + MI->addOperand(*MF, MachineOperand::CreateRegMask(Mask, Words)); return *this; } diff --git a/llvm/include/llvm/CodeGen/MachineOperand.h b/llvm/include/llvm/CodeGen/MachineOperand.h --- a/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/llvm/include/llvm/CodeGen/MachineOperand.h @@ -168,7 +168,6 @@ const ConstantFP *CFP; // For MO_FPImmediate. const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit. int64_t ImmVal; // For MO_Immediate. - const uint32_t *RegMask; // For MO_RegisterMask and MO_RegisterLiveOut. const MDNode *MD; // For MO_Metadata. MCSymbol *Sym; // For MO_MCSymbol. unsigned CFIIndex; // For MO_CFI. @@ -176,6 +175,18 @@ unsigned Pred; // For MO_Predicate const Constant *ShuffleMask; // For MO_ShuffleMask + // For MO_RegisterMask and MO_RegisterLiveOut. + // + // We store the size mostly for convenience; it's invariant for each + // subtarget, but some APIs don't have any easy way to look up the current + // subtarget. (We could change how those APIs work, but there isn't + // really any point; this union is at least two pointers wide for other + // reasons.) + struct { + const uint32_t *Ptr; + uint32_t Words; + } RegMask; + struct { // For MO_Register. // Register number is in SmallContents.RegNo. MachineOperand *Prev; // Access list for register. See MRI. @@ -622,7 +633,13 @@ /// operand. const uint32_t *getRegMask() const { assert(isRegMask() && "Wrong MachineOperand accessor"); - return Contents.RegMask; + return Contents.RegMask.Ptr; + } + + /// getRegMask - Returns a bit mask of registers preserved by this RegMask + /// operand, as an ArrayRef. + const ArrayRef getRegMaskArray() const { + return ArrayRef(Contents.RegMask.Ptr, Contents.RegMask.Words); } /// Returns number of elements needed for a regmask array. @@ -633,7 +650,12 @@ /// getRegLiveOut - Returns a bit mask of live-out registers. const uint32_t *getRegLiveOut() const { assert(isRegLiveOut() && "Wrong MachineOperand accessor"); - return Contents.RegMask; + return Contents.RegMask.Ptr; + } + + /// getRegLiveOut - Returns a bit mask of live-out registers, as an ArrayRef. + const ArrayRef getRegLiveOutArray() const { + return ArrayRef(Contents.RegMask.Ptr, Contents.RegMask.Words); } const MDNode *getMetadata() const { @@ -688,9 +710,10 @@ /// operand does not take ownership of the memory referenced by Mask, it must /// remain valid for the lifetime of the operand. See CreateRegMask(). /// Any physreg with a 0 bit in the mask is clobbered by the instruction. - void setRegMask(const uint32_t *RegMaskPtr) { + void setRegMask(const uint32_t *RegMaskPtr, uint32_t RegMaskWords) { assert(isRegMask() && "Wrong MachineOperand mutator"); - Contents.RegMask = RegMaskPtr; + Contents.RegMask.Ptr = RegMaskPtr; + Contents.RegMask.Words = RegMaskWords; } void setPredicate(unsigned Predicate) { @@ -866,16 +889,20 @@ /// /// Any physreg with a 0 bit in the mask is clobbered by the instruction. /// - static MachineOperand CreateRegMask(const uint32_t *Mask) { + static MachineOperand CreateRegMask(const uint32_t *Mask, + uint32_t MaskWords) { assert(Mask && "Missing register mask"); MachineOperand Op(MachineOperand::MO_RegisterMask); - Op.Contents.RegMask = Mask; + Op.Contents.RegMask.Ptr = Mask; + Op.Contents.RegMask.Words = MaskWords; return Op; } - static MachineOperand CreateRegLiveOut(const uint32_t *Mask) { + static MachineOperand CreateRegLiveOut(const uint32_t *Mask, + uint32_t MaskWords) { assert(Mask && "Missing live-out register mask"); MachineOperand Op(MachineOperand::MO_RegisterLiveOut); - Op.Contents.RegMask = Mask; + Op.Contents.RegMask.Ptr = Mask; + Op.Contents.RegMask.Words = MaskWords; return Op; } static MachineOperand CreateMetadata(const MDNode *Meta) { diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -2381,7 +2381,9 @@ if (expectAndConsume(MIToken::rparen)) return true; - Dest = MachineOperand::CreateRegMask(Mask); + uint32_t NumRegs = MF.getSubtarget().getRegisterInfo()->getNumRegs(); + uint32_t Words = MachineOperand::getRegMaskSize(NumRegs); + Dest = MachineOperand::CreateRegMask(Mask, Words); return false; } @@ -2406,7 +2408,9 @@ } if (expectAndConsume(MIToken::rparen)) return true; - Dest = MachineOperand::CreateRegLiveOut(Mask); + uint32_t NumRegs = MF.getSubtarget().getRegisterInfo()->getNumRegs(); + uint32_t Words = MachineOperand::getRegMaskSize(NumRegs); + Dest = MachineOperand::CreateRegLiveOut(Mask, Words); return false; } @@ -2492,7 +2496,9 @@ return true; case MIToken::Identifier: if (const auto *RegMask = PFS.Target.getRegMask(Token.stringValue())) { - Dest = MachineOperand::CreateRegMask(RegMask); + uint32_t NumRegs = MF.getSubtarget().getRegisterInfo()->getNumRegs(); + uint32_t Words = MachineOperand::getRegMaskSize(NumRegs); + Dest = MachineOperand::CreateRegMask(RegMask, Words); lex(); break; } else if (Token.stringValue() == "CustomRegMask") { diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp --- a/llvm/lib/CodeGen/MachineOperand.cpp +++ b/llvm/lib/CodeGen/MachineOperand.cpp @@ -304,25 +304,9 @@ return getBlockAddress() == Other.getBlockAddress() && getOffset() == Other.getOffset(); case MachineOperand::MO_RegisterMask: - case MachineOperand::MO_RegisterLiveOut: { - // Shallow compare of the two RegMasks - const uint32_t *RegMask = getRegMask(); - const uint32_t *OtherRegMask = Other.getRegMask(); - if (RegMask == OtherRegMask) - return true; - - if (const MachineFunction *MF = getMFIfAvailable(*this)) { - // Calculate the size of the RegMask - const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); - unsigned RegMaskSize = (TRI->getNumRegs() + 31) / 32; - - // Deep compare of the two RegMasks - return std::equal(RegMask, RegMask + RegMaskSize, OtherRegMask); - } - // We don't know the size of the RegMask, so we can't deep compare the two - // reg masks. - return false; - } + return getRegMaskArray() == Other.getRegMaskArray(); + case MachineOperand::MO_RegisterLiveOut: + return getRegLiveOutArray() == Other.getRegLiveOutArray(); case MachineOperand::MO_MCSymbol: return getMCSymbol() == Other.getMCSymbol(); case MachineOperand::MO_CFIIndex: @@ -371,8 +355,11 @@ return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getBlockAddress(), MO.getOffset()); case MachineOperand::MO_RegisterMask: + return hash_combine(MO.getType(), MO.getTargetFlags(), + MO.getRegMaskArray()); case MachineOperand::MO_RegisterLiveOut: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask()); + return hash_combine(MO.getType(), MO.getTargetFlags(), + MO.getRegLiveOutArray()); case MachineOperand::MO_Metadata: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata()); case MachineOperand::MO_MCSymbol: diff --git a/llvm/lib/CodeGen/RegUsageInfoPropagate.cpp b/llvm/lib/CodeGen/RegUsageInfoPropagate.cpp --- a/llvm/lib/CodeGen/RegUsageInfoPropagate.cpp +++ b/llvm/lib/CodeGen/RegUsageInfoPropagate.cpp @@ -69,7 +69,7 @@ && "expected register mask size"); for (MachineOperand &MO : MI.operands()) { if (MO.isRegMask()) - MO.setRegMask(RegMask.data()); + MO.setRegMask(RegMask.data(), RegMask.size()); } } }; diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1003,8 +1003,10 @@ return false; // Push the register mask info. + uint32_t NumRegs = MF->getSubtarget().getRegisterInfo()->getNumRegs(); + uint32_t Words = MachineOperand::getRegMaskSize(NumRegs); Ops.push_back(MachineOperand::CreateRegMask( - TRI.getCallPreservedMask(*FuncInfo.MF, CC))); + TRI.getCallPreservedMask(*FuncInfo.MF, CC), Words)); // Add scratch registers as implicit def and early clobber. const MCPhysReg *ScratchRegs = TLI.getScratchRegisters(CC); diff --git a/llvm/lib/CodeGen/StackMapLivenessAnalysis.cpp b/llvm/lib/CodeGen/StackMapLivenessAnalysis.cpp --- a/llvm/lib/CodeGen/StackMapLivenessAnalysis.cpp +++ b/llvm/lib/CodeGen/StackMapLivenessAnalysis.cpp @@ -151,7 +151,9 @@ void StackMapLiveness::addLiveOutSetToMI(MachineFunction &MF, MachineInstr &MI) { uint32_t *Mask = createRegisterMask(MF); - MachineOperand MO = MachineOperand::CreateRegLiveOut(Mask); + uint32_t NumRegs = MF.getSubtarget().getRegisterInfo()->getNumRegs(); + uint32_t Words = MachineOperand::getRegMaskSize(NumRegs); + MachineOperand MO = MachineOperand::CreateRegLiveOut(Mask, Words); MI.addOperand(MF, MO); } diff --git a/llvm/unittests/CodeGen/MachineOperandTest.cpp b/llvm/unittests/CodeGen/MachineOperandTest.cpp --- a/llvm/unittests/CodeGen/MachineOperandTest.cpp +++ b/llvm/unittests/CodeGen/MachineOperandTest.cpp @@ -46,7 +46,7 @@ TEST(MachineOperandTest, PrintRegisterMask) { uint32_t Dummy; - MachineOperand MO = MachineOperand::CreateRegMask(&Dummy); + MachineOperand MO = MachineOperand::CreateRegMask(&Dummy, 1); // Checking some preconditions on the newly created // MachineOperand. @@ -276,7 +276,7 @@ TEST(MachineOperandTest, PrintRegisterLiveOut) { // Create a MachineOperand with a register live out list and print it. uint32_t Mask = 0; - MachineOperand MO = MachineOperand::CreateRegLiveOut(&Mask); + MachineOperand MO = MachineOperand::CreateRegLiveOut(&Mask, 1); // Checking some preconditions on the newly created // MachineOperand. @@ -398,7 +398,7 @@ ASSERT_TRUE(OS.str() == "intpred(eq)"); } -TEST(MachineOperandTest, HashValue) { +TEST(MachineOperandTest, HashValueSym) { char SymName1[] = "test"; char SymName2[] = "test"; MachineOperand MO1 = MachineOperand::CreateES(SymName1); @@ -408,4 +408,13 @@ ASSERT_TRUE(MO1.isIdenticalTo(MO2)); } +TEST(MachineOperandTest, HashValueRegMask) { + uint32_t Mask1 = 1; + uint32_t Mask2 = 1; + MachineOperand MO1 = MachineOperand::CreateRegMask(&Mask1, 1); + MachineOperand MO2 = MachineOperand::CreateRegMask(&Mask2, 1); + ASSERT_NE(&Mask1, &Mask2); + ASSERT_EQ(hash_value(MO1), hash_value(MO2)); + ASSERT_TRUE(MO1.isIdenticalTo(MO2)); +} } // end namespace