Skip to content

Another mir-opt-level=4 miscompilation #91725

Closed
@leonardo-m

Description

@leonardo-m

This is a bad bug report because the code to reproduce it is long. But I'm bad at spotting what the problem is here.

If I compile this code with

rustc -O -Z mir-opt-level=3 test.rs

It runs very quickly. If I compile it with:

rustc -O -Z mir-opt-level=4 test.rs

I think it goes into an infinite loop.

I think the miscompilation problem is in the "while b != 1" loop inside the residue() function.

I've seen that the asm for the residue() function (adding inline(never) to residue() and jacobi()) gets quite shorter if I use opt-level=4.

fn mul_mod(a: u32, b: u32, m: u32) -> u32 {
    ((a as u64 * b as u64) % (m as u64)) as u32
}

fn pow_mod(a: u32, n: u32, p: u32) -> u32 {
    if n == 0 {
        return 1;
    }
    if n % 2 == 0 {
        pow_mod(mul_mod(a, a, p), n / 2, p)
    } else {
        mul_mod(a, pow_mod(a, n - 1, p), p)
    }
}

fn jacobi(mut a: u32, mut m: u32) -> i32 {
    let mut t = 1;
    a %= m;
    while a != 0 {
        while (a & 1) == 0 {
            a >>= 1;
            if (m & 7) == 3 || (m & 7) == 5 {
                t = -t;
            }
        }
        let aux = a;
        a = m;
        m = aux;
        if (a & 3) == 3 && (m & 3) == 3 {
            t = -t;
        }
        a %= m;
    }
    if m == 1 { t } else { 0 }
}

fn residue(prime: u32, arg: u32) -> u32 {
    if jacobi(arg, prime) == -1 {
        return u32::MAX;
    }

    let mut y = 2;
    while jacobi(y, prime) != -1 {
        y += 1;
    }

    let mut r: u32 = 0;
    let mut q: u32 = prime - 1;
    while q % 2 == 0 {
        r += 1;
        q /= 2;
    }

    let mut result = prime - 1;
    result >>= r;
    y = pow_mod(y, result, prime);
    result >>= 1;
    let mut b = pow_mod(arg, result, prime);
    result = mul_mod(arg, b, prime);
    b *= result;
    b = b % prime;

    while b != 1 {
        let mut t = mul_mod(b, b, prime);
        let mut m: u32 = 1;
        while t != 1 {
            t *= t;
            t = t % prime;
            m += 1;
        }
        t = 0;
        t |= 1 << (r - m - 1);
        t = pow_mod(y, t, prime);
        y = mul_mod(t, t, prime);
        r = m;
        result = mul_mod(result, t, prime);
        b = mul_mod(b, y, prime);
    }
    result
}


fn main() {
    assert_eq!(residue(5, 4), 3);
}

Using:

rustc 1.59.0-nightly (e6b883c74 2021-12-08)
binary: rustc
commit-hash: e6b883c74f49f32cb5d1cbad3457f2b8805a4a38
commit-date: 2021-12-08
host: x86_64-pc-windows-gnu
release: 1.59.0-nightly
LLVM version: 13.0.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-mir-optArea: MIR optimizationsC-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions