Index: llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -2032,6 +2032,21 @@ Observer.changedInstr(MI); return Legalized; + case TargetOpcode::G_SBFX: + case TargetOpcode::G_UBFX: + Observer.changingInstr(MI); + + if (TypeIdx == 0) { + widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT); + widenScalarDst(MI, WideTy); + } else { + widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); + widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ZEXT); + } + + Observer.changedInstr(MI); + return Legalized; + case TargetOpcode::G_SHL: Observer.changingInstr(MI); Index: llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h +++ llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h @@ -109,6 +109,7 @@ bool selectG_PTR_ADD(MachineInstr &I) const; bool selectG_IMPLICIT_DEF(MachineInstr &I) const; bool selectG_INSERT(MachineInstr &I) const; + bool selectG_SBFX_UBFX(MachineInstr &I) const; bool selectInterpP1F16(MachineInstr &MI) const; bool selectWritelane(MachineInstr &MI) const; Index: llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp @@ -754,6 +754,30 @@ return true; } +bool AMDGPUInstructionSelector::selectG_SBFX_UBFX(MachineInstr &MI) const { + Register DstReg = MI.getOperand(0).getReg(); + Register SrcReg = MI.getOperand(1).getReg(); + Register OffsetReg = MI.getOperand(2).getReg(); + Register WidthReg = MI.getOperand(3).getReg(); + + assert(RBI.getRegBank(DstReg, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID && + "scalar BFX instructions are expanded in regbankselect"); + assert(MRI->getType(MI.getOperand(0).getReg()).getSizeInBits() == 32 && + "64-bit vector BFX instructions are expanded in regbankselect"); + + const DebugLoc &DL = MI.getDebugLoc(); + MachineBasicBlock *MBB = MI.getParent(); + + bool IsSigned = MI.getOpcode() == TargetOpcode::G_SBFX; + unsigned Opc = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64; + auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc), DstReg) + .addReg(SrcReg) + .addReg(OffsetReg) + .addReg(WidthReg); + MI.eraseFromParent(); + return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); +} + bool AMDGPUInstructionSelector::selectInterpP1F16(MachineInstr &MI) const { if (STI.getLDSBankCount() != 16) return selectImpl(MI, *CoverageInfo); @@ -3169,6 +3193,9 @@ return selectBVHIntrinsic(I); case AMDGPU::G_AMDGPU_BUFFER_ATOMIC_FADD: return selectAMDGPU_BUFFER_ATOMIC_FADD(I); + case AMDGPU::G_SBFX: + case AMDGPU::G_UBFX: + return selectG_SBFX_UBFX(I); default: return selectImpl(I, *CoverageInfo); } Index: llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -1630,6 +1630,12 @@ .minScalar(0, S32) .lower(); + getActionDefinitionsBuilder({G_SBFX, G_UBFX}) + .legalFor({{S32, S32}, {S64, S32}}) + .clampScalar(1, S32, S32) + .clampScalar(0, S32, S64) + .widenScalarToNextPow2(0); + getActionDefinitionsBuilder({ // TODO: Verify V_BFI_B32 is generated from expanded bit ops G_FCOPYSIGN, Index: llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.h =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.h +++ llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.h @@ -81,8 +81,8 @@ MachineRegisterInfo &MRI, int RSrcIdx) const; bool applyMappingSBufferLoad(const OperandsMapper &OpdMapper) const; - bool applyMappingBFEIntrinsic(const OperandsMapper &OpdMapper, - bool Signed) const; + bool applyMappingBFE(const OperandsMapper &OpdMapper, + bool Signed) const; Register handleD16VData(MachineIRBuilder &B, MachineRegisterInfo &MRI, Register Reg) const; Index: llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp +++ llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp @@ -1504,7 +1504,7 @@ return true; } -bool AMDGPURegisterBankInfo::applyMappingBFEIntrinsic( +bool AMDGPURegisterBankInfo::applyMappingBFE( const OperandsMapper &OpdMapper, bool Signed) const { MachineInstr &MI = OpdMapper.getMI(); MachineRegisterInfo &MRI = OpdMapper.getMRI(); @@ -1517,19 +1517,45 @@ const LLT S32 = LLT::scalar(32); + unsigned FirstOpnd = MI.getOpcode() == AMDGPU::G_INTRINSIC ? 2 : 1; + Register SrcReg = MI.getOperand(FirstOpnd).getReg(); + Register OffsetReg = MI.getOperand(FirstOpnd+1).getReg(); + Register WidthReg = MI.getOperand(FirstOpnd+2).getReg(); + const RegisterBank *DstBank = OpdMapper.getInstrMapping().getOperandMapping(0).BreakDown[0].RegBank; if (DstBank == &AMDGPU::VGPRRegBank) { if (Ty == S32) return true; - // TODO: 64-bit version is scalar only, so we need to expand this. - return false; - } + ApplyRegBankMapping ApplyBank(*this, MRI, &AMDGPU::VGPRRegBank); + MachineIRBuilder B(MI, ApplyBank); - Register SrcReg = MI.getOperand(2).getReg(); - Register OffsetReg = MI.getOperand(3).getReg(); - Register WidthReg = MI.getOperand(4).getReg(); + // Expand to Src >> Offset & ((1 << Width) - 1) using 64-bit operations. + const LLT S1 = LLT::scalar(1); + const LLT S64 = LLT::scalar(64); + auto Zero = B.buildConstant(S32, 0); + auto ExtendOffsetReg = B.buildMerge(S64, {Zero, OffsetReg}); + // Shift the source operand so that extracted bits start at bit 0. + auto ShiftOffset = Signed ? B.buildAShr(S64, SrcReg, ExtendOffsetReg) + : B.buildLShr(S64, SrcReg, ExtendOffsetReg); + // Create a mask of ones to extract the necessary bits. + auto ExtendWidthReg = B.buildMerge(S64, {Zero, WidthReg}); + auto ShiftOne = B.buildShl(S64, B.buildConstant(S64, 1), ExtendWidthReg); + auto Unmerge = B.buildUnmerge({S32, S32}, ShiftOne); + auto One = B.buildConstant(S32, 1); + // Use 32-bit instructions for the substraction. + auto SubLo = Signed ? B.buildSSubo(S32, S1, Unmerge.getReg(0), One) + : B.buildUSubo(S32, S1, Unmerge.getReg(0), One); + auto SubHi = + Signed ? B.buildSSube(S32, S1, Unmerge.getReg(1), One, SubLo.getReg(1)) + : B.buildUSube(S32, S1, Unmerge.getReg(1), One, SubLo.getReg(1)); + auto Merge = B.buildMerge(S64, {SubHi, SubLo}); + // Produce the extracted bitfield. + B.buildAnd(S64, ShiftOffset, Merge); + MI.eraseFromParent(); + return true; + } // The scalar form packs the offset and width in a single operand. @@ -2897,10 +2923,10 @@ return; } case Intrinsic::amdgcn_sbfe: - applyMappingBFEIntrinsic(OpdMapper, true); + applyMappingBFE(OpdMapper, true); return; case Intrinsic::amdgcn_ubfe: - applyMappingBFEIntrinsic(OpdMapper, false); + applyMappingBFE(OpdMapper, false); return; case Intrinsic::amdgcn_ballot: // Use default handling and insert copy to vcc source. @@ -2992,6 +3018,12 @@ case AMDGPU::G_DYN_STACKALLOC: applyMappingDynStackAlloc(MI, OpdMapper, MRI); return; + case AMDGPU::G_SBFX: + applyMappingBFE(OpdMapper, /*Signed*/true); + return; + case AMDGPU::G_UBFX: + applyMappingBFE(OpdMapper, /*Signed*/false); + return; default: break; } @@ -3465,6 +3497,8 @@ case AMDGPU::G_UMIN: case AMDGPU::G_UMAX: case AMDGPU::G_SHUFFLE_VECTOR: + case AMDGPU::G_SBFX: + case AMDGPU::G_UBFX: if (isSALUMapping(MI)) return getDefaultMappingSOP(MI); LLVM_FALLTHROUGH; Index: llvm/test/CodeGen/AMDGPU/GlobalISel/inst-select-sbfx.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/GlobalISel/inst-select-sbfx.mir @@ -0,0 +1,65 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=instruction-select -verify-machineinstrs -o - %s | FileCheck -check-prefix=WAVE64 %s +# RUN: llc -march=amdgcn -mcpu=gfx1010 -run-pass=instruction-select -verify-machineinstrs -o - %s | FileCheck -check-prefix=WAVE32 %s + +# The only simple instruction selection for G_SBFX/G_UBFX are the 64-bit +# vector versions. All other versions are expanded during register bank +# selection. + +--- +name: sbfx_s32_vii +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0 + ; WAVE64-LABEL: name: sbfx_s32_vii + ; WAVE64: liveins: $vgpr0 + ; WAVE64: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; WAVE64: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 2, implicit $exec + ; WAVE64: [[V_MOV_B32_e32_1:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 10, implicit $exec + ; WAVE64: [[V_BFE_I32_e64_:%[0-9]+]]:vgpr_32 = V_BFE_I32_e64 [[COPY]], [[V_MOV_B32_e32_]], [[V_MOV_B32_e32_1]], implicit $exec + ; WAVE64: S_ENDPGM 0, implicit [[V_BFE_I32_e64_]] + ; WAVE32-LABEL: name: sbfx_s32_vii + ; WAVE32: liveins: $vgpr0 + ; WAVE32: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; WAVE32: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 2, implicit $exec + ; WAVE32: [[V_MOV_B32_e32_1:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 10, implicit $exec + ; WAVE32: [[V_BFE_I32_e64_:%[0-9]+]]:vgpr_32 = V_BFE_I32_e64 [[COPY]], [[V_MOV_B32_e32_]], [[V_MOV_B32_e32_1]], implicit $exec + ; WAVE32: S_ENDPGM 0, implicit [[V_BFE_I32_e64_]] + %0:vgpr(s32) = COPY $vgpr0 + %1:vgpr(s32) = G_CONSTANT i32 2 + %2:vgpr(s32) = G_CONSTANT i32 10 + %3:vgpr(s32) = G_SBFX %0, %1(s32), %2 + S_ENDPGM 0, implicit %3 +... + +--- +name: sbfx_s32_vvv +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0, $vgpr1, $vgpr2 + ; WAVE64-LABEL: name: sbfx_s32_vvv + ; WAVE64: liveins: $vgpr0, $vgpr1, $vgpr2 + ; WAVE64: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; WAVE64: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; WAVE64: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; WAVE64: [[V_BFE_I32_e64_:%[0-9]+]]:vgpr_32 = V_BFE_I32_e64 [[COPY]], [[COPY1]], [[COPY2]], implicit $exec + ; WAVE64: S_ENDPGM 0, implicit [[V_BFE_I32_e64_]] + ; WAVE32-LABEL: name: sbfx_s32_vvv + ; WAVE32: liveins: $vgpr0, $vgpr1, $vgpr2 + ; WAVE32: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; WAVE32: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; WAVE32: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; WAVE32: [[V_BFE_I32_e64_:%[0-9]+]]:vgpr_32 = V_BFE_I32_e64 [[COPY]], [[COPY1]], [[COPY2]], implicit $exec + ; WAVE32: S_ENDPGM 0, implicit [[V_BFE_I32_e64_]] + %0:vgpr(s32) = COPY $vgpr0 + %1:vgpr(s32) = COPY $vgpr1 + %2:vgpr(s32) = COPY $vgpr2 + %3:vgpr(s32) = G_SBFX %0, %1(s32), %2 + S_ENDPGM 0, implicit %3 +... Index: llvm/test/CodeGen/AMDGPU/GlobalISel/inst-select-ubfx.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/GlobalISel/inst-select-ubfx.mir @@ -0,0 +1,65 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=instruction-select -verify-machineinstrs -o - %s | FileCheck -check-prefix=WAVE64 %s +# RUN: llc -march=amdgcn -mcpu=gfx1010 -run-pass=instruction-select -verify-machineinstrs -o - %s | FileCheck -check-prefix=WAVE32 %s + +# The only simple instruction selection for G_SBFX/G_UBFX are the 64-bit +# vector versions. All other versions are expanded during register bank +# selection. + +--- +name: ubfx_s32_vii +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0 + ; WAVE64-LABEL: name: ubfx_s32_vii + ; WAVE64: liveins: $vgpr0 + ; WAVE64: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; WAVE64: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 2, implicit $exec + ; WAVE64: [[V_MOV_B32_e32_1:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 10, implicit $exec + ; WAVE64: [[V_BFE_U32_e64_:%[0-9]+]]:vgpr_32 = V_BFE_U32_e64 [[COPY]], [[V_MOV_B32_e32_]], [[V_MOV_B32_e32_1]], implicit $exec + ; WAVE64: S_ENDPGM 0, implicit [[V_BFE_U32_e64_]] + ; WAVE32-LABEL: name: ubfx_s32_vii + ; WAVE32: liveins: $vgpr0 + ; WAVE32: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; WAVE32: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 2, implicit $exec + ; WAVE32: [[V_MOV_B32_e32_1:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 10, implicit $exec + ; WAVE32: [[V_BFE_U32_e64_:%[0-9]+]]:vgpr_32 = V_BFE_U32_e64 [[COPY]], [[V_MOV_B32_e32_]], [[V_MOV_B32_e32_1]], implicit $exec + ; WAVE32: S_ENDPGM 0, implicit [[V_BFE_U32_e64_]] + %0:vgpr(s32) = COPY $vgpr0 + %1:vgpr(s32) = G_CONSTANT i32 2 + %2:vgpr(s32) = G_CONSTANT i32 10 + %3:vgpr(s32) = G_UBFX %0, %1(s32), %2 + S_ENDPGM 0, implicit %3 +... + +--- +name: ubfx_s32_vvv +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0, $vgpr1, $vgpr2 + ; WAVE64-LABEL: name: ubfx_s32_vvv + ; WAVE64: liveins: $vgpr0, $vgpr1, $vgpr2 + ; WAVE64: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; WAVE64: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; WAVE64: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; WAVE64: [[V_BFE_U32_e64_:%[0-9]+]]:vgpr_32 = V_BFE_U32_e64 [[COPY]], [[COPY1]], [[COPY2]], implicit $exec + ; WAVE64: S_ENDPGM 0, implicit [[V_BFE_U32_e64_]] + ; WAVE32-LABEL: name: ubfx_s32_vvv + ; WAVE32: liveins: $vgpr0, $vgpr1, $vgpr2 + ; WAVE32: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; WAVE32: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; WAVE32: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; WAVE32: [[V_BFE_U32_e64_:%[0-9]+]]:vgpr_32 = V_BFE_U32_e64 [[COPY]], [[COPY1]], [[COPY2]], implicit $exec + ; WAVE32: S_ENDPGM 0, implicit [[V_BFE_U32_e64_]] + %0:vgpr(s32) = COPY $vgpr0 + %1:vgpr(s32) = COPY $vgpr1 + %2:vgpr(s32) = COPY $vgpr2 + %3:vgpr(s32) = G_UBFX %0, %1(s32), %2 + S_ENDPGM 0, implicit %3 +... Index: llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sbfx.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sbfx.mir @@ -0,0 +1,122 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -O0 -run-pass=legalizer -global-isel-abort=0 %s -o - | FileCheck --check-prefix=VI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 -O0 -run-pass=legalizer -global-isel-abort=0 %s -o - | FileCheck --check-prefix=GFX9 %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx1010 -O0 -run-pass=legalizer -global-isel-abort=0 %s -o - | FileCheck --check-prefix=GFX10 %s +... +--- +name: test_sbfx_s32 +body: | + bb.0.entry: + liveins: $vgpr0, $vgpr1, $vgpr2 + + ; VI-LABEL: name: test_sbfx_s32 + ; VI: %copy:_(s32) = COPY $vgpr0 + ; VI: %offset:_(s32) = COPY $vgpr1 + ; VI: %width:_(s32) = COPY $vgpr2 + ; VI: %sbfx:_(s32) = G_SBFX %copy, %offset(s32), %width + ; VI: $vgpr0 = COPY %sbfx(s32) + ; GFX9-LABEL: name: test_sbfx_s32 + ; GFX9: %copy:_(s32) = COPY $vgpr0 + ; GFX9: %offset:_(s32) = COPY $vgpr1 + ; GFX9: %width:_(s32) = COPY $vgpr2 + ; GFX9: %sbfx:_(s32) = G_SBFX %copy, %offset(s32), %width + ; GFX9: $vgpr0 = COPY %sbfx(s32) + ; GFX10-LABEL: name: test_sbfx_s32 + ; GFX10: %copy:_(s32) = COPY $vgpr0 + ; GFX10: %offset:_(s32) = COPY $vgpr1 + ; GFX10: %width:_(s32) = COPY $vgpr2 + ; GFX10: %sbfx:_(s32) = G_SBFX %copy, %offset(s32), %width + ; GFX10: $vgpr0 = COPY %sbfx(s32) + %copy:_(s32) = COPY $vgpr0 + %offset:_(s32) = COPY $vgpr1 + %width:_(s32) = COPY $vgpr2 + %sbfx:_(s32) = G_SBFX %copy, %offset(s32), %width + $vgpr0 = COPY %sbfx(s32) +... + +--- +name: test_sbfx_s64 +body: | + bb.0.entry: + liveins: $vgpr0_vgpr1, $vgpr2, $vgpr3 + + ; VI-LABEL: name: test_sbfx_s64 + ; VI: %copy:_(s64) = COPY $vgpr0_vgpr1 + ; VI: %offset:_(s32) = COPY $vgpr2 + ; VI: %width:_(s32) = COPY $vgpr3 + ; VI: %sbfx:_(s64) = G_SBFX %copy, %offset(s32), %width + ; VI: $vgpr0_vgpr1 = COPY %sbfx(s64) + ; GFX9-LABEL: name: test_sbfx_s64 + ; GFX9: %copy:_(s64) = COPY $vgpr0_vgpr1 + ; GFX9: %offset:_(s32) = COPY $vgpr2 + ; GFX9: %width:_(s32) = COPY $vgpr3 + ; GFX9: %sbfx:_(s64) = G_SBFX %copy, %offset(s32), %width + ; GFX9: $vgpr0_vgpr1 = COPY %sbfx(s64) + ; GFX10-LABEL: name: test_sbfx_s64 + ; GFX10: %copy:_(s64) = COPY $vgpr0_vgpr1 + ; GFX10: %offset:_(s32) = COPY $vgpr2 + ; GFX10: %width:_(s32) = COPY $vgpr3 + ; GFX10: %sbfx:_(s64) = G_SBFX %copy, %offset(s32), %width + ; GFX10: $vgpr0_vgpr1 = COPY %sbfx(s64) + %copy:_(s64) = COPY $vgpr0_vgpr1 + %offset:_(s32) = COPY $vgpr2 + %width:_(s32) = COPY $vgpr3 + %sbfx:_(s64) = G_SBFX %copy, %offset(s32), %width + $vgpr0_vgpr1 = COPY %sbfx(s64) +... + +--- +name: test_sbfx_s8 +body: | + bb.0.entry: + liveins: $vgpr0, $vgpr1, $vgpr2 + + ; VI-LABEL: name: test_sbfx_s8 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; VI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; VI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; VI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; VI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C]] + ; VI: [[COPY5:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; VI: [[SBFX:%[0-9]+]]:_(s32) = G_SBFX [[COPY5]], [[AND]](s32), [[AND1]] + ; VI: [[COPY6:%[0-9]+]]:_(s32) = COPY [[SBFX]](s32) + ; VI: $vgpr0 = COPY [[COPY6]](s32) + ; GFX9-LABEL: name: test_sbfx_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; GFX9: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX9: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; GFX9: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; GFX9: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C]] + ; GFX9: [[COPY5:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX9: [[SBFX:%[0-9]+]]:_(s32) = G_SBFX [[COPY5]], [[AND]](s32), [[AND1]] + ; GFX9: [[COPY6:%[0-9]+]]:_(s32) = COPY [[SBFX]](s32) + ; GFX9: $vgpr0 = COPY [[COPY6]](s32) + ; GFX10-LABEL: name: test_sbfx_s8 + ; GFX10: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX10: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX10: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 + ; GFX10: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; GFX10: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX10: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; GFX10: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; GFX10: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C]] + ; GFX10: [[COPY5:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX10: [[SBFX:%[0-9]+]]:_(s32) = G_SBFX [[COPY5]], [[AND]](s32), [[AND1]] + ; GFX10: [[COPY6:%[0-9]+]]:_(s32) = COPY [[SBFX]](s32) + ; GFX10: $vgpr0 = COPY [[COPY6]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = COPY $vgpr2 + %copy:_(s8) = G_TRUNC %0 + %offset:_(s8) = G_TRUNC %1 + %width:_(s8) = G_TRUNC %2 + %sbfx:_(s8) = G_SBFX %copy, %offset, %width + %4:_(s32) = G_ANYEXT %sbfx + $vgpr0 = COPY %4 +... Index: llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ubfx.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ubfx.mir @@ -0,0 +1,122 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -O0 -run-pass=legalizer -global-isel-abort=0 %s -o - | FileCheck --check-prefix=VI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 -O0 -run-pass=legalizer -global-isel-abort=0 %s -o - | FileCheck --check-prefix=GFX9 %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx1010 -O0 -run-pass=legalizer -global-isel-abort=0 %s -o - | FileCheck --check-prefix=GFX10 %s +... +--- +name: test_ubfx_s32 +body: | + bb.0.entry: + liveins: $vgpr0, $vgpr1, $vgpr2 + + ; VI-LABEL: name: test_ubfx_s32 + ; VI: %copy:_(s32) = COPY $vgpr0 + ; VI: %offset:_(s32) = COPY $vgpr1 + ; VI: %width:_(s32) = COPY $vgpr2 + ; VI: %ubfx:_(s32) = G_UBFX %copy, %offset(s32), %width + ; VI: $vgpr0 = COPY %ubfx(s32) + ; GFX9-LABEL: name: test_ubfx_s32 + ; GFX9: %copy:_(s32) = COPY $vgpr0 + ; GFX9: %offset:_(s32) = COPY $vgpr1 + ; GFX9: %width:_(s32) = COPY $vgpr2 + ; GFX9: %ubfx:_(s32) = G_UBFX %copy, %offset(s32), %width + ; GFX9: $vgpr0 = COPY %ubfx(s32) + ; GFX10-LABEL: name: test_ubfx_s32 + ; GFX10: %copy:_(s32) = COPY $vgpr0 + ; GFX10: %offset:_(s32) = COPY $vgpr1 + ; GFX10: %width:_(s32) = COPY $vgpr2 + ; GFX10: %ubfx:_(s32) = G_UBFX %copy, %offset(s32), %width + ; GFX10: $vgpr0 = COPY %ubfx(s32) + %copy:_(s32) = COPY $vgpr0 + %offset:_(s32) = COPY $vgpr1 + %width:_(s32) = COPY $vgpr2 + %ubfx:_(s32) = G_UBFX %copy, %offset(s32), %width + $vgpr0 = COPY %ubfx(s32) +... + +--- +name: test_ubfx_s64 +body: | + bb.0.entry: + liveins: $vgpr0_vgpr1, $vgpr2, $vgpr3 + + ; VI-LABEL: name: test_ubfx_s64 + ; VI: %copy:_(s64) = COPY $vgpr0_vgpr1 + ; VI: %offset:_(s32) = COPY $vgpr2 + ; VI: %width:_(s32) = COPY $vgpr3 + ; VI: %ubfx:_(s64) = G_UBFX %copy, %offset(s32), %width + ; VI: $vgpr0_vgpr1 = COPY %ubfx(s64) + ; GFX9-LABEL: name: test_ubfx_s64 + ; GFX9: %copy:_(s64) = COPY $vgpr0_vgpr1 + ; GFX9: %offset:_(s32) = COPY $vgpr2 + ; GFX9: %width:_(s32) = COPY $vgpr3 + ; GFX9: %ubfx:_(s64) = G_UBFX %copy, %offset(s32), %width + ; GFX9: $vgpr0_vgpr1 = COPY %ubfx(s64) + ; GFX10-LABEL: name: test_ubfx_s64 + ; GFX10: %copy:_(s64) = COPY $vgpr0_vgpr1 + ; GFX10: %offset:_(s32) = COPY $vgpr2 + ; GFX10: %width:_(s32) = COPY $vgpr3 + ; GFX10: %ubfx:_(s64) = G_UBFX %copy, %offset(s32), %width + ; GFX10: $vgpr0_vgpr1 = COPY %ubfx(s64) + %copy:_(s64) = COPY $vgpr0_vgpr1 + %offset:_(s32) = COPY $vgpr2 + %width:_(s32) = COPY $vgpr3 + %ubfx:_(s64) = G_UBFX %copy, %offset(s32), %width + $vgpr0_vgpr1 = COPY %ubfx(s64) +... + +--- +name: test_ubfx_s8 +body: | + bb.0.entry: + liveins: $vgpr0, $vgpr1, $vgpr2 + + ; VI-LABEL: name: test_ubfx_s8 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; VI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; VI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; VI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; VI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C]] + ; VI: [[COPY5:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; VI: [[UBFX:%[0-9]+]]:_(s32) = G_UBFX [[COPY5]], [[AND]](s32), [[AND1]] + ; VI: [[COPY6:%[0-9]+]]:_(s32) = COPY [[UBFX]](s32) + ; VI: $vgpr0 = COPY [[COPY6]](s32) + ; GFX9-LABEL: name: test_ubfx_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; GFX9: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX9: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; GFX9: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; GFX9: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C]] + ; GFX9: [[COPY5:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX9: [[UBFX:%[0-9]+]]:_(s32) = G_UBFX [[COPY5]], [[AND]](s32), [[AND1]] + ; GFX9: [[COPY6:%[0-9]+]]:_(s32) = COPY [[UBFX]](s32) + ; GFX9: $vgpr0 = COPY [[COPY6]](s32) + ; GFX10-LABEL: name: test_ubfx_s8 + ; GFX10: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX10: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX10: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 + ; GFX10: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; GFX10: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX10: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; GFX10: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY2]](s32) + ; GFX10: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[C]] + ; GFX10: [[COPY5:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX10: [[UBFX:%[0-9]+]]:_(s32) = G_UBFX [[COPY5]], [[AND]](s32), [[AND1]] + ; GFX10: [[COPY6:%[0-9]+]]:_(s32) = COPY [[UBFX]](s32) + ; GFX10: $vgpr0 = COPY [[COPY6]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = COPY $vgpr2 + %copy:_(s8) = G_TRUNC %0 + %offset:_(s8) = G_TRUNC %1 + %width:_(s8) = G_TRUNC %2 + %ubfx:_(s8) = G_UBFX %copy, %offset, %width + %4:_(s32) = G_ANYEXT %ubfx + $vgpr0 = COPY %4 +... Index: llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-sbfx.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-sbfx.mir @@ -0,0 +1,281 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect -regbankselect-fast -verify-machineinstrs -o - %s | FileCheck %s +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect -regbankselect-greedy -verify-machineinstrs -o - %s | FileCheck %s + +... + +# Generate the 3 operand vector bitfield extract instructions for 32-bit +# operations only. +--- +name: test_sbfx_s32_vvv +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0, $vgpr1, $vgpr2 + + ; CHECK-LABEL: name: test_sbfx_s32_vvv + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr2 + ; CHECK: [[SBFX:%[0-9]+]]:vgpr(s32) = G_SBFX [[COPY]], [[COPY1]](s32), [[COPY2]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = COPY $vgpr2 + %3:_(s32) = G_SBFX %0, %1(s32), %2 +... + +--- +name: test_ubfx_s32_vii +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0 + + ; CHECK-LABEL: name: test_ubfx_s32_vii + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 10 + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 4 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY [[C]](s32) + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[C1]](s32) + ; CHECK: [[UBFX:%[0-9]+]]:vgpr(s32) = G_UBFX [[COPY]], [[COPY1]](s32), [[COPY2]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = G_CONSTANT i32 10 + %2:_(s32) = G_CONSTANT i32 4 + %3:_(s32) = G_UBFX %0, %1(s32), %2 +... + +--- +name: test_sbfx_s32_vss +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0, $sgpr0, $sgpr1 + + ; CHECK-LABEL: name: test_sbfx_s32_vss + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY2]](s32) + ; CHECK: [[SBFX:%[0-9]+]]:vgpr(s32) = G_SBFX [[COPY]], [[COPY3]](s32), [[COPY4]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $sgpr0 + %2:_(s32) = COPY $sgpr1 + %3:_(s32) = G_SBFX %0, %1(s32), %2 +... + +# Expand to a sequence that implements the 64-bit bitfield extract using +# shifts and masks. +--- +name: test_sbfx_s64_vvv +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0_vgpr1, $vgpr2, $vgpr3 + + ; CHECK-LABEL: name: test_sbfx_s64_vvv + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s64) = COPY $vgpr0_vgpr1 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr2 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr3 + ; CHECK: [[C:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 0 + ; CHECK: [[MV:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY1]](s32) + ; CHECK: [[ASHR:%[0-9]+]]:vgpr(s64) = G_ASHR [[COPY]], [[MV]](s64) + ; CHECK: [[MV1:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY2]](s32) + ; CHECK: [[C1:%[0-9]+]]:vgpr(s64) = G_CONSTANT i64 1 + ; CHECK: [[SHL:%[0-9]+]]:vgpr(s64) = G_SHL [[C1]], [[MV1]](s64) + ; CHECK: [[UV:%[0-9]+]]:vgpr(s32), [[UV1:%[0-9]+]]:vgpr(s32) = G_UNMERGE_VALUES [[SHL]](s64) + ; CHECK: [[C2:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[SSUBO:%[0-9]+]]:vgpr(s32), [[SSUBO1:%[0-9]+]]:vcc(s1) = G_SSUBO [[UV]], [[C2]] + ; CHECK: [[SSUBE:%[0-9]+]]:vgpr(s32), [[SSUBE1:%[0-9]+]]:vcc(s1) = G_SSUBE [[UV1]], [[C2]], [[SSUBO1]] + ; CHECK: [[MV2:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[SSUBE]](s32), [[SSUBO]](s32) + ; CHECK: [[AND:%[0-9]+]]:vgpr(s64) = G_AND [[ASHR]], [[MV2]] + %0:_(s64) = COPY $vgpr0_vgpr1 + %1:_(s32) = COPY $vgpr2 + %2:_(s32) = COPY $vgpr3 + %3:_(s64) = G_SBFX %0, %1(s32), %2 +... + +--- +name: test_sbfx_s64_vss +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0_vgpr1, $sgpr0, $sgpr1 + + ; CHECK-LABEL: name: test_sbfx_s64_vss + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s64) = COPY $vgpr0_vgpr1 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[C:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 0 + ; CHECK: [[MV:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY1]](s32) + ; CHECK: [[ASHR:%[0-9]+]]:vgpr(s64) = G_ASHR [[COPY]], [[MV]](s64) + ; CHECK: [[MV1:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY2]](s32) + ; CHECK: [[C1:%[0-9]+]]:vgpr(s64) = G_CONSTANT i64 1 + ; CHECK: [[SHL:%[0-9]+]]:vgpr(s64) = G_SHL [[C1]], [[MV1]](s64) + ; CHECK: [[UV:%[0-9]+]]:vgpr(s32), [[UV1:%[0-9]+]]:vgpr(s32) = G_UNMERGE_VALUES [[SHL]](s64) + ; CHECK: [[C2:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[SSUBO:%[0-9]+]]:vgpr(s32), [[SSUBO1:%[0-9]+]]:vcc(s1) = G_SSUBO [[UV]], [[C2]] + ; CHECK: [[SSUBE:%[0-9]+]]:vgpr(s32), [[SSUBE1:%[0-9]+]]:vcc(s1) = G_SSUBE [[UV1]], [[C2]], [[SSUBO1]] + ; CHECK: [[MV2:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[SSUBE]](s32), [[SSUBO]](s32) + ; CHECK: [[AND:%[0-9]+]]:vgpr(s64) = G_AND [[ASHR]], [[MV2]] + %0:_(s64) = COPY $vgpr0_vgpr1 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = COPY $vgpr1 + %3:_(s64) = G_SBFX %0, %1(s32), %2 +... + +--- +name: test_sbfx_s64_svv +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0_sgpr1, $vgpr0, $vgpr1 + + ; CHECK-LABEL: name: test_sbfx_s64_svv + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s64) = COPY $sgpr0_sgpr1 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[COPY3:%[0-9]+]]:vgpr(s64) = COPY [[COPY]](s64) + ; CHECK: [[C:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 0 + ; CHECK: [[MV:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY1]](s32) + ; CHECK: [[ASHR:%[0-9]+]]:vgpr(s64) = G_ASHR [[COPY3]], [[MV]](s64) + ; CHECK: [[MV1:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY2]](s32) + ; CHECK: [[C1:%[0-9]+]]:vgpr(s64) = G_CONSTANT i64 1 + ; CHECK: [[SHL:%[0-9]+]]:vgpr(s64) = G_SHL [[C1]], [[MV1]](s64) + ; CHECK: [[UV:%[0-9]+]]:vgpr(s32), [[UV1:%[0-9]+]]:vgpr(s32) = G_UNMERGE_VALUES [[SHL]](s64) + ; CHECK: [[C2:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[SSUBO:%[0-9]+]]:vgpr(s32), [[SSUBO1:%[0-9]+]]:vcc(s1) = G_SSUBO [[UV]], [[C2]] + ; CHECK: [[SSUBE:%[0-9]+]]:vgpr(s32), [[SSUBE1:%[0-9]+]]:vcc(s1) = G_SSUBE [[UV1]], [[C2]], [[SSUBO1]] + ; CHECK: [[MV2:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[SSUBE]](s32), [[SSUBO]](s32) + ; CHECK: [[AND:%[0-9]+]]:vgpr(s64) = G_AND [[ASHR]], [[MV2]] + %0:_(s64) = COPY $sgpr0_sgpr1 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = COPY $vgpr1 + %3:_(s64) = G_SBFX %0, %1(s32), %2 +... + +# Expand to a sequence that combines the offset and width for the two operand +# version of the 32-bit instruction. +--- +name: test_sbfx_s32_svv +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0, $vgpr0, $vgpr1 + + ; CHECK-LABEL: name: test_sbfx_s32_svv + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) + ; CHECK: [[SBFX:%[0-9]+]]:vgpr(s32) = G_SBFX [[COPY3]], [[COPY1]](s32), [[COPY2]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = COPY $vgpr1 + %3:_(s32) = G_SBFX %0, %1(s32), %2 +... + +--- +name: test_sbfx_s32_sss +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr3 + + ; CHECK-LABEL: name: test_sbfx_s32_sss + ; CHECK: [[COPY:%[0-9]+]]:sreg_32(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 63 + ; CHECK: [[AND:%[0-9]+]]:sgpr(s32) = G_AND [[COPY1]], [[C]] + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL:%[0-9]+]]:sgpr(s32) = G_SHL [[COPY2]], [[C1]](s32) + ; CHECK: [[OR:%[0-9]+]]:sreg_32(s32) = G_OR [[AND]], [[SHL]] + ; CHECK: [[S_BFE_I32_:%[0-9]+]]:sreg_32(s32) = S_BFE_I32 [[COPY]](s32), [[OR]](s32), implicit-def $scc + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $sgpr1 + %2:_(s32) = COPY $sgpr2 + %3:_(s32) = G_SBFX %0, %1(s32), %2 +... + +--- +name: test_sbfx_s32_sii +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0 + + ; CHECK-LABEL: name: test_sbfx_s32_sii + ; CHECK: [[COPY:%[0-9]+]]:sreg_32(s32) = COPY $sgpr0 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 10 + ; CHECK: [[C2:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 63 + ; CHECK: [[AND:%[0-9]+]]:sgpr(s32) = G_AND [[C]], [[C2]] + ; CHECK: [[C3:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL:%[0-9]+]]:sgpr(s32) = G_SHL [[C1]], [[C3]](s32) + ; CHECK: [[OR:%[0-9]+]]:sreg_32(s32) = G_OR [[AND]], [[SHL]] + ; CHECK: [[S_BFE_I32_:%[0-9]+]]:sreg_32(s32) = S_BFE_I32 [[COPY]](s32), [[OR]](s32), implicit-def $scc + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = G_CONSTANT i32 1 + %2:_(s32) = G_CONSTANT i32 10 + %3:_(s32) = G_SBFX %0, %1(s32), %2 +... + +# Expand to a sequence that combines the offset and width for the two operand +# version of the 64-bit scalar instruction. +--- +name: test_sbfx_s64_sss +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0_sgpr1, $sgpr0, $sgpr1 + + ; CHECK-LABEL: name: test_sbfx_s64_sss + ; CHECK: [[COPY:%[0-9]+]]:sreg_64(s64) = COPY $sgpr0_sgpr1 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 63 + ; CHECK: [[AND:%[0-9]+]]:sgpr(s32) = G_AND [[COPY1]], [[C]] + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL:%[0-9]+]]:sgpr(s32) = G_SHL [[COPY2]], [[C1]](s32) + ; CHECK: [[OR:%[0-9]+]]:sreg_32(s32) = G_OR [[AND]], [[SHL]] + ; CHECK: [[S_BFE_I64_:%[0-9]+]]:sreg_64(s64) = S_BFE_I64 [[COPY]](s64), [[OR]](s32), implicit-def $scc + %0:_(s64) = COPY $sgpr0_sgpr1 + %1:_(s32) = COPY $sgpr0 + %2:_(s32) = COPY $sgpr1 + %3:_(s64) = G_SBFX %0, %1(s32), %2 +... + +--- +name: test_sbfx_s64_sii +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0_sgpr1 + + ; CHECK-LABEL: name: test_sbfx_s64_sii + ; CHECK: [[COPY:%[0-9]+]]:sreg_64(s64) = COPY $sgpr0_sgpr1 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 10 + ; CHECK: [[C2:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 63 + ; CHECK: [[AND:%[0-9]+]]:sgpr(s32) = G_AND [[C]], [[C2]] + ; CHECK: [[C3:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL:%[0-9]+]]:sgpr(s32) = G_SHL [[C1]], [[C3]](s32) + ; CHECK: [[OR:%[0-9]+]]:sreg_32(s32) = G_OR [[AND]], [[SHL]] + ; CHECK: [[S_BFE_I64_:%[0-9]+]]:sreg_64(s64) = S_BFE_I64 [[COPY]](s64), [[OR]](s32), implicit-def $scc + %0:_(s64) = COPY $sgpr0_sgpr1 + %1:_(s32) = G_CONSTANT i32 1 + %2:_(s32) = G_CONSTANT i32 10 + %3:_(s64) = G_SBFX %0, %1(s32), %2 +... Index: llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-ubfx.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-ubfx.mir @@ -0,0 +1,281 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect -regbankselect-fast -verify-machineinstrs -o - %s | FileCheck %s +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect -regbankselect-greedy -verify-machineinstrs -o - %s | FileCheck %s + +... + +# Generate the 3 operand vector bitfield extract instructions for 32-bit +# operations only. +--- +name: test_ubfx_s32_vvv +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0, $vgpr1, $vgpr2 + + ; CHECK-LABEL: name: test_ubfx_s32_vvv + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr2 + ; CHECK: [[UBFX:%[0-9]+]]:vgpr(s32) = G_UBFX [[COPY]], [[COPY1]](s32), [[COPY2]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = COPY $vgpr2 + %3:_(s32) = G_UBFX %0, %1(s32), %2 +... + +--- +name: test_ubfx_s32_vii +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0 + + ; CHECK-LABEL: name: test_ubfx_s32_vii + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 10 + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 4 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY [[C]](s32) + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[C1]](s32) + ; CHECK: [[UBFX:%[0-9]+]]:vgpr(s32) = G_UBFX [[COPY]], [[COPY1]](s32), [[COPY2]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = G_CONSTANT i32 10 + %2:_(s32) = G_CONSTANT i32 4 + %3:_(s32) = G_UBFX %0, %1(s32), %2 +... + +--- +name: test_ubfx_s32_vss +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0, $sgpr0, $sgpr1 + + ; CHECK-LABEL: name: test_ubfx_s32_vss + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY2]](s32) + ; CHECK: [[UBFX:%[0-9]+]]:vgpr(s32) = G_UBFX [[COPY]], [[COPY3]](s32), [[COPY4]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $sgpr0 + %2:_(s32) = COPY $sgpr1 + %3:_(s32) = G_UBFX %0, %1(s32), %2 +... + +# Expand to a sequence that implements the 64-bit bitfield extract using +# shifts and masks. +--- +name: test_ubfx_s64_vvv +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0_vgpr1, $vgpr2, $vgpr3 + + ; CHECK-LABEL: name: test_ubfx_s64_vvv + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s64) = COPY $vgpr0_vgpr1 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr2 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr3 + ; CHECK: [[C:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 0 + ; CHECK: [[MV:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY1]](s32) + ; CHECK: [[LSHR:%[0-9]+]]:vgpr(s64) = G_LSHR [[COPY]], [[MV]](s64) + ; CHECK: [[MV1:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY2]](s32) + ; CHECK: [[C1:%[0-9]+]]:vgpr(s64) = G_CONSTANT i64 1 + ; CHECK: [[SHL:%[0-9]+]]:vgpr(s64) = G_SHL [[C1]], [[MV1]](s64) + ; CHECK: [[UV:%[0-9]+]]:vgpr(s32), [[UV1:%[0-9]+]]:vgpr(s32) = G_UNMERGE_VALUES [[SHL]](s64) + ; CHECK: [[C2:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[USUBO:%[0-9]+]]:vgpr(s32), [[USUBO1:%[0-9]+]]:vcc(s1) = G_USUBO [[UV]], [[C2]] + ; CHECK: [[USUBE:%[0-9]+]]:vgpr(s32), [[USUBE1:%[0-9]+]]:vcc(s1) = G_USUBE [[UV1]], [[C2]], [[USUBO1]] + ; CHECK: [[MV2:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[USUBE]](s32), [[USUBO]](s32) + ; CHECK: [[AND:%[0-9]+]]:vgpr(s64) = G_AND [[LSHR]], [[MV2]] + %0:_(s64) = COPY $vgpr0_vgpr1 + %1:_(s32) = COPY $vgpr2 + %2:_(s32) = COPY $vgpr3 + %3:_(s64) = G_UBFX %0, %1(s32), %2 +... + +--- +name: test_ubfx_s64_vss +legalized: true + +body: | + bb.0.entry: + liveins: $vgpr0_vgpr1, $sgpr0, $sgpr1 + + ; CHECK-LABEL: name: test_ubfx_s64_vss + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s64) = COPY $vgpr0_vgpr1 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[C:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 0 + ; CHECK: [[MV:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY1]](s32) + ; CHECK: [[LSHR:%[0-9]+]]:vgpr(s64) = G_LSHR [[COPY]], [[MV]](s64) + ; CHECK: [[MV1:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY2]](s32) + ; CHECK: [[C1:%[0-9]+]]:vgpr(s64) = G_CONSTANT i64 1 + ; CHECK: [[SHL:%[0-9]+]]:vgpr(s64) = G_SHL [[C1]], [[MV1]](s64) + ; CHECK: [[UV:%[0-9]+]]:vgpr(s32), [[UV1:%[0-9]+]]:vgpr(s32) = G_UNMERGE_VALUES [[SHL]](s64) + ; CHECK: [[C2:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[USUBO:%[0-9]+]]:vgpr(s32), [[USUBO1:%[0-9]+]]:vcc(s1) = G_USUBO [[UV]], [[C2]] + ; CHECK: [[USUBE:%[0-9]+]]:vgpr(s32), [[USUBE1:%[0-9]+]]:vcc(s1) = G_USUBE [[UV1]], [[C2]], [[USUBO1]] + ; CHECK: [[MV2:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[USUBE]](s32), [[USUBO]](s32) + ; CHECK: [[AND:%[0-9]+]]:vgpr(s64) = G_AND [[LSHR]], [[MV2]] + %0:_(s64) = COPY $vgpr0_vgpr1 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = COPY $vgpr1 + %3:_(s64) = G_UBFX %0, %1(s32), %2 +... + +--- +name: test_ubfx_s64_svv +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0_sgpr1, $vgpr0, $vgpr1 + + ; CHECK-LABEL: name: test_ubfx_s64_svv + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s64) = COPY $sgpr0_sgpr1 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[COPY3:%[0-9]+]]:vgpr(s64) = COPY [[COPY]](s64) + ; CHECK: [[C:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 0 + ; CHECK: [[MV:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY1]](s32) + ; CHECK: [[LSHR:%[0-9]+]]:vgpr(s64) = G_LSHR [[COPY3]], [[MV]](s64) + ; CHECK: [[MV1:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[C]](s32), [[COPY2]](s32) + ; CHECK: [[C1:%[0-9]+]]:vgpr(s64) = G_CONSTANT i64 1 + ; CHECK: [[SHL:%[0-9]+]]:vgpr(s64) = G_SHL [[C1]], [[MV1]](s64) + ; CHECK: [[UV:%[0-9]+]]:vgpr(s32), [[UV1:%[0-9]+]]:vgpr(s32) = G_UNMERGE_VALUES [[SHL]](s64) + ; CHECK: [[C2:%[0-9]+]]:vgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[USUBO:%[0-9]+]]:vgpr(s32), [[USUBO1:%[0-9]+]]:vcc(s1) = G_USUBO [[UV]], [[C2]] + ; CHECK: [[USUBE:%[0-9]+]]:vgpr(s32), [[USUBE1:%[0-9]+]]:vcc(s1) = G_USUBE [[UV1]], [[C2]], [[USUBO1]] + ; CHECK: [[MV2:%[0-9]+]]:vgpr(s64) = G_MERGE_VALUES [[USUBE]](s32), [[USUBO]](s32) + ; CHECK: [[AND:%[0-9]+]]:vgpr(s64) = G_AND [[LSHR]], [[MV2]] + %0:_(s64) = COPY $sgpr0_sgpr1 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = COPY $vgpr1 + %3:_(s64) = G_UBFX %0, %1(s32), %2 +... + +# Expand to a sequence that combines the offset and width for the two operand +# version of the 32-bit instruction. +--- +name: test_ubfx_s32_svv +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0, $vgpr0, $vgpr1 + + ; CHECK-LABEL: name: test_ubfx_s32_svv + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) + ; CHECK: [[UBFX:%[0-9]+]]:vgpr(s32) = G_UBFX [[COPY3]], [[COPY1]](s32), [[COPY2]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = COPY $vgpr1 + %3:_(s32) = G_UBFX %0, %1(s32), %2 +... + +--- +name: test_ubfx_s32_sss +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2 + + ; CHECK-LABEL: name: test_ubfx_s32_sss + ; CHECK: [[COPY:%[0-9]+]]:sreg_32(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 63 + ; CHECK: [[AND:%[0-9]+]]:sgpr(s32) = G_AND [[COPY1]], [[C]] + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL:%[0-9]+]]:sgpr(s32) = G_SHL [[COPY2]], [[C1]](s32) + ; CHECK: [[OR:%[0-9]+]]:sreg_32(s32) = G_OR [[AND]], [[SHL]] + ; CHECK: [[S_BFE_U32_:%[0-9]+]]:sreg_32(s32) = S_BFE_U32 [[COPY]](s32), [[OR]](s32), implicit-def $scc + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $sgpr1 + %2:_(s32) = COPY $sgpr2 + %3:_(s32) = G_UBFX %0, %1(s32), %2 +... + +--- +name: test_ubfx_s32_sii +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2 + + ; CHECK-LABEL: name: test_ubfx_s32_sii + ; CHECK: [[COPY:%[0-9]+]]:sreg_32(s32) = COPY $sgpr0 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 10 + ; CHECK: [[C2:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 63 + ; CHECK: [[AND:%[0-9]+]]:sgpr(s32) = G_AND [[C]], [[C2]] + ; CHECK: [[C3:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL:%[0-9]+]]:sgpr(s32) = G_SHL [[C1]], [[C3]](s32) + ; CHECK: [[OR:%[0-9]+]]:sreg_32(s32) = G_OR [[AND]], [[SHL]] + ; CHECK: [[S_BFE_U32_:%[0-9]+]]:sreg_32(s32) = S_BFE_U32 [[COPY]](s32), [[OR]](s32), implicit-def $scc + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = G_CONSTANT i32 1 + %2:_(s32) = G_CONSTANT i32 10 + %3:_(s32) = G_UBFX %0, %1(s32), %2 +... + +# Expand to a sequence that combines the offset and width for the two operand +# version of the 64-bit scalar instruction. +--- +name: test_ubfx_s64_sss +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0_sgpr1, $sgpr2, $sgpr3 + + ; CHECK-LABEL: name: test_ubfx_s64_sss + ; CHECK: [[COPY:%[0-9]+]]:sreg_64(s64) = COPY $sgpr0_sgpr1 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 + ; CHECK: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 63 + ; CHECK: [[AND:%[0-9]+]]:sgpr(s32) = G_AND [[COPY1]], [[C]] + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL:%[0-9]+]]:sgpr(s32) = G_SHL [[COPY2]], [[C1]](s32) + ; CHECK: [[OR:%[0-9]+]]:sreg_32(s32) = G_OR [[AND]], [[SHL]] + ; CHECK: [[S_BFE_U64_:%[0-9]+]]:sreg_64(s64) = S_BFE_U64 [[COPY]](s64), [[OR]](s32), implicit-def $scc + %0:_(s64) = COPY $sgpr0_sgpr1 + %1:_(s32) = COPY $sgpr2 + %2:_(s32) = COPY $sgpr3 + %3:_(s64) = G_UBFX %0, %1(s32), %2 +... + +--- +name: test_ubfx_s64_sii +legalized: true + +body: | + bb.0.entry: + liveins: $sgpr0_sgpr1 + + ; CHECK-LABEL: name: test_ubfx_s64_sii + ; CHECK: [[COPY:%[0-9]+]]:sreg_64(s64) = COPY $sgpr0_sgpr1 + ; CHECK: [[C:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[C1:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 10 + ; CHECK: [[C2:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 63 + ; CHECK: [[AND:%[0-9]+]]:sgpr(s32) = G_AND [[C]], [[C2]] + ; CHECK: [[C3:%[0-9]+]]:sgpr(s32) = G_CONSTANT i32 16 + ; CHECK: [[SHL:%[0-9]+]]:sgpr(s32) = G_SHL [[C1]], [[C3]](s32) + ; CHECK: [[OR:%[0-9]+]]:sreg_32(s32) = G_OR [[AND]], [[SHL]] + ; CHECK: [[S_BFE_U64_:%[0-9]+]]:sreg_64(s64) = S_BFE_U64 [[COPY]](s64), [[OR]](s32), implicit-def $scc + %0:_(s64) = COPY $sgpr0_sgpr1 + %1:_(s32) = G_CONSTANT i32 1 + %2:_(s32) = G_CONSTANT i32 10 + %3:_(s64) = G_UBFX %0, %1(s32), %2 +...