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

Reply via email to