0

It seems to me, that clang++ miss errors in assembler code that g++ pick up. Or am I missing some compiler flag for clang? I'm new to assembler code.

Using clang++ I have compiled and linked my application error and warning free, yet I have had nasty segmentation faults. Switching to g++, I on the other hand I got these errors:

GO_F_ImageColourConversion.cpp: Assembler messages:
GO_F_ImageColourConversion.cpp:4679: Error: `(%rsi,%edx,2)' is not a valid base/index expression 
GO_F_ImageColourConversion.cpp:4682: Error: `(%rcx,%edx,1)' is not a valid base/index expression

I am using these compiler flags: -DLINUX -g -Wno-deprecated -D_GNU_SOURCE -D_REENTRANT -D__STDC_CONSTANT_MACROS -fPIC -fPIE

I have the following code (omitting unrelevant parts):

Ipp8u * pSrc;
Ipp8u * pDst;
int x, y;

                asm volatile
                    (
                     "movl      (%1, %0, 2), %%eax;\n"
                     "shlw      $8, %%ax;\n"
                     "shrl      $8, %%eax;\n"
                     "movw      %%ax, (%2, %0, 1);\n"

                    : /* no output */
                    : "r" (x), "r" (pSrc), "r" (pDst)
                    : "eax", "memory");
            }

From looking at this answer on SO, I realized I had a 32/64 bit isssue (I am porting to 64-bit).The Ipp8u* is 8 bit but int only 4 bit on my machine.

Changing the int to uintptr_t x, y; seems to fix the issue. Why does clang not give error on compile?

Community
  • 1
  • 1
Per M.
  • 95
  • 1
  • 11
  • 2
    Presumably because clang substitutes the proper 64 bit register automatically. You haven't shown the generated assembly for clang, but I assume it's a valid `(%rsi,%rdx,2)`. PS: assembly is not needed for this, the compiler surely can generate good code from C. Also this is a particularly bad assembly code. – Jester Apr 27 '16 at 10:34

1 Answers1

2

gcc and clang both choke on your code for me:

6 : error: base register is 64-bit, but index register is not
"movl (%1, %0, 2), %%eax\n"
^
<inline asm>:1:13: note: instantiated into assembly here
movl (%rdi, %edx, 2), %eax

From clang 3.8 on the godbolt compiler explorer, with a function wrapped around it so it's testable, which you failed to provide in the question. Are you sure your clang was building 64bit code? (-m64, not -m32 or -mx32).

Provide a link to your code on godbolt with some version of clang silently mis-compiling it, otherwise all I can say for your actual question is just "can't reproduce".

And yes, your problem is that x is an int, and your problem is mixed register sizes in the addressing mode. (%rsi,%edx,2) isn't encodable.


