Skip to content

Commit c8ee27e

Browse files
committed
[AArch64] Replace AND with LSL#2 for LDR target (#34101)
Currently, process of replacing bitwise operations consisting of `LSR`/`LSL` with `And` is performed by `DAGCombiner`. However, in certain cases, the `AND` generated by this process can be removed. 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 `SHIFTING` + `AND` operation on load target can be optimized and optimizes it if it can.
1 parent ee428cf commit c8ee27e

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ struct AArch64MIPeepholeOpt : public MachineFunctionPass {
128128
bool visitINSviGPR(MachineInstr &MI, unsigned Opc);
129129
bool visitINSvi64lane(MachineInstr &MI);
130130
bool visitFMOVDr(MachineInstr &MI);
131+
bool visitLOAD(MachineInstr &MI);
131132
bool runOnMachineFunction(MachineFunction &MF) override;
132133

133134
StringRef getPassName() const override {
@@ -690,6 +691,64 @@ bool AArch64MIPeepholeOpt::visitFMOVDr(MachineInstr &MI) {
690691
return true;
691692
}
692693

694+
bool AArch64MIPeepholeOpt::visitLOAD(MachineInstr &MI) {
695+
Register LdOp2Reg = MI.getOperand(2).getReg();
696+
unsigned RegSize = TRI->getRegSizeInBits(LdOp2Reg, *MRI);
697+
698+
// Consider:
699+
// (ldr w, [x, (and x, (ubfm x, x, imms, immr), C1)])
700+
// If bitmask C1 of And is all the bits remaining after
701+
// bitshifting to UBFM minus last 2 bits, try to optimize.
702+
// Optimize to:
703+
// (ldr w, [x (ubfm x, x, imms, immr), lsl #2])
704+
{
705+
if (!MI.getOperand(4).isImm() || MI.getOperand(4).getImm() != 0)
706+
return false;
707+
708+
MachineInstr *AndMI = MRI->getUniqueVRegDef(LdOp2Reg);
709+
if (!AndMI || AndMI->getOpcode() != AArch64::ANDXri ||
710+
!AndMI->getOperand(2).isImm())
711+
return false;
712+
713+
uint64_t AndMask = AArch64_AM::decodeLogicalImmediate(
714+
AndMI->getOperand(2).getImm(), RegSize);
715+
MachineInstr *ShtMI = MRI->getUniqueVRegDef(AndMI->getOperand(1).getReg());
716+
uint64_t Mask = 0;
717+
if (!ShtMI || ShtMI->getOpcode() != AArch64::UBFMXri)
718+
return false;
719+
uint64_t imms = ShtMI->getOperand(2).getImm();
720+
uint64_t immr = ShtMI->getOperand(3).getImm();
721+
uint64_t new_imms = 0;
722+
uint64_t new_immr = 0;
723+
if (imms <= immr) {
724+
if (immr != RegSize - 1)
725+
return false;
726+
Mask = ((uint64_t)1 << (RegSize - imms)) - 4;
727+
new_imms = imms + 2;
728+
new_immr = immr;
729+
} else {
730+
// we only need to handle case lsl #1
731+
if ((imms - immr != 1) || imms != RegSize - 1)
732+
return false;
733+
Mask = UINT64_MAX - 3;
734+
new_imms = 1;
735+
new_immr = imms;
736+
}
737+
738+
// check this shifting can be treat as PreIndex Shifting.
739+
if (AndMask == Mask) {
740+
AndMI->eraseFromParent();
741+
ShtMI->getOperand(2).setImm(new_imms);
742+
ShtMI->getOperand(3).setImm(new_immr);
743+
MI.getOperand(2).setReg(ShtMI->getOperand(0).getReg());
744+
MI.getOperand(4).setImm(1);
745+
return true;
746+
}
747+
}
748+
749+
return false;
750+
}
751+
693752
bool AArch64MIPeepholeOpt::runOnMachineFunction(MachineFunction &MF) {
694753
if (skipFunction(MF.getFunction()))
695754
return false;
@@ -771,6 +830,9 @@ bool AArch64MIPeepholeOpt::runOnMachineFunction(MachineFunction &MF) {
771830
case AArch64::FMOVDr:
772831
Changed |= visitFMOVDr(MI);
773832
break;
833+
case AArch64::LDRWroX:
834+
Changed |= visitLOAD(MI);
835+
break;
774836
}
775837
}
776838
}

llvm/test/CodeGen/AArch64/peephole-load.mir

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ body: |
1414
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1
1515
; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY $x0
1616
; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY1]], [[COPY2]], $xzr
17-
; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64 = UBFMXri killed [[MADDXrrr]], 56, 63
18-
; CHECK-NEXT: [[ANDXri:%[0-9]+]]:gpr64common = ANDXri killed [[UBFMXri]], 8069
19-
; CHECK-NEXT: [[LDRWroX:%[0-9]+]]:gpr32 = LDRWroX [[COPY]], killed [[ANDXri]], 0, 0
17+
; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64 = UBFMXri killed [[MADDXrrr]], 58, 63
18+
; CHECK-NEXT: [[LDRWroX:%[0-9]+]]:gpr32 = LDRWroX [[COPY]], killed [[UBFMXri]], 0, 1
2019
; CHECK-NEXT: $w0 = COPY [[LDRWroX]]
2120
; CHECK-NEXT: RET_ReallyLR implicit $w0
2221
%2:gpr64common = COPY $x2
@@ -42,9 +41,8 @@ body: |
4241
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1
4342
; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY $x0
4443
; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[COPY1]], [[COPY2]], $xzr
45-
; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64 = UBFMXri killed [[MADDXrrr]], 63, 62
46-
; CHECK-NEXT: [[ANDXri:%[0-9]+]]:gpr64common = ANDXri killed [[UBFMXri]], 8125
47-
; CHECK-NEXT: [[LDRWroX:%[0-9]+]]:gpr32 = LDRWroX [[COPY]], killed [[ANDXri]], 0, 0
44+
; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64 = UBFMXri killed [[MADDXrrr]], 1, 63
45+
; CHECK-NEXT: [[LDRWroX:%[0-9]+]]:gpr32 = LDRWroX [[COPY]], killed [[UBFMXri]], 0, 1
4846
; CHECK-NEXT: $w0 = COPY [[LDRWroX]]
4947
; CHECK-NEXT: RET_ReallyLR implicit $w0
5048
%2:gpr64common = COPY $x2

0 commit comments

Comments
 (0)