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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
