[llvm] [ValueTracking] Add missing operand checks in `computeKnownFPClassFromCond` (PR #119579)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 11 08:19:36 PST 2024


https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/119579

After https://github.com/llvm/llvm-project/pull/118257, we may call `computeKnownFPClassFromCond` with unrelated conditions. Then miscompilations may occur due to a lack of operand checks.

This bug was introduced by https://github.com/llvm/llvm-project/commit/d2404ea6ced5fce9442260bde08a02d607fdd50d and https://github.com/llvm/llvm-project/pull/80740. However, the miscompilation never occurs since we only add related conditions to `DomConditionCache/AssumptionCache`.

Fix the miscompilation reported in https://github.com/llvm/llvm-project/pull/118257#issuecomment-2536182166.


>From 64fcb7fdc89855aa5893669fb7e6581f11e70094 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Wed, 11 Dec 2024 23:59:59 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.

---
 .../InstCombine/fpclass-from-dom-cond.ll      | 58 +++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll b/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll
index 141b44cbbb7a1f..ea26bfbc3eb08e 100644
--- a/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll
+++ b/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll
@@ -456,3 +456,61 @@ if.end:
   %ret = call <2 x float> @llvm.fabs.v2f32(<2 x float> %value)
   ret <2 x float> %ret
 }
+
+define i1 @pr118257(half %v0, half %v1) {
+; CHECK-LABEL: define i1 @pr118257(
+; CHECK-SAME: half [[V0:%.*]], half [[V1:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp une half [[V1]], 0xH0000
+; CHECK-NEXT:    [[CAST0:%.*]] = bitcast half [[V0]] to i16
+; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i16 [[CAST0]], 0
+; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    ret i1 false
+; CHECK:       if.end:
+; CHECK-NEXT:    ret i1 false
+;
+entry:
+  %cmp1 = fcmp une half %v1, 0.000000e+00
+  %cast0 = bitcast half %v0 to i16
+  %cmp2 = icmp slt i16 %cast0, 0
+  %or.cond = or i1 %cmp1, %cmp2
+  br i1 %or.cond, label %if.end, label %if.else
+
+if.else:
+  %cast1 = bitcast half %v1 to i16
+  %cmp3 = icmp slt i16 %cast1, 0
+  ret i1 %cmp3
+
+if.end:
+  ret i1 false
+}
+
+define i1 @pr118257_is_fpclass(half %v0, half %v1) {
+; CHECK-LABEL: define i1 @pr118257_is_fpclass(
+; CHECK-SAME: half [[V0:%.*]], half [[V1:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP1:%.*]] = fcmp une half [[V1]], 0xH0000
+; CHECK-NEXT:    [[CMP2:%.*]] = call i1 @llvm.is.fpclass.f16(half [[V0]], i32 35)
+; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[CMP1]], [[CMP2]]
+; CHECK-NEXT:    br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    ret i1 false
+; CHECK:       if.end:
+; CHECK-NEXT:    ret i1 false
+;
+entry:
+  %cmp1 = fcmp une half %v1, 0.000000e+00
+  %cmp2 = call i1 @llvm.is.fpclass.half(half %v0, i32 35)
+  %or.cond = or i1 %cmp1, %cmp2
+  br i1 %or.cond, label %if.end, label %if.else
+
+if.else:
+  %cast1 = bitcast half %v1 to i16
+  %cmp3 = icmp slt i16 %cast1, 0
+  ret i1 %cmp3
+
+if.end:
+  ret i1 false
+}

>From 03c0ee0551404f85782cd167262720d2dda6a651 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 12 Dec 2024 00:09:45 +0800
Subject: [PATCH 2/2] [ValueTracking] Add missing op checks in
 `computeKnownFPClassFromCond`

---
 llvm/lib/Analysis/ValueTracking.cpp                       | 4 ++--
 llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll | 8 ++++++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f2c6949e535d2a..c148dbce92d1af 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4906,10 +4906,10 @@ static void computeKnownFPClassFromCond(const Value *V, Value *Cond,
     if (CmpVal == V)
       KnownFromContext.knownNot(~(CondIsTrue ? MaskIfTrue : MaskIfFalse));
   } else if (match(Cond, m_Intrinsic<Intrinsic::is_fpclass>(
-                             m_Value(LHS), m_ConstantInt(ClassVal)))) {
+                             m_Specific(V), m_ConstantInt(ClassVal)))) {
     FPClassTest Mask = static_cast<FPClassTest>(ClassVal);
     KnownFromContext.knownNot(CondIsTrue ? ~Mask : Mask);
-  } else if (match(Cond, m_ICmp(Pred, m_ElementWiseBitCast(m_Value(LHS)),
+  } else if (match(Cond, m_ICmp(Pred, m_ElementWiseBitCast(m_Specific(V)),
                                 m_APInt(RHS)))) {
     bool TrueIfSigned;
     if (!isSignBitCheck(Pred, *RHS, TrueIfSigned))
diff --git a/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll b/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll
index ea26bfbc3eb08e..78329faf341727 100644
--- a/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll
+++ b/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll
@@ -467,7 +467,9 @@ define i1 @pr118257(half %v0, half %v1) {
 ; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[CMP1]], [[CMP2]]
 ; CHECK-NEXT:    br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_ELSE:%.*]]
 ; CHECK:       if.else:
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    [[CAST1:%.*]] = bitcast half [[V1]] to i16
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp slt i16 [[CAST1]], 0
+; CHECK-NEXT:    ret i1 [[CMP3]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    ret i1 false
 ;
@@ -496,7 +498,9 @@ define i1 @pr118257_is_fpclass(half %v0, half %v1) {
 ; CHECK-NEXT:    [[OR_COND:%.*]] = or i1 [[CMP1]], [[CMP2]]
 ; CHECK-NEXT:    br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_ELSE:%.*]]
 ; CHECK:       if.else:
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    [[CAST1:%.*]] = bitcast half [[V1]] to i16
+; CHECK-NEXT:    [[CMP3:%.*]] = icmp slt i16 [[CAST1]], 0
+; CHECK-NEXT:    ret i1 [[CMP3]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    ret i1 false
 ;



More information about the llvm-commits mailing list