| /* { dg-do compile } */ |
| /* { dg-options "-O2 -mlra" } */ |
| |
| typedef int SItype __attribute__ ((mode (SI))); |
| typedef unsigned int USItype __attribute__ ((mode (SI))); |
| typedef int DItype __attribute__ ((mode (DI))); |
| typedef unsigned int UDItype __attribute__ ((mode (DI))); |
| extern DItype __mulvdi3 (DItype, DItype); |
| struct DWstruct {SItype high, low;}; |
| |
| typedef union { |
| struct DWstruct s; |
| DItype ll; |
| } DWunion; |
| |
| DItype __mulvdi3 (DItype u, DItype v) { |
| const DWunion uu = {.ll = u}; |
| const DWunion vv = {.ll = v}; |
| |
| if (__builtin_expect (uu.s.high == uu.s.low >> ((4 * 8) - 1), 1)) { |
| if (__builtin_expect (vv.s.high == vv.s.low >> ((4 * 8) - 1), 1)) { |
| return (DItype) uu.s.low * (DItype) vv.s.low; |
| } else { |
| DWunion w0 = {.ll = (UDItype) (USItype) uu.s.low * (UDItype) (USItype) vv.s.low}; |
| DWunion w1 = {.ll = (UDItype) (USItype) uu.s.low * (UDItype) (USItype) vv.s.high}; |
| |
| if (vv.s.high < 0) |
| w1.s.high -= uu.s.low; |
| if (uu.s.low < 0) |
| w1.ll -= vv.ll; |
| w1.ll += (USItype) w0.s.high; |
| if (__builtin_expect (w1.s.high == w1.s.low >> ((4 * 8) - 1), 1)) { |
| w0.s.high = w1.s.low; |
| return w0.ll; |
| } |
| } |
| } else { |
| if (__builtin_expect (vv.s.high == vv.s.low >> ((4 * 8) - 1), 1)) { |
| DWunion w0 = {.ll = (UDItype) (USItype) uu.s.low * (UDItype) (USItype) vv.s.low}; |
| DWunion w1 = {.ll = (UDItype) (USItype) uu.s.high * (UDItype) (USItype) vv.s.low}; |
| |
| if (uu.s.high < 0) |
| w1.s.high -= vv.s.low; |
| if (vv.s.low < 0) |
| w1.ll -= uu.ll; |
| w1.ll += (USItype) w0.s.high; |
| if (__builtin_expect (w1.s.high == w1.s.low >> ((4 * 8) - 1), 1)) { |
| w0.s.high = w1.s.low; |
| return w0.ll; |
| } |
| } else { |
| if (uu.s.high >= 0) { |
| if (vv.s.high >= 0) { |
| if (uu.s.high == 0 && vv.s.high == 0) { |
| const DItype w = (UDItype) (USItype) uu.s.low * (UDItype) (USItype) vv.s.low; |
| if (__builtin_expect (w >= 0, 1)) |
| return w; |
| } |
| } else { |
| if (uu.s.high == 0 && vv.s.high == (SItype) -1) { |
| DWunion ww = {.ll = (UDItype) (USItype) uu.s.low * (UDItype) (USItype) vv.s.low}; |
| ww.s.high -= uu.s.low; |
| if (__builtin_expect (ww.s.high < 0, 1)) |
| return ww.ll; |
| } |
| } |
| } else { |
| if (vv.s.high >= 0) { |
| if (uu.s.high == (SItype) -1 && vv.s.high == 0) { |
| DWunion ww = {.ll = (UDItype) (USItype) uu.s.low * (UDItype) (USItype) vv.s.low}; |
| |
| ww.s.high -= vv.s.low; |
| if (__builtin_expect (ww.s.high < 0, 1)) |
| return ww.ll; |
| } |
| } else { |
| if ((uu.s.high & vv.s.high) == (SItype) -1 && (uu.s.low | vv.s.low) != 0) { |
| DWunion ww = {.ll = (UDItype) (USItype) uu.s.low * (UDItype) (USItype) vv.s.low}; |
| |
| ww.s.high -= uu.s.low; |
| ww.s.high -= vv.s.low; |
| if (__builtin_expect (ww.s.high >= 0, 1)) |
| return ww.ll; |
| } |
| } |
| } |
| } |
| } |
| __builtin_trap (); |
| } |