Skip to content

Commit

Permalink
fix: fix udivadd and ashr
Browse files Browse the repository at this point in the history
  • Loading branch information
dtcxzyw committed Oct 11, 2023
1 parent 7115059 commit ae6efdf
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 16 deletions.
31 changes: 17 additions & 14 deletions FSubFuscatorPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <llvm/IR/Intrinsics.h>
#include <llvm/IR/PassManager.h>
#include <llvm/IR/Value.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Support/ErrorHandling.h>
#include <llvm/Transforms/InstCombine/InstCombine.h>
#include <llvm/Transforms/Scalar/EarlyCSE.h>
Expand Down Expand Up @@ -165,7 +166,7 @@ class BitFuscatorImpl final : public InstVisitor<BitFuscatorImpl, Value *> {
VectorType *VT = dyn_cast<VectorType>(Bits->getType());
unsigned BitWidth = VT->getElementCount().getFixedValue();
SmallVector<int, 64> Mask(BitWidth);
std::iota(Mask.begin(), Mask.begin(), 1);
std::iota(Mask.begin(), Mask.begin() + BitWidth - 1, 1);
Mask.back() = BitWidth - 1;
return Builder.CreateShuffleVector(Bits, Mask);
}
Expand Down Expand Up @@ -297,28 +298,27 @@ class BitFuscatorImpl final : public InstVisitor<BitFuscatorImpl, Value *> {
Builder.CreateUnreachable();
// ShiftHeader
Builder.SetInsertPoint(ShiftHeader);
// a u<= b || b s< 0
// b u< a && b s> 0
auto EvalCondExpr = [&](Value *A, Value *B) {
auto [Res, Carry] =
addWithOverflowBits(A, B,
addWithOverflowBits(B, A,
/*Sub*/ true, /*Unsigned*/ true, Bits);
auto *Cond1 =
Builder.CreateOr(BitRep->convertFromBit(Carry), equalZero(Res));
auto *Cond2 = lessThanZero(B);
auto *Cond = Builder.CreateOr(Cond1, Cond2);
auto *Cond1 = BitRep->convertFromBit(Carry);
auto *Cond2 = Builder.CreateNot(lessThanZero(B));
auto *Cond = Builder.CreateAnd(Cond1, Cond2);
return Cond;
};
Builder.CreateCondBr(EvalCondExpr(Op1, Op2), SubstractHeader, ShiftBody);
Builder.CreateCondBr(EvalCondExpr(Op1, Op2), ShiftBody, SubstractHeader);
DTUpdates.push_back({DominatorTree::Insert, ShiftHeader, SubstractHeader});
DTUpdates.push_back({DominatorTree::Insert, ShiftHeader, ShiftBody});
// ShiftBody
Builder.SetInsertPoint(ShiftBody);
auto *B = Builder.CreatePHI(Op1->getType(), 2);
auto *Bit = Builder.CreatePHI(Op1->getType(), 2);
auto *NextB = lshr1(B);
auto *NextBit = lshr1(Bit);
// a u<= NextB || NextB s< 0
Builder.CreateCondBr(EvalCondExpr(Op1, NextB), SubstractHeader, ShiftBody);
auto *NextB = shl1(B);
auto *NextBit = shl1(Bit);
// NextB u< A && NextB s> 0
Builder.CreateCondBr(EvalCondExpr(Op1, NextB), ShiftBody, SubstractHeader);
DTUpdates.push_back({DominatorTree::Insert, ShiftBody, SubstractHeader});
DTUpdates.push_back({DominatorTree::Insert, ShiftBody, ShiftBody});
B->addIncoming(Op2, ShiftHeader);
Expand Down Expand Up @@ -351,7 +351,7 @@ class BitFuscatorImpl final : public InstVisitor<BitFuscatorImpl, Value *> {
Builder.CreateSelect(Cond, PhiRes, BitRep->bitOr(PhiRes, PhiBit));
auto *NextPhiBit = lshr1(PhiBit);
auto *NextPhiB = lshr1(PhiB);
Builder.CreateCondBr(equalZero(NextPhiA), Post, SubstractBody);
Builder.CreateCondBr(equalZero(NextPhiBit), Post, SubstractBody);
DTUpdates.push_back({DominatorTree::Insert, SubstractBody, Post});
DTUpdates.push_back({DominatorTree::Insert, SubstractBody, SubstractBody});
PhiA->addIncoming(Op1, SubstractHeader);
Expand Down Expand Up @@ -574,7 +574,7 @@ class BitFuscatorImpl final : public InstVisitor<BitFuscatorImpl, Value *> {
return visitCast(I, /*NullOp1*/ false, /*Freeze*/ true, Mask);
}
Value *visitICmp(ICmpInst &I) {
if (!I.getType()->isIntegerTy())
if (!I.getOperand(0)->getType()->isIntegerTy())
return nullptr;

auto *Op0 = I.getOperand(0);
Expand Down Expand Up @@ -797,6 +797,9 @@ class BitFuscatorImpl final : public InstVisitor<BitFuscatorImpl, Value *> {
break;
}

if (verifyFunction(F, &errs()))
report_fatal_error("BitFuscatorImpl: Function verification failed");

return Changed;
}
};
Expand Down
2 changes: 1 addition & 1 deletion csmith_fuzz.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
shutil.rmtree(tmp_dir)
os.makedirs(tmp_dir)

csmith_args = "--no-volatiles --no-bitfields --max-funcs 1 --max-block-depth 1 --max-block-size 1 --max-expr-complexity 1"
csmith_args = "--no-volatiles --no-bitfields --max-funcs 3"


def try_remove(filename):
Expand Down
142 changes: 141 additions & 1 deletion test.cpp
Original file line number Diff line number Diff line change
@@ -1,2 +1,142 @@
#include <cstdint>
int8_t gcd(int8_t a, int8_t b) { return b ? gcd(b, a % b) : a; }
#include <iostream>
#include <limits>
#include <random>
#include <type_traits>

template <typename T> class Test final {
T fib(T X) {
if (X <= 1)
return 1;
return fib(X - 1) + fib(X - 2);
}

T gcd(T A, T B) {
if (B == 0)
return A;
return gcd(B, A % B);
}

// std::minstd_rand RNG;
// std::uniform_int_distribution<T> Distrib{std::numeric_limits<T>::min()};
T Idx = 0;

T generate() {
Idx = Idx * 97 + 1;
return Idx;
// return Distrib(RNG);
}

public:
void run() {
using U = std::conditional_t<
std::is_same_v<int8_t, T> || std::is_same_v<uint8_t, T>,
std::conditional_t<std::is_same_v<int8_t, T>, int16_t, uint16_t>, T>;
constexpr int Count = 1000;
for (int I = 0; I < Count; ++I) {
T V = generate() % 20;
std::cout << "fib(" << U(V) << ") = " << U(T(fib(V))) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
std::cout << "gcd(" << U(A) << ", " << U(B) << ") = " << U(T(gcd(A, B)))
<< std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
std::cout << U(A) << " + " << U(B) << " = " << U(T(A + B)) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
std::cout << U(A) << " - " << U(B) << " = " << U(T(A - B)) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
std::cout << U(A) << " * " << U(B) << " = " << U(T(A * B)) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
if (B)
std::cout << U(A) << " / " << U(B) << " = " << U(T(A / B)) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
if (B)
std::cout << U(A) << " % " << U(B) << " = " << U(T(A % B)) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate() % 5;
T B = generate() % 5;
std::cout << U(A) << " == " << U(B) << " = " << (A == B) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate() % 5;
T B = generate() % 5;
std::cout << U(A) << " != " << U(B) << " = " << (A != B) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
std::cout << U(A) << " < " << U(B) << " = " << (A < B) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate() % 5;
T B = generate() % 5;
std::cout << U(A) << " <= " << U(B) << " = " << (A <= B) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
std::cout << U(A) << " > " << U(B) << " = " << (A > B) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate() % 5;
T B = generate() % 5;
std::cout << U(A) << " >= " << U(B) << " = " << (A >= B) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
std::cout << U(A) << " & " << U(B) << " = " << U(T(A & B)) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
std::cout << U(A) << " | " << U(B) << " = " << U(T(A | B)) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate();
std::cout << U(A) << " ^ " << U(B) << " = " << U(T(A ^ B)) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate() % (sizeof(T) * 8);
std::cout << U(A) << " << " << U(B) << " = " << U(T(A << B)) << std::endl;
}
for (int I = 0; I < Count; ++I) {
T A = generate();
T B = generate() % (sizeof(T) * 8);
std::cout << U(A) << " >> " << U(B) << " = " << U(T(A >> B)) << std::endl;
}
}
};

int main() {
puts("hello");
Test<int8_t>{}.run();
Test<uint8_t>{}.run();
Test<int16_t>{}.run();
Test<uint16_t>{}.run();
Test<int32_t>{}.run();
Test<uint32_t>{}.run();
Test<int64_t>{}.run();
Test<uint64_t>{}.run();
return 0;
}
5 changes: 5 additions & 0 deletions test.ll
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ define i4 @umax(i4 %a, i4 %b) {
ret i4 %c
}

define i1 @icmp_eq_ptr_nofold(ptr %a, ptr %b) {
%c = icmp eq ptr %a, %b
ret i1 %c
}

declare {i4, i1} @llvm.uadd.with.overflow.i4(i4 %a, i4 %b)
declare {i4, i1} @llvm.usub.with.overflow.i4(i4 %a, i4 %b)
declare {i4, i1} @llvm.sadd.with.overflow.i4(i4 %a, i4 %b)
Expand Down

0 comments on commit ae6efdf

Please sign in to comment.