This is an archive of the discontinued LLVM Phabricator instance.

Add infrastructure for support of multiple memory constraints.
ClosedPublic

Authored by dsanders on Mar 9 2015, 8:55 AM.

Details

Summary

The operand flag word for ISD::INLINEASM nodes now contains a 15-bit
memory constraint ID when the operand kind is Kind_Mem. This constraint
ID is a numeric equivalent to the constraint code string and is converted
with a target specific hook in TargetLowering.

This patch maps all memory constraints to InlineAsm::Constraint_m so there
is no functional change at this point. It just proves that using these
previously unused bits in the encoding of the flag word doesn't break anything.

The next patch will make each target preserve the current mapping of
everything to Constraint_m for itself while changing the target independent
implementation of the hook to return Constraint_Unknown appropriately. Each
target will then be adapted in separate patches to use appropriate Constraint_*
values.

Depends on D8168. Without it, MSP430 will begin crashing as the new flag
word values no longer fit in the MVT it uses for pointers (i16).

Diff Detail

Event Timeline

dsanders updated this revision to Diff 21490.Mar 9 2015, 8:55 AM
dsanders retitled this revision from to Add infrastructure for support of multiple memory constraints..
dsanders updated this object.
dsanders edited the test plan for this revision. (Show Details)
dsanders added a subscriber: Unknown Object (MLST).
hfinkel added a subscriber: hfinkel.Mar 9 2015, 2:13 PM

Thanks for working on this!

include/llvm/Target/TargetLowering.h
2597

Line is too long.

2599

Once this lands, references to "this change" don't make sense. I'd say,

// Once all targets have been updated, we can use the constraint code.
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
6598

Line too long. Also, why not write?

assert(ConstraintID != InlineAsm::Constraint_Unknown &&
       "Failed to convert memory constraint code to constraint id.");

(same below too)

6749

Line is too long.

lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
215

Line too long. (same with this assert in some of the other files too).

hfinkel added inline comments.Mar 9 2015, 2:15 PM
include/llvm/Target/TargetLowering.h
2597

Also, you should take the std::string by const reference.

An updated patch will follow shortly.

include/llvm/Target/TargetLowering.h
2597

Line is too long.

It looks like I've forgotten to install my clang-format pre-commit hook again. I'll fix these.

lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
6598

If I use an assertion, then builds without assertions enabled will act as if nothing was wrong and try to continue. For most targets, this will mean that they die in SelectInlineAsmMemoryOperand() when it returns true, but a couple targets (Mips and SystemZ) will never notice and generate code. I could change Mips and SystemZ but there's also out-of-tree targets which might do the same thing. Overall, I think it's better to fail here for all builds.

dsanders updated this revision to Diff 21563.Mar 10 2015, 4:25 AM

Fix line length, comments referring to 'this change', and the 'const std::string &' argument.
I haven't changed the llvm_unreachables() to asserts() since some targets won't notice the missing mapping.

hfinkel added inline comments.Mar 10 2015, 5:53 AM
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
6598

I used to think this too (until very recently), but it's not true. llvm_unreachable is really just like assert; the implementation looks like this:

/// Marks that the current location is not supposed to be reachable.
/// In !NDEBUG builds, prints the message and location info to stderr.
/// In NDEBUG builds, becomes an optimizer hint that the current location
/// is not supposed to be reachable.  On compilers that don't support
/// such hints, prints a reduced message instead.
///
/// Use this instead of assert(0).  It conveys intent more clearly and
/// allows compilers to omit some unnecessary code.
#ifndef NDEBUG
#define llvm_unreachable(msg) \
  ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__)
#elif defined(LLVM_BUILTIN_UNREACHABLE)
#define llvm_unreachable(msg) LLVM_BUILTIN_UNREACHABLE
#else
#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
#endif

where LLVM_BUILTIN_UNREACHABLE in defined as:

/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
/// to an expression which states that it is undefined behavior for the
/// compiler to reach this point.  Otherwise is not defined.
#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0)
# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
#elif defined(_MSC_VER)
# define LLVM_BUILTIN_UNREACHABLE __assume(false)
#endif

And so, on recent compilers, this *really* is just like an assert, in fact, it is even stronger than that (providing explicit information to the optimizer than the condition is impossible).

Thus, please just use an assert.

Oh, I didn't know that. In that case I'll switch it over to an assert.

dsanders updated this revision to Diff 21577.Mar 10 2015, 7:35 AM

Switch the two conditional llvm_unreachable's to asserts.

Just to double check since I'm not 100% sure: Am I ok to commit at this point?

hfinkel accepted this revision.Mar 11 2015, 9:00 AM
hfinkel added a reviewer: hfinkel.

Yes, LGTM. Thanks!

This revision is now accepted and ready to land.Mar 11 2015, 9:00 AM
dsanders closed this revision.Mar 12 2015, 4:03 AM