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;
};
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,
///
/// 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
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;
}
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,
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 << ") ";
}
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);
+}
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,
--- /dev/null
+# 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
+...
--- /dev/null
+# 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
+...
--- /dev/null
+# 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
+...