-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[InstCombine] Missed optimization for (x * z) % (y * z) == 0
=> x % y == 0
#76585
Comments
We fail to remove constants with common factors as well: define i1 @src(i8 noundef %0, i8 noundef %1) {
%3 = mul nuw i8 9, %0
%4 = mul nuw i8 3, %1
%5 = urem i8 %3, %4
%6 = icmp eq i8 %5, 0
ret i1 %6
}
define i1 @tgt(i8 noundef %0, i8 noundef %1) {
%3 = mul nuw i8 3, %0
%4 = urem i8 %3, %1
%5 = icmp eq i8 %4, 0
ret i1 %5
}
|
Hello, I would like to work on this issue, can someone guide me through it? |
You can implement the folding here: llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp Lines 3708 to 3719 in 55395f5
|
Sorry for the late question, please confirm if I understand this correctly. I have to implement foldICmpRemConstant(Cmp, BO, C) which folds expressions where |
Yeah, you are right. Be careful with the |
I managed to write something, but it didn't work at all. I run it on: define i1 @src(i8 noundef %0, i8 noundef %1) {
%3 = mul nuw i8 9, %0
%4 = mul nuw i8 3, %1
%5 = urem i8 %3, %4
%6 = icmp eq i8 %5, 0
ret i1 %6
} and it doesn't change anything: ; ModuleID = '/home/dhairya/dev/tmp/test.ll'
source_filename = "/home/dhairya/dev/tmp/test.ll"
define i1 @src(i8 noundef %0, i8 noundef %1) {
%3 = mul nuw i8 9, %0
%4 = mul nuw i8 3, %1
%5 = urem i8 %3, %4
%6 = icmp eq i8 %5, 0
ret i1 %6
} Is something wrong with the match? Instruction *InstCombinerImpl::foldICmpRemConstant(ICmpInst &Cmp,
BinaryOperator *Rem,
const APInt &C) {
const ICmpInst::Predicate Pred = Cmp.getPredicate();
Value *X = Rem->getOperand(0);
Value *Y = Rem->getOperand(1);
// Check if the remainder operation is in the required form.
if (!isa<BinaryOperator>(X) || !isa<BinaryOperator>(Y))
return nullptr;
BinaryOperator *MulX = cast<BinaryOperator>(X);
BinaryOperator *MulY = cast<BinaryOperator>(Y);
// Check if the operands are multiplication operations.
if (MulX->getOpcode() != Instruction::Mul || MulY->getOpcode() != Instruction::Mul)
return nullptr;
// Get the multiplication operands and constants.
Value *A = MulX->getOperand(0);
Value *C1 = MulX->getOperand(1);
Value *B = MulY->getOperand(0);
Value *C2 = MulY->getOperand(1);
const APInt *C1Value, *C2Value;
// Check if the constants satisfy the condition c1 % c2 == 0.
if (!match(C1, m_APInt(C1Value)) || !match(C2, m_APInt(C2Value)) || C1Value->urem(*C2Value) != 0)
return nullptr;
// Compute the new constant k = c1 / c2.
APInt K = C1Value->udiv(*C2Value);
Type *Ty = Rem->getType();
// Create a new remainder instruction (a * k) % b.
Value *NewRem = Builder.CreateURem(Builder.CreateMul(A, ConstantInt::get(A->getType(), K)), B);
return new ICmpInst(Pred, NewRem, ConstantInt::get(Ty, C));
} Please be patient with me, as I am still in my learning phase 😅 Also, I found that in Instruction *foldICmpSRemConstant(ICmpInst &Cmp, BinaryOperator *UDiv,
const APInt &C); instead of Instruction *foldICmpSRemConstant(ICmpInst &Cmp, BinaryOperator *SRem,
const APInt &C); So I have changed it. |
Please create a pull request. I cannot leave reviews on the issue comment. |
(x * z) % (y * z) == 0
=>x % y == 0
when the multiplications/modulus do not overflow:alive
The text was updated successfully, but these errors were encountered: