This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Distributive or+mul with const operand
ClosedPublic

Authored by Allen on Aug 25 2022, 7:08 AM.

Details

Summary

We aleady support the transform: (X+C1)*CI -> X*CI+C1*CI
Here the case is a little special as the form of (X+C1)*CI is transformed into (X|C1)*CI,
so we should also support the transform: (X|C1)*CI -> X*CI+C1*CI
Fixes https://github.com/llvm/llvm-project/issues/57278

Diff Detail

Event Timeline

Allen created this revision.Aug 25 2022, 7:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 25 2022, 7:08 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
Allen requested review of this revision.Aug 25 2022, 7:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 25 2022, 7:08 AM

We may need a minimal test case.

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
232

Match 'or' then check haveNoCommonBitsSet should be better I think.

spatel added inline comments.Aug 25 2022, 8:40 AM
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
229–232

The existing code is awkward. We should update it before adding to it. Use m_ImmConstant(C1) to do this transform but ignore a constant expression.

I updated the test that was intended to go with this code change here:
5260146a8a74084f3d38d8bb448ae3c5690b9084

bcl5980 added inline comments.Aug 25 2022, 8:55 AM
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
223–224

If we update current code, Op1 should be m_ImmConstant also

Allen added inline comments.Aug 25 2022, 7:24 PM
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
229–232

hi @spatel

I tried with your new case, and it will fail on the check **if (!match(Mul, m_Mul(m_Value(), m_Value())))**, so the instcombine will not take active, is it within your expectations?
Allen updated this revision to Diff 455790.Aug 25 2022, 9:17 PM

address the comment

Allen marked 2 inline comments as done.Aug 25 2022, 9:27 PM
Allen added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
223–224

Done, thanks

232

Thanks very much, use haveNoCommonBitsSet make the code much clear.

bcl5980 added inline comments.Aug 25 2022, 10:49 PM
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
229–232

I think we can remove the condition:

if (!match(Mul, m_Mul(m_Value(), m_Value())))

But I don't know what happen if (INT_MIN * -1).
Based on current folding code, Constant (INTMIN / -1) is a poison value.

230–246

Maybe we should keep nuw flag in this change. Or add some tests and TODO for that.
https://alive2.llvm.org/ce/z/awsQrx

231

May be we need attach the context information for the function like:

haveNoCommonBitsSet(X, C1, DL, &AC, &I, &DT)

And please add at least 1 vector test also.

Allen updated this revision to Diff 455810.Aug 26 2022, 12:04 AM
Allen marked 2 inline comments as done.

1、add a vector case
2、keep nuw flag
3、update with haveNoCommonBitsSet(X, C1, DL, &AC, &I, &DT)

Allen marked 3 inline comments as done.Aug 26 2022, 12:12 AM
Allen added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
229–232

the above checking is deleted, and now i32 ptrtoint (i32* @g to i32) doesn't match the match(Op1, m_ImmConstant()) for that case, which I think it is within expectations ?

230–246

I make a try to propagation the flag, thanks

231

Apply your comment, thanks

bcl5980 added inline comments.Aug 26 2022, 12:13 AM
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
232

Only check nuw for mul works for pattern or.
But for the pattern add, we need check both instructions are nuw then can keep the flag.
And target pattern can be nuw for both instruction also.

Allen updated this revision to Diff 455827.Aug 26 2022, 1:23 AM
Allen marked 3 inline comments as done.

update the checking logic for nuw flag

Allen marked an inline comment as done.Aug 26 2022, 1:26 AM
Allen added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
232

Thank you for your patient guidance.

RKSimon edited the summary of this revision. (Show Details)Aug 26 2022, 3:02 AM
RKSimon added inline comments.Aug 26 2022, 3:12 AM
llvm/test/Transforms/InstCombine/mul.ll
690

Please can you add a case with undefs in the vector constants:

define <2 x i32> @PR57278_shl_vec_undef(<2 x i32> %v1) {

%shl = shl nuw <2 x i32> %v1, <i32 2, i32 undef>
%add = or <2 x i32> %shl, <i32 3, i32 undef>
%mul = mul nuw <2 x i32> %add, <i32 3, i32 undef>
ret <2 x i32> %mul

}

