Skip to content

Commit c350acf

Browse files
committedMay 22, 2014
ARM64: separate load/store operands to simplify assembler
This changes ARM64 to use separate operands for each component of an address, and look for separate '[', '$Rn, ..., ']' tokens when parsing. This allows us to do away with quite a bit of special C++ code to handle monolithic "addressing modes" in the MC components. The more incremental matching of the assembler operands also allows for better diagnostics when LLVM is presented with invalid input. Most of the complexity here is with the register-offset instructions, which were extremely dodgy beforehand: even when the instruction used wM, LLVM's model had xM as an operand. We papered over this discrepancy before, but that approach doesn't work now so I split them into separate X and W variants. llvm-svn: 209425
1 parent 18b68e1 commit c350acf

15 files changed

+2537
-2702
lines changed
 

‎llvm/lib/Target/ARM64/ARM64ISelDAGToDAG.cpp

+104-73
Original file line numberDiff line numberDiff line change
@@ -111,27 +111,18 @@ class ARM64DAGToDAGISel : public SelectionDAGISel {
111111
return SelectAddrModeUnscaled(N, 16, Base, OffImm);
112112
}
113113

114-
bool SelectAddrModeRO8(SDValue N, SDValue &Base, SDValue &Offset,
115-
SDValue &Imm) {
116-
return SelectAddrModeRO(N, 1, Base, Offset, Imm);
114+
template<int Width>
115+
bool SelectAddrModeWRO(SDValue N, SDValue &Base, SDValue &Offset,
116+
SDValue &SignExtend, SDValue &DoShift) {
117+
return SelectAddrModeWRO(N, Width / 8, Base, Offset, SignExtend, DoShift);
117118
}
118-
bool SelectAddrModeRO16(SDValue N, SDValue &Base, SDValue &Offset,
119-
SDValue &Imm) {
120-
return SelectAddrModeRO(N, 2, Base, Offset, Imm);
121-
}
122-
bool SelectAddrModeRO32(SDValue N, SDValue &Base, SDValue &Offset,
123-
SDValue &Imm) {
124-
return SelectAddrModeRO(N, 4, Base, Offset, Imm);
125-
}
126-
bool SelectAddrModeRO64(SDValue N, SDValue &Base, SDValue &Offset,
127-
SDValue &Imm) {
128-
return SelectAddrModeRO(N, 8, Base, Offset, Imm);
129-
}
130-
bool SelectAddrModeRO128(SDValue N, SDValue &Base, SDValue &Offset,
131-
SDValue &Imm) {
132-
return SelectAddrModeRO(N, 16, Base, Offset, Imm);
119+
120+
template<int Width>
121+
bool SelectAddrModeXRO(SDValue N, SDValue &Base, SDValue &Offset,
122+
SDValue &SignExtend, SDValue &DoShift) {
123+
return SelectAddrModeXRO(N, Width / 8, Base, Offset, SignExtend, DoShift);
133124
}
134-
bool SelectAddrModeNoIndex(SDValue N, SDValue &Val);
125+
135126

136127
/// Form sequences of consecutive 64/128-bit registers for use in NEON
137128
/// instructions making use of a vector-list (e.g. ldN, tbl). Vecs must have
@@ -179,11 +170,15 @@ class ARM64DAGToDAGISel : public SelectionDAGISel {
179170
SDValue &OffImm);
180171
bool SelectAddrModeUnscaled(SDValue N, unsigned Size, SDValue &Base,
181172
SDValue &OffImm);
182-
bool SelectAddrModeRO(SDValue N, unsigned Size, SDValue &Base,
183-
SDValue &Offset, SDValue &Imm);
173+
bool SelectAddrModeWRO(SDValue N, unsigned Size, SDValue &Base,
174+
SDValue &Offset, SDValue &SignExtend,
175+
SDValue &DoShift);
176+
bool SelectAddrModeXRO(SDValue N, unsigned Size, SDValue &Base,
177+
SDValue &Offset, SDValue &SignExtend,
178+
SDValue &DoShift);
184179
bool isWorthFolding(SDValue V) const;
185-
bool SelectExtendedSHL(SDValue N, unsigned Size, SDValue &Offset,
186-
SDValue &Imm);
180+
bool SelectExtendedSHL(SDValue N, unsigned Size, bool WantExtend,
181+
SDValue &Offset, SDValue &SignExtend);
187182

188183
template<unsigned RegWidth>
189184
bool SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos) {
@@ -219,14 +214,6 @@ static bool isOpcWithIntImmediate(const SDNode *N, unsigned Opc,
219214
isIntImmediate(N->getOperand(1).getNode(), Imm);
220215
}
221216

222-
bool ARM64DAGToDAGISel::SelectAddrModeNoIndex(SDValue N, SDValue &Val) {
223-
EVT ValTy = N.getValueType();
224-
if (ValTy != MVT::i64)
225-
return false;
226-
Val = N;
227-
return true;
228-
}
229-
230217
bool ARM64DAGToDAGISel::SelectInlineAsmMemoryOperand(
231218
const SDValue &Op, char ConstraintCode, std::vector<SDValue> &OutOps) {
232219
assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
@@ -563,8 +550,8 @@ bool ARM64DAGToDAGISel::SelectArithExtendedRegister(SDValue N, SDValue &Reg,
563550
// if we're folding a (sext i8), we need the RHS to be a GPR32, even though
564551
// there might not be an actual 32-bit value in the program. We can
565552
// (harmlessly) synthesize one by injected an EXTRACT_SUBREG here.
566-
if (Reg.getValueType() == MVT::i64 && Ext != ARM64_AM::UXTX &&
567-
Ext != ARM64_AM::SXTX) {
553+
assert(Ext != ARM64_AM::UXTX && Ext != ARM64_AM::SXTX);
554+
if (Reg.getValueType() == MVT::i64) {
568555
SDValue SubReg = CurDAG->getTargetConstant(ARM64::sub_32, MVT::i32);
569556
MachineSDNode *Node = CurDAG->getMachineNode(
570557
TargetOpcode::EXTRACT_SUBREG, SDLoc(N), MVT::i32, Reg, SubReg);
@@ -675,47 +662,44 @@ static SDValue Widen(SelectionDAG *CurDAG, SDValue N) {
675662
return SDValue(Node, 0);
676663
}
677664

678-
static SDValue WidenIfNeeded(SelectionDAG *CurDAG, SDValue N) {
679-
if (N.getValueType() == MVT::i32) {
680-
return Widen(CurDAG, N);
681-
}
682-
683-
return N;
684-
}
685-
686665
/// \brief Check if the given SHL node (\p N), can be used to form an
687666
/// extended register for an addressing mode.
688667
bool ARM64DAGToDAGISel::SelectExtendedSHL(SDValue N, unsigned Size,
689-
SDValue &Offset, SDValue &Imm) {
668+
bool WantExtend, SDValue &Offset,
669+
SDValue &SignExtend) {
690670
assert(N.getOpcode() == ISD::SHL && "Invalid opcode.");
691671
ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N.getOperand(1));
692-
if (CSD && (CSD->getZExtValue() & 0x7) == CSD->getZExtValue()) {
672+
if (!CSD || (CSD->getZExtValue() & 0x7) != CSD->getZExtValue())
673+
return false;
693674

675+
if (WantExtend) {
694676
ARM64_AM::ShiftExtendType Ext = getExtendTypeForNode(N.getOperand(0), true);
695-
if (Ext == ARM64_AM::InvalidShiftExtend) {
696-
Ext = ARM64_AM::UXTX;
697-
Offset = WidenIfNeeded(CurDAG, N.getOperand(0));
698-
} else {
699-
Offset = WidenIfNeeded(CurDAG, N.getOperand(0).getOperand(0));
700-
}
701-
702-
unsigned LegalShiftVal = Log2_32(Size);
703-
unsigned ShiftVal = CSD->getZExtValue();
704-
705-
if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
677+
if (Ext == ARM64_AM::InvalidShiftExtend)
706678
return false;
707679

708-
Imm = CurDAG->getTargetConstant(
709-
ARM64_AM::getMemExtendImm(Ext, ShiftVal != 0), MVT::i32);
710-
if (isWorthFolding(N))
711-
return true;
680+
Offset = N.getOperand(0).getOperand(0);
681+
SignExtend = CurDAG->getTargetConstant(Ext == ARM64_AM::SXTW, MVT::i32);
682+
} else {
683+
Offset = N.getOperand(0);
684+
SignExtend = CurDAG->getTargetConstant(0, MVT::i32);
712685
}
686+
687+
unsigned LegalShiftVal = Log2_32(Size);
688+
unsigned ShiftVal = CSD->getZExtValue();
689+
690+
if (ShiftVal != 0 && ShiftVal != LegalShiftVal)
691+
return false;
692+
693+
if (isWorthFolding(N))
694+
return true;
695+
713696
return false;
714697
}
715698

716-
bool ARM64DAGToDAGISel::SelectAddrModeRO(SDValue N, unsigned Size,
699+
bool ARM64DAGToDAGISel::SelectAddrModeWRO(SDValue N, unsigned Size,
717700
SDValue &Base, SDValue &Offset,
718-
SDValue &Imm) {
701+
SDValue &SignExtend,
702+
SDValue &DoShift) {
719703
if (N.getOpcode() != ISD::ADD)
720704
return false;
721705
SDValue LHS = N.getOperand(0);
@@ -740,26 +724,30 @@ bool ARM64DAGToDAGISel::SelectAddrModeRO(SDValue N, unsigned Size,
740724

741725
// Try to match a shifted extend on the RHS.
742726
if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL &&
743-
SelectExtendedSHL(RHS, Size, Offset, Imm)) {
727+
SelectExtendedSHL(RHS, Size, true, Offset, SignExtend)) {
744728
Base = LHS;
729+
DoShift = CurDAG->getTargetConstant(true, MVT::i32);
745730
return true;
746731
}
747732

748733
// Try to match a shifted extend on the LHS.
749734
if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL &&
750-
SelectExtendedSHL(LHS, Size, Offset, Imm)) {
735+
SelectExtendedSHL(LHS, Size, true, Offset, SignExtend)) {
751736
Base = RHS;
737+
DoShift = CurDAG->getTargetConstant(true, MVT::i32);
752738
return true;
753739
}
754740

755-
ARM64_AM::ShiftExtendType Ext = ARM64_AM::UXTX;
741+
// There was no shift, whatever else we find.
742+
DoShift = CurDAG->getTargetConstant(false, MVT::i32);
743+
744+
ARM64_AM::ShiftExtendType Ext = ARM64_AM::InvalidShiftExtend;
756745
// Try to match an unshifted extend on the LHS.
757746
if (IsExtendedRegisterWorthFolding &&
758747
(Ext = getExtendTypeForNode(LHS, true)) != ARM64_AM::InvalidShiftExtend) {
759748
Base = RHS;
760-
Offset = WidenIfNeeded(CurDAG, LHS.getOperand(0));
761-
Imm = CurDAG->getTargetConstant(ARM64_AM::getMemExtendImm(Ext, false),
762-
MVT::i32);
749+
Offset = LHS.getOperand(0);
750+
SignExtend = CurDAG->getTargetConstant(Ext == ARM64_AM::SXTW, MVT::i32);
763751
if (isWorthFolding(LHS))
764752
return true;
765753
}
@@ -768,19 +756,62 @@ bool ARM64DAGToDAGISel::SelectAddrModeRO(SDValue N, unsigned Size,
768756
if (IsExtendedRegisterWorthFolding &&
769757
(Ext = getExtendTypeForNode(RHS, true)) != ARM64_AM::InvalidShiftExtend) {
770758
Base = LHS;
771-
Offset = WidenIfNeeded(CurDAG, RHS.getOperand(0));
772-
Imm = CurDAG->getTargetConstant(ARM64_AM::getMemExtendImm(Ext, false),
773-
MVT::i32);
759+
Offset = RHS.getOperand(0);
760+
SignExtend = CurDAG->getTargetConstant(Ext == ARM64_AM::SXTW, MVT::i32);
774761
if (isWorthFolding(RHS))
775762
return true;
776763
}
777764

765+
return false;
766+
}
767+
768+
bool ARM64DAGToDAGISel::SelectAddrModeXRO(SDValue N, unsigned Size,
769+
SDValue &Base, SDValue &Offset,
770+
SDValue &SignExtend,
771+
SDValue &DoShift) {
772+
if (N.getOpcode() != ISD::ADD)
773+
return false;
774+
SDValue LHS = N.getOperand(0);
775+
SDValue RHS = N.getOperand(1);
776+
777+
// We don't want to match immediate adds here, because they are better lowered
778+
// to the register-immediate addressing modes.
779+
if (isa<ConstantSDNode>(LHS) || isa<ConstantSDNode>(RHS))
780+
return false;
781+
782+
// Check if this particular node is reused in any non-memory related
783+
// operation. If yes, do not try to fold this node into the address
784+
// computation, since the computation will be kept.
785+
const SDNode *Node = N.getNode();
786+
for (SDNode *UI : Node->uses()) {
787+
if (!isa<MemSDNode>(*UI))
788+
return false;
789+
}
790+
791+
// Remember if it is worth folding N when it produces extended register.
792+
bool IsExtendedRegisterWorthFolding = isWorthFolding(N);
793+
794+
// Try to match a shifted extend on the RHS.
795+
if (IsExtendedRegisterWorthFolding && RHS.getOpcode() == ISD::SHL &&
796+
SelectExtendedSHL(RHS, Size, false, Offset, SignExtend)) {
797+
Base = LHS;
798+
DoShift = CurDAG->getTargetConstant(true, MVT::i32);
799+
return true;
800+
}
801+
802+
// Try to match a shifted extend on the LHS.
803+
if (IsExtendedRegisterWorthFolding && LHS.getOpcode() == ISD::SHL &&
804+
SelectExtendedSHL(LHS, Size, false, Offset, SignExtend)) {
805+
Base = RHS;
806+
DoShift = CurDAG->getTargetConstant(true, MVT::i32);
807+
return true;
808+
}
809+
778810
// Match any non-shifted, non-extend, non-immediate add expression.
779811
Base = LHS;
780-
Offset = WidenIfNeeded(CurDAG, RHS);
781-
Ext = ARM64_AM::UXTX;
782-
Imm = CurDAG->getTargetConstant(ARM64_AM::getMemExtendImm(Ext, false),
783-
MVT::i32);
812+
Offset = RHS;
813+
SignExtend = CurDAG->getTargetConstant(false, MVT::i32);
814+
DoShift = CurDAG->getTargetConstant(false, MVT::i32);
784815
// Reg1 + Reg2 is free: no check needed.
785816
return true;
786817
}

0 commit comments

Comments
 (0)
Please sign in to comment.