constant propagation produces undef

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

constant propagation produces undef

Alireza.Moshtaghi

I’m sure I’m missing something in my port for PIC16 because the following code produces undef for pic16 but it is ok for other ports but I’m not sure what is it that I’m missing.

Looks like the constant propagation pass finds out that f() is always returning 16 and it tries to substitute the call site in the shift with statement 16. But since int is 16 bit it results in undef in the input of check() function while zero is expected.

If I modify f() to return 15 I will get the correct code.

I was wondering if someone can give me a clue as what is it that I’m missing.

 

By the way, this problem is happening on clang with optimizations on (-O1). Without optimizations, things work fine.

 

extern int k; //int is 16 bit

extern int C;

int f(void)

{

  return 16;

}

 

void check(int );

 

int main (void)

{

  k = 1;

  C = k << f();

  check (C);

  return 0;

}

 

Produces :

 

@k = external global i16                          ; <i16*> [#uses=1]

 

define i16 @f() nounwind readnone {

entry:

  ret i16 16

}

 

define i16 @main() nounwind {

entry:

  store i16 1, i16* @k

  tail call void @check(i16 undef) nounwind

  ret i16 0

}

 

Thanks

Ali

 


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] constant propagation produces undef

Eli Friedman
On Fri, Jan 22, 2010 at 8:57 AM,  <[hidden email]> wrote:
> I’m sure I’m missing something in my port for PIC16 because the following
> code produces undef for pic16 but it is ok for other ports but I’m not sure
> what is it that I’m missing.
>
> Looks like the constant propagation pass finds out that f() is always
> returning 16 and it tries to substitute the call site in the shift with
> statement 16. But since int is 16 bit it results in undef in the input of
> check() function while zero is expected.

If int is 16 bits, 1<<16 is undefined, not zero.  If you want a "safe"
shift, try defining something like the following:

static inline int safe_shift(int a, int b) {
  return b>=16?0:a<<b;
}

-Eli

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] constant propagation produces undef

Alireza.Moshtaghi
For us all undefined values are zero, I tried it on ARM and X86 also and
clang generates zero, and not an undefined.

Maybe the better question would be "how can I tell clang to replace all
undefined values with zero constant?"

Thanks
A.

-----Original Message-----
From: Eli Friedman [mailto:[hidden email]]
Sent: Friday, January 22, 2010 10:10 AM
To: Alireza Moshtaghi - C13012
Cc: [hidden email]
Subject: Re: [cfe-dev] constant propagation produces undef

On Fri, Jan 22, 2010 at 8:57 AM,  <[hidden email]>
wrote:
> I'm sure I'm missing something in my port for PIC16 because the
following
> code produces undef for pic16 but it is ok for other ports but I'm not
sure
> what is it that I'm missing.
>
> Looks like the constant propagation pass finds out that f() is always
> returning 16 and it tries to substitute the call site in the shift
with
> statement 16. But since int is 16 bit it results in undef in the input
of
> check() function while zero is expected.

If int is 16 bits, 1<<16 is undefined, not zero.  If you want a "safe"
shift, try defining something like the following:

static inline int safe_shift(int a, int b) {
  return b>=16?0:a<<b;
}

-Eli

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] constant propagation produces undef

Chris Lattner

On Jan 22, 2010, at 9:24 AM, [hidden email] wrote:

> For us all undefined values are zero, I tried it on ARM and X86 also  
> and
> clang generates zero, and not an undefined.

That is because on x86 and arm, int -> i32.  This produces undef on x86:

int test() {
int x = 1;
return x << 32;
}


> Maybe the better question would be "how can I tell clang to replace  
> all
> undefined values with zero constant?"

You can't, that's not how C works.  If you build with the -fcatch-
undefined-behavior option, it should catch this error at runtime.

-Chris
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [cfe-dev] constant propagation produces undef

Alireza.Moshtaghi
Thanks,
I fixed it in the backend.

A.

-----Original Message-----
From: Chris Lattner [mailto:[hidden email]]
Sent: Friday, January 22, 2010 11:11 AM
To: Alireza Moshtaghi - C13012
Cc: [hidden email]; [hidden email]
Subject: Re: [cfe-dev] constant propagation produces undef


On Jan 22, 2010, at 9:24 AM, [hidden email] wrote:

> For us all undefined values are zero, I tried it on ARM and X86 also  
> and
> clang generates zero, and not an undefined.

That is because on x86 and arm, int -> i32.  This produces undef on x86:

int test() {
int x = 1;
return x << 32;
}


> Maybe the better question would be "how can I tell clang to replace  
> all
> undefined values with zero constant?"

You can't, that's not how C works.  If you build with the -fcatch-
undefined-behavior option, it should catch this error at runtime.

-Chris

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev