/* PR rtl-optimization/91347 */
/* Reported by John David Anglin <danglin@gcc.gnu.org> */
/* { dg-additional-options "-std=gnu17" } */
/* { dg-require-effective-target int32plus } */

typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
typedef __u16 u16;
typedef __s32 s32;
typedef __u32 u32;
typedef __u64 u64;
typedef _Bool bool;
typedef s32 int32_t;
typedef u32 uint32_t;
typedef u64 uint64_t;

char hex_asc_upper[16];
u16 decpair[100];

static __attribute__((noipa)) void
put_dec_full4(char *buf, unsigned r) {
    unsigned q;
    q = (r * 0x147b) >> 19;
    *((u16 *)buf) = decpair[r - 100 * q];
    buf += 2;
    *((u16 *)buf) = decpair[q];
}

static __attribute__((noipa)) unsigned
put_dec_helper4(char *buf, unsigned x) {
    uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
    put_dec_full4(buf, x - q * 10000);
    return q;
}

static __attribute__((noipa)) char *
put_dec(char *buf, unsigned long long n) {
    uint32_t d3, d2, d1, q, h;
    d1 = ((uint32_t)n >> 16);
    h = (n >> 32);
    d2 = (h) & 0xffff;
    d3 = (h >> 16);
    q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
    q = put_dec_helper4(buf, q);
    q += 7671 * d3 + 9496 * d2 + 6 * d1;
    q = put_dec_helper4(buf + 4, q);
    q += 4749 * d3 + 42 * d2;
    q = put_dec_helper4(buf + 8, q);
    return buf;
}

struct printf_spec {
    unsigned int type : 8;
    signed int field_width : 24;
    unsigned int flags : 8;
    unsigned int base : 8;
    signed int precision : 16;
} __attribute__((__packed__));

static __attribute__((noipa)) char *
number(char *buf, char *end, unsigned long long num, struct printf_spec spec) {

    char tmp[3 * sizeof(num)] __attribute__((__aligned__(2)));
    char sign;
    char locase;
    int need_pfx = ((spec.flags & 64) && spec.base != 10);
    int i;
    bool is_zero = num == 0LL;
    int field_width = spec.field_width;
    int precision = spec.precision;

    i = 0;
    if (num < spec.base)
        tmp[i++] = hex_asc_upper[num] | locase;
    else if (spec.base != 10) {
        int mask = spec.base - 1;
        int shift = 3;
        if (spec.base == 16)
            shift = 4;
        else
            __builtin_abort();
        do {
            tmp[i++] = (hex_asc_upper[((unsigned char)num) & mask] | locase);
            num >>= shift;
        } while (num);
    } else {
        i = put_dec(tmp, num) - tmp;
    }
    return buf;
}

static __attribute__((noipa)) char *
pointer_string(char *buf, char *end, const void *ptr, struct printf_spec spec) {
    spec.base = 16;
    spec.flags = 0;
    return number(buf, end, 100, spec);
}

int main(void) {
    struct printf_spec spec;
    char *s = pointer_string(0, 0, 0, spec);
    return 0;
}
