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
