This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Fold zext(shl(trunc)) into and(shl)
Needs ReviewPublic

Authored by kazu on Apr 15 2023, 2:40 PM.

Details

Summary

If we are truncating to a narrower type, shifting left, and extending
back to the original type, we could do a left shift in the original
type followed by masking.

https://alive2.llvm.org/ce/z/etjn25

This patch fixes:

https://github.com/llvm/llvm-project/issues/61650

Diff Detail

Event Timeline

kazu created this revision.Apr 15 2023, 2:40 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 15 2023, 2:40 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
kazu requested review of this revision.Apr 15 2023, 2:40 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 15 2023, 2:40 PM
goldstein.w.n added inline comments.Apr 15 2023, 3:43 PM
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
1214

Why only shl, this seems to be pretty generically true:
https://alive2.llvm.org/ce/z/kTBKC7

kazu added a comment.Apr 15 2023, 8:01 PM

I missed the entire block of code in InstCombinerImpl::visitZExt to widen an expression tree:

// Try to extend the entire expression tree to the wide destination type.                                            
unsigned BitsToClear;
if (shouldChangeType(SrcTy, DestTy) &&
    canEvaluateZExtd(Src, DestTy, BitsToClear, *this, &Zext)) {

Let me see if I could modify this block code to accommodate our trunc-shl-zext sequence.

RKSimon added inline comments.Apr 17 2023, 10:16 AM
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
1214

Also, why just APInt? We should be able to perform this for any Constant (and just create the Mask below generically with Builder).

kazu added a comment.Apr 17 2023, 12:27 PM

I missed the entire block of code in InstCombinerImpl::visitZExt to widen an expression tree:

// Try to extend the entire expression tree to the wide destination type.                                            
unsigned BitsToClear;
if (shouldChangeType(SrcTy, DestTy) &&
    canEvaluateZExtd(Src, DestTy, BitsToClear, *this, &Zext)) {

Let me see if I could modify this block code to accommodate our trunc-shl-zext sequence.

On X86 at least, shouldChangeType returns false on going from 16-bit integers to 32-bit integers because DataLayout::isLegalInteger always returns false. Note that LegalIntWidths is empty on X86.

Widening narrow computation to well supported types like i32 or i64 seems to be a worthwhile transformation.

Do we happen to know why LegalIntWidths is empty on X86? Anyone?