'__restrict' defined empty when I include some RISC-V Newlib headers like <cmath>, <cstring>

17 views
Skip to first unread message

Bandhav Veluri

unread,
Jun 29, 2020, 12:48:48 PM6/29/20
to RISC-V SW Dev
Hi,

I am observing a strange behaviour in which Clang ignores __restirct when I include some standard headers. I'm running this with LLVM RISC-V backend using RISC-V GCC compiled Newlib as the C/C++ library: 

For example, this code:
void vec_add(int* __restrict a,
             int* __restrict b,
             int n) {
  #pragma unroll 4
  for(int i=0; i<n; ++i) {
    a[i] += b[i];
  }
}


results in:
; Function Attrs: nofree norecurse nounwind
define dso_local void @_Z7vec_addPiS_i(i32* noalias nocapture %a, i32* noalias nocapture readonly %b, i32 %n) local_unnam
ed_addr #0 {
entry:

.
.
...
(note the noaliass before function arguments).

But this code:
 #include <cmath>

 void vec_add(int* __restrict a,
              int* __restrict b,
              int n) {
   #pragma unroll 4
   for(int i=0; i<n; ++i) {
     a[i] += b[i];
   }
 }

results in:
; Function Attrs: nofree norecurse nounwind
define dso_local void @_Z7vec_addPiS_i(i32* nocapture %a, i32* nocapture readonly %b, i32 %n) local_unnamed_addr #0 {
entry:
  %cmp6 = icmp sgt i32 %n, 0
  br i1 %cmp6, label %for.body.preheader, label %for.cond.cleanup
.
.
...

I've a specific question and a broader question:
  1. Later found out __restrict__ seems to work. Is __restrict__ the right one to use? 
  2. Is it okay to use RISC-V GCC libraries & corresponding headers with LLVM?

Thank you,
Bandhav

Jim Wilson

unread,
Jun 29, 2020, 2:10:32 PM6/29/20
to Bandhav Veluri, RISC-V SW Dev
On Mon, Jun 29, 2020 at 9:48 AM Bandhav Veluri
<bandhav....@gmail.com> wrote:
> I am observing a strange behaviour in which Clang ignores __restirct when I include some standard headers. I'm running this with LLVM RISC-V backend using RISC-V GCC compiled Newlib as the C/C++ library:

I don't follow C++ or LLVM, but looking at this as a gcc/newlib problem...

The ISO C99 standard defines a keyword restrict. The __restrict and
__restrict__ keywords are a gcc extension that allows you to use
restrict even if you have chosen a C language version that doesn't
support restrict, such as C90. This also works for C++.

If you suspect a problem with a macro definition, with gcc, you can
use gcc -E-dD tmp.c > tmp.i to see all of the macro definitions, and
where they are. Trying this with your testcase, I find a problem in
sys/cdefs.h which translates to newlib/libc/include/sys/cdefs.h in the
newlib source tree. This file has

/*
* GCC 2.95 provides `__restrict' as an extension to C90 to support the
* C99-specific `restrict' type qualifier. We happen to use `__restrict' as
* a way to define the `restrict' type qualifier without disturbing older
* software that is unaware of C99 keywords.
*/
#if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95)
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901
#define __restrict
#else
#define __restrict restrict
#endif
#endif

So this is a newlib feature to use __restrict, leave it alone if
gcc-2.95 because it is a gcc feature, redefine it to restrict if
compiled with a C99+ compiler that supports restrict, and define it
away otherwise. The flaw here is that C++ compilers don't define
__STDC_VERSION__, so it always gets defined away for C++, even if this
is a C++ compiler that supports __restrict. This bug probably goes
back 20 years or so. I would suggest filing a bug report with
upstream newlib.

Jim

Jim Wilson

unread,
Jul 13, 2020, 9:59:22 PM7/13/20
to Bandhav Veluri, RISC-V SW Dev
On Mon, Jun 29, 2020 at 11:10 AM Jim Wilson <ji...@sifive.com> wrote:
> back 20 years or so. I would suggest filing a bug report with
> upstream newlib.

I didn't see anything on the newlib mailing list about this, so I
reported it myself.
https://sourceware.org/pipermail/newlib/2020/017769.html

Jim
Reply all
Reply to author
Forward
0 new messages