Skip to content

Commit

Permalink
compiler_rt: alu: add bitwise xor polyfills
Browse files Browse the repository at this point in the history
Add `__llvm_xor_iN_iN` family of polyfills to ALU.

Signed-off-by: Wojciech Zmuda <[email protected]>
  • Loading branch information
wzmuda committed Nov 18, 2024
1 parent e5a69c6 commit 85051eb
Show file tree
Hide file tree
Showing 8 changed files with 434 additions and 0 deletions.
1 change: 1 addition & 0 deletions compiler_rt/src/alu.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod and;
pub mod or;
pub mod xor;

mod test_case;
6 changes: 6 additions & 0 deletions compiler_rt/src/alu/xor.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub mod xor_i1;
pub mod xor_i8;
pub mod xor_i16;
pub mod xor_i32;
pub mod xor_i64;
pub mod xor_i128;
37 changes: 37 additions & 0 deletions compiler_rt/src/alu/xor/xor_i1.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use core::integer::Bitwise;
extern fn bitwise(lhs: u128, rhs: u128) -> (u128, u128, u128) implicits(Bitwise) nopanic;

pub fn __llvm_xor_i1_i1(lhs: u128, rhs: u128) -> u128 {
if lhs > 1 {
panic!("lhs = {:?} does not fit in bool", lhs)
}

if rhs > 1 {
panic!("rhs = {:?} does not fit in bool", rhs)
};

let (_, xor_result, _) = bitwise(lhs, rhs);
xor_result
}

#[cfg(test)]
mod tests {
use super::__llvm_xor_i1_i1;
use crate::alu::test_case::TestCase;
#[cairofmt::skip]
pub const test_cases: [TestCase; 4] = [
// All possible 1-bit cases
TestCase { lhs: 1, rhs: 1, expected: 0 },
TestCase { lhs: 1, rhs: 0, expected: 1 },
TestCase { lhs: 0, rhs: 1, expected: 1 },
TestCase { lhs: 0, rhs: 0, expected: 0 },
];

#[test]
fn test_i1() {
for case in test_cases
.span() {
assert_eq!(__llvm_xor_i1_i1(*case.lhs, *case.rhs), *case.expected);
}
}
}
70 changes: 70 additions & 0 deletions compiler_rt/src/alu/xor/xor_i128.cairo

Large diffs are not rendered by default.

80 changes: 80 additions & 0 deletions compiler_rt/src/alu/xor/xor_i16.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use core::integer::Bitwise;
extern fn bitwise(lhs: u128, rhs: u128) -> (u128, u128, u128) implicits(Bitwise) nopanic;

pub fn __llvm__xor_i16_i16(lhs: u128, rhs: u128) -> u128 {
let _: u16 = match lhs.try_into() {
Option::Some(value) => value,
Option::None => { panic!("lhs = {:?} does not fit in u16", lhs) },
};

let _: u16 = match rhs.try_into() {
Option::Some(value) => value,
Option::None => { panic!("rhs = {:?} does not fit in u16", rhs) },
};

let (_, xor_result, _) = bitwise(lhs, rhs);
xor_result
}

