[llvm] [GlobalISel] Drop poison flags by default in combiners (PR #218306)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 23 19:45:33 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-globalisel
Author: 陈子昂 (Michael-Chen-NJU)
<details>
<summary>Changes</summary>
GlobalISel TableGen combiners were implicitly copying poison-generating flags from the root instruction to newly-created instructions. This is unsafe because the replacement instruction may not preserve the same `nuw`/`nsw` guarantees.
Drop those flags by default for combiners, while keeping explicit `MIFlags` preservation intact.
Fixes #<!-- -->210470
---
Full diff: https://github.com/llvm/llvm-project/pull/218306.diff
6 Files Affected:
- (modified) llvm/include/llvm/CodeGen/GlobalISel/Combiner.h (+2)
- (modified) llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h (+5)
- (modified) llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h (+4-1)
- (modified) llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h (+9-3)
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir (+28)
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir (+197)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h b/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
index bd9a526eae606..bb4c7be459753 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h
@@ -67,6 +67,8 @@ class LLVM_ABI Combiner : public GIMatchTableExecutor {
protected:
virtual bool canMatchOpcode(unsigned Opc) const { return true; }
+ bool shouldDropRootPoisonGeneratingFlags() const override { return true; }
+
const CombinerInfo &CInfo;
GISelChangeObserver &Observer;
MachineIRBuilder &B;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
index 6e3ccf1923c40..ccce4b79f4419 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
@@ -739,6 +739,11 @@ class GIMatchTableExecutor {
llvm_unreachable("Subclass does not implement runCustomAction!");
}
+ /// Return true to drop root poison-generating flags from the implicit flag
+ /// propagation performed for newly-built instructions. Explicit MIFlags
+ /// actions in the match table still apply to the output instruction.
+ virtual bool shouldDropRootPoisonGeneratingFlags() const { return false; }
+
LLVM_ABI bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
const MachineRegisterInfo &MRI,
bool Splat = false) const;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
index e0720928c6526..1eb6715c4a249 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
+#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -58,7 +59,9 @@ bool GIMatchTableExecutor::executeMatchTable(
// Bypass the flag check on the instruction, and only look at the MCInstrDesc.
bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException();
- const uint32_t Flags = State.MIs[0]->getFlags();
+ uint32_t Flags = State.MIs[0]->getFlags();
+ if (shouldDropRootPoisonGeneratingFlags())
+ Flags &= ~GenericMachineInstr::getPoisonGeneratingFlags();
bool BuilderInitialized = false;
const auto initializeBuilder = [&]() {
if (BuilderInitialized)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 6daa7f3808f43..1a24434bb388f 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -26,7 +26,7 @@ namespace llvm {
/// A base class for all GenericMachineInstrs.
class GenericMachineInstr : public MachineInstr {
- constexpr static unsigned PoisonFlags =
+ constexpr static unsigned PoisonGeneratingFlags =
NoUWrap | NoSWrap | NoUSWrap | IsExact | Disjoint | NonNeg | FmNoNans |
FmNoInfs | SameSign | InBounds;
@@ -41,10 +41,16 @@ class GenericMachineInstr : public MachineInstr {
return isPreISelGenericOpcode(MI->getOpcode());
}
- bool hasPoisonGeneratingFlags() const { return getFlags() & PoisonFlags; }
+ static constexpr unsigned getPoisonGeneratingFlags() {
+ return PoisonGeneratingFlags;
+ }
+
+ bool hasPoisonGeneratingFlags() const {
+ return getFlags() & PoisonGeneratingFlags;
+ }
void dropPoisonGeneratingFlags() {
- clearFlags(PoisonFlags);
+ clearFlags(PoisonGeneratingFlags);
assert(!hasPoisonGeneratingFlags());
}
};
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
index 1bf856cd6f704..2c06724978f05 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
@@ -359,6 +359,34 @@ body: |
RET_ReallyLR implicit $w0
...
+---
+name: add_shl_neg_nuw
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $w0, $w1, $w2
+
+ ; CHECK-LABEL: name: add_shl_neg_nuw
+ ; CHECK: liveins: $w0, $w1, $w2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(i32) = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(i32) = COPY $w2
+ ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(i32) = G_SHL [[COPY1]], [[COPY2]](i32)
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(i32) = G_SUB [[COPY]], [[SHL]]
+ ; CHECK-NEXT: $w0 = COPY [[SUB]](i32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(i32) = COPY $w0
+ %1:_(i32) = COPY $w1
+ %2:_(i32) = COPY $w2
+ %3:_(i32) = G_CONSTANT i32 0
+ %4:_(i32) = G_SUB %3, %1
+ %5:_(i32) = G_SHL %4, %2
+ %6:_(i32) = nuw G_ADD %0, %5
+ $w0 = COPY %6
+ RET_ReallyLR implicit $w0
+...
+
---
name: add_shl_neg_commuted
tracksRegLiveness: true
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 3de9527bb3584..3f57fb256873d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -24,6 +24,29 @@ body: |
$x0 = COPY %sub
RET_ReallyLR implicit $x0
+...
+---
+name: APlusBMinusCMinusB_nuw
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+ ; CHECK-LABEL: name: APlusBMinusCMinusB_nuw
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(i64) = COPY $x0
+ ; CHECK-NEXT: %c:_(i64) = COPY $x2
+ ; CHECK-NEXT: %sub:_(i64) = G_SUB %a, %c
+ ; CHECK-NEXT: $x0 = COPY %sub(i64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(i64) = COPY $x0
+ %b:_(i64) = COPY $x1
+ %c:_(i64) = COPY $x2
+ %sub1:_(i64) = G_SUB %b, %c
+ %add1:_(i64) = G_ADD %a, %sub1
+ %sub:_(i64) = nuw G_SUB %add1, %b
+ $x0 = COPY %sub
+ RET_ReallyLR implicit $x0
+
...
---
name: AMinusBMinusCMinusC
@@ -47,6 +70,29 @@ body: |
$x0 = COPY %sub
RET_ReallyLR implicit $x0
+...
+---
+name: AMinusBMinusCMinusC_nuw
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+ ; CHECK-LABEL: name: AMinusBMinusCMinusC_nuw
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(i64) = COPY $x0
+ ; CHECK-NEXT: %b:_(i64) = COPY $x1
+ ; CHECK-NEXT: %sub:_(i64) = G_SUB %a, %b
+ ; CHECK-NEXT: $x0 = COPY %sub(i64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(i64) = COPY $x0
+ %b:_(i64) = COPY $x1
+ %c:_(i64) = COPY $x2
+ %sub1:_(i64) = G_SUB %b, %c
+ %sub2:_(i64) = G_SUB %a, %sub1
+ %sub:_(i64) = nuw G_SUB %sub2, %c
+ $x0 = COPY %sub
+ RET_ReallyLR implicit $x0
+
...
---
name: ZeroMinusAPlusB
@@ -190,6 +236,31 @@ body: |
$x0 = COPY %add
RET_ReallyLR implicit $x0
+...
+---
+name: AMinusBPlusCMinusA_nuw
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+
+ ; CHECK-LABEL: name: AMinusBPlusCMinusA_nuw
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %b:_(i64) = COPY $x1
+ ; CHECK-NEXT: %c:_(i64) = COPY $x2
+ ; CHECK-NEXT: %add:_(i64) = G_SUB %c, %b
+ ; CHECK-NEXT: $x0 = COPY %add(i64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(i64) = COPY $x0
+ %b:_(i64) = COPY $x1
+ %c:_(i64) = COPY $x2
+ %zero:_(i64) = G_CONSTANT i64 0
+ %sub2:_(i64) = G_SUB %c, %a
+ %sub1:_(i64) = G_SUB %a, %b
+ %add:_(i64) = nuw G_ADD %sub1, %sub2
+ $x0 = COPY %add
+ RET_ReallyLR implicit $x0
+
...
---
name: AMinusBPlusBMinusC
@@ -216,6 +287,32 @@ body: |
RET_ReallyLR implicit $x0
+...
+---
+name: AMinusBPlusBMinusC_nuw
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+
+ ; CHECK-LABEL: name: AMinusBPlusBMinusC_nuw
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(i64) = COPY $x0
+ ; CHECK-NEXT: %c:_(i64) = COPY $x2
+ ; CHECK-NEXT: %add:_(i64) = G_SUB %a, %c
+ ; CHECK-NEXT: $x0 = COPY %add(i64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(i64) = COPY $x0
+ %b:_(i64) = COPY $x1
+ %c:_(i64) = COPY $x2
+ %zero:_(i64) = G_CONSTANT i64 0
+ %sub2:_(i64) = G_SUB %b, %c
+ %sub1:_(i64) = G_SUB %a, %b
+ %add:_(i64) = nuw G_ADD %sub1, %sub2
+ $x0 = COPY %add
+ RET_ReallyLR implicit $x0
+
+
...
---
name: APlusBMinusAplusC
@@ -241,6 +338,31 @@ body: |
$x0 = COPY %add
RET_ReallyLR implicit $x0
+...
+---
+name: APlusBMinusAplusC_nuw
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+
+ ; CHECK-LABEL: name: APlusBMinusAplusC_nuw
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %b:_(i64) = COPY $x1
+ ; CHECK-NEXT: %c:_(i64) = COPY $x2
+ ; CHECK-NEXT: %add:_(i64) = G_SUB %b, %c
+ ; CHECK-NEXT: $x0 = COPY %add(i64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(i64) = COPY $x0
+ %b:_(i64) = COPY $x1
+ %c:_(i64) = COPY $x2
+ %zero:_(i64) = G_CONSTANT i64 0
+ %add1:_(i64) = G_ADD %a, %c
+ %sub1:_(i64) = G_SUB %b, %add1
+ %add:_(i64) = nuw G_ADD %a, %sub1
+ $x0 = COPY %add
+ RET_ReallyLR implicit $x0
+
...
---
name: APlusBMinusCPlusA
@@ -266,6 +388,31 @@ body: |
$x0 = COPY %add
RET_ReallyLR implicit $x0
+...
+---
+name: APlusBMinusCPlusA_nuw
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+
+ ; CHECK-LABEL: name: APlusBMinusCPlusA_nuw
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %b:_(i64) = COPY $x1
+ ; CHECK-NEXT: %c:_(i64) = COPY $x2
+ ; CHECK-NEXT: %add:_(i64) = G_SUB %b, %c
+ ; CHECK-NEXT: $x0 = COPY %add(i64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(i64) = COPY $x0
+ %b:_(i64) = COPY $x1
+ %c:_(i64) = COPY $x2
+ %zero:_(i64) = G_CONSTANT i64 0
+ %add1:_(i64) = G_ADD %c, %a
+ %sub1:_(i64) = G_SUB %b, %add1
+ %add:_(i64) = nuw G_ADD %a, %sub1
+ $x0 = COPY %add
+ RET_ReallyLR implicit $x0
+
...
---
name: APlusBMinusCPlusA_BV
@@ -496,6 +643,56 @@ body: |
$x0 = COPY %sub2
RET_ReallyLR implicit $x0
+...
+---
+name: AMinusBMinusC_nuw
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+
+ ; CHECK-LABEL: name: AMinusBMinusC_nuw
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(i64) = COPY $x0
+ ; CHECK-NEXT: %b:_(i64) = COPY $x1
+ ; CHECK-NEXT: %c:_(i64) = COPY $x2
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(i64) = G_SUB %c, %b
+ ; CHECK-NEXT: %sub2:_(i64) = G_ADD %a, [[SUB]]
+ ; CHECK-NEXT: $x0 = COPY %sub2(i64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(i64) = COPY $x0
+ %b:_(i64) = COPY $x1
+ %c:_(i64) = COPY $x2
+ %sub1:_(i64) = G_SUB %b, %c
+ %sub2:_(i64) = nuw G_SUB %a, %sub1
+ $x0 = COPY %sub2
+ RET_ReallyLR implicit $x0
+
+...
+---
+name: AMinusBMinusC_nsw
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+
+ ; CHECK-LABEL: name: AMinusBMinusC_nsw
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(i64) = COPY $x0
+ ; CHECK-NEXT: %b:_(i64) = COPY $x1
+ ; CHECK-NEXT: %c:_(i64) = COPY $x2
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(i64) = G_SUB %c, %b
+ ; CHECK-NEXT: %sub2:_(i64) = G_ADD %a, [[SUB]]
+ ; CHECK-NEXT: $x0 = COPY %sub2(i64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(i64) = COPY $x0
+ %b:_(i64) = COPY $x1
+ %c:_(i64) = COPY $x2
+ %sub1:_(i64) = G_SUB %b, %c
+ %sub2:_(i64) = nsw G_SUB %a, %sub1
+ $x0 = COPY %sub2
+ RET_ReallyLR implicit $x0
+
...
---
name: AMinusZeroMinusB
``````````
</details>
https://github.com/llvm/llvm-project/pull/218306
More information about the llvm-commits
mailing list