This is an archive of the discontinued LLVM Phabricator instance.

[AArch64] Improve getUsefulBitsForUse for narrow stores.
ClosedPublic

Authored by mcrosier on May 11 2016, 10:23 AM.

Details

Summary

For narrow stores (e.g., strb, srth) we know the upper bits of the register are unused/not useful. In some cases we can use this information to eliminate unnecessary instructions.

For example, without this patch we generate (from the 2nd test case):

ldr w8, [x0]
and w8, w8, #0xfff0
bfxil w8, w2, #16, #4
strh w8, [x1]

and after the patch the 'and' is removed:

ldr w8, [x0]
bfxil w8, w2, #16, #4
strh w8, [x1]
ret

During the lowering of the bitfield insert instruction the 'and' is eliminated because we know the upper 16-bits that are masked off are unused and the lower 4-bits that are masked off are overwritten by the insert itself. Therefore, the 'and' is unnecessary.

Please take a look,
Chad

Diff Detail

Repository
rL LLVM

Event Timeline

mcrosier updated this revision to Diff 56934.May 11 2016, 10:23 AM
mcrosier retitled this revision from to [AArch64] Improve getUsefulBitsForUse for narrow stores..
mcrosier updated this object.
mcrosier added reviewers: t.p.northover, jmolloy.
mcrosier added a subscriber: llvm-commits.
mcrosier updated this object.May 11 2016, 10:24 AM
mcrosier updated this object.May 11 2016, 10:29 AM
t.p.northover accepted this revision.May 11 2016, 10:54 AM
t.p.northover edited edge metadata.

Looks good to me. Thanks!

Tim.

This revision is now accepted and ready to land.May 11 2016, 10:54 AM
gberry added a subscriber: gberry.May 11 2016, 10:58 AM

You might want to fix the typo in the first line of the description: (i.e., ldrb, ldrh) should be (i.e. strb, strh) (and probably should be e.g. not i.e. if you want to be pedantic :))

gberry added inline comments.May 11 2016, 11:13 AM
lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
1852 ↗(On Diff #56934)

Aren't there more of these opcodes? Also don't you need to make sure that the Orig node is the stored value operand, and not an address operand?

mcrosier updated this revision to Diff 56951.May 11 2016, 12:39 PM
mcrosier updated this object.
mcrosier edited edge metadata.
mcrosier updated this object.

Address Geoff's comments:
-Update description
-Make sure the use is the stores first source operand (i.e., the value being stored).

mcrosier marked an inline comment as done.May 11 2016, 12:41 PM
mcrosier added inline comments.May 11 2016, 1:15 PM
lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
1852 ↗(On Diff #56951)

I'll have to see if there are other opcodes. I don't think we have pre/post or versions at this point.

1855 ↗(On Diff #56951)

I tried to come up with a test case, but I don't think this problem can be exposed.

define void @test(i64 %ptr32, i8* %ptr8, i64 %x)  {
entry:
  %and = and i64 %ptr32, -8
  %shr = lshr i64 %x, 8
  %and1 = and i64 %shr, 7
  %or = or i64 %and, %and1
  %trunc = trunc i64 %or to i8
  %conv = inttoptr i8 %trunc to i8*
  store i8 1, i8* %conv
  ret void
}

Basically, in the cases I tried it looks like there will be a zero-extend between the 'strb/strh' and the 'or' preventing such a case from happening. Regardless, I think the check is correct (but not testable AFAICT).

This revision was automatically updated to reflect the committed changes.