|
10 | 10 | //
|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
| 13 | +#include "AArch64ExpandImm.h" |
13 | 14 | #include "AArch64MachineFunctionInfo.h"
|
14 | 15 | #include "AArch64TargetMachine.h"
|
15 | 16 | #include "MCTargetDesc/AArch64AddressingModes.h"
|
@@ -1074,6 +1075,41 @@ bool AArch64DAGToDAGISel::SelectAddrModeIndexedBitWidth(SDValue N, bool IsSigned
|
1074 | 1075 | return true;
|
1075 | 1076 | }
|
1076 | 1077 |
|
| 1078 | +// 16-bit optionally shifted immediates are legal for single mov. |
| 1079 | +static bool isLegalSingleMOVImmediate(int64_t Immed) { |
| 1080 | + if (Immed == std::numeric_limits<int64_t>::min()) { |
| 1081 | + LLVM_DEBUG(dbgs() << "Illegal single mov imm " << Immed |
| 1082 | + << ": avoid UB for INT64_MIN\n"); |
| 1083 | + return false; |
| 1084 | + } |
| 1085 | + |
| 1086 | + // Calculate how many moves we will need to materialize this constant. |
| 1087 | + SmallVector<AArch64_IMM::ImmInsnModel, 4> Insn; |
| 1088 | + AArch64_IMM::expandMOVImm(Immed, 64, Insn); |
| 1089 | + return Insn.size() == 1; |
| 1090 | +} |
| 1091 | + |
| 1092 | +// Check whether a unsigned vaule is not in the immediate range of mov but in |
| 1093 | +// the immediate range of imm24. The "Size" argument is the size in bytes of the |
| 1094 | +// memory reference. |
| 1095 | +static bool isPreferredBaseAddrMode(const TargetLowering *TLI, int64_t ImmOff, |
| 1096 | + unsigned Size) { |
| 1097 | + if ((ImmOff & (Size - 1)) != 0 || ImmOff < 0) |
| 1098 | + return false; |
| 1099 | + |
| 1100 | + // If the immediate already can be encoded in mov, then just keep the existing |
| 1101 | + // logic. |
| 1102 | + if (isLegalSingleMOVImmediate(ImmOff)) |
| 1103 | + return false; |
| 1104 | + |
| 1105 | + // For a imm24, its low imm12 can be fold as the immediate of load or store, |
| 1106 | + // and its high part can be encoded in an add. |
| 1107 | + int64_t HighPart = ImmOff & ~0xfffULL; |
| 1108 | + if (TLI->isLegalAddImmediate(HighPart)) |
| 1109 | + return true; |
| 1110 | + return false; |
| 1111 | +} |
| 1112 | + |
1077 | 1113 | /// SelectAddrModeIndexed - Select a "register plus scaled unsigned 12-bit
|
1078 | 1114 | /// immediate" address. The "Size" argument is the size in bytes of the memory
|
1079 | 1115 | /// reference, which determines the scale.
|
@@ -1115,6 +1151,24 @@ bool AArch64DAGToDAGISel::SelectAddrModeIndexed(SDValue N, unsigned Size,
|
1115 | 1151 | OffImm = CurDAG->getTargetConstant(RHSC >> Scale, dl, MVT::i64);
|
1116 | 1152 | return true;
|
1117 | 1153 | }
|
| 1154 | + |
| 1155 | + // Perfer [Reg + imm] mode. |
| 1156 | + // ADD BaseReg, WideImmediate & 0x0fff000 |
| 1157 | + // LDR X2, [BaseReg, WideImmediate & 0x0fff] |
| 1158 | + SDValue LHS = N.getOperand(0); |
| 1159 | + if (isPreferredBaseAddrMode(TLI, RHSC, Size)) { |
| 1160 | + int64_t ImmOffUnScale = RHSC; |
| 1161 | + int64_t ImmOffLow = ImmOffUnScale & 0x0fff; |
| 1162 | + int64_t ImmOffHigh = RHSC - ImmOffLow; |
| 1163 | + SDValue ImmHighSDV = |
| 1164 | + CurDAG->getTargetConstant(ImmOffHigh >> 12, dl, MVT::i64); |
| 1165 | + Base = SDValue(CurDAG->getMachineNode( |
| 1166 | + AArch64::ADDXri, dl, MVT::i64, LHS, ImmHighSDV, |
| 1167 | + CurDAG->getTargetConstant(12, dl, MVT::i32)), |
| 1168 | + 0); |
| 1169 | + OffImm = CurDAG->getTargetConstant(ImmOffLow >> Scale, dl, MVT::i64); |
| 1170 | + return true; |
| 1171 | + } |
1118 | 1172 | }
|
1119 | 1173 | }
|
1120 | 1174 |
|
@@ -1356,6 +1410,14 @@ bool AArch64DAGToDAGISel::SelectAddrModeXRO(SDValue N, unsigned Size,
|
1356 | 1410 | return true;
|
1357 | 1411 | }
|
1358 | 1412 |
|
| 1413 | + // Perfer [Reg + imm] mode, so skip this scenarios. |
| 1414 | + if (auto *OffsetC = dyn_cast<ConstantSDNode>(RHS)) { |
| 1415 | + int64_t ImmOff = (int64_t)OffsetC->getZExtValue(); |
| 1416 | + const TargetLowering *TLI = getTargetLowering(); |
| 1417 | + if (isPreferredBaseAddrMode(TLI, ImmOff, Size)) { |
| 1418 | + return false; |
| 1419 | + } |
| 1420 | + } |
1359 | 1421 | // Match any non-shifted, non-extend, non-immediate add expression.
|
1360 | 1422 | Base = LHS;
|
1361 | 1423 | Offset = RHS;
|
|
0 commit comments