Allen updated this revision to Diff 455868.Aug 26 2022, 4:06 AM
Allen marked an inline comment as done.

Add a new vector case with undef

Allen marked an inline comment as done.Aug 26 2022, 4:43 AM
Allen added inline comments.
llvm/test/Transforms/InstCombine/mul.ll
690

Done, Thanks

bcl5980 added inline comments.Aug 26 2022, 5:51 AM
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
236

Should be

if (I.hasNoUnsignedWrap() && OrNUW) {
  cast<BinaryOperator>(NewMul)->setHasNoUnsignedWrap();
  BO->setHasNoUnsignedWrap();
}

I think it would be better to make the 'nuw' change separately. That is missing from the current transform, so it could be done before this patch with 'add' alone, or make that a follow-up patch to this one.

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
229–232

Yes, that is the expectation - the transform should not be attempted with constant expressions.

229–232

It would be clearer to capture Op1 as a constant and create this constant directly:

Constant *MulC;
if (match(Op1, m_ImmConstant(MulC))) {
  ...
  Constant *NewC = ConstantExpr::getMul(C1, MulC);

Please adjust the code comment above here to match whatever variable names you choose. So it may look like this:

// (X + C1) * MulC --> (X * MulC) + (C1 * MulC)
Allen marked an inline comment as done.Aug 26 2022, 6:57 PM

I think it would be better to make the 'nuw' change separately. That is missing from the current transform, so it could be done before this patch with 'add' alone, or make that a follow-up patch to this one.

Thanks for your suggestion, addressed with D132777

Allen updated this revision to Diff 456189.Aug 28 2022, 8:35 AM

rebase after D132777

Please pre-commit the baseline tests. If something is not transforming, you can add a comment in this patch to make it clear that it is a negative test or TODO item.

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
234

Is there a reason to not use the more direct ConstExpr::getMul() API and make it explicit that NewC is a Constant *?

llvm/test/Transforms/InstCombine/mul.ll
746

Replace "undef" with "poison" in this test - we are transitioning away from undef in IR.

Allen marked 6 inline comments as done.Aug 28 2022, 8:32 PM

Please pre-commit the baseline tests. If something is not transforming, you can add a comment in this patch to make it clear that it is a negative test or TODO item.

Addressed in the link D132820, and I'll rebase this commit after D132820 merged, thanks!

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
234

Thanks your suggestion, done

llvm/test/Transforms/InstCombine/mul.ll
746

Thanks, apply with your comment

bcl5980 added inline comments.Aug 28 2022, 8:48 PM
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
234

@spatel, based on nikic's RFC, maybe we need avoid use ConstExpr.
https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179

239–240

If NewMulBO is constant we also can set BO to nuw. So the logic should be this

if (I.hasNoUnsignedWrap() && Op0NUW && NewMulBO) {
  if (auto *NewMulBO = dyn_cast<BinaryOperator>(NewMul))
    NewMulBO->setHasNoUnsignedWrap();
  BO->setHasNoUnsignedWrap();
}
239–240

Sorry should be this one:

if (I.hasNoUnsignedWrap() && Op0NUW) {
  if (auto *NewMulBO = dyn_cast<BinaryOperator>(NewMul))
    NewMulBO->setHasNoUnsignedWrap();
  BO->setHasNoUnsignedWrap();
}
Allen updated this revision to Diff 456262.Aug 28 2022, 11:46 PM
Allen marked 2 inline comments as done.

a) rebase to the top as the baseline test case merged
b) update the logic of propagate nuw
c) Still use the Buillder.CreateMul as RFC https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179

LGTM, but please wait until someone else to approve it.

spatel accepted this revision.Aug 30 2022, 4:52 AM

LGTM

This revision is now accepted and ready to land.Aug 30 2022, 4:52 AM
This revision was automatically updated to reflect the committed changes.
Allen marked 2 inline comments as done and an inline comment as not done.