Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -1332,6 +1332,35 @@ report("G_BRJT src operand 2 must be a scalar reg type", MI); break; } + case TargetOpcode::G_INTRINSIC: + case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: { + // TODO: Should verify number of def and use operands, but the current + // interface requires passing in IR types for mangling. + const MachineOperand &IntrIDOp = MI->getOperand(MI->getNumExplicitDefs()); + if (!IntrIDOp.isIntrinsicID()) { + report("G_INTRINSIC first src operand must be an intrinsic ID", MI); + break; + } + + bool NoSideEffects = MI->getOpcode() == TargetOpcode::G_INTRINSIC; + unsigned IntrID = IntrIDOp.getIntrinsicID(); + if (IntrID != 0 && IntrID < Intrinsic::num_intrinsics) { + AttributeList Attrs + = Intrinsic::getAttributes(MF->getFunction().getContext(), + static_cast(IntrID)); + bool DeclHasSideEffects = !Attrs.hasFnAttribute(Attribute::ReadNone); + if (NoSideEffects && DeclHasSideEffects) { + report("G_INTRINSIC used with intrinsic that accesses memory", MI); + break; + } + if (!NoSideEffects && !DeclHasSideEffects) { + report("G_INTRINSIC_W_SIDE_EFFECTS used with readnone intrinsic", MI); + break; + } + } + + break; + } default: break; } Index: test/MachineVerifier/test_g_intrinsic.mir =================================================================== --- /dev/null +++ test/MachineVerifier/test_g_intrinsic.mir @@ -0,0 +1,38 @@ +# RUN: not llc -o - -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# REQUIRES: amdgpu-registered-target + +--- +name: test_intrinsic +legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +liveins: +body: | + bb.0: + + %0:_(p3) = G_IMPLICIT_DEF + %1:_(s32) = G_IMPLICIT_DEF + + ; CHECK: Bad machine code: Too few operands + G_INTRINSIC + + ; CHECK: Bad machine code: G_INTRINSIC first src operand must be an intrinsic ID + G_INTRINSIC 0 + + ; CHECK: Bad machine code: G_INTRINSIC first src operand must be an intrinsic ID + G_INTRINSIC %0, %1 + + ; CHECK: Bad machine code: G_INTRINSIC first src operand must be an intrinsic ID + %2:_(s32) = G_INTRINSIC %0, %1 + + ; CHECK: Bad machine code: G_INTRINSIC first src operand must be an intrinsic ID + %3:_(s32), %4:_(s32) = G_INTRINSIC %0, %1 + + ; CHECK: Bad machine code: G_INTRINSIC used with intrinsic that accesses memory + G_INTRINSIC intrinsic(@llvm.amdgcn.s.barrier) + + ; CHECK: Bad machine code: G_INTRINSIC used with intrinsic that accesses memory + %3:_(s32) = G_INTRINSIC intrinsic(@llvm.amdgcn.ds.append), %0, 1 + +... Index: test/MachineVerifier/test_g_intrinsic_w_side_effects.mir =================================================================== --- /dev/null +++ test/MachineVerifier/test_g_intrinsic_w_side_effects.mir @@ -0,0 +1,35 @@ +# RUN: not llc -o - -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# REQUIRES: amdgpu-registered-target + +--- +name: test_intrinsic_w_side_effects +legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +liveins: +body: | + bb.0: + + %0:_(p3) = G_IMPLICIT_DEF + %1:_(s32) = G_IMPLICIT_DEF + + ; CHECK: Bad machine code: Too few operands + G_INTRINSIC + + ; CHECK: Bad machine code: G_INTRINSIC first src operand must be an intrinsic ID + G_INTRINSIC_W_SIDE_EFFECTS 0 + + ; CHECK: Bad machine code: G_INTRINSIC first src operand must be an intrinsic ID + G_INTRINSIC_W_SIDE_EFFECTS %0, %1 + + ; CHECK: Bad machine code: G_INTRINSIC first src operand must be an intrinsic ID + %2:_(s32) = G_INTRINSIC %0, %1 + + ; CHECK: Bad machine code: G_INTRINSIC first src operand must be an intrinsic ID + %3:_(s32), %4:_(s32) = G_INTRINSIC_W_SIDE_EFFECTS %0, %1 + + ; CHECK: Bad machine code: G_INTRINSIC_W_SIDE_EFFECTS used with readnone intrinsic + %5:_(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.amdgcn.rcp), %1 + +...