for (unsigned OpI = 0, OpE = I.getNumExplicitOperands(); OpI != OpE; ++OpI) {
MachineOperand &MO = I.getOperand(OpI);
- // There's nothing to be done on immediates and frame indexes.
- if (MO.isImm() || MO.isFI())
+ // There's nothing to be done on non-register operands.
+ if (!MO.isReg())
continue;
DEBUG(dbgs() << "Converting operand: " << MO << '\n');
#include "AArch64RegisterBankInfo.h"
#include "AArch64RegisterInfo.h"
#include "AArch64Subtarget.h"
+#include "AArch64TargetMachine.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#endif
AArch64InstructionSelector::AArch64InstructionSelector(
- const AArch64Subtarget &STI, const AArch64RegisterBankInfo &RBI)
- : InstructionSelector(), TII(*STI.getInstrInfo()),
+ const AArch64TargetMachine &TM, const AArch64Subtarget &STI,
+ const AArch64RegisterBankInfo &RBI)
+ : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()), RBI(RBI) {}
/// Check whether \p I is a currently unsupported binary operation:
return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
}
+
+ case TargetOpcode::G_GLOBAL_VALUE: {
+ auto GV = I.getOperand(1).getGlobal();
+ if (GV->isThreadLocal()) {
+ // FIXME: we don't support TLS yet.
+ return false;
+ }
+ unsigned char OpFlags = STI.ClassifyGlobalReference(GV, TM);
+ if (OpFlags & AArch64II::MO_GOT)
+ I.setDesc(TII.get(AArch64::LOADgot));
+ else {
+ I.setDesc(TII.get(AArch64::MOVaddr));
+ I.getOperand(1).setTargetFlags(OpFlags | AArch64II::MO_PAGE);
+ MachineInstrBuilder MIB(MF, I);
+ MIB.addGlobalAddress(GV, I.getOperand(1).getOffset(),
+ OpFlags | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
+ }
+ return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
+ }
+
case TargetOpcode::G_LOAD:
case TargetOpcode::G_STORE: {
LLT MemTy = Ty;
class AArch64RegisterBankInfo;
class AArch64RegisterInfo;
class AArch64Subtarget;
+class AArch64TargetMachine;
class AArch64InstructionSelector : public InstructionSelector {
public:
- AArch64InstructionSelector(const AArch64Subtarget &STI,
+ AArch64InstructionSelector(const AArch64TargetMachine &TM,
+ const AArch64Subtarget &STI,
const AArch64RegisterBankInfo &RBI);
virtual bool select(MachineInstr &I) const override;
private:
+ const AArch64TargetMachine &TM;
+ const AArch64Subtarget &STI;
const AArch64InstrInfo &TII;
const AArch64RegisterInfo &TRI;
const AArch64RegisterBankInfo &RBI;
// FIXME: At this point, we can't rely on Subtarget having RBI.
// It's awkward to mix passing RBI and the Subtarget; should we pass
// TII/TRI as well?
- GISel->InstSelector.reset(new AArch64InstructionSelector(*I, *RBI));
+ GISel->InstSelector.reset(new AArch64InstructionSelector(*this, *I, *RBI));
GISel->RegBankInfo.reset(RBI);
#endif
--- |
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
- target triple = "aarch64--"
+ target triple = "aarch64-apple-ios"
define void @add_s32_gpr() { ret void }
define void @add_s64_gpr() { ret void }
define i64 @const_s64() { ret i64 1234567890123 }
define i8* @gep(i8* %in) { ret i8* undef }
+
+ @var_local = global i8 0
+ define i8* @global_local() { ret i8* undef }
+
+ @var_got = external global i8
+ define i8* @global_got() { ret i8* undef }
...
---
%1(s64) = G_CONSTANT 42
%2(p0) = G_GEP %0, %1(s64)
...
+
+---
+# Global defined in the same linkage unit so no GOT is needed
+# CHECK-LABEL: name: global_local
+name: global_local
+legalized: true
+regBankSelected: true
+registers:
+ - { id: 0, class: gpr }
+
+# CHECK: body:
+# CHECK: %0 = MOVaddr target-flags(aarch64-page) @var_local, target-flags(aarch64-pageoff, aarch64-nc) @var_local
+body: |
+ bb.0:
+ %0(p0) = G_GLOBAL_VALUE @var_local
+...
+
+---
+# CHECK-LABEL: name: global_got
+name: global_got
+legalized: true
+regBankSelected: true
+registers:
+ - { id: 0, class: gpr }
+
+# CHECK: body:
+# CHECK: %0 = LOADgot @var_got
+body: |
+ bb.0:
+ %0(p0) = G_GLOBAL_VALUE @var_got
+...