[clang] [llvm] [AMDGPU] Fix assertion failure isReg() in SIPreEmitPeephole (PR #176590)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 17 11:59:38 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: Serosh (Serosh-commits)
<details>
<summary>Changes</summary>
Fixes #<!-- -->176578.
The [optimizeVccBranch]
(llvm-project/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp:104:0-280:1) function was triggering an assertion failure because it attempted to call `getReg()` on an operand without first verifying it was a register. This occurred when the instruction used an immediate value (like a constant mask).
I updated the code to check `isReg()` before accessing the operand. This prevents the crash by safely skipping non-register operands.
I verified the fix using the reproduction IR from the issue, and it now compiles successfully.
---
Full diff: https://github.com/llvm/llvm-project/pull/176590.diff
4 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+11-9)
- (added) clang/test/AST/ByteCode/gh176549.cpp (+8)
- (modified) llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp (+3-2)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+42)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 21f8db06919ed..66b0cc4b5f6ab 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1083,20 +1083,22 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
if (Op == BO_Add) {
if (!this->emitAddOffset(OffsetType, E))
return false;
-
- if (classifyPrim(E) != PT_Ptr)
- return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);
- return true;
- }
- if (Op == BO_Sub) {
+ } else if (Op == BO_Sub) {
if (!this->emitSubOffset(OffsetType, E))
return false;
+ } else {
+ return false;
+ }
- if (classifyPrim(E) != PT_Ptr)
- return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);
- return true;
+ if (classifyPrim(E) != PT_Ptr) {
+ if (!this->emitDecayPtr(PT_Ptr, classifyPrim(E), E))
+ return false;
}
+ if (DiscardResult)
+ return this->emitPop(classifyPrim(E), E);
+ return true;
+
return false;
}
diff --git a/clang/test/AST/ByteCode/gh176549.cpp b/clang/test/AST/ByteCode/gh176549.cpp
new file mode 100644
index 0000000000000..b56f762b7ede4
--- /dev/null
+++ b/clang/test/AST/ByteCode/gh176549.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
+// expected-no-diagnostics
+
+const char a[4] = "abc";
+void foo() {
+ int i = 0;
+ i = 1 > (a + 1, sizeof(a));
+}
diff --git a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
index 8785968569d92..d15f89fdc78fc 100644
--- a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
@@ -153,11 +153,12 @@ bool SIPreEmitPeephole::optimizeVccBranch(MachineInstr &MI) const {
MachineOperand &Op1 = A->getOperand(1);
MachineOperand &Op2 = A->getOperand(2);
- if (Op1.getReg() != ExecReg && Op2.isReg() && Op2.getReg() == ExecReg) {
+ if ((!Op1.isReg() || Op1.getReg() != ExecReg) && Op2.isReg() &&
+ Op2.getReg() == ExecReg) {
TII->commuteInstruction(*A);
Changed = true;
}
- if (Op1.getReg() != ExecReg)
+ if (!Op1.isReg() || Op1.getReg() != ExecReg)
return Changed;
if (Op2.isImm() && !(Op2.getImm() == -1 || Op2.getImm() == 0))
return Changed;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index aacb2e2a91c57..80a7f0de363f0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3612,6 +3612,48 @@ Value *InstCombinerImpl::foldBooleanAndOr(Value *LHS, Value *RHS,
if (Value *Res = foldEqOfParts(LHS, RHS, IsAnd))
return Res;
+ // Handle reassociation-like folding: (A op B) op C --> A op (B op C)
+ // where B and C are ICmps and can be folded.
+ // This handles patterns like:
+ // select (and %cond, icmp1), icmp2, false -> select %cond, folded_icmp, false
+ // (A & icmp1) & icmp2 -> A & folded_icmp
+ auto TryFold = [&](Value *L, Value *R) -> Value * {
+ Value *A, *B;
+ Instruction::BinaryOps Opcode = IsAnd ? Instruction::And : Instruction::Or;
+
+ // Look through (Op A, B)
+ if (match(L, m_BinOp(Opcode, m_Value(A), m_Value(B))) ||
+ (IsLogical && (IsAnd ? match(L, m_LogicalAnd(m_Value(A), m_Value(B)))
+ : match(L, m_LogicalOr(m_Value(A), m_Value(B)))))) {
+ for (int i = 0; i < 2; ++i) {
+ Value *InnerCmp = i == 0 ? B : A;
+ Value *Other = i == 0 ? A : B;
+ auto *ICmpInner = dyn_cast<ICmpInst>(InnerCmp);
+ auto *ICmpR = dyn_cast<ICmpInst>(R);
+ if (ICmpInner && ICmpR) {
+ if (Value *Res = foldAndOrOfICmps(ICmpInner, ICmpR, I, IsAnd, IsLogical)) {
+ if (IsLogical) {
+ if (IsAnd)
+ return Builder.CreateSelect(Other, Res,
+ ConstantInt::getFalse(LHS->getType()));
+ else
+ return Builder.CreateSelect(Other, ConstantInt::getTrue(LHS->getType()),
+ Res);
+ } else {
+ return Builder.CreateBinOp(Opcode, Other, Res);
+ }
+ }
+ }
+ }
+ }
+ return nullptr;
+ };
+
+ if (Value *V = TryFold(LHS, RHS))
+ return V;
+ if (Value *V = TryFold(RHS, LHS))
+ return V;
+
return nullptr;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/176590
More information about the llvm-commits
mailing list