diff options
-rw-r--r-- | llvm/include/llvm/Target/TargetInstrInfo.h | 10 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MIRParser/MIParser.cpp | 51 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MIRPrinter.cpp | 42 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.h | 8 | ||||
-rw-r--r-- | llvm/test/CodeGen/MIR/AArch64/expected-target-flag-name.mir | 23 | ||||
-rw-r--r-- | llvm/test/CodeGen/MIR/AArch64/invalid-target-flag-name.mir | 23 | ||||
-rw-r--r-- | llvm/test/CodeGen/MIR/AArch64/target-flags.mir | 39 |
8 files changed, 218 insertions, 9 deletions
diff --git a/llvm/include/llvm/Target/TargetInstrInfo.h b/llvm/include/llvm/Target/TargetInstrInfo.h index 0b45507893a..421666cef8f 100644 --- a/llvm/include/llvm/Target/TargetInstrInfo.h +++ b/llvm/include/llvm/Target/TargetInstrInfo.h @@ -1289,6 +1289,16 @@ public: return None; } + /// Return an array that contains the bitmask target flag values and their + /// names. + /// + /// MIR Serialization is able to serialize only the target flags that are + /// defined by this method. + virtual ArrayRef<std::pair<unsigned, const char *>> + getSerializableBitmaskMachineOperandTargetFlags() const { + return None; + } + private: unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode; }; diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 557b72596f8..20581a1692f 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -72,6 +72,8 @@ class MIParser { StringMap<int> Names2TargetIndices; /// Maps from direct target flag names to the direct target flag values. StringMap<unsigned> Names2DirectTargetFlags; + /// Maps from direct target flag names to the bitmask target flag values. + StringMap<unsigned> Names2BitmaskTargetFlags; public: MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error, @@ -211,6 +213,14 @@ private: /// /// Return true if the name isn't a name of a direct flag. bool getDirectTargetFlag(StringRef Name, unsigned &Flag); + + void initNames2BitmaskTargetFlags(); + + /// Try to convert a name of a bitmask target flag to the corresponding + /// target flag. + /// + /// Return true if the name isn't a name of a bitmask target flag. + bool getBitmaskTargetFlag(StringRef Name, unsigned &Flag); }; } // end anonymous namespace @@ -1351,11 +1361,24 @@ bool MIParser::parseMachineOperandAndTargetFlags(MachineOperand &Dest) { return true; if (Token.isNot(MIToken::Identifier)) return error("expected the name of the target flag"); - if (getDirectTargetFlag(Token.stringValue(), TF)) - return error("use of undefined target flag '" + Token.stringValue() + - "'"); + if (getDirectTargetFlag(Token.stringValue(), TF)) { + if (getBitmaskTargetFlag(Token.stringValue(), TF)) + return error("use of undefined target flag '" + Token.stringValue() + + "'"); + } lex(); - // TODO: Parse target's bit target flags. + while (Token.is(MIToken::comma)) { + lex(); + if (Token.isNot(MIToken::Identifier)) + return error("expected the name of the target flag"); + unsigned BitFlag = 0; + if (getBitmaskTargetFlag(Token.stringValue(), BitFlag)) + return error("use of undefined target flag '" + Token.stringValue() + + "'"); + // TODO: Report an error when using a duplicate bit target flag. + TF |= BitFlag; + lex(); + } if (expectAndConsume(MIToken::rparen)) return true; } @@ -1759,6 +1782,26 @@ bool MIParser::getDirectTargetFlag(StringRef Name, unsigned &Flag) { return false; } +void MIParser::initNames2BitmaskTargetFlags() { + if (!Names2BitmaskTargetFlags.empty()) + return; + const auto *TII = MF.getSubtarget().getInstrInfo(); + assert(TII && "Expected target instruction info"); + auto Flags = TII->getSerializableBitmaskMachineOperandTargetFlags(); + for (const auto &I : Flags) + Names2BitmaskTargetFlags.insert( + std::make_pair(StringRef(I.second), I.first)); +} + +bool MIParser::getBitmaskTargetFlag(StringRef Name, unsigned &Flag) { + initNames2BitmaskTargetFlags(); + auto FlagInfo = Names2BitmaskTargetFlags.find(Name); + if (FlagInfo == Names2BitmaskTargetFlags.end()) + return true; + Flag = FlagInfo->second; + return false; +} + bool llvm::parseMachineBasicBlockDefinitions(MachineFunction &MF, StringRef Src, PerFunctionMIParsingState &PFS, const SlotMapping &IRSlots, diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 9e3f6bb65f6..67fd5c226a5 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -611,11 +611,43 @@ void MIPrinter::printTargetFlags(const MachineOperand &Op) { assert(TII && "expected instruction info"); auto Flags = TII->decomposeMachineOperandsTargetFlags(Op.getTargetFlags()); OS << "target-flags("; - if (const auto *Name = getTargetFlagName(TII, Flags.first)) - OS << Name; - else - OS << "<unknown target flag>"; - // TODO: Print the target's bit flags. + const bool HasDirectFlags = Flags.first; + const bool HasBitmaskFlags = Flags.second; + if (!HasDirectFlags && !HasBitmaskFlags) { + OS << "<unknown>) "; + return; + } + if (HasDirectFlags) { + if (const auto *Name = getTargetFlagName(TII, Flags.first)) + OS << Name; + else + OS << "<unknown target flag>"; + } + if (!HasBitmaskFlags) { + OS << ") "; + return; + } + bool IsCommaNeeded = HasDirectFlags; + unsigned BitMask = Flags.second; + auto BitMasks = TII->getSerializableBitmaskMachineOperandTargetFlags(); + for (const auto &Mask : BitMasks) { + // Check if the flag's bitmask has the bits of the current mask set. + if ((BitMask & Mask.first) == Mask.first) { + if (IsCommaNeeded) + OS << ", "; + IsCommaNeeded = true; + OS << Mask.second; + // Clear the bits which were serialized from the flag's bitmask. + BitMask &= ~(Mask.first); + } + } + if (BitMask) { + // When the resulting flag's bitmask isn't zero, we know that we didn't + // serialize all of the bit flags. + if (IsCommaNeeded) + OS << ", "; + OS << "<unknown bitmask target flag>"; + } OS << ") "; } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index bcf11d00e9e..f0e02489ae3 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -2978,3 +2978,34 @@ bool AArch64InstrInfo::optimizeCondBranch(MachineInstr *MI) const { MI->eraseFromParent(); return true; } + +std::pair<unsigned, unsigned> +AArch64InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { + const unsigned Mask = AArch64II::MO_FRAGMENT; + return std::make_pair(TF & Mask, TF & ~Mask); +} + +ArrayRef<std::pair<unsigned, const char *>> +AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags() const { + using namespace AArch64II; + static std::pair<unsigned, const char *> TargetFlags[] = { + {MO_PAGE, "aarch64-page"}, + {MO_PAGEOFF, "aarch64-pageoff"}, + {MO_G3, "aarch64-g3"}, + {MO_G2, "aarch64-g2"}, + {MO_G1, "aarch64-g1"}, + {MO_G0, "aarch64-g0"}, + {MO_HI12, "aarch64-hi12"}}; + return makeArrayRef(TargetFlags); +} + +ArrayRef<std::pair<unsigned, const char *>> +AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { + using namespace AArch64II; + static std::pair<unsigned, const char *> TargetFlags[] = { + {MO_GOT, "aarch64-got"}, + {MO_NC, "aarch64-nc"}, + {MO_TLS, "aarch64-tls"}, + {MO_CONSTPOOL, "aarch64-constant-pool"}}; + return makeArrayRef(TargetFlags); +} diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h index 68c2a288258..ce7a3058ef9 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h @@ -181,6 +181,14 @@ public: bool useMachineCombiner() const override; bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override; + + std::pair<unsigned, unsigned> + decomposeMachineOperandsTargetFlags(unsigned TF) const override; + ArrayRef<std::pair<unsigned, const char *>> + getSerializableDirectMachineOperandTargetFlags() const override; + ArrayRef<std::pair<unsigned, const char *>> + getSerializableBitmaskMachineOperandTargetFlags() const override; + private: void instantiateCondBranch(MachineBasicBlock &MBB, DebugLoc DL, MachineBasicBlock *TBB, diff --git a/llvm/test/CodeGen/MIR/AArch64/expected-target-flag-name.mir b/llvm/test/CodeGen/MIR/AArch64/expected-target-flag-name.mir new file mode 100644 index 00000000000..b7bac2682c7 --- /dev/null +++ b/llvm/test/CodeGen/MIR/AArch64/expected-target-flag-name.mir @@ -0,0 +1,23 @@ +# RUN: not llc -mtriple=aarch64-none-linux-gnu -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + @var_i32 = global i32 42 + @var_i64 = global i64 0 + + define i32 @sub_small() { + entry: + %val32 = load i32, i32* @var_i32 + ret i32 %val32 + } + +... +--- +name: sub_small +body: | + bb.0.entry: + %x8 = ADRP target-flags(aarch64-page) @var_i32 + ; CHECK: [[@LINE+1]]:60: expected the name of the target flag + %w0 = LDRWui killed %x8, target-flags(aarch64-pageoff, ) @var_i32 + RET_ReallyLR implicit %w0 +... diff --git a/llvm/test/CodeGen/MIR/AArch64/invalid-target-flag-name.mir b/llvm/test/CodeGen/MIR/AArch64/invalid-target-flag-name.mir new file mode 100644 index 00000000000..d4145b8961d --- /dev/null +++ b/llvm/test/CodeGen/MIR/AArch64/invalid-target-flag-name.mir @@ -0,0 +1,23 @@ +# RUN: not llc -mtriple=aarch64-none-linux-gnu -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + @var_i32 = global i32 42 + @var_i64 = global i64 0 + + define i32 @sub_small() { + entry: + %val32 = load i32, i32* @var_i32 + ret i32 %val32 + } + +... +--- +name: sub_small +body: | + bb.0.entry: + %x8 = ADRP target-flags(aarch64-page) @var_i32 + ; CHECK: [[@LINE+1]]:60: use of undefined target flag 'ncc' + %w0 = LDRWui killed %x8, target-flags(aarch64-pageoff, ncc) @var_i32 + RET_ReallyLR implicit %w0 +... diff --git a/llvm/test/CodeGen/MIR/AArch64/target-flags.mir b/llvm/test/CodeGen/MIR/AArch64/target-flags.mir new file mode 100644 index 00000000000..e96fce7c2f2 --- /dev/null +++ b/llvm/test/CodeGen/MIR/AArch64/target-flags.mir @@ -0,0 +1,39 @@ +# RUN: llc -mtriple=aarch64-none-linux-gnu -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s + +--- | + + @var_i32 = global i32 42 + @var_i64 = global i64 0 + + define void @sub_small() { + entry: + %val32 = load i32, i32* @var_i32 + %newval32 = sub i32 %val32, 4095 + store i32 %newval32, i32* @var_i32 + %val64 = load i64, i64* @var_i64 + %newval64 = sub i64 %val64, 52 + store i64 %newval64, i64* @var_i64 + ret void + } + +... +--- +name: sub_small +body: | + bb.0.entry: + ; CHECK: %x8 = ADRP target-flags(aarch64-page) @var_i32 + ; CHECK-NEXT: %x9 = ADRP target-flags(aarch64-page) @var_i64 + ; CHECK-NEXT: %w10 = LDRWui %x8, target-flags(aarch64-pageoff, aarch64-nc) @var_i32 + ; CHECK-NEXT: %x11 = LDRXui %x9, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @var_i64 + ; CHECK: STRWui killed %w10, killed %x8, target-flags(aarch64-nc) @var_i32 + ; CHECK: STRXui killed %x11, killed %x9, target-flags(aarch64-pageoff, aarch64-nc) @var_i64 + %x8 = ADRP target-flags(aarch64-page) @var_i32 + %x9 = ADRP target-flags(aarch64-page) @var_i64 + %w10 = LDRWui %x8, target-flags(aarch64-pageoff, aarch64-nc) @var_i32 + %x11 = LDRXui %x9, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @var_i64 + %w10 = SUBWri killed %w10, 4095, 0 + %x11 = SUBXri killed %x11, 52, 0 + STRWui killed %w10, killed %x8, target-flags(aarch64-nc) @var_i32 + STRXui killed %x11, killed %x9, target-flags(aarch64-pageoff, aarch64-nc) @var_i64 + RET_ReallyLR +... |