Index: lib/Target/Mips/MipsLegalizerInfo.h =================================================================== --- lib/Target/Mips/MipsLegalizerInfo.h +++ lib/Target/Mips/MipsLegalizerInfo.h @@ -24,6 +24,9 @@ class MipsLegalizerInfo : public LegalizerInfo { public: MipsLegalizerInfo(const MipsSubtarget &ST); + + bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const override; }; } // end namespace llvm #endif Index: lib/Target/Mips/MipsLegalizerInfo.cpp =================================================================== --- lib/Target/Mips/MipsLegalizerInfo.cpp +++ 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 @@ 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 @@ 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; +} Index: test/CodeGen/Mips/GlobalISel/legalizer/add.mir =================================================================== --- test/CodeGen/Mips/GlobalISel/legalizer/add.mir +++ 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 @@ 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 + +... Index: test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll =================================================================== --- test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll +++ test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll @@ -86,3 +86,18 @@ %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