From 4e66147d1e6fffa1a009f726e5d62d58f7b709a9 Mon Sep 17 00:00:00 2001 From: Igor Breger Date: Mon, 4 Sep 2017 09:06:45 +0000 Subject: [PATCH] [GlobalISel][X86] G_PHI support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312473 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86InstructionSelector.cpp | 20 +- lib/Target/X86/X86LegalizerInfo.cpp | 7 + test/CodeGen/X86/GlobalISel/legalize-phi.mir | 592 ++++++++++++++++++ test/CodeGen/X86/GlobalISel/phi.ll | 168 +++++ .../X86/GlobalISel/regbankselect-X86_64.mir | 139 +++- test/CodeGen/X86/GlobalISel/select-phi.mir | 423 +++++++++++++ 6 files changed, 1339 insertions(+), 10 deletions(-) create mode 100644 test/CodeGen/X86/GlobalISel/legalize-phi.mir create mode 100644 test/CodeGen/X86/GlobalISel/phi.ll create mode 100644 test/CodeGen/X86/GlobalISel/select-phi.mir diff --git a/lib/Target/X86/X86InstructionSelector.cpp b/lib/Target/X86/X86InstructionSelector.cpp index be3826a36c5..b43f88232bc 100644 --- a/lib/Target/X86/X86InstructionSelector.cpp +++ b/lib/Target/X86/X86InstructionSelector.cpp @@ -85,7 +85,7 @@ private: MachineFunction &MF) const; bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; - bool selectImplicitDef(MachineInstr &I, MachineRegisterInfo &MRI) const; + bool selectImplicitDefOrPHI(MachineInstr &I, MachineRegisterInfo &MRI) const; // emit insert subreg instruction and insert it before MachineInstr &I bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I, @@ -290,13 +290,10 @@ bool X86InstructionSelector::select(MachineInstr &I) const { if (Opcode == TargetOpcode::LOAD_STACK_GUARD) return false; - if (Opcode == TargetOpcode::PHI) - return false; if (I.isCopy()) return selectCopy(I, MRI); - // TODO: handle more cases - LOAD_STACK_GUARD, PHI return true; } @@ -335,7 +332,7 @@ bool X86InstructionSelector::select(MachineInstr &I) const { return true; if (selectCondBranch(I, MRI, MF)) return true; - if (selectImplicitDef(I, MRI)) + if (selectImplicitDefOrPHI(I, MRI)) return true; return false; @@ -1131,10 +1128,11 @@ bool X86InstructionSelector::selectCondBranch(MachineInstr &I, return true; } -bool X86InstructionSelector::selectImplicitDef(MachineInstr &I, - MachineRegisterInfo &MRI) const { +bool X86InstructionSelector::selectImplicitDefOrPHI( + MachineInstr &I, MachineRegisterInfo &MRI) const { - if (I.getOpcode() != TargetOpcode::G_IMPLICIT_DEF) + if (I.getOpcode() != TargetOpcode::G_IMPLICIT_DEF && + I.getOpcode() != TargetOpcode::G_PHI) return false; unsigned DstReg = I.getOperand(0).getReg(); @@ -1150,7 +1148,11 @@ bool X86InstructionSelector::selectImplicitDef(MachineInstr &I, } } - I.setDesc(TII.get(X86::IMPLICIT_DEF)); + if (I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF) + I.setDesc(TII.get(X86::IMPLICIT_DEF)); + else + I.setDesc(TII.get(X86::PHI)); + return true; } diff --git a/lib/Target/X86/X86LegalizerInfo.cpp b/lib/Target/X86/X86LegalizerInfo.cpp index f7d7f2398a9..8bceb2c4c6a 100644 --- a/lib/Target/X86/X86LegalizerInfo.cpp +++ b/lib/Target/X86/X86LegalizerInfo.cpp @@ -52,6 +52,11 @@ void X86LegalizerInfo::setLegalizerInfo32bit() { for (auto Ty : {p0, s1, s8, s16, s32}) setAction({G_IMPLICIT_DEF, Ty}, Legal); + for (auto Ty : {s8, s16, s32, p0}) + setAction({G_PHI, Ty}, Legal); + + setAction({G_PHI, s1}, WidenScalar); + for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) for (auto Ty : {s8, s16, s32}) setAction({BinOp, Ty}, Legal); @@ -118,6 +123,8 @@ void X86LegalizerInfo::setLegalizerInfo64bit() { setAction({G_IMPLICIT_DEF, s64}, Legal); + setAction({G_PHI, s64}, Legal); + for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) setAction({BinOp, s64}, Legal); diff --git a/test/CodeGen/X86/GlobalISel/legalize-phi.mir b/test/CodeGen/X86/GlobalISel/legalize-phi.mir new file mode 100644 index 00000000000..70035c5cae2 --- /dev/null +++ b/test/CodeGen/X86/GlobalISel/legalize-phi.mir @@ -0,0 +1,592 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL + +--- | + + define zeroext i1 @test_i1(i32 %a, i1 zeroext %f, i1 zeroext %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i1 [ %f, %cond.true ], [ %t, %cond.false ] + ret i1 %cond + } + + define i8 @test_i8(i32 %a, i8 %f, i8 %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i8 [ %f, %cond.true ], [ %t, %cond.false ] + ret i8 %cond + } + + define i16 @test_i16(i32 %a, i16 %f, i16 %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i16 [ %f, %cond.true ], [ %t, %cond.false ] + ret i16 %cond + } + + define i32 @test_i32(i32 %a, i32 %f, i32 %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i32 [ %f, %cond.true ], [ %t, %cond.false ] + ret i32 %cond + } + + define i64 @test_i64(i32 %a, i64 %f, i64 %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i64 [ %f, %cond.true ], [ %t, %cond.false ] + ret i64 %cond + } + + define float @test_float(i32 %a, float %f, float %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi float [ %f, %cond.true ], [ %t, %cond.false ] + ret float %cond + } + + define double @test_double(i32 %a, double %f, double %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi double [ %f, %cond.true ], [ %t, %cond.false ] + ret double %cond + } + +... +--- +name: test_i1 +# ALL-LABEL: name: test_i1 +alignment: 4 +legalized: false +regBankSelected: 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: '' } +liveins: +fixedStack: +stack: +constants: +# ALL: bb.0.entry: +# ALL-NEXT: successors: %bb.1.cond.true(0x40000000), %bb.2.cond.false(0x40000000) +# ALL-NEXT: liveins: %edi, %edx, %esi + +# ALL: %0(s32) = COPY %edi +# ALL-NEXT: %1(s1) = COPY %esi +# ALL-NEXT: %2(s1) = COPY %edx +# ALL-NEXT: %3(s32) = G_CONSTANT i32 0 +# ALL-NEXT: %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 +# ALL-NEXT: G_BRCOND %4(s1), %bb.1.cond.true +# ALL-NEXT: G_BR %bb.2.cond.false + +# ALL-LABEL: bb.1.cond.true: +# ALL: %8(s8) = G_ANYEXT %1(s1) +# ALL-NEXT: G_BR %bb.3.cond.end + +# ALL-LABEL: bb.2.cond.false: +# ALL: %9(s8) = G_ANYEXT %2(s1) + +# ALL-LABEL: bb.3.cond.end: +# ALL-NEXT: %7(s8) = G_PHI %8(s8), %bb.1.cond.true, %9(s8), %bb.2.cond.false +# ALL-NEXT: %5(s1) = G_TRUNC %7(s8) +# ALL-NEXT: %6(s8) = G_ZEXT %5(s1) +# ALL-NEXT: %al = COPY %6(s8) +# ALL-NEXT: RET 0, implicit %al +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %edx, %esi + + %0(s32) = COPY %edi + %1(s1) = COPY %esi + %2(s1) = COPY %edx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s1) = G_PHI %1(s1), %bb.2.cond.true, %2(s1), %bb.3.cond.false + %6(s8) = G_ZEXT %5(s1) + %al = COPY %6(s8) + RET 0, implicit %al + +... +--- +name: test_i8 +# ALL-LABEL: name: test_i8 +alignment: 4 +legalized: false +regBankSelected: 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: '' } +liveins: +fixedStack: +stack: +constants: +# ALL: bb.0.entry: +# ALL-NEXT: successors: %bb.1.cond.true(0x40000000), %bb.2.cond.false(0x40000000) +# ALL-NEXT: liveins: %edi, %edx, %esi +# ALL: %0(s32) = COPY %edi +# ALL-NEXT: %1(s8) = COPY %esi +# ALL-NEXT: %2(s8) = COPY %edx +# ALL-NEXT: %3(s32) = G_CONSTANT i32 0 +# ALL-NEXT: %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 +# ALL-NEXT: G_BRCOND %4(s1), %bb.1.cond.true +# ALL-NEXT: G_BR %bb.2.cond.false + +# ALL-LABEL: bb.1.cond.true: +# ALL: G_BR %bb.3.cond.end + +# ALL-LABEL: bb.2.cond.false: +# ALL-NEXT: successors: %bb.3.cond.end(0x80000000) + +# ALL-LABEL: bb.3.cond.end: +# ALL-NEXT: %5(s8) = G_PHI %1(s8), %bb.1.cond.true, %2(s8), %bb.2.cond.false +# ALL-NEXT: %al = COPY %5(s8) +# ALL-NEXT: RET 0, implicit %al +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %edx, %esi + + %0(s32) = COPY %edi + %1(s8) = COPY %esi + %2(s8) = COPY %edx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s8) = G_PHI %1(s8), %bb.2.cond.true, %2(s8), %bb.3.cond.false + %al = COPY %5(s8) + RET 0, implicit %al + +... +--- +name: test_i16 +# ALL-LABEL: name: test_i16 +alignment: 4 +legalized: false +regBankSelected: 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: '' } +liveins: +fixedStack: +stack: +constants: +# ALL: bb.0.entry: +# ALL-NEXT: successors: %bb.1.cond.true(0x40000000), %bb.2.cond.false(0x40000000) +# ALL-NEXT: liveins: %edi, %edx, %esi +# ALL: %0(s32) = COPY %edi +# ALL-NEXT: %1(s16) = COPY %esi +# ALL-NEXT: %2(s16) = COPY %edx +# ALL-NEXT: %3(s32) = G_CONSTANT i32 0 +# ALL-NEXT: %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 +# ALL-NEXT: G_BRCOND %4(s1), %bb.1.cond.true +# ALL-NEXT: G_BR %bb.2.cond.false + +# ALL-LABEL: bb.1.cond.true: +# ALL: G_BR %bb.3.cond.end + +# ALL-LABEL: bb.2.cond.false: +# ALL-NEXT: successors: %bb.3.cond.end(0x80000000) + +# ALL-LABEL: bb.3.cond.end: +# ALL-NEXT: %5(s16) = G_PHI %1(s16), %bb.1.cond.true, %2(s16), %bb.2.cond.false +# ALL-NEXT: %ax = COPY %5(s16) +# ALL-NEXT: RET 0, implicit %ax +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %edx, %esi + + %0(s32) = COPY %edi + %1(s16) = COPY %esi + %2(s16) = COPY %edx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s16) = G_PHI %1(s16), %bb.2.cond.true, %2(s16), %bb.3.cond.false + %ax = COPY %5(s16) + RET 0, implicit %ax + +... +--- +name: test_i32 +# ALL-LABEL: name: test_i32 +alignment: 4 +legalized: false +regBankSelected: 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: '' } +liveins: +fixedStack: +stack: +constants: +# ALL: bb.0.entry: +# ALL-NEXT: successors: %bb.1.cond.true(0x40000000), %bb.2.cond.false(0x40000000) +# ALL-NEXT: liveins: %edi, %edx, %esi +# ALL: %0(s32) = COPY %edi +# ALL-NEXT: %1(s32) = COPY %esi +# ALL-NEXT: %2(s32) = COPY %edx +# ALL-NEXT: %3(s32) = G_CONSTANT i32 0 +# ALL-NEXT: %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 +# ALL-NEXT: G_BRCOND %4(s1), %bb.1.cond.true +# ALL-NEXT: G_BR %bb.2.cond.false + +# ALL-LABEL: bb.1.cond.true: +# ALL: G_BR %bb.3.cond.end + +# ALL-LABEL: bb.2.cond.false: +# ALL-NEXT: successors: %bb.3.cond.end(0x80000000) + +# ALL-LABEL: bb.3.cond.end: +# ALL-NEXT: %5(s32) = G_PHI %1(s32), %bb.1.cond.true, %2(s32), %bb.2.cond.false +# ALL-NEXT: %eax = COPY %5(s32) +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %edx, %esi + + %0(s32) = COPY %edi + %1(s32) = COPY %esi + %2(s32) = COPY %edx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s32) = G_PHI %1(s32), %bb.2.cond.true, %2(s32), %bb.3.cond.false + %eax = COPY %5(s32) + RET 0, implicit %eax + +... +--- +name: test_i64 +# ALL-LABEL: name: test_i64 +alignment: 4 +legalized: false +regBankSelected: 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: '' } +liveins: +fixedStack: +stack: +constants: +# ALL: bb.0.entry: +# ALL-NEXT: successors: %bb.1.cond.true(0x40000000), %bb.2.cond.false(0x40000000) +# ALL-NEXT: liveins: %edi, %rdx, %rsi +# ALL: %0(s32) = COPY %edi +# ALL-NEXT: %1(s64) = COPY %rsi +# ALL-NEXT: %2(s64) = COPY %rdx +# ALL-NEXT: %3(s32) = G_CONSTANT i32 0 +# ALL-NEXT: %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 +# ALL-NEXT: G_BRCOND %4(s1), %bb.1.cond.true +# ALL-NEXT: G_BR %bb.2.cond.false + +# ALL-LABEL: bb.1.cond.true: +# ALL: G_BR %bb.3.cond.end + +# ALL-LABEL: bb.2.cond.false: +# ALL-NEXT: successors: %bb.3.cond.end(0x80000000) + +# ALL-LABEL: bb.3.cond.end: +# ALL-NEXT: %5(s64) = G_PHI %1(s64), %bb.1.cond.true, %2(s64), %bb.2.cond.false +# ALL-NEXT: %rax = COPY %5(s64) +# ALL-NEXT: RET 0, implicit %rax +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %rdx, %rsi + + %0(s32) = COPY %edi + %1(s64) = COPY %rsi + %2(s64) = COPY %rdx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s64) = G_PHI %1(s64), %bb.2.cond.true, %2(s64), %bb.3.cond.false + %rax = COPY %5(s64) + RET 0, implicit %rax + +... +--- +name: test_float +# ALL-LABEL: name: test_float +alignment: 4 +legalized: false +regBankSelected: 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: '' } +liveins: +fixedStack: +stack: +constants: +# ALL: bb.0.entry: +# ALL-NEXT: successors: %bb.1.cond.true(0x40000000), %bb.2.cond.false(0x40000000) +# ALL-NEXT: liveins: %edi, %xmm0, %xmm1 +# ALL: %0(s32) = COPY %edi +# ALL-NEXT: %1(s32) = COPY %xmm0 +# ALL-NEXT: %2(s32) = COPY %xmm1 +# ALL-NEXT: %3(s32) = G_CONSTANT i32 0 +# ALL-NEXT: %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 +# ALL-NEXT: G_BRCOND %4(s1), %bb.1.cond.true +# ALL-NEXT: G_BR %bb.2.cond.false + +# ALL-LABEL: bb.1.cond.true: +# ALL: G_BR %bb.3.cond.end + +# ALL-LABEL: bb.2.cond.false: +# ALL-NEXT: successors: %bb.3.cond.end(0x80000000) + +# ALL-LABEL: bb.3.cond.end: +# ALL-NEXT: %5(s32) = G_PHI %1(s32), %bb.1.cond.true, %2(s32), %bb.2.cond.false +# ALL-NEXT: %xmm0 = COPY %5(s32) +# ALL-NEXT: RET 0, implicit %xmm0 +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %xmm0, %xmm1 + + %0(s32) = COPY %edi + %1(s32) = COPY %xmm0 + %2(s32) = COPY %xmm1 + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s32) = G_PHI %1(s32), %bb.2.cond.true, %2(s32), %bb.3.cond.false + %xmm0 = COPY %5(s32) + RET 0, implicit %xmm0 + +... +--- +name: test_double +# ALL-LABEL: name: test_double +alignment: 4 +legalized: false +regBankSelected: 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: '' } +liveins: +fixedStack: +stack: +constants: +# ALL: bb.0.entry: +# ALL-NEXT: successors: %bb.1.cond.true(0x40000000), %bb.2.cond.false(0x40000000) +# ALL-NEXT: liveins: %edi, %xmm0, %xmm1 +# ALL: %0(s32) = COPY %edi +# ALL-NEXT: %1(s64) = COPY %xmm0 +# ALL-NEXT: %2(s64) = COPY %xmm1 +# ALL-NEXT: %3(s32) = G_CONSTANT i32 0 +# ALL-NEXT: %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 +# ALL-NEXT: G_BRCOND %4(s1), %bb.1.cond.true +# ALL-NEXT: G_BR %bb.2.cond.false + +# ALL-LABEL: bb.1.cond.true: +# ALL: G_BR %bb.3.cond.end + +# ALL-LABEL: bb.2.cond.false: +# ALL-NEXT: successors: %bb.3.cond.end(0x80000000) + +# ALL-LABEL: bb.3.cond.end: +# ALL-NEXT: %5(s64) = G_PHI %1(s64), %bb.1.cond.true, %2(s64), %bb.2.cond.false +# ALL-NEXT: %xmm0 = COPY %5(s64) +# ALL-NEXT: RET 0, implicit %xmm0 +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %xmm0, %xmm1 + + %0(s32) = COPY %edi + %1(s64) = COPY %xmm0 + %2(s64) = COPY %xmm1 + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s64) = G_PHI %1(s64), %bb.2.cond.true, %2(s64), %bb.3.cond.false + %xmm0 = COPY %5(s64) + RET 0, implicit %xmm0 + +... diff --git a/test/CodeGen/X86/GlobalISel/phi.ll b/test/CodeGen/X86/GlobalISel/phi.ll new file mode 100644 index 00000000000..71bd7fecc05 --- /dev/null +++ b/test/CodeGen/X86/GlobalISel/phi.ll @@ -0,0 +1,168 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=ALL + +define i8 @test_i8(i32 %a, i8 %f, i8 %t) { +; ALL-LABEL: test_i8: +; ALL: # BB#0: # %entry +; ALL-NEXT: xorl %eax, %eax +; ALL-NEXT: cmpl %eax, %edi +; ALL-NEXT: setg %al +; ALL-NEXT: testb $1, %al +; ALL-NEXT: jne .LBB0_2 +; ALL-NEXT: # BB#1: # %cond.false +; ALL-NEXT: movl %edx, %esi +; ALL-NEXT: .LBB0_2: # %cond.end +; ALL-NEXT: movl %esi, %eax +; ALL-NEXT: retq +entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + +cond.true: ; preds = %entry + br label %cond.end + +cond.false: ; preds = %entry + br label %cond.end + +cond.end: ; preds = %cond.false, %cond.true + %cond = phi i8 [ %f, %cond.true ], [ %t, %cond.false ] + ret i8 %cond +} + +define i16 @test_i16(i32 %a, i16 %f, i16 %t) { +; ALL-LABEL: test_i16: +; ALL: # BB#0: # %entry +; ALL-NEXT: xorl %eax, %eax +; ALL-NEXT: cmpl %eax, %edi +; ALL-NEXT: setg %al +; ALL-NEXT: testb $1, %al +; ALL-NEXT: jne .LBB1_2 +; ALL-NEXT: # BB#1: # %cond.false +; ALL-NEXT: movl %edx, %esi +; ALL-NEXT: .LBB1_2: # %cond.end +; ALL-NEXT: movl %esi, %eax +; ALL-NEXT: retq +entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + +cond.true: ; preds = %entry + br label %cond.end + +cond.false: ; preds = %entry + br label %cond.end + +cond.end: ; preds = %cond.false, %cond.true + %cond = phi i16 [ %f, %cond.true ], [ %t, %cond.false ] + ret i16 %cond +} + +define i32 @test_i32(i32 %a, i32 %f, i32 %t) { +; ALL-LABEL: test_i32: +; ALL: # BB#0: # %entry +; ALL-NEXT: xorl %eax, %eax +; ALL-NEXT: cmpl %eax, %edi +; ALL-NEXT: setg %al +; ALL-NEXT: testb $1, %al +; ALL-NEXT: jne .LBB2_2 +; ALL-NEXT: # BB#1: # %cond.false +; ALL-NEXT: movl %edx, %esi +; ALL-NEXT: .LBB2_2: # %cond.end +; ALL-NEXT: movl %esi, %eax +; ALL-NEXT: retq +entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + +cond.true: ; preds = %entry + br label %cond.end + +cond.false: ; preds = %entry + br label %cond.end + +cond.end: ; preds = %cond.false, %cond.true + %cond = phi i32 [ %f, %cond.true ], [ %t, %cond.false ] + ret i32 %cond +} + +define i64 @test_i64(i32 %a, i64 %f, i64 %t) { +; ALL-LABEL: test_i64: +; ALL: # BB#0: # %entry +; ALL-NEXT: xorl %eax, %eax +; ALL-NEXT: cmpl %eax, %edi +; ALL-NEXT: setg %al +; ALL-NEXT: testb $1, %al +; ALL-NEXT: jne .LBB3_2 +; ALL-NEXT: # BB#1: # %cond.false +; ALL-NEXT: movq %rdx, %rsi +; ALL-NEXT: .LBB3_2: # %cond.end +; ALL-NEXT: movq %rsi, %rax +; ALL-NEXT: retq +entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + +cond.true: ; preds = %entry + br label %cond.end + +cond.false: ; preds = %entry + br label %cond.end + +cond.end: ; preds = %cond.false, %cond.true + %cond = phi i64 [ %f, %cond.true ], [ %t, %cond.false ] + ret i64 %cond +} + +define float @test_float(i32 %a, float %f, float %t) { +; ALL-LABEL: test_float: +; ALL: # BB#0: # %entry +; ALL-NEXT: xorl %eax, %eax +; ALL-NEXT: cmpl %eax, %edi +; ALL-NEXT: setg %al +; ALL-NEXT: testb $1, %al +; ALL-NEXT: jne .LBB4_2 +; ALL-NEXT: # BB#1: # %cond.false +; ALL-NEXT: movaps %xmm1, %xmm0 +; ALL-NEXT: .LBB4_2: # %cond.end +; ALL-NEXT: retq +entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + +cond.true: ; preds = %entry + br label %cond.end + +cond.false: ; preds = %entry + br label %cond.end + +cond.end: ; preds = %cond.false, %cond.true + %cond = phi float [ %f, %cond.true ], [ %t, %cond.false ] + ret float %cond +} + +define double @test_double(i32 %a, double %f, double %t) { +; ALL-LABEL: test_double: +; ALL: # BB#0: # %entry +; ALL-NEXT: xorl %eax, %eax +; ALL-NEXT: cmpl %eax, %edi +; ALL-NEXT: setg %al +; ALL-NEXT: testb $1, %al +; ALL-NEXT: jne .LBB5_2 +; ALL-NEXT: # BB#1: # %cond.false +; ALL-NEXT: movaps %xmm1, %xmm0 +; ALL-NEXT: .LBB5_2: # %cond.end +; ALL-NEXT: retq +entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + +cond.true: ; preds = %entry + br label %cond.end + +cond.false: ; preds = %entry + br label %cond.end + +cond.end: ; preds = %cond.false, %cond.true + %cond = phi double [ %f, %cond.true ], [ %t, %cond.false ] + ret double %cond +} diff --git a/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir b/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir index 34e19b28657..b25c05d9116 100644 --- a/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir +++ b/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir @@ -197,7 +197,41 @@ define float @test_undef4(float %a) { %r = fadd float %a, undef ret float %r - } + } + + define i32 @test_i32(i32 %a, i32 %f, i32 %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i32 [ %f, %cond.true ], [ %t, %cond.false ] + ret i32 %cond + } + + define float @test_float(i32 %a, float %f, float %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi float [ %f, %cond.true ], [ %t, %cond.false ] + ret float %cond + } + + ... --- name: test_add_i8 @@ -1246,4 +1280,107 @@ body: | RET 0, implicit %xmm0 ... +--- +name: test_i32 +# CHECK-LABEL: name: test_i32 +alignment: 4 +legalized: true +regBankSelected: false +tracksRegLiveness: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } +# CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' } +# CHECK-NEXT: - { id: 2, class: gpr, preferred-register: '' } +# CHECK-NEXT: - { id: 3, class: gpr, preferred-register: '' } +# CHECK-NEXT: - { id: 4, class: gpr, preferred-register: '' } +# CHECK-NEXT: - { id: 5, class: gpr, preferred-register: '' } +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: '' } +# CHECK: bb.3.cond.end: +# CHECK-NEXT: %5(s32) = G_PHI %1(s32), %bb.1.cond.true, %2(s32), %bb.2.cond.false +# CHECK-NEXT: %eax = COPY %5(s32) +# CHECK-NEXT: RET 0, implicit %eax +body: | + bb.0.entry: + successors: %bb.1.cond.true(0x40000000), %bb.2.cond.false(0x40000000) + liveins: %edi, %edx, %esi + + %0(s32) = COPY %edi + %1(s32) = COPY %esi + %2(s32) = COPY %edx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.1.cond.true + G_BR %bb.2.cond.false + bb.1.cond.true: + successors: %bb.3.cond.end(0x80000000) + + G_BR %bb.3.cond.end + + bb.2.cond.false: + successors: %bb.3.cond.end(0x80000000) + + bb.3.cond.end: + %5(s32) = G_PHI %1(s32), %bb.1.cond.true, %2(s32), %bb.2.cond.false + %eax = COPY %5(s32) + RET 0, implicit %eax + +... +--- +name: test_float +# CHECK-LABEL: name: test_float +alignment: 4 +legalized: true +regBankSelected: false +tracksRegLiveness: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } +# CHECK-NEXT: - { id: 1, class: vecr, preferred-register: '' } +# CHECK-NEXT: - { id: 2, class: vecr, preferred-register: '' } +# CHECK-NEXT: - { id: 3, class: gpr, preferred-register: '' } +# CHECK-NEXT: - { id: 4, class: gpr, preferred-register: '' } +# CHECK-NEXT: - { id: 5, class: vecr, preferred-register: '' } +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: '' } +# CHECK: bb.3.cond.end: +# CHECK-NEXT: %5(s32) = G_PHI %1(s32), %bb.1.cond.true, %2(s32), %bb.2.cond.false +# CHECK-NEXT: %xmm0 = COPY %5(s32) +# CHECK-NEXT: RET 0, implicit %xmm0 +body: | + bb.0.entry: + successors: %bb.1.cond.true(0x40000000), %bb.2.cond.false(0x40000000) + liveins: %edi, %xmm0, %xmm1 + + %0(s32) = COPY %edi + %1(s32) = COPY %xmm0 + %2(s32) = COPY %xmm1 + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.1.cond.true + G_BR %bb.2.cond.false + + bb.1.cond.true: + successors: %bb.3.cond.end(0x80000000) + + G_BR %bb.3.cond.end + + bb.2.cond.false: + successors: %bb.3.cond.end(0x80000000) + + bb.3.cond.end: + %5(s32) = G_PHI %1(s32), %bb.1.cond.true, %2(s32), %bb.2.cond.false + %xmm0 = COPY %5(s32) + RET 0, implicit %xmm0 + +... diff --git a/test/CodeGen/X86/GlobalISel/select-phi.mir b/test/CodeGen/X86/GlobalISel/select-phi.mir new file mode 100644 index 00000000000..099e1e50c7d --- /dev/null +++ b/test/CodeGen/X86/GlobalISel/select-phi.mir @@ -0,0 +1,423 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=ALL + +--- | + + define i8 @test_i8(i32 %a, i8 %f, i8 %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i8 [ %f, %cond.true ], [ %t, %cond.false ] + ret i8 %cond + } + + define i16 @test_i16(i32 %a, i16 %f, i16 %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i16 [ %f, %cond.true ], [ %t, %cond.false ] + ret i16 %cond + } + + define i32 @test_i32(i32 %a, i32 %f, i32 %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i32 [ %f, %cond.true ], [ %t, %cond.false ] + ret i32 %cond + } + + define i64 @test_i64(i32 %a, i64 %f, i64 %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi i64 [ %f, %cond.true ], [ %t, %cond.false ] + ret i64 %cond + } + + define float @test_float(i32 %a, float %f, float %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi float [ %f, %cond.true ], [ %t, %cond.false ] + ret float %cond + } + + define double @test_double(i32 %a, double %f, double %t) { + entry: + %cmp = icmp sgt i32 %a, 0 + br i1 %cmp, label %cond.true, label %cond.false + + cond.true: ; preds = %entry + br label %cond.end + + cond.false: ; preds = %entry + br label %cond.end + + cond.end: ; preds = %cond.false, %cond.true + %cond = phi double [ %f, %cond.true ], [ %t, %cond.false ] + ret double %cond + } + +... +--- +name: test_i8 +# ALL-LABEL: name: test_i8 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 2, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 3, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 4, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 5, class: gr8, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } + - { id: 2, class: gpr, preferred-register: '' } + - { id: 3, class: gpr, preferred-register: '' } + - { id: 4, class: gpr, preferred-register: '' } + - { id: 5, class: gpr, preferred-register: '' } +# ALL-LABEL: bb.3.cond.end: +# ALL: %5 = PHI %1, %bb.1.cond.true, %2, %bb.2.cond.false +# ALL-NEXT: %al = COPY %5 +# ALL-NEXT: RET 0, implicit %al +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %edx, %esi + + %0(s32) = COPY %edi + %1(s8) = COPY %esi + %2(s8) = COPY %edx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s8) = G_PHI %1(s8), %bb.2.cond.true, %2(s8), %bb.3.cond.false + %al = COPY %5(s8) + RET 0, implicit %al + +... +--- +name: test_i16 +# ALL-LABEL: name: test_i16 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr16, preferred-register: '' } +# ALL-NEXT: - { id: 2, class: gr16, preferred-register: '' } +# ALL-NEXT: - { id: 3, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 4, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 5, class: gr16, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } + - { id: 2, class: gpr, preferred-register: '' } + - { id: 3, class: gpr, preferred-register: '' } + - { id: 4, class: gpr, preferred-register: '' } + - { id: 5, class: gpr, preferred-register: '' } +# ALL-LABEL: bb.3.cond.end: +# ALL: %5 = PHI %1, %bb.1.cond.true, %2, %bb.2.cond.false +# ALL-NEXT: %ax = COPY %5 +# ALL-NEXT: RET 0, implicit %ax +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %edx, %esi + + %0(s32) = COPY %edi + %1(s16) = COPY %esi + %2(s16) = COPY %edx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s16) = G_PHI %1(s16), %bb.2.cond.true, %2(s16), %bb.3.cond.false + %ax = COPY %5(s16) + RET 0, implicit %ax + +... +--- +name: test_i32 +# ALL-LABEL: name: test_i32 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 2, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 3, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 4, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 5, class: gr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } + - { id: 2, class: gpr, preferred-register: '' } + - { id: 3, class: gpr, preferred-register: '' } + - { id: 4, class: gpr, preferred-register: '' } + - { id: 5, class: gpr, preferred-register: '' } +# ALL-LABEL: bb.3.cond.end: +# ALL: %5 = PHI %1, %bb.1.cond.true, %2, %bb.2.cond.false +# ALL-NEXT: %eax = COPY %5 +# ALL-NEXT: RET 0, implicit %eax +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %edx, %esi + + %0(s32) = COPY %edi + %1(s32) = COPY %esi + %2(s32) = COPY %edx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s32) = G_PHI %1(s32), %bb.2.cond.true, %2(s32), %bb.3.cond.false + %eax = COPY %5(s32) + RET 0, implicit %eax + +... +--- +name: test_i64 +# ALL-LABEL: name: test_i64 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: gr64, preferred-register: '' } +# ALL-NEXT: - { id: 2, class: gr64, preferred-register: '' } +# ALL-NEXT: - { id: 3, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 4, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 5, class: gr64, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } + - { id: 2, class: gpr, preferred-register: '' } + - { id: 3, class: gpr, preferred-register: '' } + - { id: 4, class: gpr, preferred-register: '' } + - { id: 5, class: gpr, preferred-register: '' } +# ALL-LABEL: bb.3.cond.end: +# ALL: %5 = PHI %1, %bb.1.cond.true, %2, %bb.2.cond.false +# ALL-NEXT: %rax = COPY %5 +# ALL-NEXT: RET 0, implicit %rax +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %rdx, %rsi + + %0(s32) = COPY %edi + %1(s64) = COPY %rsi + %2(s64) = COPY %rdx + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s64) = G_PHI %1(s64), %bb.2.cond.true, %2(s64), %bb.3.cond.false + %rax = COPY %5(s64) + RET 0, implicit %rax + +... +--- +name: test_float +# ALL-LABEL: name: test_float +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: fr32, preferred-register: '' } +# ALL-NEXT: - { id: 2, class: fr32, preferred-register: '' } +# ALL-NEXT: - { id: 3, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 4, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 5, class: fr32, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: vecr, preferred-register: '' } + - { id: 2, class: vecr, preferred-register: '' } + - { id: 3, class: gpr, preferred-register: '' } + - { id: 4, class: gpr, preferred-register: '' } + - { id: 5, class: vecr, preferred-register: '' } +liveins: +fixedStack: +stack: +constants: +# ALL-LABEL: bb.3.cond.end: +# ALL: %5 = PHI %1, %bb.1.cond.true, %2, %bb.2.cond.false +# ALL-NEXT: %xmm0 = COPY %5 +# ALL-NEXT: RET 0, implicit %xmm0 +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %xmm0, %xmm1 + + %0(s32) = COPY %edi + %1(s32) = COPY %xmm0 + %2(s32) = COPY %xmm1 + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s32) = G_PHI %1(s32), %bb.2.cond.true, %2(s32), %bb.3.cond.false + %xmm0 = COPY %5(s32) + RET 0, implicit %xmm0 + +... +--- +name: test_double +# ALL-LABEL: name: test_double +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +# ALL: registers: +# ALL-NEXT: - { id: 0, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 1, class: fr64, preferred-register: '' } +# ALL-NEXT: - { id: 2, class: fr64, preferred-register: '' } +# ALL-NEXT: - { id: 3, class: gr32, preferred-register: '' } +# ALL-NEXT: - { id: 4, class: gr8, preferred-register: '' } +# ALL-NEXT: - { id: 5, class: fr64, preferred-register: '' } +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: vecr, preferred-register: '' } + - { id: 2, class: vecr, preferred-register: '' } + - { id: 3, class: gpr, preferred-register: '' } + - { id: 4, class: gpr, preferred-register: '' } + - { id: 5, class: vecr, preferred-register: '' } +# ALL-LABEL: bb.3.cond.end: +# ALL: %5 = PHI %1, %bb.1.cond.true, %2, %bb.2.cond.false +# ALL-NEXT: %xmm0 = COPY %5 +# ALL-NEXT: RET 0, implicit %xmm0 +body: | + bb.1.entry: + successors: %bb.2.cond.true(0x40000000), %bb.3.cond.false(0x40000000) + liveins: %edi, %xmm0, %xmm1 + + %0(s32) = COPY %edi + %1(s64) = COPY %xmm0 + %2(s64) = COPY %xmm1 + %3(s32) = G_CONSTANT i32 0 + %4(s1) = G_ICMP intpred(sgt), %0(s32), %3 + G_BRCOND %4(s1), %bb.2.cond.true + G_BR %bb.3.cond.false + + bb.2.cond.true: + successors: %bb.4.cond.end(0x80000000) + + G_BR %bb.4.cond.end + + bb.3.cond.false: + successors: %bb.4.cond.end(0x80000000) + + + bb.4.cond.end: + %5(s64) = G_PHI %1(s64), %bb.2.cond.true, %2(s64), %bb.3.cond.false + %xmm0 = COPY %5(s64) + RET 0, implicit %xmm0 + +... -- 2.50.1