Skip to content

Commit 5f02043

Browse files
committed
[AArch64] prevent (shl (srl x, c1), c2) -> (and (shift x, c3)) when load
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, #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 #2]` and right-shifting amount change to 56 to 58. after changed: ``` lsr x8, x8, #58 ldr w0, [x2, x8, lsl #2] ret ``` This patch checks to see if the `(shl (srl x, c1) 2)` operation on `load` target can be prevent transform to `And`.
1 parent 5251d57 commit 5f02043

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16918,6 +16918,24 @@ bool AArch64TargetLowering::shouldFoldConstantShiftPairToMask(
1691816918
return (!C1 || !C2 || C1->getZExtValue() >= C2->getZExtValue());
1691916919
}
1692016920

16921+
// We do not need to fold when this shifting used in specific load case:
16922+
// (ldr x, (add x, (shl (srl x, c1) 2)))
16923+
if (N->getOpcode() == ISD::SHL) {
16924+
auto C2 = dyn_cast_or_null<ConstantSDNode>(N->getOperand(1));
16925+
if (C2 && C2->getZExtValue() == 2) {
16926+
auto ShouldADD =
16927+
dyn_cast_or_null<SDNode>(N->use_begin().getUse().getUser());
16928+
if (ShouldADD && ShouldADD->getOpcode() == ISD::ADD) {
16929+
auto ShouldLOAD = dyn_cast_or_null<LoadSDNode>(
16930+
ShouldADD->use_begin().getUse().getUser());
16931+
if (ShouldLOAD) {
16932+
if (isIndexedLoadLegal(ISD::PRE_INC, ShouldLOAD->getMemoryVT()))
16933+
return false;
16934+
}
16935+
}
16936+
}
16937+
}
16938+
1692116939
return true;
1692216940
}
1692316941

llvm/test/CodeGen/AArch64/arm64-fold-lshr.ll

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ define i32 @load_shr63(i64 %a, i64 %b, ptr %table) {
1919
; CHECK-LABEL: load_shr63:
2020
; CHECK: // %bb.0: // %entry
2121
; CHECK-NEXT: mul x8, x1, x0
22-
; CHECK-NEXT: lsr x8, x8, #61
23-
; CHECK-NEXT: and x8, x8, #0x4
24-
; CHECK-NEXT: ldr w0, [x2, x8]
22+
; CHECK-NEXT: lsr x8, x8, #63
23+
; CHECK-NEXT: ldr w0, [x2, x8, lsl #2]
2524
; CHECK-NEXT: ret
2625
entry:
2726
%mul = mul i64 %b, %a
@@ -35,8 +34,8 @@ define i32 @load_shr2(i64 %a, i64 %b, ptr %table) {
3534
; CHECK-LABEL: load_shr2:
3635
; CHECK: // %bb.0: // %entry
3736
; CHECK-NEXT: mul x8, x1, x0
38-
; CHECK-NEXT: and x8, x8, #0xfffffffffffffffc
39-
; CHECK-NEXT: ldr w0, [x2, x8]
37+
; CHECK-NEXT: lsr x8, x8, #2
38+
; CHECK-NEXT: ldr w0, [x2, x8, lsl #2]
4039
; CHECK-NEXT: ret
4140
entry:
4241
%mul = mul i64 %b, %a
@@ -50,9 +49,8 @@ define i32 @load_shr1(i64 %a, i64 %b, ptr %table) {
5049
; CHECK-LABEL: load_shr1:
5150
; CHECK: // %bb.0: // %entry
5251
; CHECK-NEXT: mul x8, x1, x0
53-
; CHECK-NEXT: lsl x8, x8, #1
54-
; CHECK-NEXT: and x8, x8, #0xfffffffffffffffc
55-
; CHECK-NEXT: ldr w0, [x2, x8]
52+
; CHECK-NEXT: lsr x8, x8, #1
53+
; CHECK-NEXT: ldr w0, [x2, x8, lsl #2]
5654
; CHECK-NEXT: ret
5755
entry:
5856
%mul = mul i64 %b, %a

0 commit comments

Comments
 (0)