Using %q0 to get %rdx doesn't guarantee that there isn't garbage in the high 32bits of the register (although it's highly unlikely). Instead, you could use "r" ((int64_t)x) to sign-extend x to 64bits.

Why do you need inline asm at all? How bad is the compiler output for your C version of this?

If you do want to use inline asm, this is much better:

uint32_t asm_tmp = *(uint32_t *)(x*2 + (char*)pSrc);  // I think I've reproduced the same pointer math as the addressing mode you used.
asm ( "shlw      $8, %w[v]\n\t"    // e.g.  ax
      "shrl      $8, %k[v]\n\t"    // e.g. eax.  potential partial-register slowdown from reading eax after writing ax on older CPUs
      : [v] "+&r" (asm_tmp)
      );
*(uint16_t *)(x + (char*)pDst) = asm_tmp;  // store the low 16

This compiles nicely with clang, but gcc is kinda braindead about generating the address. Maybe with a different expression for the addresses?

Your code was defeating the purpose of constraints by starting with a load and ending with a store. Always let the compiler handle as much as possible. It's possible you'd get better code from this without inline asm, and the compiler would understand what it does and could potentially auto-vectorize or do other transformations. Removing the need for the asm statement to be volatile with a "memory" clobber is already a big improvement for the optimizer: Now it's a pure function that the compiler knows just transforms one register.

Also see the end of this answer for more guides to writing inline asm that doesn't suck.

Community
  • 1
  • 1
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Let me stress that I'm new to inline asm. I'm porting some old C++ code and there is a lot of assembly in it. I would rather have it all in C(++), but I would need to learn to read asm first in order to rewrite it. I am sure the compiler could produce good code, as @Jester also points out. Thanks for pointing out godbolt. I changed compiler to clang 3.0, which I use and it compiled ok [link](https://godbolt.org/g/tDFrhk) I don't know if the result is good though... I guess it would be a good idea for me to update my clang-compiler. – Per M. Apr 27 '16 at 14:46
  • @PerM.: Why are you using such an ancient version of clang? The new release version is 3.8, and the current stable is 3.7. Anyway, the clang3.0 output uses 32bit registers for both parts of the addressing mode, so it will break any time you use it on addresses outside the low 2G of virtual address space. (32bit addressing modes in 64bit code are sign-extended). In this one case, you should use my code. It compiles to optimal code with clang, and can inline. For the rest of your code, I don't think trial and error is going to work very well. You need someone that understands asm. – Peter Cordes Apr 27 '16 at 15:04
  • @PeterCordes : Clang 3.0 to me is not unusual at all. It is the version that Ubuntu 12.04 (long Term Support) uses. Canonical will be supporting 12.04 through part of 2017. I've got a couple clients that use this particular Linux distro as they also pay for Canonical support. – Michael Petch Apr 27 '16 at 18:32
  • @MichaelPetch: I wouldn't recommend using the compiler shipped with a crusty old LTS release, esp. one that's not even the current LTS release. Sure it will build correct code, but if you want it to auto-vectorize for modern CPUs, newer clang has significant improvements. There's an [official (llvm.or) PPA for clang](http://llvm.org/apt/) on Debian / Ubuntu, with stable and current versions. I think I'd recommend clang 3.7 for shipping binaries. clang 3.8 does better in some cases, but it's still very new and has the occasional bug. – Peter Cordes Apr 27 '16 at 18:43
  • @PeterCordes : You must not do a lot of development for larger companies. Many will standardize on a set of tools across their enterprise. You may feel it is "crusty", but in the enterprise they may see it as "proven", and if they use officially supported versions for that platform they can get direct Enterprise support from Canonical. Windows XP still has a large install base for the same reason. Sometimes large businesses work on the premise of "If it's not broken don't fix it". – Michael Petch Apr 27 '16 at 18:49
  • @PeterCordes : I know your feeling on Windows XP and 32-bit, but you seem to take what appears to me (correct me if I'm wrong) an individualistic or academic approach to software tools and development. In the business world there is often the pragmatic approach to hardware, software, and support. What you consider outdated would be your opinion, but there can be very legitimate reasons why companies hold onto older technology. – Michael Petch Apr 27 '16 at 18:51
  • Do I tell my client who has an install base of thousands of embedded devices that they should remove their 80188 processors running FreeDOS in real mode because DOS by modern academic standards is somehow not a real OS, and that no one would dare program in segmented real mode if they are a real programmer? They don't change because that environment and the processor they use does exactly the job they need and it works great in their critical infrastructure. – Michael Petch Apr 27 '16 at 18:55
  • @MichaelPetch: Yeah, you're correct on both counts. I haven't worked for a big company, and I'm not a fan of holding back progress for short-term reasons. I understand there are reasons for using obsolete software, mainly that they've had time to work the bugs out. Compiler bugs happen, and take time to be discovered. However, when I look at compiler output, newer versions almost always make better code than old versions, so there is a real upside to new versions. I'm not mad at people for keeping the same compiler version for existing projects, though. – Peter Cordes Apr 27 '16 at 18:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/110422/discussion-between-peter-cordes-and-michael-petch). – Peter Cordes Apr 27 '16 at 18:58