This is an archive of the discontinued LLVM Phabricator instance.

SystemZ: keep AND masks before SHL i128
AbandonedPublic

Authored by cuviper on Jul 30 2018, 3:00 PM.

Details

Summary

SystemZ normally tries to combine away AND masks for the lower bits of a shift operand, as it only uses the least 6 bits anyway. This is fine for native integers <= 64 bits, but it leads to bad results when shifting i128, as the builtin __ashlti3 needs the operand to remain masked.

Diff Detail

Repository
rL LLVM

Event Timeline

cuviper created this revision.Jul 30 2018, 3:00 PM

The transform is wrong whether or not the shift type is legal: ISD::SHL returns poison for out-of-range shifts, just like the IR "shl", and DAGCombine will take advantage of this.

The transform is wrong whether or not the shift type is legal: ISD::SHL returns poison for out-of-range shifts, just like the IR "shl", and DAGCombine will take advantage of this.

So then our two options are to either combine this to a target specific SHL-like SDNode or select (shl x ( and y, mask)) directly to SystemZ's sll during instruction selection?

To be clear, this function actually combines SHL, SRA, SRL, and ROTL, so they should all be addressed accordingly. I only called out SHL because this was the particular one that bit me.

Yes, that's right. (Well, except that ISD::ROTL specifically is defined to wrap in the obvious way.)

jonpa added a comment.Jul 31 2018, 1:04 AM

The transform is wrong whether or not the shift type is legal: ISD::SHL returns poison for out-of-range shifts

As Eli pointed out, this transformation is actually buggy! We have hit this just recently in testing and a patch is in the making. I think Uli can help here and fill in more on the details.

I've just posted a patch to reimplement the broken SystemZ shift count logic: https://reviews.llvm.org/D50096

cuviper abandoned this revision.Aug 1 2018, 11:42 AM

Superseded by D50096.