Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -1261,6 +1261,28 @@ break; } + case TargetOpcode::G_EXTRACT: { + const MachineOperand &SrcOp = MI->getOperand(1); + if (!SrcOp.isReg()) { + report("extract source must be a register", MI); + break; + } + + const MachineOperand &OffsetOp = MI->getOperand(2); + if (!OffsetOp.isImm()) { + report("extract offset must be a constant", MI); + break; + } + + unsigned DstSize = MRI->getType(MI->getOperand(0).getReg()).getSizeInBits(); + unsigned SrcSize = MRI->getType(SrcOp.getReg()).getSizeInBits(); + if (SrcSize == DstSize) + report("extract source must be larger than result", MI); + + if (DstSize + OffsetOp.getImm() > SrcSize) + report("extract reads past end of register", MI); + break; + } default: break; } Index: test/CodeGen/AMDGPU/GlobalISel/legalize-extract.mir =================================================================== --- test/CodeGen/AMDGPU/GlobalISel/legalize-extract.mir +++ test/CodeGen/AMDGPU/GlobalISel/legalize-extract.mir @@ -197,11 +197,11 @@ bb.0: ; CHECK-LABEL: name: extract_s8_v5s1_offset4 ; CHECK: [[DEF:%[0-9]+]]:_(<5 x s16>) = G_IMPLICIT_DEF - ; CHECK: [[EXTRACT:%[0-9]+]]:_(s16) = G_EXTRACT [[DEF]](<5 x s16>), 80 + ; CHECK: [[EXTRACT:%[0-9]+]]:_(s16) = G_EXTRACT [[DEF]](<5 x s16>), 64 ; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[EXTRACT]](s16) ; CHECK: $vgpr0 = COPY [[ANYEXT]](s32) %0:_(<5 x s1>) = G_IMPLICIT_DEF - %1:_(s1) = G_EXTRACT %0, 5 + %1:_(s1) = G_EXTRACT %0, 4 %2:_(s32) = G_ANYEXT %1 $vgpr0 = COPY %2 ... Index: test/Verifier/test_g_extract.mir =================================================================== --- /dev/null +++ test/Verifier/test_g_extract.mir @@ -0,0 +1,35 @@ +# RUN: not llc -march=aarch64 -o /dev/null -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# REQUIRES: global-isel, aarch64-registered-target + +--- +name: test_extract +legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +liveins: +body: | + bb.0: + + ; CHECK: Bad machine code: Too few operands + %0:_(s32) = G_EXTRACT + + ; CHECK: Bad machine code: Too few operands + %1:_(s32) = G_EXTRACT 0 + + ; CHECK: Bad machine code: extract source must be a register + %2:_(s32) = G_EXTRACT 0, 1 + + ; CHECK: Bad machine code: extract offset must be a constant + %3:_(s32) = G_IMPLICIT_DEF + %4:_(s32) = G_CONSTANT i32 0 + %5:_(s16) = G_EXTRACT %3, %4 + + ; CHECK: Bad machine code: extract source must be larger than result + %6:_(s32) = G_IMPLICIT_DEF + %7:_(s32) = G_EXTRACT %6, 0 + + ; CHECK: Bad machine code: extract reads past end of register + %8:_(s1) = G_EXTRACT %6, 32 + +...