#[cfg(test)]
mod tests {
use super::__llvm__xor_i16_i16;
use crate::alu::test_case::TestCase;
#[cairofmt::skip]
pub const test_cases: [TestCase; 43] = [
// Random test cases
TestCase{lhs: 0b0010111111101001, rhs: 0b0110000101011010, expected: 0b0100111010110011},
TestCase{lhs: 0b0000100110100100, rhs: 0b0101101001101110, expected: 0b0101001111001010},
TestCase{lhs: 0b0000011100111010, rhs: 0b0001111101011010, expected: 0b0001100001100000},
TestCase{lhs: 0b0001000011111100, rhs: 0b0000000001011011, expected: 0b0001000010100111},
TestCase{lhs: 0b0010111001111100, rhs: 0b0010100100010011, expected: 0b0000011101101111},
TestCase{lhs: 0b0100000011001010, rhs: 0b0100111111101110, expected: 0b0000111100100100},
TestCase{lhs: 0b0101000110101111, rhs: 0b0100010010000001, expected: 0b0001010100101110},
TestCase{lhs: 0b0001001010101000, rhs: 0b0001100000010000, expected: 0b0000101010111000},
TestCase{lhs: 0b0011101001001110, rhs: 0b0001101100001101, expected: 0b0010000101000011},
TestCase{lhs: 0b0011110001110011, rhs: 0b0101101111111111, expected: 0b0110011110001100},
TestCase{lhs: 0b1101111101111101, rhs: 0b0111111001001000, expected: 0b1010000100110101},
TestCase{lhs: 0b1011001100111101, rhs: 0b0110011111111000, expected: 0b1101010011000101},
TestCase{lhs: 0b1010001000001110, rhs: 0b0111111110100100, expected: 0b1101110110101010},
TestCase{lhs: 0b1101111111001100, rhs: 0b0011001110101100, expected: 0b1110110001100000},
TestCase{lhs: 0b1000101010101011, rhs: 0b0101001110110001, expected: 0b1101100100011010},
TestCase{lhs: 0b1000010001101001, rhs: 0b0100001011111010, expected: 0b1100011010010011},
TestCase{lhs: 0b1010110110100010, rhs: 0b0111000010000111, expected: 0b1101110100100101},
TestCase{lhs: 0b1001001111001100, rhs: 0b0110001000110110, expected: 0b1111000111111010},
TestCase{lhs: 0b1111000000101010, rhs: 0b0011010010111101, expected: 0b1100010010010111},
TestCase{lhs: 0b1000011001011100, rhs: 0b0010001110010001, expected: 0b1010010111001101},
TestCase{lhs: 0b0001101100111110, rhs: 0b1100110001100101, expected: 0b1101011101011011},
TestCase{lhs: 0b0101001111110000, rhs: 0b1111000100001001, expected: 0b1010001011111001},
TestCase{lhs: 0b0011011011001101, rhs: 0b1000011101111000, expected: 0b1011000110110101},
TestCase{lhs: 0b0001000110110000, rhs: 0b1101101100001011, expected: 0b1100101010111011},
TestCase{lhs: 0b0101010101000000, rhs: 0b1000000000101110, expected: 0b1101010101101110},
TestCase{lhs: 0b0000111100000010, rhs: 0b1101011111101111, expected: 0b1101100011101101},
TestCase{lhs: 0b0110110000001011, rhs: 0b1111101000111101, expected: 0b1001011000110110},
TestCase{lhs: 0b0101101011100000, rhs: 0b1101101010001001, expected: 0b1000000001101001},
TestCase{lhs: 0b0000011101010001, rhs: 0b1000101001010010, expected: 0b1000110100000011},
TestCase{lhs: 0b0001001101111110, rhs: 0b1010010101101100, expected: 0b1011011000010010},
TestCase{lhs: 0b1110101111100101, rhs: 0b1000100011010000, expected: 0b0110001100110101},
TestCase{lhs: 0b1100011001101100, rhs: 0b1011110111101111, expected: 0b0111101110000011},
TestCase{lhs: 0b1011010110010110, rhs: 0b1100010011110110, expected: 0b0111000101100000},
TestCase{lhs: 0b1000010010111111, rhs: 0b1100111110111001, expected: 0b0100101100000110},
TestCase{lhs: 0b1110100000011010, rhs: 0b1000110000011000, expected: 0b0110010000000010},
TestCase{lhs: 0b1001100100010000, rhs: 0b1111011110111110, expected: 0b0110111010101110},
TestCase{lhs: 0b1011011101001010, rhs: 0b1110101011000100, expected: 0b0101110110001110},
TestCase{lhs: 0b1000110000011111, rhs: 0b1011110011111101, expected: 0b0011000011100010},
TestCase{lhs: 0b1100010100101011, rhs: 0b1100001111110000, expected: 0b0000011011011011},
TestCase{lhs: 0b1001111111110001, rhs: 0b1110001001000010, expected: 0b0111110110110011},

// Edge cases
TestCase{lhs: 0b1111111111111111, rhs: 0b1111111111111111, expected: 0b0000000000000000}, // Edge case: max & max (all bits set)
TestCase{lhs: 0b0000000000000000, rhs: 0b0000000000000000, expected: 0b0000000000000000}, // Edge case: min & min (no bits set)
TestCase{lhs: 0b1111111111111111, rhs: 0b0000000000000000, expected: 0b1111111111111111}, // Edge case: max & min (all bits vs no bits)
];

#[test]
fn test_i16() {
for case in test_cases
.span() {
assert_eq!(__llvm__xor_i16_i16(*case.lhs, *case.rhs), *case.expected);
}
}
}
80 changes: 80 additions & 0 deletions compiler_rt/src/alu/xor/xor_i32.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use core::integer::Bitwise;
extern fn bitwise(lhs: u128, rhs: u128) -> (u128, u128, u128) implicits(Bitwise) nopanic;

