diff options
author | Petar Jovanovic <petar.jovanovic@mips.com> | 2018-10-08 23:59:37 +0000 |
---|---|---|
committer | Petar Jovanovic <petar.jovanovic@mips.com> | 2018-10-08 23:59:37 +0000 |
commit | cf9eeb0c053cbd9943c3f0807178a90bab10302d (patch) | |
tree | 69acdab56bbfc9907e9bc006d43aa770b585cc1e | |
parent | b13f4230aa9b7eed2ac2b62173d391a7c54e29c0 (diff) |
[MIPS GlobalISel] Legalize i64 add
Custom legalize s64 G_ADD for MIPS32.
Patch by Petar Avramovic.
Differential Revision: https://reviews.llvm.org/D52652
-rw-r--r-- | llvm/lib/Target/Mips/MipsLegalizerInfo.cpp | 48 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsLegalizerInfo.h | 3 | ||||
-rw-r--r-- | llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir | 36 | ||||
-rw-r--r-- | llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll | 15 |
4 files changed, 101 insertions, 1 deletions
diff --git a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp index 4da1fb205e5..6a16e7955a1 100644 --- a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp +++ b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -13,6 +13,7 @@ #include "MipsLegalizerInfo.h" #include "MipsTargetMachine.h" +#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" using namespace llvm; @@ -20,11 +21,13 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { using namespace TargetOpcode; const LLT s32 = LLT::scalar(32); + const LLT s64 = LLT::scalar(64); const LLT p0 = LLT::pointer(0, 32); getActionDefinitionsBuilder(G_ADD) .legalFor({s32}) - .minScalar(0, s32); + .minScalar(0, s32) + .customFor({s64}); getActionDefinitionsBuilder({G_LOAD, G_STORE}) .legalForCartesianProduct({p0, s32}, {p0}); @@ -51,3 +54,46 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { computeTables(); verify(*ST.getInstrInfo()); } + +bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const { + + using namespace TargetOpcode; + + MIRBuilder.setInstr(MI); + + switch (MI.getOpcode()) { + case G_ADD: { + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + + const LLT sHalf = LLT::scalar(Size / 2); + + unsigned RHSLow = MRI.createGenericVirtualRegister(sHalf); + unsigned RHSHigh = MRI.createGenericVirtualRegister(sHalf); + unsigned LHSLow = MRI.createGenericVirtualRegister(sHalf); + unsigned LHSHigh = MRI.createGenericVirtualRegister(sHalf); + unsigned ResLow = MRI.createGenericVirtualRegister(sHalf); + unsigned ResHigh = MRI.createGenericVirtualRegister(sHalf); + unsigned Carry = MRI.createGenericVirtualRegister(sHalf); + unsigned TmpResHigh = MRI.createGenericVirtualRegister(sHalf); + + MIRBuilder.buildUnmerge({RHSHigh, RHSLow}, MI.getOperand(2).getReg()); + MIRBuilder.buildUnmerge({LHSHigh, LHSLow}, MI.getOperand(1).getReg()); + + MIRBuilder.buildAdd(TmpResHigh, LHSHigh, RHSHigh); + MIRBuilder.buildAdd(ResLow, LHSLow, RHSLow); + MIRBuilder.buildICmp(CmpInst::ICMP_ULT, Carry, ResLow, LHSLow); + MIRBuilder.buildAdd(ResHigh, TmpResHigh, Carry); + + MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {ResHigh, ResLow}); + + MI.eraseFromParent(); + break; + } + default: + return false; + } + + return true; +} diff --git a/llvm/lib/Target/Mips/MipsLegalizerInfo.h b/llvm/lib/Target/Mips/MipsLegalizerInfo.h index 36dd39c8c1c..96d95746ac8 100644 --- a/llvm/lib/Target/Mips/MipsLegalizerInfo.h +++ b/llvm/lib/Target/Mips/MipsLegalizerInfo.h @@ -24,6 +24,9 @@ class MipsSubtarget; class MipsLegalizerInfo : public LegalizerInfo { public: MipsLegalizerInfo(const MipsSubtarget &ST); + + bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const override; }; } // end namespace llvm #endif diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir index 6d59d82efa1..efd071636b5 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir +++ b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir @@ -9,6 +9,8 @@ define void @add_i16_sext() {entry: ret void} define void @add_i16_zext() {entry: ret void} define void @add_i16_aext() {entry: ret void} + define void @add_i64() {entry: ret void} + ... --- name: add_i32 @@ -210,3 +212,37 @@ body: | RetRA implicit $v0 ... +--- +name: add_i64 +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1, $a2, $a3 + + ; MIPS32-LABEL: name: add_i64 + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY3]], [[COPY1]] + ; MIPS32: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY2]], [[COPY]] + ; MIPS32: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD1]](s32), [[COPY2]] + ; MIPS32: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[ICMP]] + ; MIPS32: $v0 = COPY [[ADD1]](s32) + ; MIPS32: $v1 = COPY [[ADD2]](s32) + ; MIPS32: RetRA implicit $v0, implicit $v1 + %2:_(s32) = COPY $a0 + %3:_(s32) = COPY $a1 + %0:_(s64) = G_MERGE_VALUES %3(s32), %2(s32) + %4:_(s32) = COPY $a2 + %5:_(s32) = COPY $a3 + %1:_(s64) = G_MERGE_VALUES %5(s32), %4(s32) + %6:_(s64) = G_ADD %1, %0 + %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6(s64) + $v0 = COPY %8(s32) + $v1 = COPY %7(s32) + RetRA implicit $v0, implicit $v1 + +... diff --git a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll index d32dfb2cedf..cf6d1e2c561 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll +++ b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll @@ -86,3 +86,18 @@ entry: %add = add i16 %b, %a ret i16 %add } + +define i64 @add_i64(i64 %a, i64 %b) { +; MIPS32-LABEL: add_i64: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: addu $5, $7, $5 +; MIPS32-NEXT: addu $4, $6, $4 +; MIPS32-NEXT: sltu $6, $4, $6 +; MIPS32-NEXT: addu $3, $5, $6 +; MIPS32-NEXT: move $2, $4 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %add = add i64 %b, %a + ret i64 %add +}
\ No newline at end of file |