summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/TargetInstrInfo.cpp
diff options
context:
space:
mode:
authorAlex Bradbury <asb@lowrisc.org>2017-09-28 09:31:46 +0000
committerAlex Bradbury <asb@lowrisc.org>2017-09-28 09:31:46 +0000
commit5518cbfc4187564302dbc23515d812eab8e584e7 (patch)
treeb00dba8ae20855256f09990240f99d3da5758c95 /llvm/lib/CodeGen/TargetInstrInfo.cpp
parent0b4d10c8b3cc883e498fe6905bdb31befb8cd735 (diff)
downloadbcm5719-llvm-5518cbfc4187564302dbc23515d812eab8e584e7.tar.gz
bcm5719-llvm-5518cbfc4187564302dbc23515d812eab8e584e7.zip
Teach TargetInstrInfo::getInlineAsmLength to parse .space directives with integer arguments
It's currently quite difficult to test passes like branch relaxation, which requires branches with large displacement to be generated. The .space assembler directive makes it easy to create arbitrarily large basic blocks, but getInlineAsmLength is not able to parse it and so the size of the block is not correctly estimated. Other backends (AArch64, AMDGPU) introduce options just for testing that artificially restrict the ranges of branch instructions (e.g. aarch64-tbz-offset-bits). Although parsing a single form of the .space directive feels inelegant, it does allow a more direct testing approach. This patch adapts the .space parsing code from Mips16InstrInfo::getInlineAsmLength and removes it now the extra functionality is provided by the base implementation. I want to move this functionality to the generic getInlineAsmLength as 1) I need the same for RISC-V, and 2) I feel other backends will benefit from more direct testing of large branch displacements. Differential Revision: https://reviews.llvm.org/D37798 llvm-svn: 314393
Diffstat (limited to 'llvm/lib/CodeGen/TargetInstrInfo.cpp')
-rw-r--r--llvm/lib/CodeGen/TargetInstrInfo.cpp42
1 files changed, 32 insertions, 10 deletions
diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 5e92cbf1ee0..b1edf023022 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -67,6 +67,11 @@ void TargetInstrInfo::insertNoop(MachineBasicBlock &MBB,
llvm_unreachable("Target didn't implement insertNoop!");
}
+static bool isAsmComment(const char *Str, const MCAsmInfo &MAI) {
+ return strncmp(Str, MAI.getCommentString().data(),
+ MAI.getCommentString().size()) == 0;
+}
+
/// Measure the specified inline asm to determine an approximation of its
/// length.
/// Comments (which run till the next SeparatorString or newline) do not
@@ -75,29 +80,46 @@ void TargetInstrInfo::insertNoop(MachineBasicBlock &MBB,
/// multiple instructions separated by SeparatorString or newlines.
/// Variable-length instructions are not handled here; this function
/// may be overloaded in the target code to do that.
+/// We implement a special case of the .space directive which takes only a
+/// single integer argument in base 10 that is the size in bytes. This is a
+/// restricted form of the GAS directive in that we only interpret
+/// simple--i.e. not a logical or arithmetic expression--size values without
+/// the optional fill value. This is primarily used for creating arbitrary
+/// sized inline asm blocks for testing purposes.
unsigned TargetInstrInfo::getInlineAsmLength(const char *Str,
const MCAsmInfo &MAI) const {
// Count the number of instructions in the asm.
- bool atInsnStart = true;
- unsigned InstCount = 0;
+ bool AtInsnStart = true;
+ unsigned Length = 0;
for (; *Str; ++Str) {
if (*Str == '\n' || strncmp(Str, MAI.getSeparatorString(),
strlen(MAI.getSeparatorString())) == 0) {
- atInsnStart = true;
- } else if (strncmp(Str, MAI.getCommentString().data(),
- MAI.getCommentString().size()) == 0) {
+ AtInsnStart = true;
+ } else if (isAsmComment(Str, MAI)) {
// Stop counting as an instruction after a comment until the next
// separator.
- atInsnStart = false;
+ AtInsnStart = false;
}
- if (atInsnStart && !std::isspace(static_cast<unsigned char>(*Str))) {
- ++InstCount;
- atInsnStart = false;
+ if (AtInsnStart && !std::isspace(static_cast<unsigned char>(*Str))) {
+ unsigned AddLength = MAI.getMaxInstLength();
+ if (strncmp(Str, ".space", 6) == 0) {
+ char *EStr;
+ int SpaceSize;
+ SpaceSize = strtol(Str + 6, &EStr, 10);
+ SpaceSize = SpaceSize < 0 ? 0 : SpaceSize;
+ while (*EStr != '\n' && std::isspace(static_cast<unsigned char>(*EStr)))
+ ++EStr;
+ if (*EStr == '\0' || *EStr == '\n' ||
+ isAsmComment(EStr, MAI)) // Successfully parsed .space argument
+ AddLength = SpaceSize;
+ }
+ Length += AddLength;
+ AtInsnStart = false;
}
}
- return InstCount * MAI.getMaxInstLength();
+ return Length;
}
/// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything
OpenPOWER on IntegriCloud