From a401e10f12ba555eefc3da607fa5168603caa9c6 Mon Sep 17 00:00:00 2001 From: Amara Emerson Date: Tue, 4 Apr 2023 11:00:50 -0700 Subject: [PATCH] [AArch64][GlobalISel][RegBankSelect] Guess the bank for loads using the MMO. We had this patch downstream for a long time, we need to find the users of the IR load to guess the bank since with opaque pointers we lost the type information. --- .../AArch64/GISel/AArch64RegisterBankInfo.cpp | 30 +++++++- .../AArch64/GlobalISel/regbankselect-fp-loads.mir | 88 ++++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/regbankselect-fp-loads.mir diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp index d6d5c60..822a7b1 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp @@ -753,7 +753,7 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank, OpSize[0]); break; - case TargetOpcode::G_LOAD: + case TargetOpcode::G_LOAD: { // Loading in vector unit is slightly more expensive. // This is actually only true for the LD1R and co instructions, // but anyway for the fast mode this number does not matter and @@ -771,6 +771,33 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { break; } + // Try to guess the type of the load from the MMO. + const auto &MMO = **MI.memoperands_begin(); + const Value *LdVal = MMO.getValue(); + if (LdVal) { + Type *EltTy = nullptr; + if (const GlobalValue *GV = dyn_cast(LdVal)) { + EltTy = GV->getValueType(); + } else { + // FIXME: grubbing around uses is pretty ugly, but with no more + // `getPointerElementType` there's not much else we can do. + for (const auto *LdUser : LdVal->users()) { + if (isa(LdUser)) { + EltTy = LdUser->getType(); + break; + } + if (isa(LdUser) && LdUser->getOperand(1) == LdVal) { + EltTy = LdUser->getOperand(0)->getType(); + break; + } + } + } + if (EltTy && EltTy->isFPOrFPVectorTy()) { + OpRegBankIdx[0] = PMI_FirstFPR; + break; + } + } + // Check if that load feeds fp instructions. // In that case, we want the default mapping to be on FPR // instead of blind map every scalar to GPR. @@ -788,6 +815,7 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { })) OpRegBankIdx[0] = PMI_FirstFPR; break; + } case TargetOpcode::G_STORE: // Check if that store is fed by fp instructions. if (OpRegBankIdx[0] == PMI_FirstGPR) { diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/regbankselect-fp-loads.mir b/llvm/test/CodeGen/AArch64/GlobalISel/regbankselect-fp-loads.mir new file mode 100644 index 0000000..cfa0ba9 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/regbankselect-fp-loads.mir @@ -0,0 +1,88 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=aarch64-apple-ios -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + @var_fp = global float 0.0 + @var_int = global i32 0 + + define float @fp_load_phi() { ret float undef } + define i32 @int_load_phi() { ret i32 undef } + +... +--- +name: fp_load_phi +legalized: true +regBankSelected: false +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: fp_load_phi + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $w0 + ; CHECK: [[COPY:%[0-9]+]]:gpr(s32) = COPY $w0 + ; CHECK: [[GV:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var_fp + ; CHECK: %fp_load:fpr(s32) = G_LOAD [[GV]](p0) :: (load (s32) from @var_fp) + ; CHECK: bb.1: + ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; CHECK: [[PHI:%[0-9]+]]:fpr(s32) = PHI %fp_load(s32), %bb.0, [[PHI]](s32), %bb.1 + ; CHECK: G_BRCOND [[COPY]](s32), %bb.1 + ; CHECK: bb.2: + ; CHECK: $s0 = COPY [[PHI]](s32) + ; CHECK: RET_ReallyLR implicit $s0 + ; Here we're checking that the load is assigned an FPR bank, since it's + ; loading from an fp type in the IR. + bb.0: + liveins: $w0 + successors: %bb.1 + %0:_(s32) = COPY $w0 + %1:_(p0) = G_GLOBAL_VALUE @var_fp + %fp_load:_(s32) = G_LOAD %1 :: (load 4 from @var_fp) + + bb.1: + successors: %bb.1, %bb.2 + %2:_(s32) = PHI %fp_load, %bb.0, %2, %bb.1 + G_BRCOND %0, %bb.1 + + bb.2: + $s0 = COPY %2 + RET_ReallyLR implicit $s0 +... + +--- +name: int_load_phi +legalized: true +regBankSelected: false +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: int_load_phi + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $w0 + ; CHECK: [[COPY:%[0-9]+]]:gpr(s32) = COPY $w0 + ; CHECK: [[GV:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var_fp + ; CHECK: %fp_load:gpr(s32) = G_LOAD [[GV]](p0) :: (load (s32) from @var_int) + ; CHECK: bb.1: + ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; CHECK: [[PHI:%[0-9]+]]:gpr(s32) = PHI %fp_load(s32), %bb.0, [[PHI]](s32), %bb.1 + ; CHECK: G_BRCOND [[COPY]](s32), %bb.1 + ; CHECK: bb.2: + ; CHECK: $s0 = COPY [[PHI]](s32) + ; CHECK: RET_ReallyLR implicit $s0 + bb.0: + liveins: $w0 + successors: %bb.1 + %0:_(s32) = COPY $w0 + %1:_(p0) = G_GLOBAL_VALUE @var_fp + %fp_load:_(s32) = G_LOAD %1 :: (load 4 from @var_int) + + bb.1: + successors: %bb.1, %bb.2 + %2:_(s32) = PHI %fp_load, %bb.0, %2, %bb.1 + G_BRCOND %0, %bb.1 + + bb.2: + $s0 = COPY %2 + RET_ReallyLR implicit $s0 +... -- 2.7.4