From: Aditya Nandakumar Date: Fri, 25 Aug 2017 04:57:27 +0000 (+0000) Subject: [GISel]: Implement widenScalar for Legalizing G_PHI X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=43aeabcde1c4f772205ecc66f87954e8e2f42a83;p=llvm [GISel]: Implement widenScalar for Legalizing G_PHI https://reviews.llvm.org/D37018 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311763 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index e24b62cd849..d5761baaa79 100644 --- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -84,6 +84,11 @@ class MachineIRBuilder { addUseFromArg(MIB, Arg1); addUsesFromArgs(MIB, std::forward(Args)...); } + unsigned getRegFromArg(unsigned Reg) { return Reg; } + unsigned getRegFromArg(const MachineInstrBuilder &MIB) { + return MIB->getOperand(0).getReg(); + } + public: /// Some constructors for easy use. MachineIRBuilder() = default; @@ -372,7 +377,12 @@ public: /// \pre \p Op must be smaller than \p Res /// /// \return The newly created instruction. + MachineInstrBuilder buildAnyExt(unsigned Res, unsigned Op); + template + MachineInstrBuilder buildAnyExt(DstType &&Res, ArgType &&Arg) { + return buildAnyExt(getDestFromArg(Res), getRegFromArg(Arg)); + } /// Build and insert \p Res = G_SEXT \p Op /// @@ -422,6 +432,32 @@ public: /// \return The newly created instruction. MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op); + // Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_TRUNC \p Op, or + /// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op. + /// /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register with scalar or vector type. + /// \pre \p Op must be a generic virtual register with scalar or vector type. + /// + /// \return The newly created instruction. + template + MachineInstrBuilder buildAnyExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) { + return buildAnyExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use)); + } + MachineInstrBuilder buildAnyExtOrTrunc(unsigned Res, unsigned Op); + + /// Build and insert \p Res = \p ExtOpc, \p Res = G_TRUNC \p + /// Op, or \p Res = COPY \p Op depending on the differing sizes of \p Res and + /// \p Op. + /// /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register with scalar or vector type. + /// \pre \p Op must be a generic virtual register with scalar or vector type. + /// + /// \return The newly created instruction. + MachineInstrBuilder buildExtOrTrunc(unsigned ExtOpc, unsigned Res, + unsigned Op); + /// Build and insert an appropriate cast between two registers of equal size. MachineInstrBuilder buildCast(unsigned Dst, unsigned Src); diff --git a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index c54b12b52ee..5e75f4da9bd 100644 --- a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -659,6 +659,37 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { 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 FirstTermIt = MBB.getFirstTerminator(); + MIRBuilder.setInsertPt(MBB, FirstTermIt); + 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(); + }; + auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI, WideTy); + for (auto OpIt = MI.operands_begin() + 1, OpE = MI.operands_end(); + OpIt != OpE;) { + unsigned Reg = OpIt++->getReg(); + MachineBasicBlock *OpMBB = OpIt++->getMBB(); + MIB.addReg(getExtendedReg(Reg, *OpMBB)); + MIB.addMBB(OpMBB); + } + auto *MBB = MI.getParent(); + MIRBuilder.setInsertPt(*MBB, MBB->getFirstNonPHI()); + MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), + MIB->getOperand(0).getReg()); + MI.eraseFromParent(); + return Legalized; + } } } diff --git a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 8ca07f36c9c..b4fe5f15fdd 100644 --- a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -346,14 +346,17 @@ MachineInstrBuilder MachineIRBuilder::buildZExt(unsigned Res, unsigned Op) { return buildInstr(TargetOpcode::G_ZEXT).addDef(Res).addUse(Op); } -MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(unsigned Res, - unsigned Op) { +MachineInstrBuilder +MachineIRBuilder::buildExtOrTrunc(unsigned ExtOpc, unsigned Res, unsigned Op) { + assert((TargetOpcode::G_ANYEXT == ExtOpc || TargetOpcode::G_ZEXT == ExtOpc || + TargetOpcode::G_SEXT == ExtOpc) && + "Expecting Extending Opc"); assert(MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()); assert(MRI->getType(Res).isScalar() == MRI->getType(Op).isScalar()); unsigned Opcode = TargetOpcode::COPY; if (MRI->getType(Res).getSizeInBits() > MRI->getType(Op).getSizeInBits()) - Opcode = TargetOpcode::G_SEXT; + Opcode = ExtOpc; else if (MRI->getType(Res).getSizeInBits() < MRI->getType(Op).getSizeInBits()) Opcode = TargetOpcode::G_TRUNC; else @@ -362,20 +365,19 @@ MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(unsigned Res, return buildInstr(Opcode).addDef(Res).addUse(Op); } -MachineInstrBuilder MachineIRBuilder::buildZExtOrTrunc(unsigned Res, +MachineInstrBuilder MachineIRBuilder::buildSExtOrTrunc(unsigned Res, unsigned Op) { - assert(MRI->getType(Res).isScalar() || MRI->getType(Res).isVector()); - assert(MRI->getType(Res).isScalar() == MRI->getType(Op).isScalar()); + return buildExtOrTrunc(TargetOpcode::G_SEXT, Res, Op); +} - unsigned Opcode = TargetOpcode::COPY; - if (MRI->getType(Res).getSizeInBits() > MRI->getType(Op).getSizeInBits()) - Opcode = TargetOpcode::G_ZEXT; - else if (MRI->getType(Res).getSizeInBits() < MRI->getType(Op).getSizeInBits()) - Opcode = TargetOpcode::G_TRUNC; - else - assert(MRI->getType(Res) == MRI->getType(Op)); +MachineInstrBuilder MachineIRBuilder::buildZExtOrTrunc(unsigned Res, + unsigned Op) { + return buildExtOrTrunc(TargetOpcode::G_ZEXT, Res, Op); +} - return buildInstr(Opcode).addDef(Res).addUse(Op); +MachineInstrBuilder MachineIRBuilder::buildAnyExtOrTrunc(unsigned Res, + unsigned Op) { + return buildExtOrTrunc(TargetOpcode::G_ANYEXT, Res, Op); } MachineInstrBuilder MachineIRBuilder::buildCast(unsigned Dst, unsigned Src) { diff --git a/lib/Target/AArch64/AArch64LegalizerInfo.cpp b/lib/Target/AArch64/AArch64LegalizerInfo.cpp index c2b5e16a101..9a86cac44b5 100644 --- a/lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ b/lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -41,6 +41,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo() { for (auto Ty : {s16, s32, s64}) setAction({G_PHI, 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. diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-phi.mir b/test/CodeGen/AArch64/GlobalISel/legalize-phi.mir new file mode 100644 index 00000000000..36840bb22af --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/legalize-phi.mir @@ -0,0 +1,433 @@ +# 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: + ret i32 0 + } + + define i32 @legalize_phi_empty(i32 %argc) { + entry: + ret i32 0 + } + + define i32 @legalize_phi_loop(i32 %argc) { + entry: + ret i32 0 + } + + define i32 @legalize_phi_cycle(i32 %argc) { + entry: + ret i32 0 + } + define i32 @legalize_phi_same_bb(i32 %argc) { + entry: + ret i32 0 + } + + define i32 @legalize_phi_diff_bb(i32 %argc, i32 %argc2) { + entry: + ret i32 0 + } + +... +--- +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: +body: | + bb.0: + ; Test that we insert legalization artifacts(Truncs here) into the correct BBs + ; while legalizing the G_PHI to s16. + ; CHECK-LABEL: name: legalize_phi + ; CHECK-LABEL: bb.1: + ; CHECK: [[ADD_BB1:%.*]](s32) = G_ADD + ; CHECK: [[RES_BB1:%.*]](s16) = G_TRUNC [[ADD_BB1]] + + ; CHECK-LABEL: bb.2: + ; CHECK: [[ADD_BB2:%.*]](s32) = G_ADD + ; CHECK: [[RES_BB2:%.*]](s16) = G_TRUNC [[ADD_BB2]] + + ; CHECK-LABEL: bb.3: + ; CHECK: [[RES_PHI:%.*]](s16) = G_PHI [[RES_BB1]](s16), %bb.1, [[RES_BB2]](s16), %bb.2 + ; CHECK: [[RES:%.*]](s1) = G_TRUNC [[RES_PHI]] + successors: %bb.1(0x40000000), %bb.2(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.1 + G_BR %bb.2 + + bb.1: + successors: %bb.3(0x80000000) + + %4(s32) = G_ADD %0, %3 + %5(s1) = G_TRUNC %4(s32) + G_BR %bb.3 + + bb.2: + successors: %bb.3(0x80000000) + + %7(s32) = G_ADD %0, %6 + %8(s1) = G_TRUNC %7(s32) + + bb.3: + %9(s1) = G_PHI %5(s1), %bb.1, %8(s1), %bb.2 + %10(s32) = G_ZEXT %9(s1) + %w0 = COPY %10(s32) + RET_ReallyLR implicit %w0 + +... +--- +name: legalize_phi_empty +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: +body: | + bb.0: + successors: %bb.1(0x40000000), %bb.2(0x40000000) + liveins: %w0 + ; Test that we properly legalize a phi with a predecessor that's empty + ; CHECK-LABEL: name: legalize_phi_empty + ; CHECK-LABEL: bb.0: + ; CHECK: [[ENTRY_ADD:%.*]](s32) = G_ADD + + ; CHECK-LABEL: bb.1: + ; CHECK: [[ADD_BB1:%.*]](s32) = G_ADD + ; CHECK: [[RES_BB1:%.*]](s16) = G_TRUNC [[ADD_BB1]] + + ; CHECK-LABEL: bb.2: + ; CHECK: [[RES_BB2:%.*]](s16) = G_TRUNC [[ENTRY_ADD]] + + ; CHECK: [[RES_PHI:%.*]](s16) = G_PHI [[RES_BB1]](s16), %bb.1, [[RES_BB2]](s16), %bb.2 + ; CHECK: [[RES:%.*]](s1) = G_TRUNC [[RES_PHI]] + + %0(s32) = COPY %w0 + %1(s32) = G_CONSTANT i32 0 + %3(s32) = G_CONSTANT i32 3 + %6(s32) = G_CONSTANT i32 1 + %2(s1) = G_ICMP intpred(ugt), %0(s32), %1 + %4(s32) = G_ADD %0, %3 + %5(s1) = G_TRUNC %4(s32) + G_BRCOND %2(s1), %bb.1 + G_BR %bb.2 + + bb.1: + successors: %bb.3(0x80000000) + + %7(s32) = G_ADD %0, %6 + %8(s1) = G_TRUNC %7(s32) + G_BR %bb.3 + + bb.2: + successors: %bb.3(0x80000000) + + + bb.3: + %9(s1) = G_PHI %8(s1), %bb.1, %5(s1), %bb.2 + %10(s32) = G_ZEXT %9(s1) + %w0 = COPY %10(s32) + RET_ReallyLR implicit %w0 + +... +--- +name: legalize_phi_loop +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: '' } +liveins: +body: | + bb.0: + successors: %bb.1(0x80000000) + liveins: %w0 + ; Test that we properly legalize a phi that uses a value from the same BB + ; CHECK-LABEL: name: legalize_phi_loop + ; CHECK-LABEL: bb.0: + ; CHECK: [[C0:%.*]](s32) = G_CONSTANT i32 0 + ; CHECK: [[RES_BB1:%.*]](s16) = G_TRUNC [[C0]] + + ; CHECK-LABEL: bb.1: + ; CHECK: [[RES_PHI:%.*]](s16) = G_PHI [[RES_BB1]](s16), %bb.0, [[RES_BB2:%.*]](s16), %bb.1 + ; CHECK-NEXT: G_TRUNC + ; CHECK: [[RES_BB2]](s16) = G_ANYEXT + %0(s32) = COPY %w0 + %2(s8) = G_CONSTANT i8 1 + %7(s8) = G_CONSTANT i8 0 + + bb.1: + successors: %bb.1(0x40000000), %bb.3(0x40000000) + + %1(s8) = G_PHI %7(s8), %bb.0, %3(s8), %bb.1 + %3(s8) = G_ADD %1, %2 + %4(s32) = G_ZEXT %3(s8) + %5(s1) = G_ICMP intpred(ugt), %4(s32), %0 + G_BRCOND %5(s1), %bb.1 + + bb.3: + %6(s32) = G_ZEXT %3(s8) + %w0 = COPY %6(s32) + RET_ReallyLR implicit %w0 + +... +--- +name: legalize_phi_cycle +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: '' } +liveins: +body: | + bb.0: + successors: %bb.1(0x80000000) + liveins: %w0 + ; Test that we properly legalize a phi that uses itself + ; CHECK-LABEL: name: legalize_phi_cycle + ; CHECK-LABEL: bb.0: + ; CHECK: [[C0:%.*]](s32) = G_CONSTANT i32 0 + ; CHECK: [[RES_BB1:%.*]](s16) = G_TRUNC [[C0]] + + ; CHECK-LABEL: bb.1: + ; CHECK: [[RES_PHI:%.*]](s16) = G_PHI [[RES_BB1]](s16), %bb.0, [[RES_BB2:%.*]](s16), %bb.1 + ; CHECK-NEXT: G_TRUNC + ; CHECK: [[RES_BB2]](s16) = G_ANYEXT + + %0(s32) = COPY %w0 + %4(s8) = G_CONSTANT i8 0 + + bb.1: + successors: %bb.1(0x40000000), %bb.3(0x40000000) + + %1(s8) = G_PHI %4(s8), %bb.0, %1(s8), %bb.1 + %2(s32) = G_ZEXT %1(s8) + %3(s1) = G_ICMP intpred(ugt), %2(s32), %0 + G_BRCOND %3(s1), %bb.1 + + bb.3: + %w0 = COPY %2(s32) + RET_ReallyLR implicit %w0 + +... +--- +name: legalize_phi_same_bb +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: '' } + - { id: 11, class: _, preferred-register: '' } + - { id: 12, class: _, preferred-register: '' } + - { id: 13, class: _, preferred-register: '' } + - { id: 14, class: _, preferred-register: '' } +liveins: +body: | + bb.0: + successors: %bb.1(0x40000000), %bb.2(0x40000000) + liveins: %w0 + ; Make sure that we correctly insert the new legalized G_PHI at the + ; correct location (ie make sure G_PHIs are the first insts in the BB). + ; CHECK-LABEL: name: legalize_phi_same_bb + ; CHECK-LABEL: bb.0: + ; CHECK: [[C42:%.*]](s32) = G_CONSTANT i32 42 + ; CHECK: [[ENTRY_ADD:%.*]](s32) = G_ADD + + ; CHECK-LABEL: bb.1: + ; CHECK: [[BB1_ADD:%.*]](s32) = G_ADD + ; CHECK: [[RES1_BB1:%.*]](s16) = G_TRUNC [[BB1_ADD]] + ; CHECK: [[RES2_BB1:%.*]](s16) = G_TRUNC [[BB1_ADD]] + + ; CHECK-LABEL: bb.2: + ; CHECK: [[RES1_BB2:%.*]](s16) = G_TRUNC [[ENTRY_ADD]] + ; CHECK: [[RES2_BB2:%.*]](s16) = G_TRUNC [[C42]] + + ; CHECK-LABEL: bb.3: + ; CHECK: [[RES1_PHI:%.*]](s16) = G_PHI [[RES1_BB1]](s16), %bb.1, [[RES1_BB2]](s16), %bb.2 + ; CHECK-NEXT: [[RES_PHI:%.*]](s16) = G_PHI [[RES2_BB1]](s16), %bb.1, [[RES2_BB2]](s16), %bb.2 + ; CHECK-NEXT: G_TRUNC + ; CHECK-NEXT: G_TRUNC + + %0(s32) = COPY %w0 + %1(s32) = G_CONSTANT i32 0 + %3(s32) = G_CONSTANT i32 3 + %6(s32) = G_CONSTANT i32 1 + %14(s8) = G_CONSTANT i8 42 + %2(s1) = G_ICMP intpred(ugt), %0(s32), %1 + %4(s32) = G_ADD %0, %3 + %5(s8) = G_TRUNC %4(s32) + G_BRCOND %2(s1), %bb.1 + G_BR %bb.2 + + bb.1: + successors: %bb.3(0x80000000) + + %7(s32) = G_ADD %0, %6 + %8(s8) = G_TRUNC %7(s32) + G_BR %bb.3 + + bb.2: + successors: %bb.3(0x80000000) + + + bb.3: + %9(s8) = G_PHI %8(s8), %bb.1, %5(s8), %bb.2 + %10(s8) = G_PHI %8(s8), %bb.1, %14(s8), %bb.2 + %11(s32) = G_ZEXT %9(s8) + %12(s32) = G_ZEXT %10(s8) + %13(s32) = G_ADD %11, %12 + %w0 = COPY %13(s32) + RET_ReallyLR implicit %w0 + +... +--- +name: legalize_phi_diff_bb +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: '' } + - { id: 11, class: _, preferred-register: '' } + - { id: 12, class: _, preferred-register: '' } + - { id: 13, class: _, preferred-register: '' } + - { id: 14, class: _, preferred-register: '' } + - { id: 15, class: _, preferred-register: '' } +liveins: +body: | + bb.0: + successors: %bb.1(0x40000000), %bb.3(0x40000000) + liveins: %w0, %w1 + ; Make sure that we correctly legalize PHIs sharing common defs + ; in different BBs. + ; CHECK-LABEL: name: legalize_phi_diff_bb + ; CHECK-LABEL: bb.0: + ; CHECK: [[C44:%.*]](s32) = G_CONSTANT i32 44 + ; CHECK: [[C43:%.*]](s32) = G_CONSTANT i32 43 + ; CHECK: [[ENTRY_ADD:%.*]](s32) = G_ADD + ; CHECK: [[RES_ENTRY:%.*]](s16) = G_TRUNC [[ENTRY_ADD]] + ; CHECK: [[RES_ENTRY1:%.*]](s16) = G_TRUNC [[ENTRY_ADD]] + + ; CHECK-LABEL: bb.1: + ; CHECK: [[RES1_PHI:%.*]](s16) = G_PHI [[RES_ENTRY]](s16), %bb.0, [[RES_BB1:%.*]](s16), %bb.1 + ; CHECK: [[RES_BB1:%.*]](s16) = G_TRUNC + ; CHECK: [[RES_FOR_BB2:%.*]](s16) = COPY [[RES1_PHI]] + + ; CHECK-LABEL: bb.2: + ; CHECK: [[RES2_PHI:%.*]](s16) = G_PHI [[RES_FOR_BB2]](s16), %bb.1, [[RES_ENTRY1:%.*]](s16), %bb.0 + ; CHECK-NEXT: G_TRUNC + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_CONSTANT i32 0 + %4(s32) = G_CONSTANT i32 3 + %9(s32) = G_CONSTANT i32 1 + %11(s32) = G_CONSTANT i32 44 + %15(s8) = G_CONSTANT i8 43 + %3(s1) = G_ICMP intpred(ugt), %0(s32), %2 + %5(s32) = G_ADD %0, %4 + %6(s8) = G_TRUNC %5(s32) + G_BRCOND %3(s1), %bb.1 + G_BR %bb.3 + + bb.1: + successors: %bb.3(0x40000000), %bb.1(0x40000000) + + %7(s8) = G_PHI %6(s8), %bb.0, %15(s8), %bb.1 + %8(s32) = G_ZEXT %7(s8) + %10(s32) = G_ADD %8, %9 + %12(s1) = G_ICMP intpred(ugt), %10(s32), %11 + G_BRCOND %12(s1), %bb.3 + G_BR %bb.1 + + bb.3: + %13(s8) = G_PHI %7(s8), %bb.1, %6(s8), %bb.0 + %14(s32) = G_ZEXT %13(s8) + %w0 = COPY %14(s32) + RET_ReallyLR implicit %w0 + +... +