mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
AVR: target/114981 - Support __builtin_powi[l] / __powidf2.
This supports __powidf2 by means of a double wrapper for already existing f7_powi (renamed to __f7_powi by f7-renames.h). It tweaks the implementation so that it does not perform trivial multiplications with 1.0 any more, but instead uses a move. It also fixes the last statement of f7_powi, which was wrong. Notice that f7_powi was unused until now. PR target/114981 libgcc/config/avr/libf7/ * libf7-common.mk (F7_ASM_PARTS): Add D_powi * libf7-asm.sx (F7MOD_D_powi_, __powidf2): New module and function. * libf7.c (f7_powi): Fix last (wrong) statement. Tweak trivial multiplications with 1.0. gcc/testsuite/ * gcc.target/avr/pr114981-powil.c: New test.
This commit is contained in:
parent
2f00e6caca
commit
de4eea7d7e
33
gcc/testsuite/gcc.target/avr/pr114981-powil.c
Normal file
33
gcc/testsuite/gcc.target/avr/pr114981-powil.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* { dg-do run { target { ! avr_tiny } } } */
|
||||
/* { dg-additional-options "-Os" } */
|
||||
|
||||
const long double vals[] =
|
||||
{
|
||||
0.0625L, -0.125L, 0.25L, -0.5L,
|
||||
1.0L,
|
||||
-2.0L, 4.0L, -8.0L, 16.0L
|
||||
};
|
||||
|
||||
#define ARRAY_SIZE(X) ((int) (sizeof(X) / sizeof(*X)))
|
||||
|
||||
__attribute__((noinline,noclone))
|
||||
void test1 (long double x)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (vals); ++i)
|
||||
{
|
||||
long double val0 = vals[i];
|
||||
long double val1 = __builtin_powil (x, i - 4);
|
||||
__asm ("" : "+r" (val0));
|
||||
|
||||
if (val0 != val1)
|
||||
__builtin_exit (__LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
test1 (-2.0L);
|
||||
return 0;
|
||||
}
|
@ -1877,4 +1877,16 @@ ENDF call_ddd
|
||||
|
||||
#include "f7-wraps.h"
|
||||
|
||||
;;; Some additional, singular wraps that don't match any pattern.
|
||||
|
||||
;; double __powidf2 (double, int) ; __builtin_powi
|
||||
#ifdef F7MOD_D_powi_
|
||||
_DEFUN __powidf2
|
||||
.global F7_NAME(powi)
|
||||
ldi ZH, hi8(gs(F7_NAME(powi)))
|
||||
ldi ZL, lo8(gs(F7_NAME(powi)))
|
||||
F7jmp call_ddx
|
||||
_ENDF __powidf2
|
||||
#endif /* F7MOD_D_powi_ */
|
||||
|
||||
#endif /* !AVR_TINY */
|
||||
|
@ -22,7 +22,7 @@ F7_ASM_PARTS += addsub_mant_scaled store load
|
||||
F7_ASM_PARTS += to_integer to_unsigned clz normalize_with_carry normalize
|
||||
F7_ASM_PARTS += store_expo sqrt16 sqrt_approx div
|
||||
|
||||
F7_ASM_PARTS += D_class D_fma
|
||||
F7_ASM_PARTS += D_class D_fma D_powi
|
||||
F7_ASM_PARTS += D_isnan D_isinf D_isfinite D_signbit D_copysign D_neg D_fabs
|
||||
|
||||
F7_ASM_PARTS += call_dd call_ddd
|
||||
|
@ -1752,20 +1752,33 @@ void f7_powi (f7_t *cc, const f7_t *aa, int ii)
|
||||
{
|
||||
uint16_t u16 = ii;
|
||||
f7_t xx27, *xx2 = &xx27;
|
||||
bool cc_is_one = true;
|
||||
bool expo_is_neg = false;
|
||||
|
||||
if (ii < 0)
|
||||
{
|
||||
u16 = -u16;
|
||||
expo_is_neg = true;
|
||||
}
|
||||
|
||||
f7_copy (xx2, aa);
|
||||
|
||||
f7_set_u16 (cc, 1);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (u16 & 1)
|
||||
{
|
||||
if (cc_is_one)
|
||||
{
|
||||
// C *= X2 simplifies to C = X2.
|
||||
f7_copy (cc, xx2);
|
||||
cc_is_one = false;
|
||||
}
|
||||
else
|
||||
f7_Imul (cc, xx2);
|
||||
}
|
||||
|
||||
if (! f7_is_nonzero (cc))
|
||||
if (! cc_is_one
|
||||
&& ! f7_is_nonzero (cc))
|
||||
break;
|
||||
|
||||
u16 >>= 1;
|
||||
@ -1774,8 +1787,10 @@ void f7_powi (f7_t *cc, const f7_t *aa, int ii)
|
||||
f7_Isquare (xx2);
|
||||
}
|
||||
|
||||
if (ii < 0)
|
||||
f7_div1 (xx2, aa);
|
||||
if (cc_is_one)
|
||||
f7_set_u16 (cc, 1);
|
||||
else if (expo_is_neg)
|
||||
f7_div1 (cc, cc);
|
||||
}
|
||||
#endif // F7MOD_powi_
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user