Index: lib/Target/AMDGPU/AMDGPUInstructionSelector.h =================================================================== --- lib/Target/AMDGPU/AMDGPUInstructionSelector.h +++ lib/Target/AMDGPU/AMDGPUInstructionSelector.h @@ -82,6 +82,7 @@ bool selectG_LOAD(MachineInstr &I) const; bool selectG_SELECT(MachineInstr &I) const; bool selectG_STORE(MachineInstr &I) const; + bool selectG_BRCOND(MachineInstr &I) const; InstructionSelector::ComplexRendererFns selectVCSRC(MachineOperand &Root) const; Index: lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp +++ lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp @@ -918,6 +918,37 @@ return Ret; } +bool AMDGPUInstructionSelector::selectG_BRCOND(MachineInstr &I) const { + MachineBasicBlock *BB = I.getParent(); + MachineFunction *MF = BB->getParent(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + MachineOperand &CondOp = I.getOperand(0); + Register CondReg = CondOp.getReg(); + const DebugLoc &DL = I.getDebugLoc(); + + if (isSCC(CondReg, MRI)) { + // In SelectionDAG, we inspect the IR block for uniformity metadata to decide + // whether the branch is uniform when selecting the instruction. In + // GlobalISel, we should push that decision into RegBankSelect. Assume for now + // RegBankSelect knows what it's doing if the branch condition is scc, even + // though it currently does not. + BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::SCC) + .addReg(CondReg); + if (!MRI.getRegClassOrNull(CondReg)) { + const TargetRegisterClass *RC + = TRI.getConstrainedRegClassForOperand(CondOp, MRI); + MRI.setRegClass(CondReg, RC); + } + + BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_CBRANCH_SCC1)) + .addMBB(I.getOperand(1).getMBB()); + I.eraseFromParent(); + return true; + } + + return false; +} + bool AMDGPUInstructionSelector::select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const { @@ -971,6 +1002,8 @@ } return false; + case TargetOpcode::G_BRCOND: + return selectG_BRCOND(I); } return false; } Index: test/CodeGen/AMDGPU/GlobalISel/inst-select-br.mir =================================================================== --- /dev/null +++ test/CodeGen/AMDGPU/GlobalISel/inst-select-br.mir @@ -0,0 +1,21 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=GCN + +--- + +name: br +legalized: true +regBankSelected: true + +body: | + ; GCN-LABEL: name: br + ; GCN: bb.0: + ; GCN: successors: %bb.1(0x80000000) + ; GCN: S_BRANCH %bb.1 + ; GCN: bb.1: + bb.0: + G_BR %bb.1 + + bb.1: + +... Index: test/CodeGen/AMDGPU/GlobalISel/inst-select-brcond.mir =================================================================== --- /dev/null +++ test/CodeGen/AMDGPU/GlobalISel/inst-select-brcond.mir @@ -0,0 +1,173 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -run-pass=instruction-select -global-isel-abort=2 -pass-remarks-missed='gisel*' -verify-machineinstrs %s -o - 2> %t | FileCheck -check-prefixes=GCN %s +# RUN: FileCheck -check-prefix=ERR %s < %t + +# ERR-NOT: remark: +# ERR: remark: :0:0: cannot select: G_BRCOND %1:sgpr(s1), %bb.1 (in function: brcond_sgpr) +# ERR-NEXT: remark: :0:0: cannot select: G_BRCOND %2:vcc(s1), %bb.1 (in function: brcond_vcc) +# ERR-NOT: remark: + +--- + +name: brcond_scc +legalized: true +regBankSelected: true + +body: | + ; GCN-LABEL: name: brcond_scc + ; GCN: bb.0: + ; GCN: successors: %bb.1(0x80000000) + ; GCN: [[COPY:%[0-9]+]]:sreg_32 = COPY $sgpr0 + ; GCN: [[COPY1:%[0-9]+]]:sreg_32 = COPY $sgpr1 + ; GCN: S_CMP_EQ_U32 [[COPY]], [[COPY1]], implicit-def $scc + ; GCN: [[COPY2:%[0-9]+]]:sreg_32_xm0 = COPY $scc + ; GCN: $scc = COPY [[COPY2]] + ; GCN: S_CBRANCH_SCC1 %bb.1, implicit $scc + ; GCN: bb.1: + bb.0: + liveins: $sgpr0, $sgpr1 + + %0:sgpr(s32) = COPY $sgpr0 + %1:sgpr(s32) = COPY $sgpr1 + %2:scc(s1) = G_ICMP intpred(eq), %0, %1 + G_BRCOND %2, %bb.1 + + bb.1: + +... + +--- + +name: brcond_scc_impdef +legalized: true +regBankSelected: true + +body: | + ; GCN-LABEL: name: brcond_scc_impdef + ; GCN: bb.0: + ; GCN: successors: %bb.1(0x80000000) + ; GCN: [[DEF:%[0-9]+]]:sreg_32_xm0 = IMPLICIT_DEF + ; GCN: $scc = COPY [[DEF]] + ; GCN: S_CBRANCH_SCC1 %bb.1, implicit $scc + ; GCN: bb.1: + bb.0: + liveins: $sgpr0, $sgpr1 + + %0:scc(s1) = G_IMPLICIT_DEF + G_BRCOND %0, %bb.1 + + bb.1: + +... + +--- + +name: brcond_scc_undef +legalized: true +regBankSelected: true + +body: | + ; GCN-LABEL: name: brcond_scc_undef + ; GCN: bb.0: + ; GCN: successors: %bb.1(0x80000000) + ; GCN: $scc = COPY %0:sreg_32_xm0 + ; GCN: S_CBRANCH_SCC1 %bb.1, implicit $scc + ; GCN: bb.1: + bb.0: + liveins: $sgpr0, $sgpr1 + + G_BRCOND undef %0:scc(s1), %bb.1 + + bb.1: + +... + +--- + +name: brcond_scc_br +legalized: true +regBankSelected: true + +body: | + ; GCN-LABEL: name: brcond_scc_br + ; GCN: bb.0: + ; GCN: successors: %bb.1(0x80000000) + ; GCN: [[COPY:%[0-9]+]]:sreg_32 = COPY $sgpr0 + ; GCN: [[COPY1:%[0-9]+]]:sreg_32 = COPY $sgpr1 + ; GCN: S_CMP_EQ_U32 [[COPY]], [[COPY1]], implicit-def $scc + ; GCN: [[COPY2:%[0-9]+]]:sreg_32_xm0 = COPY $scc + ; GCN: $scc = COPY [[COPY2]] + ; GCN: S_CBRANCH_SCC1 %bb.1, implicit $scc + ; GCN: S_BRANCH %bb.1 + ; GCN: bb.1: + ; GCN: successors: %bb.2(0x80000000) + ; GCN: bb.2: + bb.0: + liveins: $sgpr0, $sgpr1 + + %0:sgpr(s32) = COPY $sgpr0 + %1:sgpr(s32) = COPY $sgpr1 + %2:scc(s1) = G_ICMP intpred(eq), %0, %1 + G_BRCOND %2, %bb.1 + G_BR %bb.1 + + bb.1: + + bb.2: + +... + +# Don't try to select this. +--- + +name: brcond_sgpr +legalized: true +regBankSelected: true + +body: | + ; GCN-LABEL: name: brcond_sgpr + ; GCN: bb.0: + ; GCN: successors: %bb.1(0x80000000) + ; GCN: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; GCN: [[TRUNC:%[0-9]+]]:sgpr(s1) = G_TRUNC [[COPY]](s32) + ; GCN: G_BRCOND [[TRUNC]](s1), %bb.1 + ; GCN: bb.1: + bb.0: + liveins: $sgpr0, $sgpr1 + + %0:sgpr(s32) = COPY $sgpr0 + %1:sgpr(s1) = G_TRUNC %0 + G_BRCOND %1, %bb.1 + + bb.1: + +... + + +# Don't try to select this for now. +--- + +name: brcond_vcc +legalized: true +regBankSelected: true + +body: | + ; GCN-LABEL: name: brcond_vcc + ; GCN: bb.0: + ; GCN: successors: %bb.1(0x80000000) + ; GCN: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; GCN: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; GCN: [[ICMP:%[0-9]+]]:vcc(s1) = G_ICMP intpred(eq), [[COPY]](s32), [[COPY1]] + ; GCN: G_BRCOND [[ICMP]](s1), %bb.1 + ; GCN: bb.1: + bb.0: + liveins: $vgpr0, $vgpr1 + + %0:vgpr(s32) = COPY $vgpr0 + %1:vgpr(s32) = COPY $vgpr1 + %2:vcc(s1) = G_ICMP intpred(eq), %0, %1 + G_BRCOND %2, %bb.1 + + bb.1: + +...