Index: lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -659,6 +659,40 @@ MI.getOperand(2).setReg(OffsetExt); return Legalized; } + case TargetOpcode::G_PHI: { + assert(TypeIdx == 0 && "Expecting only Idx 0"); + MachineFunction *MF = MI.getParent()->getParent(); + auto getExtendedReg = [this, MF, WideTy](unsigned Reg, + MachineBasicBlock &MBB) { + auto NonTermIt = std::prev(MBB.getFirstTerminator()); + MIRBuilder.setInstr(*NonTermIt, true); + MachineInstr *DefMI = MRI.getVRegDef(Reg); + MachineInstrBuilder MIB; + if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) { + MIB = MIRBuilder.buildAnyExtOrTrunc(WideTy, + DefMI->getOperand(1).getReg()); + } else { + MIB = MIRBuilder.buildAnyExt(WideTy, Reg); + } + return MIB->getOperand(0).getReg(); + }; + SmallVector, 8> NewRegs; + for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end(); + OpIt != OpE;) { + unsigned Reg = OpIt++->getReg(); + MachineBasicBlock *OpMBB = OpIt++->getMBB(); + NewRegs.push_back(std::make_pair(getExtendedReg(Reg, *OpMBB), OpMBB)); + } + MIRBuilder.setInstr(MI); + auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy); + for (auto &P : NewRegs) { + MIB.addReg(P.first).addMBB(P.second); + } + MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), + MIB->getOperand(0).getReg()); + MI.eraseFromParent(); + return Legalized; + } } } Index: lib/Target/AArch64/AArch64LegalizerInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -38,6 +38,9 @@ for (auto Ty : {p0, s1, s8, s16, s32, s64}) setAction({G_IMPLICIT_DEF, Ty}, Legal); + for (auto Ty : {s1, s8}) + setAction({G_PHI, Ty}, WidenScalar); + for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL}) { // These operations naturally get the right answer when used on // GPR32, even if the actual type is narrower. Index: test/CodeGen/AArch64/GlobalISel/legalize-phi.mir =================================================================== --- /dev/null +++ test/CodeGen/AArch64/GlobalISel/legalize-phi.mir @@ -0,0 +1,115 @@ +# RUN: llc -mtriple=aarch64-unknown-unknown -global-isel -verify-machineinstrs -run-pass=legalizer %s -o - | FileCheck %s +--- | + ; ModuleID = '/tmp/test.ll' + source_filename = "/tmp/test.ll" + target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + target triple = "aarch64-unknown-unknown" + + define i32 @legalize_phi(i32 %argc) { + entry: + %cmp = icmp ugt i32 %argc, 0 + br i1 %cmp, label %case1, label %case2 + + case1: ; preds = %entry + %tmp11 = add i32 %argc, 1 + %tmp1 = trunc i32 %tmp11 to i1 + br label %return + + case2: ; preds = %entry + %tmp22 = add i32 %argc, 2 + %tmp2 = trunc i32 %tmp22 to i1 + br label %return + + return: ; preds = %case2, %case1 + %res = phi i1 [ %tmp1, %case1 ], [ %tmp2, %case2 ] + %res_ext = zext i1 %res to i32 + ret i32 %res_ext + } + +... +--- +name: legalize_phi +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } + - { id: 3, class: _, preferred-register: '' } + - { id: 4, class: _, preferred-register: '' } + - { id: 5, class: _, preferred-register: '' } + - { id: 6, class: _, preferred-register: '' } + - { id: 7, class: _, preferred-register: '' } + - { id: 8, class: _, preferred-register: '' } + - { id: 9, class: _, preferred-register: '' } + - { id: 10, class: _, preferred-register: '' } +liveins: +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + bb.1.entry: + ; CHECK-LABEL: name: legalize_phi + ; CHECK-LABEL: bb.1.case1: + ; CHECK: [[ADD_BB1:%.*]](s32) = G_ADD + ; CHECK: [[RES_BB1:%.*]](s16) = G_TRUNC [[ADD_BB1]] + + ; CHECK-LABEL: bb.2.case2: + ; CHECK: [[ADD_BB2:%.*]](s32) = G_ADD + ; CHECK: [[RES_BB2:%.*]](s16) = G_TRUNC [[ADD_BB2]] + + ; CHECK-LABEL: bb.3.return: + ; CHECK: [[RES_PHI:%.*]](s16) = G_PHI [[RES_BB1]](s16), %bb.1.case1, [[RES_BB2]](s16), %bb.2.case2 + ; CHECK: [[RES:%.*]](s1) = G_TRUNC [[RES_PHI]] + successors: %bb.2.case1(0x40000000), %bb.3.case2(0x40000000) + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s32) = G_CONSTANT i32 0 + %3(s32) = G_CONSTANT i32 1 + %6(s32) = G_CONSTANT i32 2 + %2(s1) = G_ICMP intpred(ugt), %0(s32), %1 + G_BRCOND %2(s1), %bb.2.case1 + G_BR %bb.3.case2 + + bb.2.case1: + successors: %bb.4.return(0x80000000) + + %4(s32) = G_ADD %0, %3 + %5(s1) = G_TRUNC %4(s32) + G_BR %bb.4.return + + bb.3.case2: + successors: %bb.4.return(0x80000000) + + %7(s32) = G_ADD %0, %6 + %8(s1) = G_TRUNC %7(s32) + + bb.4.return: + %9(s1) = G_PHI %5(s1), %bb.2.case1, %8(s1), %bb.3.case2 + %10(s32) = G_ZEXT %9(s1) + %w0 = COPY %10(s32) + RET_ReallyLR implicit %w0 + +...