mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-28 22:00:30 +00:00
[MIPS GlobalISel] Register bank select for G_LOAD. Select i64 load
Select gprb or fprb when loaded value is used by either: copy to physical register or instruction with only one mapping available for that use operand. Load of integer s64 is handled with narrowScalar when mapping is applied, produced artifacts are combined away. Manually set gprb to all register operands of instructions created during narrowScalar. Differential Revision: https://reviews.llvm.org/D64269 llvm-svn: 365323
This commit is contained in:
parent
e165bef5cc
commit
34379b96a5
@ -43,6 +43,9 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
|
||||
{p0, p0, 32, 8}})
|
||||
.minScalar(0, s32);
|
||||
|
||||
getActionDefinitionsBuilder(G_UNMERGE_VALUES)
|
||||
.legalFor({{s32, s64}});
|
||||
|
||||
getActionDefinitionsBuilder(G_MERGE_VALUES)
|
||||
.legalFor({{s64, s32}});
|
||||
|
||||
|
@ -112,6 +112,22 @@ static bool isFloatingPointOpcode(unsigned Opc) {
|
||||
}
|
||||
}
|
||||
|
||||
// Instructions where use operands are floating point registers.
|
||||
// Def operands are general purpose.
|
||||
static bool isFloatingPointOpcodeUse(unsigned Opc) {
|
||||
switch (Opc) {
|
||||
case TargetOpcode::G_FPTOSI:
|
||||
case TargetOpcode::G_FPTOUI:
|
||||
case TargetOpcode::G_FCMP:
|
||||
case Mips::MFC1:
|
||||
case Mips::ExtractElementF64:
|
||||
case Mips::ExtractElementF64_64:
|
||||
return true;
|
||||
default:
|
||||
return isFloatingPointOpcode(Opc);
|
||||
}
|
||||
}
|
||||
|
||||
// Instructions where def operands are floating point registers.
|
||||
// Use operands are general purpose.
|
||||
static bool isFloatingPointOpcodeDef(unsigned Opc) {
|
||||
@ -139,6 +155,20 @@ static bool isAmbiguous(unsigned Opc) {
|
||||
}
|
||||
}
|
||||
|
||||
void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
|
||||
Register Reg, const MachineRegisterInfo &MRI) {
|
||||
assert(!MRI.getType(Reg).isPointer() &&
|
||||
"Pointers are gprb, they should not be considered as ambiguous.\n");
|
||||
for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
|
||||
if (UseMI.getOpcode() == TargetOpcode::COPY &&
|
||||
!TargetRegisterInfo::isPhysicalRegister(UseMI.getOperand(0).getReg()))
|
||||
// Copies of non-physical registers are not supported
|
||||
return;
|
||||
|
||||
DefUses.push_back(&UseMI);
|
||||
}
|
||||
}
|
||||
|
||||
void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
|
||||
Register Reg, const MachineRegisterInfo &MRI) {
|
||||
assert(!MRI.getType(Reg).isPointer() &&
|
||||
@ -159,6 +189,9 @@ MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
|
||||
|
||||
const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
|
||||
|
||||
if (MI->getOpcode() == TargetOpcode::G_LOAD)
|
||||
addDefUses(MI->getOperand(0).getReg(), MRI);
|
||||
|
||||
if (MI->getOpcode() == TargetOpcode::G_STORE)
|
||||
addUseDef(MI->getOperand(0).getReg(), MRI);
|
||||
}
|
||||
@ -169,27 +202,33 @@ bool MipsRegisterBankInfo::TypeInfoForMF::visit(const MachineInstr *MI) {
|
||||
startVisit(MI);
|
||||
AmbiguousRegDefUseContainer DefUseContainer(MI);
|
||||
|
||||
// Visit instructions where MI's DEF operands are USED.
|
||||
if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true))
|
||||
return true;
|
||||
|
||||
// Visit instructions that DEFINE MI's USE operands.
|
||||
if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs()))
|
||||
if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
|
||||
const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs) {
|
||||
const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
|
||||
bool isDefUse) {
|
||||
while (!AdjacentInstrs.empty()) {
|
||||
MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
|
||||
|
||||
if (isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
|
||||
if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
|
||||
: isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
|
||||
setTypes(MI, InstType::FloatingPoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine InstType from register bank of phys register that is
|
||||
// use of this copy.
|
||||
// 'isDefUse ? def : use' of this copy.
|
||||
if (AdjMI->getOpcode() == TargetOpcode::COPY) {
|
||||
setTypesAccordingToPhysicalRegister(MI, AdjMI, 1);
|
||||
setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -276,7 +315,6 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
|
||||
case G_SUB:
|
||||
case G_MUL:
|
||||
case G_UMULH:
|
||||
case G_LOAD:
|
||||
case G_ZEXTLOAD:
|
||||
case G_SEXTLOAD:
|
||||
case G_GEP:
|
||||
@ -292,6 +330,30 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
|
||||
case G_UREM:
|
||||
OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
|
||||
break;
|
||||
case G_LOAD: {
|
||||
unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
|
||||
InstType InstTy = InstType::Integer;
|
||||
if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
|
||||
InstTy = TI.determineInstType(&MI);
|
||||
}
|
||||
|
||||
if (InstTy == InstType::FloatingPoint) { // fprb
|
||||
OperandsMapping =
|
||||
getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
|
||||
: &Mips::ValueMappings[Mips::DPRIdx],
|
||||
&Mips::ValueMappings[Mips::GPRIdx]});
|
||||
break;
|
||||
} else { // gprb
|
||||
OperandsMapping =
|
||||
getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
|
||||
: &Mips::ValueMappings[Mips::DPRIdx],
|
||||
&Mips::ValueMappings[Mips::GPRIdx]});
|
||||
if (Size == 64)
|
||||
MappingID = CustomMappingID;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case G_STORE: {
|
||||
unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
|
||||
InstType InstTy = InstType::Integer;
|
||||
@ -315,6 +377,13 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case G_UNMERGE_VALUES: {
|
||||
OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
|
||||
&Mips::ValueMappings[Mips::GPRIdx],
|
||||
&Mips::ValueMappings[Mips::DPRIdx]});
|
||||
MappingID = CustomMappingID;
|
||||
break;
|
||||
}
|
||||
case G_MERGE_VALUES: {
|
||||
OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
|
||||
&Mips::ValueMappings[Mips::GPRIdx],
|
||||
@ -449,6 +518,7 @@ void MipsRegisterBankInfo::applyMappingImpl(
|
||||
B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo());
|
||||
|
||||
switch (MI.getOpcode()) {
|
||||
case TargetOpcode::G_LOAD:
|
||||
case TargetOpcode::G_STORE: {
|
||||
Helper.narrowScalar(MI, 0, LLT::scalar(32));
|
||||
// Handle new instructions.
|
||||
@ -462,7 +532,12 @@ void MipsRegisterBankInfo::applyMappingImpl(
|
||||
ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs);
|
||||
for (MachineInstr *DeadMI : DeadInstrs)
|
||||
DeadMI->eraseFromParent();
|
||||
} else
|
||||
}
|
||||
// This G_MERGE will be combined away when its corresponding G_UNMERGE
|
||||
// gets regBankSelected.
|
||||
else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
|
||||
continue;
|
||||
else
|
||||
// Manually set register banks for all register operands to 32 bit gprb.
|
||||
for (auto Op : NewMI->operands()) {
|
||||
if (Op.isReg()) {
|
||||
@ -474,6 +549,13 @@ void MipsRegisterBankInfo::applyMappingImpl(
|
||||
}
|
||||
return;
|
||||
}
|
||||
case TargetOpcode::G_UNMERGE_VALUES: {
|
||||
SmallVector<MachineInstr *, 2> DeadInstrs;
|
||||
ArtCombiner.tryCombineMerges(MI, DeadInstrs);
|
||||
for (MachineInstr *DeadMI : DeadInstrs)
|
||||
DeadMI->eraseFromParent();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -57,15 +57,19 @@ private:
|
||||
/// Some generic instructions have operands that can be mapped to either fprb
|
||||
/// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1
|
||||
/// is always gprb since it is a pointer.
|
||||
/// This class provides container for MI's ambiguous:
|
||||
/// This class provides containers for MI's ambiguous:
|
||||
/// DefUses : MachineInstrs that use one of MI's ambiguous def operands.
|
||||
/// UseDefs : MachineInstrs that define MI's ambiguous use operands.
|
||||
class AmbiguousRegDefUseContainer {
|
||||
SmallVector<MachineInstr *, 2> DefUses;
|
||||
SmallVector<MachineInstr *, 2> UseDefs;
|
||||
|
||||
void addDefUses(Register Reg, const MachineRegisterInfo &MRI);
|
||||
void addUseDef(Register Reg, const MachineRegisterInfo &MRI);
|
||||
|
||||
public:
|
||||
AmbiguousRegDefUseContainer(const MachineInstr *MI);
|
||||
SmallVectorImpl<MachineInstr *> &getDefUses() { return DefUses; }
|
||||
SmallVectorImpl<MachineInstr *> &getUseDefs() { return UseDefs; }
|
||||
};
|
||||
|
||||
@ -77,9 +81,10 @@ private:
|
||||
|
||||
bool visit(const MachineInstr *MI);
|
||||
|
||||
/// Visit MI's adjacent UseDefs.
|
||||
/// Visit MI's adjacent UseDefs or DefUses.
|
||||
bool visitAdjacentInstrs(const MachineInstr *MI,
|
||||
SmallVectorImpl<MachineInstr *> &AdjacentInstrs);
|
||||
SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
|
||||
bool isDefUse);
|
||||
|
||||
void setTypes(const MachineInstr *MI, InstType ITy);
|
||||
|
||||
|
94
test/CodeGen/Mips/GlobalISel/legalizer/load.mir
Normal file
94
test/CodeGen/Mips/GlobalISel/legalizer/load.mir
Normal file
@ -0,0 +1,94 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
--- |
|
||||
|
||||
define void @load_i32(i32* %ptr) {entry: ret void}
|
||||
define void @load_i64(i64* %ptr) {entry: ret void}
|
||||
define void @load_float(float* %ptr) {entry: ret void}
|
||||
define void @load_double(double* %ptr) {entry: ret void}
|
||||
|
||||
...
|
||||
---
|
||||
name: load_i32
|
||||
alignment: 2
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $a0
|
||||
|
||||
; MIPS32-LABEL: name: load_i32
|
||||
; MIPS32: liveins: $a0
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY]](p0) :: (load 4 from %ir.ptr)
|
||||
; MIPS32: $v0 = COPY [[LOAD]](s32)
|
||||
; MIPS32: RetRA implicit $v0
|
||||
%0:_(p0) = COPY $a0
|
||||
%1:_(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr)
|
||||
$v0 = COPY %1(s32)
|
||||
RetRA implicit $v0
|
||||
|
||||
...
|
||||
---
|
||||
name: load_i64
|
||||
alignment: 2
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $a0
|
||||
|
||||
; MIPS32-LABEL: name: load_i64
|
||||
; MIPS32: liveins: $a0
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[COPY]](p0) :: (load 8 from %ir.ptr)
|
||||
; MIPS32: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[LOAD]](s64)
|
||||
; MIPS32: $v0 = COPY [[UV]](s32)
|
||||
; MIPS32: $v1 = COPY [[UV1]](s32)
|
||||
; MIPS32: RetRA implicit $v0, implicit $v1
|
||||
%0:_(p0) = COPY $a0
|
||||
%1:_(s64) = G_LOAD %0(p0) :: (load 8 from %ir.ptr)
|
||||
%2:_(s32), %3:_(s32) = G_UNMERGE_VALUES %1(s64)
|
||||
$v0 = COPY %2(s32)
|
||||
$v1 = COPY %3(s32)
|
||||
RetRA implicit $v0, implicit $v1
|
||||
|
||||
...
|
||||
---
|
||||
name: load_float
|
||||
alignment: 2
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $a0
|
||||
|
||||
; MIPS32-LABEL: name: load_float
|
||||
; MIPS32: liveins: $a0
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[COPY]](p0) :: (load 4 from %ir.ptr)
|
||||
; MIPS32: $f0 = COPY [[LOAD]](s32)
|
||||
; MIPS32: RetRA implicit $f0
|
||||
%0:_(p0) = COPY $a0
|
||||
%1:_(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr)
|
||||
$f0 = COPY %1(s32)
|
||||
RetRA implicit $f0
|
||||
|
||||
...
|
||||
---
|
||||
name: load_double
|
||||
alignment: 2
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $a0
|
||||
|
||||
; MIPS32-LABEL: name: load_double
|
||||
; MIPS32: liveins: $a0
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[COPY]](p0) :: (load 8 from %ir.ptr)
|
||||
; MIPS32: $d0 = COPY [[LOAD]](s64)
|
||||
; MIPS32: RetRA implicit $d0
|
||||
%0:_(p0) = COPY $a0
|
||||
%1:_(s64) = G_LOAD %0(p0) :: (load 8 from %ir.ptr)
|
||||
$d0 = COPY %1(s64)
|
||||
RetRA implicit $d0
|
||||
|
||||
...
|
27
test/CodeGen/Mips/GlobalISel/llvm-ir/load.ll
Normal file
27
test/CodeGen/Mips/GlobalISel/llvm-ir/load.ll
Normal file
@ -0,0 +1,27 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32
|
||||
|
||||
define i32 @load_i32(i32* %ptr) {
|
||||
; MIPS32-LABEL: load_i32:
|
||||
; MIPS32: # %bb.0: # %entry
|
||||
; MIPS32-NEXT: lw $2, 0($4)
|
||||
; MIPS32-NEXT: jr $ra
|
||||
; MIPS32-NEXT: nop
|
||||
entry:
|
||||
%0 = load i32, i32* %ptr
|
||||
ret i32 %0
|
||||
}
|
||||
|
||||
define i64 @load_i64(i64* %ptr) {
|
||||
; MIPS32-LABEL: load_i64:
|
||||
; MIPS32: # %bb.0: # %entry
|
||||
; MIPS32-NEXT: lw $2, 0($4)
|
||||
; MIPS32-NEXT: ori $1, $zero, 4
|
||||
; MIPS32-NEXT: addu $1, $4, $1
|
||||
; MIPS32-NEXT: lw $3, 0($1)
|
||||
; MIPS32-NEXT: jr $ra
|
||||
; MIPS32-NEXT: nop
|
||||
entry:
|
||||
%0 = load i64, i64* %ptr
|
||||
ret i64 %0
|
||||
}
|
100
test/CodeGen/Mips/GlobalISel/regbankselect/load.mir
Normal file
100
test/CodeGen/Mips/GlobalISel/regbankselect/load.mir
Normal file
@ -0,0 +1,100 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
--- |
|
||||
|
||||
define void @load_i32(i32* %ptr) {entry: ret void}
|
||||
define void @load_i64(i64* %ptr) {entry: ret void}
|
||||
define void @load_float(float* %ptr) {entry: ret void}
|
||||
define void @load_double(double* %ptr) {entry: ret void}
|
||||
|
||||
...
|
||||
---
|
||||
name: load_i32
|
||||
alignment: 2
|
||||
legalized: true
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $a0
|
||||
|
||||
; MIPS32-LABEL: name: load_i32
|
||||
; MIPS32: liveins: $a0
|
||||
; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:gprb(s32) = G_LOAD [[COPY]](p0) :: (load 4 from %ir.ptr)
|
||||
; MIPS32: $v0 = COPY [[LOAD]](s32)
|
||||
; MIPS32: RetRA implicit $v0
|
||||
%0:_(p0) = COPY $a0
|
||||
%1:_(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr)
|
||||
$v0 = COPY %1(s32)
|
||||
RetRA implicit $v0
|
||||
|
||||
...
|
||||
---
|
||||
name: load_i64
|
||||
alignment: 2
|
||||
legalized: true
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $a0
|
||||
|
||||
; MIPS32-LABEL: name: load_i64
|
||||
; MIPS32: liveins: $a0
|
||||
; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:gprb(s32) = G_LOAD [[COPY]](p0) :: (load 4 from %ir.ptr, align 8)
|
||||
; MIPS32: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 4
|
||||
; MIPS32: [[GEP:%[0-9]+]]:gprb(p0) = G_GEP [[COPY]], [[C]](s32)
|
||||
; MIPS32: [[LOAD1:%[0-9]+]]:gprb(s32) = G_LOAD [[GEP]](p0) :: (load 4 from %ir.ptr + 4, align 8)
|
||||
; MIPS32: $v0 = COPY [[LOAD]](s32)
|
||||
; MIPS32: $v1 = COPY [[LOAD1]](s32)
|
||||
; MIPS32: RetRA implicit $v0, implicit $v1
|
||||
%0:_(p0) = COPY $a0
|
||||
%1:_(s64) = G_LOAD %0(p0) :: (load 8 from %ir.ptr)
|
||||
%2:_(s32), %3:_(s32) = G_UNMERGE_VALUES %1(s64)
|
||||
$v0 = COPY %2(s32)
|
||||
$v1 = COPY %3(s32)
|
||||
RetRA implicit $v0, implicit $v1
|
||||
|
||||
...
|
||||
---
|
||||
name: load_float
|
||||
alignment: 2
|
||||
legalized: true
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $a0
|
||||
|
||||
; MIPS32-LABEL: name: load_float
|
||||
; MIPS32: liveins: $a0
|
||||
; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:fprb(s32) = G_LOAD [[COPY]](p0) :: (load 4 from %ir.ptr)
|
||||
; MIPS32: $f0 = COPY [[LOAD]](s32)
|
||||
; MIPS32: RetRA implicit $f0
|
||||
%0:_(p0) = COPY $a0
|
||||
%1:_(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr)
|
||||
$f0 = COPY %1(s32)
|
||||
RetRA implicit $f0
|
||||
|
||||
...
|
||||
---
|
||||
name: load_double
|
||||
alignment: 2
|
||||
legalized: true
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $a0
|
||||
|
||||
; MIPS32-LABEL: name: load_double
|
||||
; MIPS32: liveins: $a0
|
||||
; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0
|
||||
; MIPS32: [[LOAD:%[0-9]+]]:fprb(s64) = G_LOAD [[COPY]](p0) :: (load 8 from %ir.ptr)
|
||||
; MIPS32: $d0 = COPY [[LOAD]](s64)
|
||||
; MIPS32: RetRA implicit $d0
|
||||
%0:_(p0) = COPY $a0
|
||||
%1:_(s64) = G_LOAD %0(p0) :: (load 8 from %ir.ptr)
|
||||
$d0 = COPY %1(s64)
|
||||
RetRA implicit $d0
|
||||
|
||||
...
|
Loading…
Reference in New Issue
Block a user