This is an archive of the discontinued LLVM Phabricator instance.

[clang] model 'p' inline asm constraint as reading memory
AbandonedPublic

Authored by nickdesaulniers on Mar 6 2023, 1:00 PM.

Details

Summary

GCC doesn't CSE inline asm when 'p' is used on inputs, neither should
clang. In order to do so, we must not set memory(none) modref on such
inline asm.

If you're passing the address of a variable into inline asm as an
operand, you're going to be reading memory!

Link: https://lore.kernel.org/lkml/20230306120106.GE1267364@hirez.programming.kicks-ass.net/

Diff Detail

Event Timeline

nickdesaulniers created this revision.Mar 6 2023, 1:00 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 6 2023, 1:00 PM
nickdesaulniers requested review of this revision.Mar 6 2023, 1:00 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 6 2023, 1:00 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript

I think this is going to change what inputs Sema will accept for "p". If that's intentional, please add test coverage. Otherwise, please make a narrower change.

nickdesaulniers planned changes to this revision.EditedMar 6 2023, 1:27 PM

I think this is going to change what inputs Sema will accept for "p". If that's intentional, please add test coverage. Otherwise, please make a narrower change.

Your hunch is correct, though this change as written doesn't change what Sema will accept. Testing this locally, I previously had tried just adding Info.setAllowsMemory(); for "p" and NOT Info.setAllowsRegister();; that caused Sema to reject non-ptr arguments.

I will add test cases regardless.

  • add sema test to validate 'p' inputs as per @efriedma
nickdesaulniers added inline comments.Mar 6 2023, 1:34 PM
clang/lib/Basic/TargetInfo.cpp
747–748

I wonder if we should make this change for outputs, too?

nickdesaulniers planned changes to this revision.Mar 6 2023, 2:42 PM
nickdesaulniers added inline comments.
clang/test/Sema/inline-asm-validate.c
9

I should add a test case for "p"(&t).

  • add test additional case for Sema

It looks to me from GCC that constraint 'p' is intended to be used internally, not for inline-asm. I question whether the kernel should be using it, and whether we should even implement it at all.

It looks to me from GCC that constraint 'p' is intended to be used internally, not for inline-asm. I question whether the kernel should be using it, and whether we should even implement it at all.

p is a documented "simple constraint": https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html#Simple-Constraints

‘p’ in the constraint must be accompanied by address_operand as the predicate in the match_operand. This predicate interprets the mode specified in the match_operand as the mode of the memory reference for which the address would be valid.

How do you do that with inline-asm?

‘p’ in the constraint must be accompanied by address_operand as the predicate in the match_operand. This predicate interprets the mode specified in the match_operand as the mode of the memory reference for which the address would be valid.

How do you do that with inline-asm?

Good question. The only tests I see GCC using with "=p" or "p" (no "+p" AFAICT) are:

  1. https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/testsuite/gcc.dg/pr58805.c;h=b46f7764260b29bc82fc8226d20019f05c5e05c0;hb=HEAD
  2. https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/testsuite/gcc.dg/asm-4.c;h=180578e64e1dd68c2f5619f31fa46ac3433fd226;hb=HEAD

(maybe my grep-fu is weak). These didn't help explain what that sentence means (though maybe my comprehension skills are weak). AFAICT, the docs were added in this massive commit:
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=03dda8e3c3b2f

Looking at why the kernel ever used it, it looks like:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v6.3-rc1&id=97b67ae559947f1e208439a1bf6a734da3087006 introduced it. That commit refers to an issue that was fixed in gcc 4.9:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63637

The linux kernel only support gcc 5.1+, so that issue is now irrelevant from the kernel's standpoint. Maybe it is time to unwind that change (97b67ae559947f1e208439a1bf6a734da3087006)...

Wrong commit. Hard to spot, but "p" was being used previously.

Also, I note the doc says it's useful for for “load address” and “push address” instructions (note, "load address" means e.g. x86 "lea" instruction) -- which should NOT be dependent upon the value stored in the memory. The x86 backend actually uses a "Ts" constraint for *lea<mode> which is defined by define_address_constraint, documented as making a constraint that is basically equivalent to p (just with different limits as to what kinds of addresses are accepted.)

"p" and other define_address_constraints are also used a lot for "prefetch" kinds of instructions, which also should not be memory-value-dependent.

So, at least per that description, and usage within GCC, I think LLVM's previous behavior of allowing it to move past a store to the same address actually seems correct?

jyknight requested changes to this revision.Apr 24 2023, 9:24 AM

I believe this is abandoned, correct?

This revision now requires changes to proceed.Apr 24 2023, 9:24 AM
nickdesaulniers abandoned this revision.Apr 24 2023, 9:26 AM