summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp8
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp56
2 files changed, 62 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
index 07a4b3d7170..5cb7e184a6c 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
@@ -31,9 +31,13 @@ bool InstructionSelector::constrainSelectedInstRegOperands(
for (unsigned OpI = 0, OpE = I.getNumExplicitOperands(); OpI != OpE; ++OpI) {
MachineOperand &MO = I.getOperand(OpI);
- DEBUG(dbgs() << "Converting operand: " << MO << '\n');
- assert(MO.isReg() && "Unsupported binop non-reg operand");
+ // There's nothing to be done on immediates.
+ if (MO.isImm())
+ continue;
+
+ DEBUG(dbgs() << "Converting operand: " << MO << '\n');
+ assert(MO.isReg() && "Unsupported non-reg operand");
const TargetRegisterClass *RC = TII.getRegClass(I.getDesc(), OpI, &TRI, MF);
assert(RC && "Selected inst should have regclass operand");
diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
index 492024ecd1a..9c48d32897f 100644
--- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
@@ -79,6 +79,26 @@ static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID,
return GenericOpc;
}
+/// Select the AArch64 opcode for the G_LOAD or G_STORE operation \p GenericOpc,
+/// appropriate for the (value) register bank \p RegBankID and of memory access
+/// size \p OpSize. This returns the variant with the base+unsigned-immediate
+/// addressing mode (e.g., LDRXui).
+/// \returns \p GenericOpc if the combination is unsupported.
+static unsigned selectLoadStoreUIOp(unsigned GenericOpc, unsigned RegBankID,
+ unsigned OpSize) {
+ const bool isStore = GenericOpc == TargetOpcode::G_STORE;
+ switch (RegBankID) {
+ case AArch64::GPRRegBankID:
+ switch (OpSize) {
+ case 32:
+ return isStore ? AArch64::STRWui : AArch64::LDRWui;
+ case 64:
+ return isStore ? AArch64::STRXui : AArch64::LDRXui;
+ }
+ };
+ return GenericOpc;
+}
+
bool AArch64InstructionSelector::select(MachineInstr &I) const {
assert(I.getParent() && "Instruction should be in a basic block!");
assert(I.getParent()->getParent() && "Instruction should be in a function!");
@@ -109,6 +129,42 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
return true;
}
+ case TargetOpcode::G_LOAD:
+ case TargetOpcode::G_STORE: {
+ LLT MemTy = I.getType(0);
+ LLT PtrTy = I.getType(1);
+
+ if (PtrTy != LLT::pointer(0)) {
+ DEBUG(dbgs() << "Load/Store pointer has type: " << PtrTy
+ << ", expected: " << LLT::pointer(0) << '\n');
+ return false;
+ }
+
+#ifndef NDEBUG
+ // Sanity-check the pointer register.
+ const unsigned PtrReg = I.getOperand(1).getReg();
+ const RegisterBank &PtrRB = *RBI.getRegBank(PtrReg, MRI, TRI);
+ assert(PtrRB.getID() == AArch64::GPRRegBankID &&
+ "Load/Store pointer operand isn't a GPR");
+ assert(MRI.getSize(PtrReg) == 64 &&
+ "Load/Store pointer operand isn't 64-bit");
+#endif
+
+ const unsigned ValReg = I.getOperand(0).getReg();
+ const RegisterBank &RB = *RBI.getRegBank(ValReg, MRI, TRI);
+
+ const unsigned NewOpc =
+ selectLoadStoreUIOp(I.getOpcode(), RB.getID(), MemTy.getSizeInBits());
+ if (NewOpc == I.getOpcode())
+ return false;
+
+ I.setDesc(TII.get(NewOpc));
+ I.removeTypes();
+
+ I.addOperand(MachineOperand::CreateImm(0));
+ return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
+ }
+
case TargetOpcode::G_OR:
case TargetOpcode::G_AND:
case TargetOpcode::G_ADD:
OpenPOWER on IntegriCloud