[llvm] [IR][CodeGen] Add llvm.is.debugging.enabled intrinsic (PR #219175)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 04:45:03 PDT 2026
Alexander =?utf-8?q?Hück?= <alexander.huck at amd.com>,
Alexander =?utf-8?q?Hück?= <alexander.huck at amd.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/219175 at github.com>
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Alexander Hück (ahueck)
<details>
<summary>Changes</summary>
This is PR 2 of 4 in a series adding llvm.is.debugging.enabled intrinsic to LLVM IR and lowering this intrinsic for AMDGPU targets, see [[[RFC] Introduce `llvm.is.debugging.enabled` intrinsic](https://discourse.llvm.org/t/rfc-introduce-llvm-is-debugging-enabled-intrinsic/91676)
## Changes of this PR
- Add llvm.is.debugging.enabled, an intrinsic reporting whether debugging is enabled for the target-defined execution context. Each call is a distinct observation, so calls must not be removed, commoned, or reordered with one another.
- Add TargetMachine::canLowerIsDebuggingEnabled(), defaulting to false. Pre-ISel intrinsic lowering replaces the intrinsic with false unless the target opts in. No target does so in this PR.
PR 3 adds the AMDGPU implementation.
## PR stack
1. [[AMDGPU][GlobalISel][SelectionDAG] Refactor control-flow intrinsic branch matching](https://github.com/llvm/llvm-project/pull/219173)
2. [[IR][CodeGen] Add llvm.is.debugging.enabled intrinsic](https://github.com/llvm/llvm-project/pull/219175)
3. [[AMDGPU][GFX12/GFX13] Add cdbg branch support and lower llvm.is.debugging.enabled](https://github.com/llvm/llvm-project/pull/219178)
4. [[AMDGPU] Add AMDPAL support for llvm.debugtrap](https://github.com/llvm/llvm-project/pull/219179)
*Disclaimer*: Agentic AI assisted development.
---
Patch is 28.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/219175.diff
17 Files Affected:
- (modified) llvm/docs/LangRef.md (+30)
- (modified) llvm/include/llvm/IR/Intrinsics.td (+6)
- (modified) llvm/include/llvm/Target/TargetMachine.h (+7)
- (modified) llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp (+8)
- (modified) llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp (+71-63)
- (modified) llvm/lib/Target/AMDGPU/SIISelLowering.cpp (+81-43)
- (added) llvm/test/Assembler/is-debugging-enabled.ll (+11)
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-amdgcn.if-invalid.mir (+26-1)
- (added) llvm/test/CodeGen/NVPTX/is-debugging-enabled.ll (+11)
- (added) llvm/test/CodeGen/X86/is-debugging-enabled.ll (+12)
- (added) llvm/test/Transforms/DCE/is-debugging-enabled.ll (+12)
- (added) llvm/test/Transforms/EarlyCSE/is-debugging-enabled.ll (+17)
- (added) llvm/test/Transforms/LICM/is-debugging-enabled.ll (+25)
- (added) llvm/test/Transforms/LoopUnroll/is-debugging-enabled.ll (+30)
- (added) llvm/test/Transforms/PreISelIntrinsicLowering/is-debugging-enabled.ll (+13)
- (added) llvm/test/Transforms/SimplifyCFG/is-debugging-enabled.ll (+58)
- (added) llvm/test/Verifier/is-debugging-enabled.ll (+15)
``````````diff
diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index ee1600b96f1dd..9f2ab993f3a80 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -26263,6 +26263,36 @@ This intrinsic is lowered to code which is intended to cause an
execution trap with the intention of requesting the attention of a
debugger.
+(llvm.is.debugging.enabled)=
+
+#### '`llvm.is.debugging.enabled`' Intrinsic
+
+##### Syntax:
+
+```llvm
+declare noundef i1 @llvm.is.debugging.enabled() nomerge memory(inaccessiblemem: readwrite)
+```
+
+##### Overview:
+
+The '`llvm.is.debugging.enabled`' intrinsic returns whether debugging is enabled
+for the target-defined execution context of the current invocation.
+
+##### Arguments:
+
+None.
+
+##### Semantics:
+
+Each call observes the current debugging-enabled state. Calls are distinct
+observations: LLVM must not assume separate calls return the same value, and a
+call may not be removed when its result is unused, commoned with another call,
+or reordered with respect to one.
+
+On targets that do not support querying debugging-enabled state, the intrinsic
+returns `false` and performs no observation.
+
+
(llvm.ubsantrap)=
#### '`llvm.ubsantrap`' Intrinsic
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index c20ea64c7eef4..b14375e277e7a 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -2059,6 +2059,12 @@ def int_trap : Intrinsic<[], [],
ClangBuiltin<"__builtin_trap">;
def int_debugtrap : Intrinsic<[]>,
ClangBuiltin<"__builtin_debugtrap">;
+// Query whether debugging is enabled for the current execution context.
+def int_is_debugging_enabled :
+ DefaultAttrsIntrinsic<[llvm_i1_ty], [],
+ [IntrInaccessibleMemOnly,
+ IntrNoMerge,
+ NoUndef<RetIndex>]>;
def int_ubsantrap : Intrinsic<[], [llvm_i8_ty],
[IntrNoReturn, IntrCold, ImmArg<ArgIndex<0>>,
IntrInaccessibleMemOnly, IntrWriteMem]>;
diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index a6b73d636dc27..ea26be5e48bfb 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -567,6 +567,13 @@ class LLVM_ABI TargetMachine {
/// this function returns false, the intrinsic will be supported generically
/// but without loop detection support.
virtual bool canLowerCondLoop() const { return false; }
+
+ /// Returns whether this target takes responsibility for lowering
+ /// llvm.is.debugging.enabled. If false, generic lowering replaces the intrinsic
+ /// with false. If true, the target must handle every supported subtarget,
+ /// including replacing the intrinsic with false on subtargets without native
+ /// lowering.
+ virtual bool canLowerIsDebuggingEnabled() const { return false; }
};
} // end namespace llvm
diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
index 24788148b9f15..4ec866d7b973f 100644
--- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
+++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
@@ -815,6 +815,14 @@ bool PreISelIntrinsicLowering::lowerIntrinsics(Module &M) const {
case Intrinsic::protected_field_ptr:
Changed |= expandProtectedFieldPtr(F);
break;
+ case Intrinsic::is_debugging_enabled:
+ if (!TM || !TM->canLowerIsDebuggingEnabled())
+ Changed |= forEachCall(F, [](CallInst *CI) {
+ CI->replaceAllUsesWith(ConstantInt::getFalse(CI->getContext()));
+ CI->eraseFromParent();
+ return true;
+ });
+ break;
case Intrinsic::cond_loop:
if (!TM->canLowerCondLoop())
Changed |= expandCondLoop(F);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index 7c1a26f761c96..0f0812a5cac36 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -4804,47 +4804,77 @@ static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI) {
return ConstVal == -1;
}
-// Return the use branch instruction, otherwise null if the usage is invalid.
-static MachineInstr *
-verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br,
- MachineBasicBlock *&UncondBrTarget, bool &Negated) {
+namespace {
+struct CFIntrinsicBranchMatch {
+ MachineInstr *Negation = nullptr;
+ MachineInstr *CondBr = nullptr;
+ MachineInstr *UncondBr = nullptr;
+
+ MachineBasicBlock *ConditionTrueTarget = nullptr;
+ MachineBasicBlock *ConditionFalseTarget = nullptr;
+
+ bool isNegated() const { return Negation != nullptr; }
+
+ // Retarget the explicit branch for the fallthrough edge, or materialize
+ // the branch when that edge was represented by layout fallthrough. The
+ // builder must be positioned at the replacement branch.
+ void redirectFallthroughEdge(MachineIRBuilder &B,
+ MachineBasicBlock &Target) const {
+ if (UncondBr)
+ UncondBr->getOperand(0).setMBB(&Target);
+ else
+ B.buildBr(Target);
+ }
+
+ void eraseDeadNegation(MachineRegisterInfo &MRI) {
+ if (Negation)
+ eraseInstr(*Negation, MRI);
+ }
+};
+} // namespace
+
+static std::optional<CFIntrinsicBranchMatch>
+matchCFIntrinsicBranchUse(MachineInstr &MI, MachineRegisterInfo &MRI) {
Register CondDef = MI.getOperand(0).getReg();
if (!MRI.hasOneNonDBGUse(CondDef))
- return nullptr;
+ return std::nullopt;
MachineBasicBlock *Parent = MI.getParent();
MachineInstr *UseMI = &*MRI.use_instr_nodbg_begin(CondDef);
+ MachineInstr *Negation = nullptr;
if (isNot(MRI, *UseMI)) {
+ Negation = UseMI;
Register NegatedCond = UseMI->getOperand(0).getReg();
if (!MRI.hasOneNonDBGUse(NegatedCond))
- return nullptr;
-
- // We're deleting the def of this value, so we need to remove it.
- eraseInstr(*UseMI, MRI);
+ return std::nullopt;
UseMI = &*MRI.use_instr_nodbg_begin(NegatedCond);
- Negated = true;
}
if (UseMI->getParent() != Parent || UseMI->getOpcode() != AMDGPU::G_BRCOND)
- return nullptr;
+ return std::nullopt;
// Make sure the cond br is followed by a G_BR, or is the last instruction.
+ MachineInstr *UncondBr = nullptr;
+ MachineBasicBlock *OtherTarget = nullptr;
MachineBasicBlock::iterator Next = std::next(UseMI->getIterator());
if (Next == Parent->end()) {
MachineFunction::iterator NextMBB = std::next(Parent->getIterator());
if (NextMBB == Parent->getParent()->end()) // Illegal intrinsic use.
- return nullptr;
- UncondBrTarget = &*NextMBB;
+ return std::nullopt;
+ OtherTarget = &*NextMBB;
} else {
if (Next->getOpcode() != AMDGPU::G_BR)
- return nullptr;
- Br = &*Next;
- UncondBrTarget = Br->getOperand(0).getMBB();
+ return std::nullopt;
+ UncondBr = &*Next;
+ OtherTarget = UncondBr->getOperand(0).getMBB();
}
- return UseMI;
+ MachineBasicBlock *TakenTarget = UseMI->getOperand(1).getMBB();
+ return CFIntrinsicBranchMatch{Negation, UseMI, UncondBr,
+ Negation ? OtherTarget : TakenTarget,
+ Negation ? TakenTarget : OtherTarget};
}
void AMDGPULegalizerInfo::buildLoadInputValue(Register DstReg,
@@ -8230,80 +8260,58 @@ bool AMDGPULegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
return true;
case Intrinsic::amdgcn_if:
case Intrinsic::amdgcn_else: {
- MachineInstr *Br = nullptr;
- MachineBasicBlock *UncondBrTarget = nullptr;
- bool Negated = false;
- if (MachineInstr *BrCond =
- verifyCFIntrinsic(MI, MRI, Br, UncondBrTarget, Negated)) {
- const SIRegisterInfo *TRI
- = static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
+ if (auto Match = matchCFIntrinsicBranchUse(MI, MRI)) {
+ const SIRegisterInfo *TRI =
+ static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
Register Def = MI.getOperand(1).getReg();
Register Use = MI.getOperand(3).getReg();
- MachineBasicBlock *CondBrTarget = BrCond->getOperand(1).getMBB();
-
- if (Negated)
- std::swap(CondBrTarget, UncondBrTarget);
-
- B.setInsertPt(B.getMBB(), BrCond->getIterator());
+ B.setInsertPt(B.getMBB(), Match->CondBr->getIterator());
if (IntrID == Intrinsic::amdgcn_if) {
B.buildInstr(AMDGPU::SI_IF)
- .addDef(Def)
- .addUse(Use)
- .addMBB(UncondBrTarget);
+ .addDef(Def)
+ .addUse(Use)
+ .addMBB(Match->ConditionFalseTarget);
} else {
B.buildInstr(AMDGPU::SI_ELSE)
.addDef(Def)
.addUse(Use)
- .addMBB(UncondBrTarget);
+ .addMBB(Match->ConditionFalseTarget);
}
- if (Br) {
- Br->getOperand(0).setMBB(CondBrTarget);
- } else {
- // The IRTranslator skips inserting the G_BR for fallthrough cases, but
- // since we're swapping branch targets it needs to be reinserted.
- // FIXME: IRTranslator should probably not do this
- B.buildBr(*CondBrTarget);
- }
+ // The IRTranslator skips inserting the G_BR for fallthrough cases, but
+ // since we're swapping branch targets it needs to be reinserted.
+ // FIXME: IRTranslator should probably not do this
+ Match->redirectFallthroughEdge(B, *Match->ConditionTrueTarget);
MRI.setRegClass(Def, TRI->getWaveMaskRegClass());
MRI.setRegClass(Use, TRI->getWaveMaskRegClass());
+ Match->eraseDeadNegation(MRI);
MI.eraseFromParent();
- BrCond->eraseFromParent();
+ Match->CondBr->eraseFromParent();
return true;
}
return false;
}
case Intrinsic::amdgcn_loop: {
- MachineInstr *Br = nullptr;
- MachineBasicBlock *UncondBrTarget = nullptr;
- bool Negated = false;
- if (MachineInstr *BrCond =
- verifyCFIntrinsic(MI, MRI, Br, UncondBrTarget, Negated)) {
- const SIRegisterInfo *TRI
- = static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
-
- MachineBasicBlock *CondBrTarget = BrCond->getOperand(1).getMBB();
- Register Reg = MI.getOperand(2).getReg();
+ if (auto Match = matchCFIntrinsicBranchUse(MI, MRI)) {
+ const SIRegisterInfo *TRI =
+ static_cast<const SIRegisterInfo *>(MRI.getTargetRegisterInfo());
- if (Negated)
- std::swap(CondBrTarget, UncondBrTarget);
+ Register Reg = MI.getOperand(2).getReg();
- B.setInsertPt(B.getMBB(), BrCond->getIterator());
+ B.setInsertPt(B.getMBB(), Match->CondBr->getIterator());
B.buildInstr(AMDGPU::SI_LOOP)
- .addUse(Reg)
- .addMBB(UncondBrTarget);
+ .addUse(Reg)
+ .addMBB(Match->ConditionFalseTarget);
- if (Br)
- Br->getOperand(0).setMBB(CondBrTarget);
- else
- B.buildBr(*CondBrTarget);
+ Match->redirectFallthroughEdge(B, *Match->ConditionTrueTarget);
+ Match->eraseDeadNegation(MRI);
MI.eraseFromParent();
- BrCond->eraseFromParent();
+ Match->CondBr->eraseFromParent();
MRI.setRegClass(Reg, TRI->getWaveMaskRegClass());
return true;
}
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index d9810e3d9fbd9..86cfd885c4f8f 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -8584,6 +8584,72 @@ static SDNode *findUser(SDValue Value, unsigned Opcode) {
return nullptr;
}
+namespace {
+struct BRCONDMatch {
+ SDValue CondBr;
+ SDValue Condition;
+ SDValue ConditionWrapper;
+ SDNode *UncondBr = nullptr;
+
+ SDValue ConditionTrueTarget;
+ SDValue ConditionFalseTarget;
+
+ void redirectFallthroughEdge(SelectionDAG &DAG, SDValue Target) const {
+ if (UncondBr->getOperand(1) == Target)
+ return;
+
+ SDValue NewBr = DAG.getNode(ISD::BR, SDLoc(CondBr), UncondBr->getVTList(),
+ {UncondBr->getOperand(0), Target});
+ DAG.ReplaceAllUsesWith(UncondBr, NewBr.getNode());
+ }
+};
+} // namespace
+
+static std::optional<BRCONDMatch> matchBRCOND(SDValue CondBr) {
+ if (CondBr.getOpcode() != ISD::BRCOND)
+ return std::nullopt;
+
+ SDValue Condition = CondBr.getOperand(1);
+ SDValue ConditionWrapper;
+ bool IsNegated = false;
+
+ switch (Condition.getOpcode()) {
+ case ISD::SETCC: {
+ ISD::CondCode CC = cast<CondCodeSDNode>(Condition.getOperand(2))->get();
+ if (auto *C = dyn_cast<ConstantSDNode>(Condition.getOperand(1));
+ C && (CC == ISD::SETEQ || CC == ISD::SETNE)) {
+ IsNegated = (CC == ISD::SETEQ) == (C->getZExtValue() == 0);
+ ConditionWrapper = Condition;
+ Condition = Condition.getOperand(0);
+ }
+ break;
+ }
+ case ISD::XOR:
+ if (auto *C = dyn_cast<ConstantSDNode>(Condition.getOperand(1));
+ C && C->getZExtValue()) {
+ ConditionWrapper = Condition;
+ Condition = Condition.getOperand(0);
+ IsNegated = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ SDNode *UncondBr = findUser(CondBr, ISD::BR);
+ if (!UncondBr)
+ return std::nullopt;
+
+ SDValue TakenTarget = CondBr.getOperand(2);
+ SDValue OtherTarget = UncondBr->getOperand(1);
+ return BRCONDMatch{CondBr,
+ Condition,
+ ConditionWrapper,
+ UncondBr,
+ IsNegated ? OtherTarget : TakenTarget,
+ IsNegated ? TakenTarget : OtherTarget};
+}
+
unsigned SITargetLowering::isCFIntrinsic(const SDNode *Intr) const {
if (Intr->getOpcode() == ISD::INTRINSIC_W_CHAIN) {
switch (Intr->getConstantOperandVal(1)) {
@@ -8650,37 +8716,12 @@ bool SITargetLowering::shouldUseLDSConstAddress(const GlobalValue *GV) const {
/// This transforms the control flow intrinsics to get the branch destination as
/// last parameter, also switches branch target with BR if the need arise
SDValue SITargetLowering::LowerBRCOND(SDValue BRCOND, SelectionDAG &DAG) const {
- SDLoc DL(BRCOND);
+ auto Match = matchBRCOND(BRCOND);
+ if (!Match)
+ return BRCOND;
- SDNode *Intr = BRCOND.getOperand(1).getNode();
- SDValue Target = BRCOND.getOperand(2);
- SDNode *BR = nullptr;
- SDNode *SetCC = nullptr;
-
- switch (Intr->getOpcode()) {
- case ISD::SETCC: {
- // As long as we negate the condition everything is fine
- SetCC = Intr;
- Intr = SetCC->getOperand(0).getNode();
- break;
- }
- case ISD::XOR: {
- // Similar to SETCC, if we have (xor c, -1), we will be fine.
- SDValue LHS = Intr->getOperand(0);
- SDValue RHS = Intr->getOperand(1);
- if (auto *C = dyn_cast<ConstantSDNode>(RHS); C && C->getZExtValue()) {
- Intr = LHS.getNode();
- break;
- }
- [[fallthrough]];
- }
- default: {
- // Get the target from BR if we don't negate the condition
- BR = findUser(BRCOND, ISD::BR);
- assert(BR && "brcond missing unconditional branch user");
- Target = BR->getOperand(1);
- }
- }
+ SDLoc DL(Match->CondBr);
+ SDNode *Intr = Match->Condition.getNode();
unsigned CFNode = isCFIntrinsic(Intr);
if (CFNode == 0) {
@@ -8691,18 +8732,20 @@ SDValue SITargetLowering::LowerBRCOND(SDValue BRCOND, SelectionDAG &DAG) const {
bool HaveChain = Intr->getOpcode() == ISD::INTRINSIC_VOID ||
Intr->getOpcode() == ISD::INTRINSIC_W_CHAIN;
- assert(!SetCC ||
- (SetCC->getConstantOperandVal(1) == 1 &&
- cast<CondCodeSDNode>(SetCC->getOperand(2).getNode())->get() ==
- ISD::SETNE));
+ assert((!Match->ConditionWrapper ||
+ Match->ConditionWrapper.getOpcode() != ISD::SETCC ||
+ (Match->ConditionWrapper.getConstantOperandVal(1) == 1 &&
+ cast<CondCodeSDNode>(Match->ConditionWrapper.getOperand(2).getNode())
+ ->get() == ISD::SETNE)) &&
+ "unexpected control flow intrinsic condition wrapper");
// operands of the new intrinsic call
SmallVector<SDValue, 4> Ops;
if (HaveChain)
- Ops.push_back(BRCOND.getOperand(0));
+ Ops.push_back(Match->CondBr.getOperand(0));
Ops.append(Intr->op_begin() + (HaveChain ? 2 : 1), Intr->op_end());
- Ops.push_back(Target);
+ Ops.push_back(Match->ConditionFalseTarget);
ArrayRef<EVT> Res(Intr->value_begin() + 1, Intr->value_end());
@@ -8710,17 +8753,12 @@ SDValue SITargetLowering::LowerBRCOND(SDValue BRCOND, SelectionDAG &DAG) const {
SDNode *Result = DAG.getNode(CFNode, DL, DAG.getVTList(Res), Ops).getNode();
if (!HaveChain) {
- SDValue Ops[] = {SDValue(Result, 0), BRCOND.getOperand(0)};
+ SDValue Ops[] = {SDValue(Result, 0), Match->CondBr.getOperand(0)};
Result = DAG.getMergeValues(Ops, DL).getNode();
}
- if (BR) {
- // Give the branch instruction our target
- SDValue Ops[] = {BR->getOperand(0), BRCOND.getOperand(2)};
- SDValue NewBR = DAG.getNode(ISD::BR, DL, BR->getVTList(), Ops);
- DAG.ReplaceAllUsesWith(BR, NewBR.getNode());
- }
+ Match->redirectFallthroughEdge(DAG, Match->ConditionTrueTarget);
SDValue Chain = SDValue(Result, Result->getNumValues() - 1);
diff --git a/llvm/test/Assembler/is-debugging-enabled.ll b/llvm/test/Assembler/is-debugging-enabled.ll
new file mode 100644
index 0000000000000..a48d002373e38
--- /dev/null
+++ b/llvm/test/Assembler/is-debugging-enabled.ll
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+
+define i1 @query_debugging_enabled() {
+ %enabled = call i1 @llvm.is.debugging.enabled()
+ ret i1 %enabled
+}
+
+; CHECK: declare noundef i1 @llvm.is.debugging.enabled() #[[ATTRS:[0-9]+]]
+; CHECK: attributes #[[ATTRS]] = { nocallback nofree nomerge nosync nounwind willreturn memory(inaccessiblemem: readwrite) }
+
+declare i1 @llvm.is.debugging.enabled()
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-amdgcn.if-invalid.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-amdgcn.if-invalid.mir
index d351eb6a57446..77040216daca8 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-amdgcn.if-invalid.mir
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-amdgcn.if-invalid.mir
@@ -1,4 +1,5 @@
# RUN: llc -mtriple=amdgpu8.03-mesa-mesa3d -O0 -run-pass=legalizer -global-isel-abort=2 -pass-remarks-missed='gisel*' -filetype=null %s 2>&1 | FileCheck -check-prefix=ERR %s
+# RUN: llc -mtriple=amdgpu8.03-mesa-mesa3d -O0 -run-pass=legalizer -global-isel-abort=0 %s -o - | FileCheck -check-prefix=MIR %s
# Make sure incorrect usage of control flow intrinsics fails to select in case some transform separated the intrinsic from its branch.
@@ -8,7 +9,7 @@
# ERR-NEXT: remark: <unknown>:0:0: unable to legalize instruction: %3:_(s1), %4:_(s64) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.amdgcn.if), %2:_(s1) (in function: brcond_si_if_xor_0)
# ERR-NEXT: remark: <unknown>:0:0: unable to legalize instruction: %3:_(s1), %4:_(s64) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.amdgcn.if), %2:_(s1) (in function: brcond_si_if_or_neg1)
# ERR-NEXT: remark: <unknown>:0:0: unable to legalize instruction: %3:_(s1), %4:_(s64) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.amdgcn.if), %2:_(s1) (in function: brcond_si_if_negated_multi_use)
-
+# ERR-NEXT: remark: <unknown>:0:0: unable to legalize instruction: %3:_(s1), %4:_(s64) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.amdgcn.if), %2:_(s1) (in function: si_if_negated_invalid_branch_layout)
---
name: brcond_si_if_different_block
@@ -134,3 +135,27 @@ body: |
bb.3:
S_NOP 2
...
+
+# A failed match after recognizing the negation must not modify the MIR.
+# MIR-LABEL: name: si_if_negated_invalid_branch_layout
+# MIR: [[NOT:%[0-9]+]]:_(s1) = G_XOR
+# MIR-NEXT: G_BRCOND [[NOT]](s1), %bb.1
+# MIR-NEXT: S_ENDPGM 0
+---
+name: si_if_negated_invalid_branch_layout
+body: |
+ bb.0:
+ successors: %bb.1
+ liveins: $vgpr0, $vgpr1
+ %0:_(s32) = COPY $vgpr0
+ %1:_(s32) = COPY $vgpr1
+ %2:_(s1) = G_ICMP intpred(ne), %0, %1
+ %3:_(s1), %4:_(s64) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.amdgcn.if), %2
+ %5:_(s1) = G_CONSTANT i1 true
+ %6:_(s1) = G_XOR %3, %5
+ G_BRCOND %6, %bb.1
+ S_ENDPGM 0
+
+ bb.1:
+ S_ENDPGM 0
+...
diff --git a/llvm/test/CodeGen/NVPTX/is-debugging-enabled.ll b/llvm/test/CodeGen/NVPTX/is-debugging-enabled.ll
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/219175
More information about the llvm-commits
mailing list