Skip to content

Commit

Permalink
[AArch64] prevent (shl (srl x, c1), c2) -> (and (shift x, c3)) when load
Browse files Browse the repository at this point in the history
Currently, process of replacing bitwise operations consisting of
`(shl (srl x, c1), c2)` with `And` is performed by `DAGCombiner`.

However, in certain case like `(shl (srl, x, c1) 2)` is do not
need to transform to `AND` if it was used to `Load` Target.

Consider following case:
```
        lsr x8, x8, llvm#56
        and x8, x8, #0xfc
        ldr w0, [x2, x8]
        ret
```

In this case, we can remove the `AND` by changing the target of `LDR`
to `[X2, X8, LSL llvm#2]` and right-shifting amount change to 56 to 58.

after changed:
```
        lsr x8, x8, llvm#58
        ldr w0, [x2, x8, lsl llvm#2]
        ret
```

This patch checks to see if the `(shl (srl x, c1) 2)` operation on
`load` target can be prevent transform to `And`.
  • Loading branch information
ParkHanbum committed Jun 1, 2024
1 parent 5251d57 commit 5f02043
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 8 deletions.
18 changes: 18 additions & 0 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16918,6 +16918,24 @@ bool AArch64TargetLowering::shouldFoldConstantShiftPairToMask(
return (!C1 || !C2 || C1->getZExtValue() >= C2->getZExtValue());
}

// We do not need to fold when this shifting used in specific load case:
// (ldr x, (add x, (shl (srl x, c1) 2)))
if (N->getOpcode() == ISD::SHL) {
auto C2 = dyn_cast_or_null<ConstantSDNode>(N->getOperand(1));
if (C2 && C2->getZExtValue() == 2) {
auto ShouldADD =
dyn_cast_or_null<SDNode>(N->use_begin().getUse().getUser());
if (ShouldADD && ShouldADD->getOpcode() == ISD::ADD) {
auto ShouldLOAD = dyn_cast_or_null<LoadSDNode>(
ShouldADD->use_begin().getUse().getUser());
if (ShouldLOAD) {
if (isIndexedLoadLegal(ISD::PRE_INC, ShouldLOAD->getMemoryVT()))
return false;
}
}
}
}

return true;
}

Expand Down
14 changes: 6 additions & 8 deletions llvm/test/CodeGen/AArch64/arm64-fold-lshr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ define i32 @load_shr63(i64 %a, i64 %b, ptr %table) {
; CHECK-LABEL: load_shr63:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mul x8, x1, x0
; CHECK-NEXT: lsr x8, x8, #61
; CHECK-NEXT: and x8, x8, #0x4
; CHECK-NEXT: ldr w0, [x2, x8]
; CHECK-NEXT: lsr x8, x8, #63
; CHECK-NEXT: ldr w0, [x2, x8, lsl #2]
; CHECK-NEXT: ret
entry:
%mul = mul i64 %b, %a
Expand All @@ -35,8 +34,8 @@ define i32 @load_shr2(i64 %a, i64 %b, ptr %table) {
; CHECK-LABEL: load_shr2:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mul x8, x1, x0
; CHECK-NEXT: and x8, x8, #0xfffffffffffffffc
; CHECK-NEXT: ldr w0, [x2, x8]
; CHECK-NEXT: lsr x8, x8, #2
; CHECK-NEXT: ldr w0, [x2, x8, lsl #2]
; CHECK-NEXT: ret
entry:
%mul = mul i64 %b, %a
Expand All @@ -50,9 +49,8 @@ define i32 @load_shr1(i64 %a, i64 %b, ptr %table) {
; CHECK-LABEL: load_shr1:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mul x8, x1, x0
; CHECK-NEXT: lsl x8, x8, #1
; CHECK-NEXT: and x8, x8, #0xfffffffffffffffc
; CHECK-NEXT: ldr w0, [x2, x8]
; CHECK-NEXT: lsr x8, x8, #1
; CHECK-NEXT: ldr w0, [x2, x8, lsl #2]
; CHECK-NEXT: ret
entry:
%mul = mul i64 %b, %a
Expand Down

0 comments on commit 5f02043

Please sign in to comment.