https://github.com/kmpeng updated 
https://github.com/llvm/llvm-project/pull/214332

>From 51e1a3eae51ca0a0a5034782a5fe02234650e912 Mon Sep 17 00:00:00 2001
From: kmpeng <[email protected]>
Date: Wed, 5 Aug 2026 12:59:14 -0700
Subject: [PATCH 1/2] fix conversion bug and add tests

---
 clang/lib/Sema/SemaExpr.cpp                   |  7 ++
 .../Operators/half-vector-comparisons.hlsl    | 70 +++++++++++++++++++
 .../Operators/half-vector-comparisons.hlsl    | 63 +++++++++++++++++
 3 files changed, 140 insertions(+)
 create mode 100644 
clang/test/CodeGenHLSL/Operators/half-vector-comparisons.hlsl
 create mode 100644 clang/test/SemaHLSL/Operators/half-vector-comparisons.hlsl

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 59b8c9b60663c..e18be2a03bd99 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15753,6 +15753,13 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation 
OpLoc,
   ConvertHalfVec =
       needsConversionOfHalfVec(ConvertHalfVec, Context, LHS.get(), RHS.get());
 
+  // Skip the vector conversion when the result is not a half/short vector 
(e.g.
+  // HLSL comparisons).
+  if (ConvertHalfVec && ResultTy->isVectorType() &&
+      !isVector(ResultTy, Context.HalfTy) &&
+      !isVector(ResultTy, Context.ShortTy))
+    ConvertHalfVec = false;
+
   // Check for array bounds violations for both sides of the BinaryOperator
   CheckArrayAccess(LHS.get());
   CheckArrayAccess(RHS.get());
diff --git a/clang/test/CodeGenHLSL/Operators/half-vector-comparisons.hlsl 
b/clang/test/CodeGenHLSL/Operators/half-vector-comparisons.hlsl
new file mode 100644
index 0000000000000..c289f372f4542
--- /dev/null
+++ b/clang/test/CodeGenHLSL/Operators/half-vector-comparisons.hlsl
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -finclude-default-header -triple 
dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm 
-disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -triple 
dxil-pc-shadermodel6.6-library %s -emit-llvm -disable-llvm-passes -o - | 
FileCheck %s --check-prefixes=CHECK,NO_HALF
+
+// Regression test for issue llvm/llvm-project#213814
+
+// CHECK-LABEL: test_lt
+// NATIVE_HALF: [[CMP:%.*]] = fcmp {{.*}} olt <4 x half>
+// NATIVE_HALF-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i16>
+// NATIVE_HALF-NEXT: [[RET:%.*]] = sext <4 x i16> [[SEXT]] to <4 x i32>
+// NO_HALF: [[CMP:%.*]] = fcmp {{.*}} olt <4 x float>
+// NO_HALF-NEXT: [[RET:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32>
+// CHECK-NEXT: ret <4 x i32> [[RET]]
+int4 test_lt(half4 a, half4 b) {
+    return a < b;
+}
+
+// CHECK-LABEL: test_le
+// NATIVE_HALF: [[CMP:%.*]] = fcmp {{.*}} ole <4 x half>
+// NATIVE_HALF-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i16>
+// NATIVE_HALF-NEXT: [[RET:%.*]] = sext <4 x i16> [[SEXT]] to <4 x i32>
+// NO_HALF: [[CMP:%.*]] = fcmp {{.*}} ole <4 x float>
+// NO_HALF-NEXT: [[RET:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32>
+// CHECK-NEXT: ret <4 x i32> [[RET]]
+int4 test_le(half4 a, half4 b) {
+    return a <= b;
+}
+
+// CHECK-LABEL: test_gt
+// NATIVE_HALF: [[CMP:%.*]] = fcmp {{.*}} ogt <4 x half>
+// NATIVE_HALF-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i16>
+// NATIVE_HALF-NEXT: [[RET:%.*]] = sext <4 x i16> [[SEXT]] to <4 x i32>
+// NO_HALF: [[CMP:%.*]] = fcmp {{.*}} ogt <4 x float>
+// NO_HALF-NEXT: [[RET:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32>
+// CHECK-NEXT: ret <4 x i32> [[RET]]
+int4 test_gt(half4 a, half4 b) {
+    return a > b;
+}
+
+// CHECK-LABEL: test_ge
+// NATIVE_HALF: [[CMP:%.*]] = fcmp {{.*}} oge <4 x half>
+// NATIVE_HALF-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i16>
+// NATIVE_HALF-NEXT: [[RET:%.*]] = sext <4 x i16> [[SEXT]] to <4 x i32>
+// NO_HALF: [[CMP:%.*]] = fcmp {{.*}} oge <4 x float>
+// NO_HALF-NEXT: [[RET:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32>
+// CHECK-NEXT: ret <4 x i32> [[RET]]
+int4 test_ge(half4 a, half4 b) {
+    return a >= b;
+}
+
+// CHECK-LABEL: test_eq
+// NATIVE_HALF: [[CMP:%.*]] = fcmp {{.*}} oeq <4 x half>
+// NATIVE_HALF-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i16>
+// NATIVE_HALF-NEXT: [[RET:%.*]] = sext <4 x i16> [[SEXT]] to <4 x i32>
+// NO_HALF: [[CMP:%.*]] = fcmp {{.*}} oeq <4 x float>
+// NO_HALF-NEXT: [[RET:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32>
+// CHECK-NEXT: ret <4 x i32> [[RET]]
+int4 test_eq(half4 a, half4 b) {
+    return a == b;
+}
+
+// CHECK-LABEL: test_ne
+// NATIVE_HALF: [[CMP:%.*]] = fcmp {{.*}} une <4 x half>
+// NATIVE_HALF-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i16>
+// NATIVE_HALF-NEXT: [[RET:%.*]] = sext <4 x i16> [[SEXT]] to <4 x i32>
+// NO_HALF: [[CMP:%.*]] = fcmp {{.*}} une <4 x float>
+// NO_HALF-NEXT: [[RET:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32>
+// CHECK-NEXT: ret <4 x i32> [[RET]]
+int4 test_ne(half4 a, half4 b) {
+    return a != b;
+}
diff --git a/clang/test/SemaHLSL/Operators/half-vector-comparisons.hlsl 
b/clang/test/SemaHLSL/Operators/half-vector-comparisons.hlsl
new file mode 100644
index 0000000000000..f3be50ef6fc62
--- /dev/null
+++ b/clang/test/SemaHLSL/Operators/half-vector-comparisons.hlsl
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -finclude-default-header -triple 
dxil-pc-shadermodel6.6-library %s -ast-dump -ast-dump-filter=test | FileCheck %s
+
+// Regression test for issue llvm/llvm-project#213814
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_lt 'int4 (half4, half4)'
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' '<'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'a' 'half4':'vector<half, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'b' 'half4':'vector<half, 4>'
+int4 test_lt(half4 a, half4 b) {
+    return a < b;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_le 'int4 (half4, half4)'
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' '<='
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'a' 'half4':'vector<half, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'b' 'half4':'vector<half, 4>'
+int4 test_le(half4 a, half4 b) {
+    return a <= b;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_gt 'int4 (half4, half4)'
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' '>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'a' 'half4':'vector<half, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'b' 'half4':'vector<half, 4>'
+int4 test_gt(half4 a, half4 b) {
+    return a > b;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_ge 'int4 (half4, half4)'
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' '>='
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'a' 'half4':'vector<half, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'b' 'half4':'vector<half, 4>'
+int4 test_ge(half4 a, half4 b) {
+    return a >= b;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_eq 'int4 (half4, half4)'
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' '=='
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'a' 'half4':'vector<half, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'b' 'half4':'vector<half, 4>'
+int4 test_eq(half4 a, half4 b) {
+    return a == b;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_ne 'int4 (half4, half4)'
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' '!='
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'a' 'half4':'vector<half, 4>'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half4':'vector<half, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'b' 'half4':'vector<half, 4>'
+int4 test_ne(half4 a, half4 b) {
+    return a != b;
+}

>From 2433d8f47c0cbc017fd5cea8302180aae92d9184 Mon Sep 17 00:00:00 2001
From: kmpeng <[email protected]>
Date: Wed, 5 Aug 2026 16:52:13 -0700
Subject: [PATCH 2/2] move fix into `needsConversionOfHalfVec`

---
 clang/lib/Sema/SemaExpr.cpp | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e18be2a03bd99..3065c7ea23870 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15502,10 +15502,17 @@ static ExprResult convertHalfVecBinOp(Sema &S, 
ExprResult LHS, ExprResult RHS,
 /// Returns true if conversion between vectors of halfs and vectors of floats
 /// is needed.
 static bool needsConversionOfHalfVec(bool OpRequiresConversion, ASTContext 
&Ctx,
-                                     Expr *E0, Expr *E1 = nullptr) {
+                                     QualType ResultTy, Expr *E0,
+                                     Expr *E1 = nullptr) {
   if (!OpRequiresConversion || Ctx.getLangOpts().NativeHalfType)
     return false;
 
+  // The conversion truncates the result to a half/short vector, so it 
shouldn't
+  // apply when the result is not that type (e.g. HLSL comparisons).
+  if (ResultTy->isVectorType() && !isVector(ResultTy, Ctx.HalfTy) &&
+      !isVector(ResultTy, Ctx.ShortTy))
+    return false;
+
   auto HasVectorOfHalfType = [&Ctx](Expr *E) {
     QualType Ty = E->IgnoreImplicit()->getType();
 
@@ -15750,15 +15757,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation 
OpLoc,
       (Opc == BO_Comma || isVector(RHS.get()->getType(), Context.HalfTy) ==
                               isVector(LHS.get()->getType(), Context.HalfTy)) 
&&
       "both sides are half vectors or neither sides are");
-  ConvertHalfVec =
-      needsConversionOfHalfVec(ConvertHalfVec, Context, LHS.get(), RHS.get());
-
-  // Skip the vector conversion when the result is not a half/short vector 
(e.g.
-  // HLSL comparisons).
-  if (ConvertHalfVec && ResultTy->isVectorType() &&
-      !isVector(ResultTy, Context.HalfTy) &&
-      !isVector(ResultTy, Context.ShortTy))
-    ConvertHalfVec = false;
+  ConvertHalfVec = needsConversionOfHalfVec(ConvertHalfVec, Context, ResultTy,
+                                            LHS.get(), RHS.get());
 
   // Check for array bounds violations for both sides of the BinaryOperator
   CheckArrayAccess(LHS.get());
@@ -16311,7 +16311,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation 
OpLoc,
       // float vector and truncating the result back to a half vector. For now,
       // we do this only when HalfArgsAndReturns is set (that is, when the
       // target is arm or arm64).
-      ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get());
+      ConvertHalfVec = needsConversionOfHalfVec(
+          true, Context, Input.get()->getType(), Input.get());
 
       // If the operand is a half vector, promote it to a float vector.
       if (ConvertHalfVec)

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to