pub fn __llvm__xor_i32_i32(lhs: u128, rhs: u128) -> u128 {
let _: u32 = match lhs.try_into() {
Option::Some(value) => value,
Option::None => { panic!("lhs = {:?} does not fit in u32", lhs) },
};

let _: u32 = match rhs.try_into() {
Option::Some(value) => value,
Option::None => { panic!("rhs = {:?} does not fit in u32", rhs) },
};

let (_, xor_result, _) = bitwise(lhs, rhs);
xor_result
}

#[cfg(test)]
mod tests {
use super::__llvm__xor_i32_i32;
use crate::alu::test_case::TestCase;
#[cairofmt::skip]
pub const test_cases: [TestCase; 43] = [
// Random test cases
TestCase{lhs: 0b00000010111100001010000000100000, rhs: 0b01000111010011101100000111110111, expected: 0b01000101101111100110000111010111},
TestCase{lhs: 0b01001011111001110111010001111100, rhs: 0b00110111010110100100111001001010, expected: 0b01111100101111010011101000110110},
TestCase{lhs: 0b01100011100011011101100010001001, rhs: 0b01111111000101011000010101110000, expected: 0b00011100100110000101110111111001},
TestCase{lhs: 0b00001110000000011001001001110000, rhs: 0b01011101110111001100110101010101, expected: 0b01010011110111010101111100100101},
TestCase{lhs: 0b00110001111011011011001000001110, rhs: 0b01011101011011110001111000010100, expected: 0b01101100100000101010110000011010},
TestCase{lhs: 0b01001101111010101001011001111100, rhs: 0b00111111010101101101000000100100, expected: 0b01110010101111000100011001011000},
TestCase{lhs: 0b01111111110100000101011011100100, rhs: 0b01011101100100010010010111111111, expected: 0b00100010010000010111001100011011},
TestCase{lhs: 0b01000010000000011100000011001100, rhs: 0b00100000000111010101110110100110, expected: 0b01100010000111001001110101101010},
TestCase{lhs: 0b00100011101000100111000100001110, rhs: 0b01001011101111010001001000000101, expected: 0b01101000000111110110001100001011},
TestCase{lhs: 0b00011101101001000111101000111000, rhs: 0b00011010000111010010010110000011, expected: 0b00000111101110010101111110111011},
TestCase{lhs: 0b11010110000110100001110001001001, rhs: 0b01111001101111101110101000101100, expected: 0b10101111101001001111011001100101},
TestCase{lhs: 0b10001110011010010001000101010100, rhs: 0b00101110001100011110001110001111, expected: 0b10100000010110001111001011011011},
TestCase{lhs: 0b11110001110001101011000001100001, rhs: 0b00000101000100110011111011110101, expected: 0b11110100110101011000111010010100},
TestCase{lhs: 0b10101000110001101011101101100111, rhs: 0b01000110111001111111000010100011, expected: 0b11101110001000010100101111000100},
TestCase{lhs: 0b10110110110010100111100011110011, rhs: 0b01000101100100000101001100011110, expected: 0b11110011010110100010101111101101},
TestCase{lhs: 0b11101100110101011111001100011011, rhs: 0b01101101000000100100100100111110, expected: 0b10000001110101111011101000100101},
TestCase{lhs: 0b10111000100111111101010111001110, rhs: 0b01010110011000101011011000100001, expected: 0b11101110111111010110001111101111},
TestCase{lhs: 0b11010110101001000000100110100001, rhs: 0b00001110100101101011001110111101, expected: 0b11011000001100101011101000011100},
TestCase{lhs: 0b10000110101100110101000110010111, rhs: 0b01110000010100001101000011000101, expected: 0b11110110111000111000000101010010},
TestCase{lhs: 0b11011001011111010110001010101100, rhs: 0b01010101001011100010000100000010, expected: 0b10001100010100110100001110101110},
TestCase{lhs: 0b00011111100000111111000001100011, rhs: 0b11010110010001111001100010000001, expected: 0b11001001110001000110100011100010},
TestCase{lhs: 0b01000001010101111001101101001100, rhs: 0b11110011010110110000001101010100, expected: 0b10110010000011001001100000011000},
TestCase{lhs: 0b00110111000101100110011001100110, rhs: 0b11000001100010100001011000110011, expected: 0b11110110100111000111000001010101},
TestCase{lhs: 0b00111000110011110000101110110010, rhs: 0b11000001001001011101010101000001, expected: 0b11111001111010101101111011110011},
TestCase{lhs: 0b00010100111110100101101101111110, rhs: 0b11010010100011001011011110000011, expected: 0b11000110011101101110110011111101},
TestCase{lhs: 0b01110000101110101000010011110010, rhs: 0b11110000111111011100000111000010, expected: 0b10000000010001110100010100110000},
TestCase{lhs: 0b01110110010001010111001011100111, rhs: 0b10101111101110111111000111000100, expected: 0b11011001111111101000001100100011},
TestCase{lhs: 0b01110111100001111100010010011101, rhs: 0b10110000001101001111111111100100, expected: 0b11000111101100110011101101111001},
TestCase{lhs: 0b01110001010010101000001101110110, rhs: 0b11011001111101001111010010011001, expected: 0b10101000101111100111011111101111},
TestCase{lhs: 0b01111001101111010000111001100111, rhs: 0b11110001100101110001010110111100, expected: 0b10001000001010100001101111011011},
TestCase{lhs: 0b10101111110000010110010000101110, rhs: 0b11101100111100000001110011110011, expected: 0b01000011001100010111100011011101},
TestCase{lhs: 0b11111110110110010101000111001110, rhs: 0b10100110000000010011110101011010, expected: 0b01011000110110000110110010010100},
TestCase{lhs: 0b11000011000001100100101111001111, rhs: 0b10101111001110111001010010101100, expected: 0b01101100001111011101111101100011},
TestCase{lhs: 0b11011101100001001100110011001110, rhs: 0b11110000110100010110110110111111, expected: 0b00101101010101011010000101110001},
TestCase{lhs: 0b10000001001011001010111101000101, rhs: 0b10011111101001000110001100001001, expected: 0b00011110100010001100110001001100},
TestCase{lhs: 0b10110100010100001011000001111001, rhs: 0b11000010001000101100100111001100, expected: 0b01110110011100100111100110110101},
TestCase{lhs: 0b11101111011111111001010111001010, rhs: 0b10001110111000000100101110101111, expected: 0b01100001100111111101111001100101},
TestCase{lhs: 0b11000010111110000011000011100100, rhs: 0b10100011001001001011111110001010, expected: 0b01100001110111001000111101101110},
TestCase{lhs: 0b10000010000111100111101110110110, rhs: 0b10110100010100100011100010001100, expected: 0b00110110010011000100001100111010},
TestCase{lhs: 0b10101011011100011101111100011110, rhs: 0b11111011000010111110000000111100, expected: 0b01010000011110100011111100100010},

// Edge cases
TestCase{lhs: 0b11111111111111111111111111111111, rhs: 0b11111111111111111111111111111111, expected: 0b00000000000000000000000000000000}, // Edge case: max & max (all bits set)
TestCase{lhs: 0b00000000000000000000000000000000, rhs: 0b00000000000000000000000000000000, expected: 0b00000000000000000000000000000000}, // Edge case: min & min (no bits set)
TestCase{lhs: 0b11111111111111111111111111111111, rhs: 0b00000000000000000000000000000000, expected: 0b11111111111111111111111111111111}, // Edge case: max & min (all bits vs no bits)
];

#[test]
fn test_i32() {
for case in test_cases
.span() {
assert_eq!(__llvm__xor_i32_i32(*case.lhs, *case.rhs), *case.expected);
}
}
}
Loading

0 comments on commit 85051eb

Please sign in to comment.