[llvm-branch-commits] [llvm] [LLVM][MIPS] Add comprehensive tests for ct.select (PR #166705)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer created 
https://github.com/llvm/llvm-project/pull/166705

None

>From 22e92921b5a3b7720e53ba32777e2bccf024896a Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 11:01:26 -0500
Subject: [PATCH] [LLVM][MIPS] Add comprehensive tests for ct.select

---
 .../Mips/ctselect-fallback-edge-cases.ll  | 244 +
 .../Mips/ctselect-fallback-patterns.ll| 426 +
 .../CodeGen/Mips/ctselect-fallback-vector.ll  | 830 ++
 llvm/test/CodeGen/Mips/ctselect-fallback.ll   | 371 
 .../CodeGen/Mips/ctselect-side-effects.ll | 183 
 5 files changed, 2054 insertions(+)
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-fallback-edge-cases.ll
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-fallback-patterns.ll
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-fallback-vector.ll
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-fallback.ll
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-side-effects.ll

diff --git a/llvm/test/CodeGen/Mips/ctselect-fallback-edge-cases.ll 
b/llvm/test/CodeGen/Mips/ctselect-fallback-edge-cases.ll
new file mode 100644
index 0..f1831a625d4a4
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/ctselect-fallback-edge-cases.ll
@@ -0,0 +1,244 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=mipsel-unknown-linux-gnu -O3 | FileCheck %s 
--check-prefix=M32
+; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -O3 | FileCheck %s 
--check-prefix=M64
+
+; Portable edge case tests
+
+; Test with small integer types
+define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
+; M32-LABEL: test_ctselect_i1:
+; M32:   # %bb.0:
+; M32-NEXT:xori $2, $4, 1
+; M32-NEXT:and $1, $4, $5
+; M32-NEXT:and $2, $2, $6
+; M32-NEXT:jr $ra
+; M32-NEXT:or $2, $1, $2
+;
+; M64-LABEL: test_ctselect_i1:
+; M64:   # %bb.0:
+; M64-NEXT:sll $2, $4, 0
+; M64-NEXT:sll $1, $6, 0
+; M64-NEXT:xori $2, $2, 1
+; M64-NEXT:and $1, $2, $1
+; M64-NEXT:and $2, $4, $5
+; M64-NEXT:sll $2, $2, 0
+; M64-NEXT:jr $ra
+; M64-NEXT:or $2, $2, $1
+  %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
+  ret i1 %result
+}
+
+; Test with extremal values
+define i32 @test_ctselect_extremal_values(i1 %cond) {
+; M32-LABEL: test_ctselect_extremal_values:
+; M32:   # %bb.0:
+; M32-NEXT:lui $3, 32767
+; M32-NEXT:andi $1, $4, 1
+; M32-NEXT:negu $2, $1
+; M32-NEXT:ori $3, $3, 65535
+; M32-NEXT:addiu $1, $1, -1
+; M32-NEXT:and $2, $2, $3
+; M32-NEXT:lui $3, 32768
+; M32-NEXT:and $1, $1, $3
+; M32-NEXT:jr $ra
+; M32-NEXT:or $2, $2, $1
+;
+; M64-LABEL: test_ctselect_extremal_values:
+; M64:   # %bb.0:
+; M64-NEXT:sll $1, $4, 0
+; M64-NEXT:lui $3, 32767
+; M64-NEXT:andi $1, $1, 1
+; M64-NEXT:ori $3, $3, 65535
+; M64-NEXT:negu $2, $1
+; M64-NEXT:addiu $1, $1, -1
+; M64-NEXT:and $2, $2, $3
+; M64-NEXT:lui $3, 32768
+; M64-NEXT:and $1, $1, $3
+; M64-NEXT:jr $ra
+; M64-NEXT:or $2, $2, $1
+  %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 
-2147483648)
+  ret i32 %result
+}
+
+; Test with null pointers
+define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
+; M32-LABEL: test_ctselect_null_ptr:
+; M32:   # %bb.0:
+; M32-NEXT:andi $1, $4, 1
+; M32-NEXT:negu $1, $1
+; M32-NEXT:jr $ra
+; M32-NEXT:and $2, $1, $5
+;
+; M64-LABEL: test_ctselect_null_ptr:
+; M64:   # %bb.0:
+; M64-NEXT:andi $1, $4, 1
+; M64-NEXT:dnegu $1, $1
+; M64-NEXT:jr $ra
+; M64-NEXT:and $2, $1, $5
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
+  ret ptr %result
+}
+
+; Test with function pointers
+define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
+; M32-LABEL: test_ctselect_function_ptr:
+; M32:   # %bb.0:
+; M32-NEXT:andi $1, $4, 1
+; M32-NEXT:negu $2, $1
+; M32-NEXT:addiu $1, $1, -1
+; M32-NEXT:and $2, $2, $5
+; M32-NEXT:and $1, $1, $6
+; M32-NEXT:jr $ra
+; M32-NEXT:or $2, $2, $1
+;
+; M64-LABEL: test_ctselect_function_ptr:
+; M64:   # %bb.0:
+; M64-NEXT:andi $1, $4, 1
+; M64-NEXT:dnegu $2, $1
+; M64-NEXT:daddiu $1, $1, -1
+; M64-NEXT:and $2, $2, $5
+; M64-NEXT:and $1, $1, $6
+; M64-NEXT:jr $ra
+; M64-NEXT:or $2, $2, $1
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %func1, ptr %func2)
+  ret ptr %result
+}
+
+; Test with condition from icmp on pointers
+define ptr @test_ctselect_ptr_cmp(ptr %p1, ptr %p2, ptr %a, ptr %b) {
+; M32-LABEL: test_ctselect_ptr_cmp:
+; M32:   # %bb.0:
+; M32-NEXT:xor $1, $4, $5
+; M32-NEXT:sltu $1, $zero, $1
+; M32-NEXT:addiu $1, $1, -1
+; M32-NEXT:and $2, $1, $6
+; M32-NEXT:not $1, $1
+; M32-NEXT:and $1, $1, $7
+; M32-NEXT:jr $ra
+; M32-NEXT:or $2, $2, $1
+;
+; M64-LABEL: test_ctselect_ptr_cmp:
+; M64:   # %bb.0:

[llvm-branch-commits] [llvm] [LLVM][AArch64] Add native ct.select support for ARM64 (PR #166706)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer created 
https://github.com/llvm/llvm-project/pull/166706

This patch implements architecture-specific lowering for ct.select on AArch64
using CSEL (conditional select) instructions for constant-time selection.

Implementation details:
- Uses CSEL family of instructions for scalar integer types
- Uses FCSEL for floating-point types (F16, BF16, F32, F64)
- Post-RA MC lowering to convert pseudo-instructions to real CSEL/FCSEL
- Handles vector types appropriately
- Comprehensive test coverage for AArch64

The implementation includes:
- ISelLowering: Custom lowering to CTSELECT pseudo-instructions
- InstrInfo: Pseudo-instruction definitions and patterns
- MCInstLower: Post-RA lowering of pseudo-instructions to actual CSEL/FCSEL
- Proper handling of condition codes for constant-time guarantees

>From 071428b7a6eed7a800364cc4b9a7e25e1d8e310e Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 17:09:45 -0500
Subject: [PATCH] [LLVM][AArch64] Add native ct.select support for ARM64

This patch implements architecture-specific lowering for ct.select on AArch64
using CSEL (conditional select) instructions for constant-time selection.

Implementation details:
- Uses CSEL family of instructions for scalar integer types
- Uses FCSEL for floating-point types (F16, BF16, F32, F64)
- Post-RA MC lowering to convert pseudo-instructions to real CSEL/FCSEL
- Handles vector types appropriately
- Comprehensive test coverage for AArch64

The implementation includes:
- ISelLowering: Custom lowering to CTSELECT pseudo-instructions
- InstrInfo: Pseudo-instruction definitions and patterns
- MCInstLower: Post-RA lowering of pseudo-instructions to actual CSEL/FCSEL
- Proper handling of condition codes for constant-time guarantees
---
 .../Target/AArch64/AArch64ISelLowering.cpp|  53 +
 llvm/lib/Target/AArch64/AArch64ISelLowering.h |  12 ++
 llvm/lib/Target/AArch64/AArch64InstrInfo.cpp  | 200 --
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  45 
 .../lib/Target/AArch64/AArch64MCInstLower.cpp |  18 ++
 llvm/test/CodeGen/AArch64/ctselect.ll | 153 ++
 6 files changed, 371 insertions(+), 110 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/ctselect.ll

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 60aa61e993b26..a86aac88b94a8 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -511,12 +511,35 @@ AArch64TargetLowering::AArch64TargetLowering(const 
TargetMachine &TM,
   setOperationAction(ISD::BR_CC, MVT::f64, Custom);
   setOperationAction(ISD::SELECT, MVT::i32, Custom);
   setOperationAction(ISD::SELECT, MVT::i64, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::i8,  Promote);
+  setOperationAction(ISD::CTSELECT, MVT::i16, Promote);
+  setOperationAction(ISD::CTSELECT, MVT::i32, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::i64, Custom);
   if (Subtarget->hasFPARMv8()) {
 setOperationAction(ISD::SELECT, MVT::f16, Custom);
 setOperationAction(ISD::SELECT, MVT::bf16, Custom);
   }
+  if (Subtarget->hasFullFP16()) {
+setOperationAction(ISD::CTSELECT, MVT::f16, Custom);
+setOperationAction(ISD::CTSELECT, MVT::bf16, Custom);
+  } else {
+setOperationAction(ISD::CTSELECT, MVT::f16, Promote);
+setOperationAction(ISD::CTSELECT, MVT::bf16, Promote);
+  }
   setOperationAction(ISD::SELECT, MVT::f32, Custom);
   setOperationAction(ISD::SELECT, MVT::f64, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::f32, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::f64, Custom);
+  for (MVT VT : MVT::vector_valuetypes()) {
+MVT elemType = VT.getVectorElementType();
+if (elemType == MVT::i8 || elemType == MVT::i16) {
+  setOperationAction(ISD::CTSELECT, VT, Promote);
+} else if ((elemType == MVT::f16 || elemType == MVT::bf16) && 
!Subtarget->hasFullFP16()) {
+  setOperationAction(ISD::CTSELECT, VT, Promote);
+} else {
+  setOperationAction(ISD::CTSELECT, VT, Expand);
+}
+  }
   setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
   setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
   setOperationAction(ISD::SELECT_CC, MVT::f16, Custom);
@@ -3328,6 +3351,18 @@ void AArch64TargetLowering::fixupPtrauthDiscriminator(
   IntDiscOp.setImm(IntDisc);
 }
 
+MachineBasicBlock *AArch64TargetLowering::EmitCTSELECT(MachineInstr &MI, 
MachineBasicBlock *MBB, unsigned Opcode) const {
+  const TargetInstrInfo *TII = Subtarget->getInstrInfo();
+  DebugLoc DL = MI.getDebugLoc();
+  MachineInstrBuilder Builder = BuildMI(*MBB, MI, DL, TII->get(Opcode));
+  for (unsigned Idx = 0; Idx < MI.getNumOperands(); ++Idx) {
+Builder.add(MI.getOperand(Idx));
+  }
+  Builder->setFlag(MachineInstr::NoMerge);
+  MBB->remove_instr(&MI);
+  return MBB;
+}
+
 MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
 MachineInstr &MI, MachineBasicBlock *BB) const

[llvm-branch-commits] [llvm] [ConstantTime][RISCV] Add comprehensive tests for ct.select (PR #166708)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer created 
https://github.com/llvm/llvm-project/pull/166708

Add comprehensive test suite for RISC-V fallback implementation:
- Edge cases (zero conditions, large integers, sign extension)
- Pattern matching (nested selects, chains)
- Vector support with RVV extensions
- Side effects and memory operations

The basic fallback test is in the core infrastructure PR.

>From 05465f4247bd1e05138118a697625b0ad9378e81 Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 11:01:00 -0500
Subject: [PATCH] [ConstantTime][RISCV] Add comprehensive tests for ct.select

Add comprehensive test suite for RISC-V fallback implementation:
- Edge cases (zero conditions, large integers, sign extension)
- Pattern matching (nested selects, chains)
- Vector support with RVV extensions
- Side effects and memory operations

The basic fallback test is in the core infrastructure PR.
---
 .../RISCV/ctselect-fallback-edge-cases.ll | 214 +
 .../RISCV/ctselect-fallback-patterns.ll   | 383 +
 .../RISCV/ctselect-fallback-vector-rvv.ll | 804 ++
 llvm/test/CodeGen/RISCV/ctselect-fallback.ll  | 330 ---
 .../CodeGen/RISCV/ctselect-side-effects.ll| 176 
 5 files changed, 1577 insertions(+), 330 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-patterns.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-vector-rvv.ll
 delete mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-side-effects.ll

diff --git a/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll 
b/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
new file mode 100644
index 0..af1be0c8f3ddc
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
@@ -0,0 +1,214 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=riscv64 -O3 | FileCheck %s --check-prefix=RV64
+; RUN: llc < %s -mtriple=riscv32 -O3 | FileCheck %s --check-prefix=RV32
+
+; Test with small integer types
+define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
+; RV64-LABEL: test_ctselect_i1:
+; RV64:   # %bb.0:
+; RV64-NEXT:and a1, a0, a1
+; RV64-NEXT:xori a0, a0, 1
+; RV64-NEXT:and a0, a0, a2
+; RV64-NEXT:or a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_i1:
+; RV32:   # %bb.0:
+; RV32-NEXT:and a1, a0, a1
+; RV32-NEXT:xori a0, a0, 1
+; RV32-NEXT:and a0, a0, a2
+; RV32-NEXT:or a0, a1, a0
+; RV32-NEXT:ret
+  %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
+  ret i1 %result
+}
+
+; Test with extremal values
+define i32 @test_ctselect_extremal_values(i1 %cond) {
+; RV64-LABEL: test_ctselect_extremal_values:
+; RV64:   # %bb.0:
+; RV64-NEXT:andi a0, a0, 1
+; RV64-NEXT:lui a1, 524288
+; RV64-NEXT:subw a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_extremal_values:
+; RV32:   # %bb.0:
+; RV32-NEXT:andi a0, a0, 1
+; RV32-NEXT:lui a1, 524288
+; RV32-NEXT:addi a2, a0, -1
+; RV32-NEXT:neg a0, a0
+; RV32-NEXT:and a1, a2, a1
+; RV32-NEXT:slli a0, a0, 1
+; RV32-NEXT:srli a0, a0, 1
+; RV32-NEXT:or a0, a0, a1
+; RV32-NEXT:ret
+  %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 
-2147483648)
+  ret i32 %result
+}
+
+; Test with null pointers
+define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
+; RV64-LABEL: test_ctselect_null_ptr:
+; RV64:   # %bb.0:
+; RV64-NEXT:slli a0, a0, 63
+; RV64-NEXT:srai a0, a0, 63
+; RV64-NEXT:and a0, a0, a1
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_null_ptr:
+; RV32:   # %bb.0:
+; RV32-NEXT:slli a0, a0, 31
+; RV32-NEXT:srai a0, a0, 31
+; RV32-NEXT:and a0, a0, a1
+; RV32-NEXT:ret
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
+  ret ptr %result
+}
+
+; Test with function pointers
+define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
+; RV64-LABEL: test_ctselect_function_ptr:
+; RV64:   # %bb.0:
+; RV64-NEXT:andi a0, a0, 1
+; RV64-NEXT:neg a3, a0
+; RV64-NEXT:addi a0, a0, -1
+; RV64-NEXT:and a1, a3, a1
+; RV64-NEXT:and a0, a0, a2
+; RV64-NEXT:or a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_function_ptr:
+; RV32:   # %bb.0:
+; RV32-NEXT:andi a0, a0, 1
+; RV32-NEXT:neg a3, a0
+; RV32-NEXT:addi a0, a0, -1
+; RV32-NEXT:and a1, a3, a1
+; RV32-NEXT:and a0, a0, a2
+; RV32-NEXT:or a0, a1, a0
+; RV32-NEXT:ret
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %func1, ptr %func2)
+  ret ptr %result
+}
+
+; Test with condition from icmp on pointers
+define ptr @test_ctselect_ptr_cmp(ptr %p1, ptr %p2, ptr %a, ptr %b) {
+; RV64-LABEL: test_ctselect_ptr_cmp:
+; RV64:   # %bb.0:
+; RV64-NEXT:xor a

[llvm-branch-commits] [llvm] [ConstantTime][WebAssembly] Add comprehensive tests for ct.select (PR #166709)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer created 
https://github.com/llvm/llvm-project/pull/166709

None

>From d55c2d69a0d48538f7376d9f06b8cbf0e2215e93 Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 11:03:23 -0500
Subject: [PATCH] [ConstantTime][WebAssembly] Add comprehensive tests for
 ct.select

---
 .../ctselect-fallback-edge-cases.ll   | 376 +
 .../WebAssembly/ctselect-fallback-patterns.ll | 641 
 .../WebAssembly/ctselect-fallback-vector.ll   | 714 ++
 .../CodeGen/WebAssembly/ctselect-fallback.ll  | 552 ++
 .../WebAssembly/ctselect-side-effects.ll  | 226 ++
 5 files changed, 2509 insertions(+)
 create mode 100644 
llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-fallback-patterns.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-fallback-vector.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-fallback.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-side-effects.ll

diff --git a/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll 
b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll
new file mode 100644
index 0..b0f7f2807debd
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll
@@ -0,0 +1,376 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=wasm32-unknown-unknown -O3 -filetype=asm | FileCheck 
%s --check-prefix=W32
+; RUN: llc < %s -mtriple=wasm64-unknown-unknown -O3 -filetype=asm | FileCheck 
%s --check-prefix=W64
+
+; Test with small integer types
+define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
+; W32-LABEL: test_ctselect_i1:
+; W32: .functype test_ctselect_i1 (i32, i32, i32) -> (i32)
+; W32-NEXT:  # %bb.0:
+; W32-NEXT:local.get 0
+; W32-NEXT:local.get 1
+; W32-NEXT:i32.and
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const 1
+; W32-NEXT:i32.xor
+; W32-NEXT:local.get 2
+; W32-NEXT:i32.and
+; W32-NEXT:i32.or
+; W32-NEXT:# fallthrough-return
+;
+; W64-LABEL: test_ctselect_i1:
+; W64: .functype test_ctselect_i1 (i32, i32, i32) -> (i32)
+; W64-NEXT:  # %bb.0:
+; W64-NEXT:local.get 0
+; W64-NEXT:local.get 1
+; W64-NEXT:i32.and
+; W64-NEXT:local.get 0
+; W64-NEXT:i32.const 1
+; W64-NEXT:i32.xor
+; W64-NEXT:local.get 2
+; W64-NEXT:i32.and
+; W64-NEXT:i32.or
+; W64-NEXT:# fallthrough-return
+  %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
+  ret i1 %result
+}
+
+; Test with extremal values
+define i32 @test_ctselect_extremal_values(i1 %cond) {
+; W32-LABEL: test_ctselect_extremal_values:
+; W32: .functype test_ctselect_extremal_values (i32) -> (i32)
+; W32-NEXT:  # %bb.0:
+; W32-NEXT:i32.const 0
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const 1
+; W32-NEXT:i32.and
+; W32-NEXT:local.tee 0
+; W32-NEXT:i32.sub
+; W32-NEXT:i32.const 2147483647
+; W32-NEXT:i32.and
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const -1
+; W32-NEXT:i32.add
+; W32-NEXT:i32.const -2147483648
+; W32-NEXT:i32.and
+; W32-NEXT:i32.or
+; W32-NEXT:# fallthrough-return
+;
+; W64-LABEL: test_ctselect_extremal_values:
+; W64: .functype test_ctselect_extremal_values (i32) -> (i32)
+; W64-NEXT:  # %bb.0:
+; W64-NEXT:i32.const 0
+; W64-NEXT:local.get 0
+; W64-NEXT:i32.const 1
+; W64-NEXT:i32.and
+; W64-NEXT:local.tee 0
+; W64-NEXT:i32.sub
+; W64-NEXT:i32.const 2147483647
+; W64-NEXT:i32.and
+; W64-NEXT:local.get 0
+; W64-NEXT:i32.const -1
+; W64-NEXT:i32.add
+; W64-NEXT:i32.const -2147483648
+; W64-NEXT:i32.and
+; W64-NEXT:i32.or
+; W64-NEXT:# fallthrough-return
+  %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 
-2147483648)
+  ret i32 %result
+}
+
+; Test with null pointers
+define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
+; W32-LABEL: test_ctselect_null_ptr:
+; W32: .functype test_ctselect_null_ptr (i32, i32) -> (i32)
+; W32-NEXT:  # %bb.0:
+; W32-NEXT:i32.const 0
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const 1
+; W32-NEXT:i32.and
+; W32-NEXT:i32.sub
+; W32-NEXT:local.get 1
+; W32-NEXT:i32.and
+; W32-NEXT:# fallthrough-return
+;
+; W64-LABEL: test_ctselect_null_ptr:
+; W64: .functype test_ctselect_null_ptr (i32, i64) -> (i64)
+; W64-NEXT:  # %bb.0:
+; W64-NEXT:i64.const 0
+; W64-NEXT:local.get 0
+; W64-NEXT:i64.extend_i32_u
+; W64-NEXT:i64.const 1
+; W64-NEXT:i64.and
+; W64-NEXT:i64.sub
+; W64-NEXT:local.get 1
+; W64-NEXT:i64.and
+; W64-NEXT:# fallthrough-return
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
+  ret ptr %result
+}
+
+; Test with function pointers
+define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
+

[llvm-branch-commits] [clang] [ConstantTime][Clang] Add __builtin_ct_select for constant-time selection (PR #166703)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

wizardengineer wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/166703?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#166703** https://app.graphite.com/github/pr/llvm/llvm-project/166703?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>: 6  dependent PRs 
([#166704](https://github.com/llvm/llvm-project/pull/166704) https://app.graphite.com/github/pr/llvm/llvm-project/166704?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166705](https://github.com/llvm/llvm-project/pull/166705) https://app.graphite.com/github/pr/llvm/llvm-project/166705?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166706](https://github.com/llvm/llvm-project/pull/166706) https://app.graphite.com/github/pr/llvm/llvm-project/166706?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> and 3 others) 👈 https://app.graphite.com/github/pr/llvm/llvm-project/166703?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#166702** https://app.graphite.com/github/pr/llvm/llvm-project/166702?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `main`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/166703
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [ConstantTime][Clang] Add __builtin_ct_select for constant-time selection (PR #166703)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer created 
https://github.com/llvm/llvm-project/pull/166703

None

>From cbb549061c8ec8023ca44b664e0f9d9b4727afde Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 10:56:34 -0500
Subject: [PATCH] [ConstantTime][Clang] Add __builtin_ct_select for
 constant-time selection

---
 clang/include/clang/Basic/Builtins.td |   8 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  35 +
 clang/lib/Sema/SemaChecking.cpp   |  87 +++
 .../test/Sema/builtin-ct-select-edge-cases.c  | 384 ++
 clang/test/Sema/builtin-ct-select.c   | 683 ++
 5 files changed, 1197 insertions(+)
 create mode 100644 clang/test/Sema/builtin-ct-select-edge-cases.c
 create mode 100644 clang/test/Sema/builtin-ct-select.c

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 2b400b012d6ed..13e2a9849bfca 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5278,3 +5278,11 @@ def CountedByRef : Builtin {
   let Attributes = [NoThrow, CustomTypeChecking];
   let Prototype = "int(...)";
 }
+
+// Constant-time select builtin
+def CtSelect : Builtin {
+  let Spellings = ["__builtin_ct_select"];
+  let Attributes = [NoThrow, Const, UnevaluatedArguments,
+ConstIgnoringExceptions, CustomTypeChecking];
+  let Prototype = "void(...)";
+}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index b81e0d02da2c9..6c0a9eb1e7d86 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -28,6 +28,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Basic/DiagnosticSema.h" 
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Intrinsics.h"
@@ -6450,6 +6451,40 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 auto Str = CGM.GetAddrOfConstantCString(Name, "");
 return RValue::get(Str.getPointer());
   }
+  case Builtin::BI__builtin_ct_select: {
+if (E->getNumArgs() != 3) {
+  CGM.getDiags().Report(E->getBeginLoc(),
+E->getNumArgs() > 3
+? diag::err_typecheck_call_too_many_args
+: diag::err_typecheck_call_too_few_args);
+  return GetUndefRValue(E->getType());
+}
+
+auto *Cond = EmitScalarExpr(E->getArg(0));
+auto *A = EmitScalarExpr(E->getArg(1));
+auto *B = EmitScalarExpr(E->getArg(2));
+
+// Verify types match
+if (A->getType() != B->getType()) {
+  CGM.getDiags().Report(E->getBeginLoc(),
+diag::err_typecheck_convert_incompatible);
+  return GetUndefRValue(E->getType());
+}
+
+// Verify condition is integer type
+if (!Cond->getType()->isIntegerTy()) {
+  CGM.getDiags().Report(E->getBeginLoc(), diag::err_typecheck_expect_int);
+  return GetUndefRValue(E->getType());
+}
+
+if (Cond->getType()->getIntegerBitWidth() != 1)
+  Cond = Builder.CreateICmpNE(
+  Cond, llvm::ConstantInt::get(Cond->getType(), 0), "cond.bool");
+
+llvm::Function *Fn =
+CGM.getIntrinsic(llvm::Intrinsic::ct_select, {A->getType()});
+return RValue::get(Builder.CreateCall(Fn, {Cond, A, B}));
+  }
   }
 
   // If this is an alias for a lib function (e.g. __builtin_sin), emit
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ad2c2e4a97bb9..bce47cc4586c6 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3494,6 +3494,93 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
 if (BuiltinCountedByRef(TheCall))
   return ExprError();
 break;
+
+  case Builtin::BI__builtin_ct_select: {
+if (TheCall->getNumArgs() != 3) {
+  // Simple argument count check without complex diagnostics
+  if (TheCall->getNumArgs() < 3) {
+return Diag(TheCall->getEndLoc(), 
diag::err_typecheck_call_too_few_args_at_least)
+   << 0 << 3 << TheCall->getNumArgs() << 0
+   << TheCall->getCallee()->getSourceRange();
+  } else {
+return Diag(TheCall->getEndLoc(), 
diag::err_typecheck_call_too_many_args)
+   << 0 << 3 << TheCall->getNumArgs() << 0
+   << TheCall->getCallee()->getSourceRange();
+  }
+}
+auto *Cond = TheCall->getArg(0);
+auto *A = TheCall->getArg(1);
+auto *B = TheCall->getArg(2);
+
+QualType CondTy = Cond->getType();
+if (!CondTy->isIntegerType()) {
+  return Diag(Cond->getBeginLoc(), diag::err_typecheck_cond_expect_scalar)
+ << CondTy << Cond->getSourceRange();
+}
+
+QualType ATy = A->getType();
+QualType BTy = B->getType();
+
+// check for scalar or vector scalar type
+if ((!ATy->isScalarType() && !ATy->isVectorType()) ||
+(!BTy

[llvm-branch-commits] [llvm] [LLVM][X86] Add native ct.select support for X86 and i386 (PR #166704)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

wizardengineer wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/166704?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#166704** https://app.graphite.com/github/pr/llvm/llvm-project/166704?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/166704?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#166703** https://app.graphite.com/github/pr/llvm/llvm-project/166703?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>: 5 other dependent PRs 
([#166705](https://github.com/llvm/llvm-project/pull/166705) https://app.graphite.com/github/pr/llvm/llvm-project/166705?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166706](https://github.com/llvm/llvm-project/pull/166706) https://app.graphite.com/github/pr/llvm/llvm-project/166706?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166707](https://github.com/llvm/llvm-project/pull/166707) https://app.graphite.com/github/pr/llvm/llvm-project/166707?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> and 2 others)
* **#166702** https://app.graphite.com/github/pr/llvm/llvm-project/166702?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `main`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/166704
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ConstantTime][WebAssembly] Add comprehensive tests for ct.select (PR #166709)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

wizardengineer wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/166709?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#166709** https://app.graphite.com/github/pr/llvm/llvm-project/166709?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/166709?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#166703** https://app.graphite.com/github/pr/llvm/llvm-project/166703?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>: 5 other dependent PRs 
([#166704](https://github.com/llvm/llvm-project/pull/166704) https://app.graphite.com/github/pr/llvm/llvm-project/166704?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166705](https://github.com/llvm/llvm-project/pull/166705) https://app.graphite.com/github/pr/llvm/llvm-project/166705?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166706](https://github.com/llvm/llvm-project/pull/166706) https://app.graphite.com/github/pr/llvm/llvm-project/166706?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> and 2 others)
* **#166702** https://app.graphite.com/github/pr/llvm/llvm-project/166702?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `main`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/166709
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [LLVM][ARM] Add native ct.select support for ARM32 and Thumb (PR #166707)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

wizardengineer wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/166707?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#166707** https://app.graphite.com/github/pr/llvm/llvm-project/166707?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/166707?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#166703** https://app.graphite.com/github/pr/llvm/llvm-project/166703?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>: 5 other dependent PRs 
([#166704](https://github.com/llvm/llvm-project/pull/166704) https://app.graphite.com/github/pr/llvm/llvm-project/166704?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166705](https://github.com/llvm/llvm-project/pull/166705) https://app.graphite.com/github/pr/llvm/llvm-project/166705?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166706](https://github.com/llvm/llvm-project/pull/166706) https://app.graphite.com/github/pr/llvm/llvm-project/166706?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> and 2 others)
* **#166702** https://app.graphite.com/github/pr/llvm/llvm-project/166702?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `main`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/166707
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ConstantTime][RISCV] Add comprehensive tests for ct.select (PR #166708)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

wizardengineer wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/166708?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#166708** https://app.graphite.com/github/pr/llvm/llvm-project/166708?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/166708?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#166703** https://app.graphite.com/github/pr/llvm/llvm-project/166703?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>: 5 other dependent PRs 
([#166704](https://github.com/llvm/llvm-project/pull/166704) https://app.graphite.com/github/pr/llvm/llvm-project/166704?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166705](https://github.com/llvm/llvm-project/pull/166705) https://app.graphite.com/github/pr/llvm/llvm-project/166705?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166706](https://github.com/llvm/llvm-project/pull/166706) https://app.graphite.com/github/pr/llvm/llvm-project/166706?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> and 2 others)
* **#166702** https://app.graphite.com/github/pr/llvm/llvm-project/166702?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `main`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/166708
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [LLVM][AArch64] Add native ct.select support for ARM64 (PR #166706)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

wizardengineer wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/166706?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#166706** https://app.graphite.com/github/pr/llvm/llvm-project/166706?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/166706?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#166703** https://app.graphite.com/github/pr/llvm/llvm-project/166703?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>: 5 other dependent PRs 
([#166704](https://github.com/llvm/llvm-project/pull/166704) https://app.graphite.com/github/pr/llvm/llvm-project/166704?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166705](https://github.com/llvm/llvm-project/pull/166705) https://app.graphite.com/github/pr/llvm/llvm-project/166705?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166707](https://github.com/llvm/llvm-project/pull/166707) https://app.graphite.com/github/pr/llvm/llvm-project/166707?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> and 2 others)
* **#166702** https://app.graphite.com/github/pr/llvm/llvm-project/166702?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `main`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/166706
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [LLVM][MIPS] Add comprehensive tests for ct.select (PR #166705)

2025-11-05 Thread Julius Alexandre via llvm-branch-commits

wizardengineer wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/166705?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#166705** https://app.graphite.com/github/pr/llvm/llvm-project/166705?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/166705?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#166703** https://app.graphite.com/github/pr/llvm/llvm-project/166703?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>: 5 other dependent PRs 
([#166704](https://github.com/llvm/llvm-project/pull/166704) https://app.graphite.com/github/pr/llvm/llvm-project/166704?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166706](https://github.com/llvm/llvm-project/pull/166706) https://app.graphite.com/github/pr/llvm/llvm-project/166706?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>, 
[#166707](https://github.com/llvm/llvm-project/pull/166707) https://app.graphite.com/github/pr/llvm/llvm-project/166707?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> and 2 others)
* **#166702** https://app.graphite.com/github/pr/llvm/llvm-project/166702?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `main`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/166705
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ConstantTime][RISCV] Add comprehensive tests for ct.select (PR #166708)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166708

>From 7aec58aa6f8029c514857a755b5a381e6a6b22af Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 11:01:00 -0500
Subject: [PATCH] [ConstantTime][RISCV] Add comprehensive tests for ct.select

Add comprehensive test suite for RISC-V fallback implementation:
- Edge cases (zero conditions, large integers, sign extension)
- Pattern matching (nested selects, chains)
- Vector support with RVV extensions
- Side effects and memory operations

The basic fallback test is in the core infrastructure PR.
---
 .../RISCV/ctselect-fallback-edge-cases.ll | 214 +
 .../RISCV/ctselect-fallback-patterns.ll   | 383 +
 .../RISCV/ctselect-fallback-vector-rvv.ll | 804 ++
 .../CodeGen/RISCV/ctselect-side-effects.ll| 176 
 4 files changed, 1577 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-patterns.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-vector-rvv.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-side-effects.ll

diff --git a/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll 
b/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
new file mode 100644
index 0..af1be0c8f3ddc
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
@@ -0,0 +1,214 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=riscv64 -O3 | FileCheck %s --check-prefix=RV64
+; RUN: llc < %s -mtriple=riscv32 -O3 | FileCheck %s --check-prefix=RV32
+
+; Test with small integer types
+define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
+; RV64-LABEL: test_ctselect_i1:
+; RV64:   # %bb.0:
+; RV64-NEXT:and a1, a0, a1
+; RV64-NEXT:xori a0, a0, 1
+; RV64-NEXT:and a0, a0, a2
+; RV64-NEXT:or a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_i1:
+; RV32:   # %bb.0:
+; RV32-NEXT:and a1, a0, a1
+; RV32-NEXT:xori a0, a0, 1
+; RV32-NEXT:and a0, a0, a2
+; RV32-NEXT:or a0, a1, a0
+; RV32-NEXT:ret
+  %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
+  ret i1 %result
+}
+
+; Test with extremal values
+define i32 @test_ctselect_extremal_values(i1 %cond) {
+; RV64-LABEL: test_ctselect_extremal_values:
+; RV64:   # %bb.0:
+; RV64-NEXT:andi a0, a0, 1
+; RV64-NEXT:lui a1, 524288
+; RV64-NEXT:subw a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_extremal_values:
+; RV32:   # %bb.0:
+; RV32-NEXT:andi a0, a0, 1
+; RV32-NEXT:lui a1, 524288
+; RV32-NEXT:addi a2, a0, -1
+; RV32-NEXT:neg a0, a0
+; RV32-NEXT:and a1, a2, a1
+; RV32-NEXT:slli a0, a0, 1
+; RV32-NEXT:srli a0, a0, 1
+; RV32-NEXT:or a0, a0, a1
+; RV32-NEXT:ret
+  %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 
-2147483648)
+  ret i32 %result
+}
+
+; Test with null pointers
+define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
+; RV64-LABEL: test_ctselect_null_ptr:
+; RV64:   # %bb.0:
+; RV64-NEXT:slli a0, a0, 63
+; RV64-NEXT:srai a0, a0, 63
+; RV64-NEXT:and a0, a0, a1
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_null_ptr:
+; RV32:   # %bb.0:
+; RV32-NEXT:slli a0, a0, 31
+; RV32-NEXT:srai a0, a0, 31
+; RV32-NEXT:and a0, a0, a1
+; RV32-NEXT:ret
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
+  ret ptr %result
+}
+
+; Test with function pointers
+define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
+; RV64-LABEL: test_ctselect_function_ptr:
+; RV64:   # %bb.0:
+; RV64-NEXT:andi a0, a0, 1
+; RV64-NEXT:neg a3, a0
+; RV64-NEXT:addi a0, a0, -1
+; RV64-NEXT:and a1, a3, a1
+; RV64-NEXT:and a0, a0, a2
+; RV64-NEXT:or a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_function_ptr:
+; RV32:   # %bb.0:
+; RV32-NEXT:andi a0, a0, 1
+; RV32-NEXT:neg a3, a0
+; RV32-NEXT:addi a0, a0, -1
+; RV32-NEXT:and a1, a3, a1
+; RV32-NEXT:and a0, a0, a2
+; RV32-NEXT:or a0, a1, a0
+; RV32-NEXT:ret
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %func1, ptr %func2)
+  ret ptr %result
+}
+
+; Test with condition from icmp on pointers
+define ptr @test_ctselect_ptr_cmp(ptr %p1, ptr %p2, ptr %a, ptr %b) {
+; RV64-LABEL: test_ctselect_ptr_cmp:
+; RV64:   # %bb.0:
+; RV64-NEXT:xor a0, a0, a1
+; RV64-NEXT:snez a0, a0
+; RV64-NEXT:addi a0, a0, -1
+; RV64-NEXT:and a2, a0, a2
+; RV64-NEXT:not a0, a0
+; RV64-NEXT:and a0, a0, a3
+; RV64-NEXT:or a0, a2, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_ptr_cmp:
+; RV32:   # %bb.0:
+; RV32-NEXT:xor a0, a0, a1
+; RV32-NEXT:snez a0, a0
+; RV32-NEXT:addi a0, a0, -1
+; RV32-NEXT:and a2, a0, a2
+; RV32-NEXT:not a0, a0
+; RV32-NEXT:  

[llvm-branch-commits] [llvm] [ConstantTime][RISCV] Add comprehensive tests for ct.select (PR #166708)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer ready_for_review 
https://github.com/llvm/llvm-project/pull/166708
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ConstantTime][WebAssembly] Add comprehensive tests for ct.select (PR #166709)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer ready_for_review 
https://github.com/llvm/llvm-project/pull/166709
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [ConstantTime][Clang] Add __builtin_ct_select for constant-time selection (PR #166703)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer ready_for_review 
https://github.com/llvm/llvm-project/pull/166703
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ConstantTime] Native ct.select support for ARM32 and Thumb (PR #166707)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer ready_for_review 
https://github.com/llvm/llvm-project/pull/166707
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ConstantTime] Native ct.select support for X86 and i386 (PR #166704)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer ready_for_review 
https://github.com/llvm/llvm-project/pull/166704
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ConstantTime][MIPS] Add comprehensive tests for ct.select (PR #166705)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer ready_for_review 
https://github.com/llvm/llvm-project/pull/166705
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ConstantTime] Native ct.select support for ARM64 (PR #166706)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer ready_for_review 
https://github.com/llvm/llvm-project/pull/166706
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ConstantTime][MIPS] Add comprehensive tests for ct.select (PR #166705)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166705

>From 9dac6cad69ae839442c551be1e0a03617f8579d8 Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 11:01:26 -0500
Subject: [PATCH] [LLVM][MIPS] Add comprehensive tests for ct.select

---
 .../Mips/ctselect-fallback-edge-cases.ll  | 244 +
 .../Mips/ctselect-fallback-patterns.ll| 426 +
 .../CodeGen/Mips/ctselect-fallback-vector.ll  | 830 ++
 llvm/test/CodeGen/Mips/ctselect-fallback.ll   | 371 
 .../CodeGen/Mips/ctselect-side-effects.ll | 183 
 5 files changed, 2054 insertions(+)
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-fallback-edge-cases.ll
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-fallback-patterns.ll
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-fallback-vector.ll
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-fallback.ll
 create mode 100644 llvm/test/CodeGen/Mips/ctselect-side-effects.ll

diff --git a/llvm/test/CodeGen/Mips/ctselect-fallback-edge-cases.ll 
b/llvm/test/CodeGen/Mips/ctselect-fallback-edge-cases.ll
new file mode 100644
index 0..f1831a625d4a4
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/ctselect-fallback-edge-cases.ll
@@ -0,0 +1,244 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=mipsel-unknown-linux-gnu -O3 | FileCheck %s 
--check-prefix=M32
+; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -O3 | FileCheck %s 
--check-prefix=M64
+
+; Portable edge case tests
+
+; Test with small integer types
+define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
+; M32-LABEL: test_ctselect_i1:
+; M32:   # %bb.0:
+; M32-NEXT:xori $2, $4, 1
+; M32-NEXT:and $1, $4, $5
+; M32-NEXT:and $2, $2, $6
+; M32-NEXT:jr $ra
+; M32-NEXT:or $2, $1, $2
+;
+; M64-LABEL: test_ctselect_i1:
+; M64:   # %bb.0:
+; M64-NEXT:sll $2, $4, 0
+; M64-NEXT:sll $1, $6, 0
+; M64-NEXT:xori $2, $2, 1
+; M64-NEXT:and $1, $2, $1
+; M64-NEXT:and $2, $4, $5
+; M64-NEXT:sll $2, $2, 0
+; M64-NEXT:jr $ra
+; M64-NEXT:or $2, $2, $1
+  %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
+  ret i1 %result
+}
+
+; Test with extremal values
+define i32 @test_ctselect_extremal_values(i1 %cond) {
+; M32-LABEL: test_ctselect_extremal_values:
+; M32:   # %bb.0:
+; M32-NEXT:lui $3, 32767
+; M32-NEXT:andi $1, $4, 1
+; M32-NEXT:negu $2, $1
+; M32-NEXT:ori $3, $3, 65535
+; M32-NEXT:addiu $1, $1, -1
+; M32-NEXT:and $2, $2, $3
+; M32-NEXT:lui $3, 32768
+; M32-NEXT:and $1, $1, $3
+; M32-NEXT:jr $ra
+; M32-NEXT:or $2, $2, $1
+;
+; M64-LABEL: test_ctselect_extremal_values:
+; M64:   # %bb.0:
+; M64-NEXT:sll $1, $4, 0
+; M64-NEXT:lui $3, 32767
+; M64-NEXT:andi $1, $1, 1
+; M64-NEXT:ori $3, $3, 65535
+; M64-NEXT:negu $2, $1
+; M64-NEXT:addiu $1, $1, -1
+; M64-NEXT:and $2, $2, $3
+; M64-NEXT:lui $3, 32768
+; M64-NEXT:and $1, $1, $3
+; M64-NEXT:jr $ra
+; M64-NEXT:or $2, $2, $1
+  %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 
-2147483648)
+  ret i32 %result
+}
+
+; Test with null pointers
+define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
+; M32-LABEL: test_ctselect_null_ptr:
+; M32:   # %bb.0:
+; M32-NEXT:andi $1, $4, 1
+; M32-NEXT:negu $1, $1
+; M32-NEXT:jr $ra
+; M32-NEXT:and $2, $1, $5
+;
+; M64-LABEL: test_ctselect_null_ptr:
+; M64:   # %bb.0:
+; M64-NEXT:andi $1, $4, 1
+; M64-NEXT:dnegu $1, $1
+; M64-NEXT:jr $ra
+; M64-NEXT:and $2, $1, $5
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
+  ret ptr %result
+}
+
+; Test with function pointers
+define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
+; M32-LABEL: test_ctselect_function_ptr:
+; M32:   # %bb.0:
+; M32-NEXT:andi $1, $4, 1
+; M32-NEXT:negu $2, $1
+; M32-NEXT:addiu $1, $1, -1
+; M32-NEXT:and $2, $2, $5
+; M32-NEXT:and $1, $1, $6
+; M32-NEXT:jr $ra
+; M32-NEXT:or $2, $2, $1
+;
+; M64-LABEL: test_ctselect_function_ptr:
+; M64:   # %bb.0:
+; M64-NEXT:andi $1, $4, 1
+; M64-NEXT:dnegu $2, $1
+; M64-NEXT:daddiu $1, $1, -1
+; M64-NEXT:and $2, $2, $5
+; M64-NEXT:and $1, $1, $6
+; M64-NEXT:jr $ra
+; M64-NEXT:or $2, $2, $1
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %func1, ptr %func2)
+  ret ptr %result
+}
+
+; Test with condition from icmp on pointers
+define ptr @test_ctselect_ptr_cmp(ptr %p1, ptr %p2, ptr %a, ptr %b) {
+; M32-LABEL: test_ctselect_ptr_cmp:
+; M32:   # %bb.0:
+; M32-NEXT:xor $1, $4, $5
+; M32-NEXT:sltu $1, $zero, $1
+; M32-NEXT:addiu $1, $1, -1
+; M32-NEXT:and $2, $1, $6
+; M32-NEXT:not $1, $1
+; M32-NEXT:and $1, $1, $7
+; M32-NEXT:jr $ra
+; M32-NEXT:or $2, $2, $1
+;
+; M64-LABEL: test_ctselect_ptr_cmp:
+; M64:   # %bb.0:
+; M6

[llvm-branch-commits] [llvm] [ConstantTime] Native ct.select support for ARM64 (PR #166706)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166706

>From 7de2b8134fa87b1f113834b5ab0b218cbde5a821 Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 17:09:45 -0500
Subject: [PATCH] [LLVM][AArch64] Add native ct.select support for ARM64

This patch implements architecture-specific lowering for ct.select on AArch64
using CSEL (conditional select) instructions for constant-time selection.

Implementation details:
- Uses CSEL family of instructions for scalar integer types
- Uses FCSEL for floating-point types (F16, BF16, F32, F64)
- Post-RA MC lowering to convert pseudo-instructions to real CSEL/FCSEL
- Handles vector types appropriately
- Comprehensive test coverage for AArch64

The implementation includes:
- ISelLowering: Custom lowering to CTSELECT pseudo-instructions
- InstrInfo: Pseudo-instruction definitions and patterns
- MCInstLower: Post-RA lowering of pseudo-instructions to actual CSEL/FCSEL
- Proper handling of condition codes for constant-time guarantees
---
 .../Target/AArch64/AArch64ISelLowering.cpp|  56 +
 llvm/lib/Target/AArch64/AArch64ISelLowering.h |  11 +
 llvm/lib/Target/AArch64/AArch64InstrInfo.cpp  | 200 --
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  40 
 .../lib/Target/AArch64/AArch64MCInstLower.cpp |  18 ++
 llvm/test/CodeGen/AArch64/ctselect.ll | 153 ++
 6 files changed, 368 insertions(+), 110 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/ctselect.ll

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 60aa61e993b26..54d0ea168d0b6 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -511,12 +511,36 @@ AArch64TargetLowering::AArch64TargetLowering(const 
TargetMachine &TM,
   setOperationAction(ISD::BR_CC, MVT::f64, Custom);
   setOperationAction(ISD::SELECT, MVT::i32, Custom);
   setOperationAction(ISD::SELECT, MVT::i64, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::i8, Promote);
+  setOperationAction(ISD::CTSELECT, MVT::i16, Promote);
+  setOperationAction(ISD::CTSELECT, MVT::i32, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::i64, Custom);
   if (Subtarget->hasFPARMv8()) {
 setOperationAction(ISD::SELECT, MVT::f16, Custom);
 setOperationAction(ISD::SELECT, MVT::bf16, Custom);
   }
+  if (Subtarget->hasFullFP16()) {
+setOperationAction(ISD::CTSELECT, MVT::f16, Custom);
+setOperationAction(ISD::CTSELECT, MVT::bf16, Custom);
+  } else {
+setOperationAction(ISD::CTSELECT, MVT::f16, Promote);
+setOperationAction(ISD::CTSELECT, MVT::bf16, Promote);
+  }
   setOperationAction(ISD::SELECT, MVT::f32, Custom);
   setOperationAction(ISD::SELECT, MVT::f64, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::f32, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::f64, Custom);
+  for (MVT VT : MVT::vector_valuetypes()) {
+MVT elemType = VT.getVectorElementType();
+if (elemType == MVT::i8 || elemType == MVT::i16) {
+  setOperationAction(ISD::CTSELECT, VT, Promote);
+} else if ((elemType == MVT::f16 || elemType == MVT::bf16) &&
+   !Subtarget->hasFullFP16()) {
+  setOperationAction(ISD::CTSELECT, VT, Promote);
+} else {
+  setOperationAction(ISD::CTSELECT, VT, Expand);
+}
+  }
   setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
   setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
   setOperationAction(ISD::SELECT_CC, MVT::f16, Custom);
@@ -3328,6 +3352,20 @@ void AArch64TargetLowering::fixupPtrauthDiscriminator(
   IntDiscOp.setImm(IntDisc);
 }
 
+MachineBasicBlock *AArch64TargetLowering::EmitCTSELECT(MachineInstr &MI,
+   MachineBasicBlock *MBB,
+   unsigned Opcode) const {
+  const TargetInstrInfo *TII = Subtarget->getInstrInfo();
+  DebugLoc DL = MI.getDebugLoc();
+  MachineInstrBuilder Builder = BuildMI(*MBB, MI, DL, TII->get(Opcode));
+  for (unsigned Idx = 0; Idx < MI.getNumOperands(); ++Idx) {
+Builder.add(MI.getOperand(Idx));
+  }
+  Builder->setFlag(MachineInstr::NoMerge);
+  MBB->remove_instr(&MI);
+  return MBB;
+}
+
 MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
 MachineInstr &MI, MachineBasicBlock *BB) const {
 
@@ -7590,6 +7628,8 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
 return LowerSELECT(Op, DAG);
   case ISD::SELECT_CC:
 return LowerSELECT_CC(Op, DAG);
+  case ISD::CTSELECT:
+return LowerCTSELECT(Op, DAG);
   case ISD::JumpTable:
 return LowerJumpTable(Op, DAG);
   case ISD::BR_JT:
@@ -12149,6 +12189,22 @@ SDValue AArch64TargetLowering::LowerSELECT(SDValue Op,
   return Res;
 }
 
+SDValue AArch64TargetLowering::LowerCTSELECT(SDValue Op,
+ SelectionDAG &DAG) const {
+  SDValue CCVal = Op->getOperand(0);
+  SDValue TVal = Op->getOper

[llvm-branch-commits] [llvm] [ConstantTime][WebAssembly] Add comprehensive tests for ct.select (PR #166709)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166709

>From 046e875568de9a6a794725bc69572151be8b8b9f Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 11:03:23 -0500
Subject: [PATCH] [ConstantTime][WebAssembly] Add comprehensive tests for
 ct.select

---
 .../ctselect-fallback-edge-cases.ll   | 376 +
 .../WebAssembly/ctselect-fallback-patterns.ll | 641 
 .../WebAssembly/ctselect-fallback-vector.ll   | 714 ++
 .../CodeGen/WebAssembly/ctselect-fallback.ll  | 552 ++
 .../WebAssembly/ctselect-side-effects.ll  | 226 ++
 5 files changed, 2509 insertions(+)
 create mode 100644 
llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-fallback-patterns.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-fallback-vector.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-fallback.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-side-effects.ll

diff --git a/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll 
b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll
new file mode 100644
index 0..b0f7f2807debd
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll
@@ -0,0 +1,376 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=wasm32-unknown-unknown -O3 -filetype=asm | FileCheck 
%s --check-prefix=W32
+; RUN: llc < %s -mtriple=wasm64-unknown-unknown -O3 -filetype=asm | FileCheck 
%s --check-prefix=W64
+
+; Test with small integer types
+define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
+; W32-LABEL: test_ctselect_i1:
+; W32: .functype test_ctselect_i1 (i32, i32, i32) -> (i32)
+; W32-NEXT:  # %bb.0:
+; W32-NEXT:local.get 0
+; W32-NEXT:local.get 1
+; W32-NEXT:i32.and
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const 1
+; W32-NEXT:i32.xor
+; W32-NEXT:local.get 2
+; W32-NEXT:i32.and
+; W32-NEXT:i32.or
+; W32-NEXT:# fallthrough-return
+;
+; W64-LABEL: test_ctselect_i1:
+; W64: .functype test_ctselect_i1 (i32, i32, i32) -> (i32)
+; W64-NEXT:  # %bb.0:
+; W64-NEXT:local.get 0
+; W64-NEXT:local.get 1
+; W64-NEXT:i32.and
+; W64-NEXT:local.get 0
+; W64-NEXT:i32.const 1
+; W64-NEXT:i32.xor
+; W64-NEXT:local.get 2
+; W64-NEXT:i32.and
+; W64-NEXT:i32.or
+; W64-NEXT:# fallthrough-return
+  %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
+  ret i1 %result
+}
+
+; Test with extremal values
+define i32 @test_ctselect_extremal_values(i1 %cond) {
+; W32-LABEL: test_ctselect_extremal_values:
+; W32: .functype test_ctselect_extremal_values (i32) -> (i32)
+; W32-NEXT:  # %bb.0:
+; W32-NEXT:i32.const 0
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const 1
+; W32-NEXT:i32.and
+; W32-NEXT:local.tee 0
+; W32-NEXT:i32.sub
+; W32-NEXT:i32.const 2147483647
+; W32-NEXT:i32.and
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const -1
+; W32-NEXT:i32.add
+; W32-NEXT:i32.const -2147483648
+; W32-NEXT:i32.and
+; W32-NEXT:i32.or
+; W32-NEXT:# fallthrough-return
+;
+; W64-LABEL: test_ctselect_extremal_values:
+; W64: .functype test_ctselect_extremal_values (i32) -> (i32)
+; W64-NEXT:  # %bb.0:
+; W64-NEXT:i32.const 0
+; W64-NEXT:local.get 0
+; W64-NEXT:i32.const 1
+; W64-NEXT:i32.and
+; W64-NEXT:local.tee 0
+; W64-NEXT:i32.sub
+; W64-NEXT:i32.const 2147483647
+; W64-NEXT:i32.and
+; W64-NEXT:local.get 0
+; W64-NEXT:i32.const -1
+; W64-NEXT:i32.add
+; W64-NEXT:i32.const -2147483648
+; W64-NEXT:i32.and
+; W64-NEXT:i32.or
+; W64-NEXT:# fallthrough-return
+  %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 
-2147483648)
+  ret i32 %result
+}
+
+; Test with null pointers
+define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
+; W32-LABEL: test_ctselect_null_ptr:
+; W32: .functype test_ctselect_null_ptr (i32, i32) -> (i32)
+; W32-NEXT:  # %bb.0:
+; W32-NEXT:i32.const 0
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const 1
+; W32-NEXT:i32.and
+; W32-NEXT:i32.sub
+; W32-NEXT:local.get 1
+; W32-NEXT:i32.and
+; W32-NEXT:# fallthrough-return
+;
+; W64-LABEL: test_ctselect_null_ptr:
+; W64: .functype test_ctselect_null_ptr (i32, i64) -> (i64)
+; W64-NEXT:  # %bb.0:
+; W64-NEXT:i64.const 0
+; W64-NEXT:local.get 0
+; W64-NEXT:i64.extend_i32_u
+; W64-NEXT:i64.const 1
+; W64-NEXT:i64.and
+; W64-NEXT:i64.sub
+; W64-NEXT:local.get 1
+; W64-NEXT:i64.and
+; W64-NEXT:# fallthrough-return
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
+  ret ptr %result
+}
+
+; Test with function pointers
+define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
+; W32-

[llvm-branch-commits] [llvm] [ConstantTime][RISCV] Add comprehensive tests for ct.select (PR #166708)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166708

>From 9ed3c7d206aa6d9dcba0fdbc3afe773b431bf597 Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 11:01:00 -0500
Subject: [PATCH] [ConstantTime][RISCV] Add comprehensive tests for ct.select

Add comprehensive test suite for RISC-V fallback implementation:
- Edge cases (zero conditions, large integers, sign extension)
- Pattern matching (nested selects, chains)
- Vector support with RVV extensions
- Side effects and memory operations

The basic fallback test is in the core infrastructure PR.
---
 .../RISCV/ctselect-fallback-edge-cases.ll | 214 +
 .../RISCV/ctselect-fallback-patterns.ll   | 383 +
 .../RISCV/ctselect-fallback-vector-rvv.ll | 804 ++
 llvm/test/CodeGen/RISCV/ctselect-fallback.ll  | 330 ---
 .../CodeGen/RISCV/ctselect-side-effects.ll| 176 
 5 files changed, 1577 insertions(+), 330 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-patterns.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-vector-rvv.ll
 delete mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-side-effects.ll

diff --git a/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll 
b/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
new file mode 100644
index 0..af1be0c8f3ddc
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
@@ -0,0 +1,214 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=riscv64 -O3 | FileCheck %s --check-prefix=RV64
+; RUN: llc < %s -mtriple=riscv32 -O3 | FileCheck %s --check-prefix=RV32
+
+; Test with small integer types
+define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
+; RV64-LABEL: test_ctselect_i1:
+; RV64:   # %bb.0:
+; RV64-NEXT:and a1, a0, a1
+; RV64-NEXT:xori a0, a0, 1
+; RV64-NEXT:and a0, a0, a2
+; RV64-NEXT:or a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_i1:
+; RV32:   # %bb.0:
+; RV32-NEXT:and a1, a0, a1
+; RV32-NEXT:xori a0, a0, 1
+; RV32-NEXT:and a0, a0, a2
+; RV32-NEXT:or a0, a1, a0
+; RV32-NEXT:ret
+  %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
+  ret i1 %result
+}
+
+; Test with extremal values
+define i32 @test_ctselect_extremal_values(i1 %cond) {
+; RV64-LABEL: test_ctselect_extremal_values:
+; RV64:   # %bb.0:
+; RV64-NEXT:andi a0, a0, 1
+; RV64-NEXT:lui a1, 524288
+; RV64-NEXT:subw a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_extremal_values:
+; RV32:   # %bb.0:
+; RV32-NEXT:andi a0, a0, 1
+; RV32-NEXT:lui a1, 524288
+; RV32-NEXT:addi a2, a0, -1
+; RV32-NEXT:neg a0, a0
+; RV32-NEXT:and a1, a2, a1
+; RV32-NEXT:slli a0, a0, 1
+; RV32-NEXT:srli a0, a0, 1
+; RV32-NEXT:or a0, a0, a1
+; RV32-NEXT:ret
+  %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 
-2147483648)
+  ret i32 %result
+}
+
+; Test with null pointers
+define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
+; RV64-LABEL: test_ctselect_null_ptr:
+; RV64:   # %bb.0:
+; RV64-NEXT:slli a0, a0, 63
+; RV64-NEXT:srai a0, a0, 63
+; RV64-NEXT:and a0, a0, a1
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_null_ptr:
+; RV32:   # %bb.0:
+; RV32-NEXT:slli a0, a0, 31
+; RV32-NEXT:srai a0, a0, 31
+; RV32-NEXT:and a0, a0, a1
+; RV32-NEXT:ret
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
+  ret ptr %result
+}
+
+; Test with function pointers
+define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
+; RV64-LABEL: test_ctselect_function_ptr:
+; RV64:   # %bb.0:
+; RV64-NEXT:andi a0, a0, 1
+; RV64-NEXT:neg a3, a0
+; RV64-NEXT:addi a0, a0, -1
+; RV64-NEXT:and a1, a3, a1
+; RV64-NEXT:and a0, a0, a2
+; RV64-NEXT:or a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_function_ptr:
+; RV32:   # %bb.0:
+; RV32-NEXT:andi a0, a0, 1
+; RV32-NEXT:neg a3, a0
+; RV32-NEXT:addi a0, a0, -1
+; RV32-NEXT:and a1, a3, a1
+; RV32-NEXT:and a0, a0, a2
+; RV32-NEXT:or a0, a1, a0
+; RV32-NEXT:ret
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %func1, ptr %func2)
+  ret ptr %result
+}
+
+; Test with condition from icmp on pointers
+define ptr @test_ctselect_ptr_cmp(ptr %p1, ptr %p2, ptr %a, ptr %b) {
+; RV64-LABEL: test_ctselect_ptr_cmp:
+; RV64:   # %bb.0:
+; RV64-NEXT:xor a0, a0, a1
+; RV64-NEXT:snez a0, a0
+; RV64-NEXT:addi a0, a0, -1
+; RV64-NEXT:and a2, a0, a2
+; RV64-NEXT:not a0, a0
+; RV64-NEXT:and a0, a0, a3
+; RV64-NEXT:or a0, a2, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_ptr_cmp:
+; RV32:   # %bb.0:
+; RV32-NEXT:xor a0, 

[llvm-branch-commits] [llvm] [ConstantTime][RISCV] Add comprehensive tests for ct.select (PR #166708)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166708

>From 9ed3c7d206aa6d9dcba0fdbc3afe773b431bf597 Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 11:01:00 -0500
Subject: [PATCH] [ConstantTime][RISCV] Add comprehensive tests for ct.select

Add comprehensive test suite for RISC-V fallback implementation:
- Edge cases (zero conditions, large integers, sign extension)
- Pattern matching (nested selects, chains)
- Vector support with RVV extensions
- Side effects and memory operations

The basic fallback test is in the core infrastructure PR.
---
 .../RISCV/ctselect-fallback-edge-cases.ll | 214 +
 .../RISCV/ctselect-fallback-patterns.ll   | 383 +
 .../RISCV/ctselect-fallback-vector-rvv.ll | 804 ++
 llvm/test/CodeGen/RISCV/ctselect-fallback.ll  | 330 ---
 .../CodeGen/RISCV/ctselect-side-effects.ll| 176 
 5 files changed, 1577 insertions(+), 330 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-patterns.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback-vector-rvv.ll
 delete mode 100644 llvm/test/CodeGen/RISCV/ctselect-fallback.ll
 create mode 100644 llvm/test/CodeGen/RISCV/ctselect-side-effects.ll

diff --git a/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll 
b/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
new file mode 100644
index 0..af1be0c8f3ddc
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/ctselect-fallback-edge-cases.ll
@@ -0,0 +1,214 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=riscv64 -O3 | FileCheck %s --check-prefix=RV64
+; RUN: llc < %s -mtriple=riscv32 -O3 | FileCheck %s --check-prefix=RV32
+
+; Test with small integer types
+define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
+; RV64-LABEL: test_ctselect_i1:
+; RV64:   # %bb.0:
+; RV64-NEXT:and a1, a0, a1
+; RV64-NEXT:xori a0, a0, 1
+; RV64-NEXT:and a0, a0, a2
+; RV64-NEXT:or a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_i1:
+; RV32:   # %bb.0:
+; RV32-NEXT:and a1, a0, a1
+; RV32-NEXT:xori a0, a0, 1
+; RV32-NEXT:and a0, a0, a2
+; RV32-NEXT:or a0, a1, a0
+; RV32-NEXT:ret
+  %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
+  ret i1 %result
+}
+
+; Test with extremal values
+define i32 @test_ctselect_extremal_values(i1 %cond) {
+; RV64-LABEL: test_ctselect_extremal_values:
+; RV64:   # %bb.0:
+; RV64-NEXT:andi a0, a0, 1
+; RV64-NEXT:lui a1, 524288
+; RV64-NEXT:subw a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_extremal_values:
+; RV32:   # %bb.0:
+; RV32-NEXT:andi a0, a0, 1
+; RV32-NEXT:lui a1, 524288
+; RV32-NEXT:addi a2, a0, -1
+; RV32-NEXT:neg a0, a0
+; RV32-NEXT:and a1, a2, a1
+; RV32-NEXT:slli a0, a0, 1
+; RV32-NEXT:srli a0, a0, 1
+; RV32-NEXT:or a0, a0, a1
+; RV32-NEXT:ret
+  %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 
-2147483648)
+  ret i32 %result
+}
+
+; Test with null pointers
+define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
+; RV64-LABEL: test_ctselect_null_ptr:
+; RV64:   # %bb.0:
+; RV64-NEXT:slli a0, a0, 63
+; RV64-NEXT:srai a0, a0, 63
+; RV64-NEXT:and a0, a0, a1
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_null_ptr:
+; RV32:   # %bb.0:
+; RV32-NEXT:slli a0, a0, 31
+; RV32-NEXT:srai a0, a0, 31
+; RV32-NEXT:and a0, a0, a1
+; RV32-NEXT:ret
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
+  ret ptr %result
+}
+
+; Test with function pointers
+define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
+; RV64-LABEL: test_ctselect_function_ptr:
+; RV64:   # %bb.0:
+; RV64-NEXT:andi a0, a0, 1
+; RV64-NEXT:neg a3, a0
+; RV64-NEXT:addi a0, a0, -1
+; RV64-NEXT:and a1, a3, a1
+; RV64-NEXT:and a0, a0, a2
+; RV64-NEXT:or a0, a1, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_function_ptr:
+; RV32:   # %bb.0:
+; RV32-NEXT:andi a0, a0, 1
+; RV32-NEXT:neg a3, a0
+; RV32-NEXT:addi a0, a0, -1
+; RV32-NEXT:and a1, a3, a1
+; RV32-NEXT:and a0, a0, a2
+; RV32-NEXT:or a0, a1, a0
+; RV32-NEXT:ret
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %func1, ptr %func2)
+  ret ptr %result
+}
+
+; Test with condition from icmp on pointers
+define ptr @test_ctselect_ptr_cmp(ptr %p1, ptr %p2, ptr %a, ptr %b) {
+; RV64-LABEL: test_ctselect_ptr_cmp:
+; RV64:   # %bb.0:
+; RV64-NEXT:xor a0, a0, a1
+; RV64-NEXT:snez a0, a0
+; RV64-NEXT:addi a0, a0, -1
+; RV64-NEXT:and a2, a0, a2
+; RV64-NEXT:not a0, a0
+; RV64-NEXT:and a0, a0, a3
+; RV64-NEXT:or a0, a2, a0
+; RV64-NEXT:ret
+;
+; RV32-LABEL: test_ctselect_ptr_cmp:
+; RV32:   # %bb.0:
+; RV32-NEXT:xor a0, 

[llvm-branch-commits] [llvm] [ConstantTime] Native ct.select support for ARM64 (PR #166706)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166706

>From 7de2b8134fa87b1f113834b5ab0b218cbde5a821 Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 17:09:45 -0500
Subject: [PATCH] [LLVM][AArch64] Add native ct.select support for ARM64

This patch implements architecture-specific lowering for ct.select on AArch64
using CSEL (conditional select) instructions for constant-time selection.

Implementation details:
- Uses CSEL family of instructions for scalar integer types
- Uses FCSEL for floating-point types (F16, BF16, F32, F64)
- Post-RA MC lowering to convert pseudo-instructions to real CSEL/FCSEL
- Handles vector types appropriately
- Comprehensive test coverage for AArch64

The implementation includes:
- ISelLowering: Custom lowering to CTSELECT pseudo-instructions
- InstrInfo: Pseudo-instruction definitions and patterns
- MCInstLower: Post-RA lowering of pseudo-instructions to actual CSEL/FCSEL
- Proper handling of condition codes for constant-time guarantees
---
 .../Target/AArch64/AArch64ISelLowering.cpp|  56 +
 llvm/lib/Target/AArch64/AArch64ISelLowering.h |  11 +
 llvm/lib/Target/AArch64/AArch64InstrInfo.cpp  | 200 --
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  40 
 .../lib/Target/AArch64/AArch64MCInstLower.cpp |  18 ++
 llvm/test/CodeGen/AArch64/ctselect.ll | 153 ++
 6 files changed, 368 insertions(+), 110 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/ctselect.ll

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 60aa61e993b26..54d0ea168d0b6 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -511,12 +511,36 @@ AArch64TargetLowering::AArch64TargetLowering(const 
TargetMachine &TM,
   setOperationAction(ISD::BR_CC, MVT::f64, Custom);
   setOperationAction(ISD::SELECT, MVT::i32, Custom);
   setOperationAction(ISD::SELECT, MVT::i64, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::i8, Promote);
+  setOperationAction(ISD::CTSELECT, MVT::i16, Promote);
+  setOperationAction(ISD::CTSELECT, MVT::i32, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::i64, Custom);
   if (Subtarget->hasFPARMv8()) {
 setOperationAction(ISD::SELECT, MVT::f16, Custom);
 setOperationAction(ISD::SELECT, MVT::bf16, Custom);
   }
+  if (Subtarget->hasFullFP16()) {
+setOperationAction(ISD::CTSELECT, MVT::f16, Custom);
+setOperationAction(ISD::CTSELECT, MVT::bf16, Custom);
+  } else {
+setOperationAction(ISD::CTSELECT, MVT::f16, Promote);
+setOperationAction(ISD::CTSELECT, MVT::bf16, Promote);
+  }
   setOperationAction(ISD::SELECT, MVT::f32, Custom);
   setOperationAction(ISD::SELECT, MVT::f64, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::f32, Custom);
+  setOperationAction(ISD::CTSELECT, MVT::f64, Custom);
+  for (MVT VT : MVT::vector_valuetypes()) {
+MVT elemType = VT.getVectorElementType();
+if (elemType == MVT::i8 || elemType == MVT::i16) {
+  setOperationAction(ISD::CTSELECT, VT, Promote);
+} else if ((elemType == MVT::f16 || elemType == MVT::bf16) &&
+   !Subtarget->hasFullFP16()) {
+  setOperationAction(ISD::CTSELECT, VT, Promote);
+} else {
+  setOperationAction(ISD::CTSELECT, VT, Expand);
+}
+  }
   setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
   setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
   setOperationAction(ISD::SELECT_CC, MVT::f16, Custom);
@@ -3328,6 +3352,20 @@ void AArch64TargetLowering::fixupPtrauthDiscriminator(
   IntDiscOp.setImm(IntDisc);
 }
 
+MachineBasicBlock *AArch64TargetLowering::EmitCTSELECT(MachineInstr &MI,
+   MachineBasicBlock *MBB,
+   unsigned Opcode) const {
+  const TargetInstrInfo *TII = Subtarget->getInstrInfo();
+  DebugLoc DL = MI.getDebugLoc();
+  MachineInstrBuilder Builder = BuildMI(*MBB, MI, DL, TII->get(Opcode));
+  for (unsigned Idx = 0; Idx < MI.getNumOperands(); ++Idx) {
+Builder.add(MI.getOperand(Idx));
+  }
+  Builder->setFlag(MachineInstr::NoMerge);
+  MBB->remove_instr(&MI);
+  return MBB;
+}
+
 MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter(
 MachineInstr &MI, MachineBasicBlock *BB) const {
 
@@ -7590,6 +7628,8 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
 return LowerSELECT(Op, DAG);
   case ISD::SELECT_CC:
 return LowerSELECT_CC(Op, DAG);
+  case ISD::CTSELECT:
+return LowerCTSELECT(Op, DAG);
   case ISD::JumpTable:
 return LowerJumpTable(Op, DAG);
   case ISD::BR_JT:
@@ -12149,6 +12189,22 @@ SDValue AArch64TargetLowering::LowerSELECT(SDValue Op,
   return Res;
 }
 
+SDValue AArch64TargetLowering::LowerCTSELECT(SDValue Op,
+ SelectionDAG &DAG) const {
+  SDValue CCVal = Op->getOperand(0);
+  SDValue TVal = Op->getOper

[llvm-branch-commits] [llvm] [ConstantTime][WebAssembly] Add comprehensive tests for ct.select (PR #166709)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166709

>From 046e875568de9a6a794725bc69572151be8b8b9f Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 11:03:23 -0500
Subject: [PATCH] [ConstantTime][WebAssembly] Add comprehensive tests for
 ct.select

---
 .../ctselect-fallback-edge-cases.ll   | 376 +
 .../WebAssembly/ctselect-fallback-patterns.ll | 641 
 .../WebAssembly/ctselect-fallback-vector.ll   | 714 ++
 .../CodeGen/WebAssembly/ctselect-fallback.ll  | 552 ++
 .../WebAssembly/ctselect-side-effects.ll  | 226 ++
 5 files changed, 2509 insertions(+)
 create mode 100644 
llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-fallback-patterns.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-fallback-vector.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-fallback.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/ctselect-side-effects.ll

diff --git a/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll 
b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll
new file mode 100644
index 0..b0f7f2807debd
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/ctselect-fallback-edge-cases.ll
@@ -0,0 +1,376 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=wasm32-unknown-unknown -O3 -filetype=asm | FileCheck 
%s --check-prefix=W32
+; RUN: llc < %s -mtriple=wasm64-unknown-unknown -O3 -filetype=asm | FileCheck 
%s --check-prefix=W64
+
+; Test with small integer types
+define i1 @test_ctselect_i1(i1 %cond, i1 %a, i1 %b) {
+; W32-LABEL: test_ctselect_i1:
+; W32: .functype test_ctselect_i1 (i32, i32, i32) -> (i32)
+; W32-NEXT:  # %bb.0:
+; W32-NEXT:local.get 0
+; W32-NEXT:local.get 1
+; W32-NEXT:i32.and
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const 1
+; W32-NEXT:i32.xor
+; W32-NEXT:local.get 2
+; W32-NEXT:i32.and
+; W32-NEXT:i32.or
+; W32-NEXT:# fallthrough-return
+;
+; W64-LABEL: test_ctselect_i1:
+; W64: .functype test_ctselect_i1 (i32, i32, i32) -> (i32)
+; W64-NEXT:  # %bb.0:
+; W64-NEXT:local.get 0
+; W64-NEXT:local.get 1
+; W64-NEXT:i32.and
+; W64-NEXT:local.get 0
+; W64-NEXT:i32.const 1
+; W64-NEXT:i32.xor
+; W64-NEXT:local.get 2
+; W64-NEXT:i32.and
+; W64-NEXT:i32.or
+; W64-NEXT:# fallthrough-return
+  %result = call i1 @llvm.ct.select.i1(i1 %cond, i1 %a, i1 %b)
+  ret i1 %result
+}
+
+; Test with extremal values
+define i32 @test_ctselect_extremal_values(i1 %cond) {
+; W32-LABEL: test_ctselect_extremal_values:
+; W32: .functype test_ctselect_extremal_values (i32) -> (i32)
+; W32-NEXT:  # %bb.0:
+; W32-NEXT:i32.const 0
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const 1
+; W32-NEXT:i32.and
+; W32-NEXT:local.tee 0
+; W32-NEXT:i32.sub
+; W32-NEXT:i32.const 2147483647
+; W32-NEXT:i32.and
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const -1
+; W32-NEXT:i32.add
+; W32-NEXT:i32.const -2147483648
+; W32-NEXT:i32.and
+; W32-NEXT:i32.or
+; W32-NEXT:# fallthrough-return
+;
+; W64-LABEL: test_ctselect_extremal_values:
+; W64: .functype test_ctselect_extremal_values (i32) -> (i32)
+; W64-NEXT:  # %bb.0:
+; W64-NEXT:i32.const 0
+; W64-NEXT:local.get 0
+; W64-NEXT:i32.const 1
+; W64-NEXT:i32.and
+; W64-NEXT:local.tee 0
+; W64-NEXT:i32.sub
+; W64-NEXT:i32.const 2147483647
+; W64-NEXT:i32.and
+; W64-NEXT:local.get 0
+; W64-NEXT:i32.const -1
+; W64-NEXT:i32.add
+; W64-NEXT:i32.const -2147483648
+; W64-NEXT:i32.and
+; W64-NEXT:i32.or
+; W64-NEXT:# fallthrough-return
+  %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 2147483647, i32 
-2147483648)
+  ret i32 %result
+}
+
+; Test with null pointers
+define ptr @test_ctselect_null_ptr(i1 %cond, ptr %ptr) {
+; W32-LABEL: test_ctselect_null_ptr:
+; W32: .functype test_ctselect_null_ptr (i32, i32) -> (i32)
+; W32-NEXT:  # %bb.0:
+; W32-NEXT:i32.const 0
+; W32-NEXT:local.get 0
+; W32-NEXT:i32.const 1
+; W32-NEXT:i32.and
+; W32-NEXT:i32.sub
+; W32-NEXT:local.get 1
+; W32-NEXT:i32.and
+; W32-NEXT:# fallthrough-return
+;
+; W64-LABEL: test_ctselect_null_ptr:
+; W64: .functype test_ctselect_null_ptr (i32, i64) -> (i64)
+; W64-NEXT:  # %bb.0:
+; W64-NEXT:i64.const 0
+; W64-NEXT:local.get 0
+; W64-NEXT:i64.extend_i32_u
+; W64-NEXT:i64.const 1
+; W64-NEXT:i64.and
+; W64-NEXT:i64.sub
+; W64-NEXT:local.get 1
+; W64-NEXT:i64.and
+; W64-NEXT:# fallthrough-return
+  %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %ptr, ptr null)
+  ret ptr %result
+}
+
+; Test with function pointers
+define ptr @test_ctselect_function_ptr(i1 %cond, ptr %func1, ptr %func2) {
+; W32-

[llvm-branch-commits] [clang] [ConstantTime][Clang] Add __builtin_ct_select for constant-time selection (PR #166703)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166703

>From 6ac8221eef92f3e8c615c2218b8db2e3d26cf692 Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 10:56:34 -0500
Subject: [PATCH] [ConstantTime][Clang] Add __builtin_ct_select for
 constant-time selection

---
 clang/include/clang/Basic/Builtins.td |   8 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  37 +-
 clang/lib/Sema/SemaChecking.cpp   |  89 +++
 .../test/Sema/builtin-ct-select-edge-cases.c  | 384 ++
 clang/test/Sema/builtin-ct-select.c   | 683 ++
 5 files changed, 1200 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Sema/builtin-ct-select-edge-cases.c
 create mode 100644 clang/test/Sema/builtin-ct-select.c

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 2b400b012d6ed..13e2a9849bfca 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5278,3 +5278,11 @@ def CountedByRef : Builtin {
   let Attributes = [NoThrow, CustomTypeChecking];
   let Prototype = "int(...)";
 }
+
+// Constant-time select builtin
+def CtSelect : Builtin {
+  let Spellings = ["__builtin_ct_select"];
+  let Attributes = [NoThrow, Const, UnevaluatedArguments,
+ConstIgnoringExceptions, CustomTypeChecking];
+  let Prototype = "void(...)";
+}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index b81e0d02da2c9..3703c9a4ffa79 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -26,8 +26,9 @@
 #include "TargetInfo.h"
 #include "clang/AST/OSLog.h"
 #include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Intrinsics.h"
@@ -6450,6 +6451,40 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 auto Str = CGM.GetAddrOfConstantCString(Name, "");
 return RValue::get(Str.getPointer());
   }
+  case Builtin::BI__builtin_ct_select: {
+if (E->getNumArgs() != 3) {
+  CGM.getDiags().Report(E->getBeginLoc(),
+E->getNumArgs() > 3
+? diag::err_typecheck_call_too_many_args
+: diag::err_typecheck_call_too_few_args);
+  return GetUndefRValue(E->getType());
+}
+
+auto *Cond = EmitScalarExpr(E->getArg(0));
+auto *A = EmitScalarExpr(E->getArg(1));
+auto *B = EmitScalarExpr(E->getArg(2));
+
+// Verify types match
+if (A->getType() != B->getType()) {
+  CGM.getDiags().Report(E->getBeginLoc(),
+diag::err_typecheck_convert_incompatible);
+  return GetUndefRValue(E->getType());
+}
+
+// Verify condition is integer type
+if (!Cond->getType()->isIntegerTy()) {
+  CGM.getDiags().Report(E->getBeginLoc(), diag::err_typecheck_expect_int);
+  return GetUndefRValue(E->getType());
+}
+
+if (Cond->getType()->getIntegerBitWidth() != 1)
+  Cond = Builder.CreateICmpNE(
+  Cond, llvm::ConstantInt::get(Cond->getType(), 0), "cond.bool");
+
+llvm::Function *Fn =
+CGM.getIntrinsic(llvm::Intrinsic::ct_select, {A->getType()});
+return RValue::get(Builder.CreateCall(Fn, {Cond, A, B}));
+  }
   }
 
   // If this is an alias for a lib function (e.g. __builtin_sin), emit
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ad2c2e4a97bb9..026912c859c73 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3494,6 +3494,95 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
 if (BuiltinCountedByRef(TheCall))
   return ExprError();
 break;
+
+  case Builtin::BI__builtin_ct_select: {
+if (TheCall->getNumArgs() != 3) {
+  // Simple argument count check without complex diagnostics
+  if (TheCall->getNumArgs() < 3) {
+return Diag(TheCall->getEndLoc(),
+diag::err_typecheck_call_too_few_args_at_least)
+   << 0 << 3 << TheCall->getNumArgs() << 0
+   << TheCall->getCallee()->getSourceRange();
+  } else {
+return Diag(TheCall->getEndLoc(),
+diag::err_typecheck_call_too_many_args)
+   << 0 << 3 << TheCall->getNumArgs() << 0
+   << TheCall->getCallee()->getSourceRange();
+  }
+}
+auto *Cond = TheCall->getArg(0);
+auto *A = TheCall->getArg(1);
+auto *B = TheCall->getArg(2);
+
+QualType CondTy = Cond->getType();
+if (!CondTy->isIntegerType()) {
+  return Diag(Cond->getBeginLoc(), diag::err_typecheck_cond_expect_scalar)
+ << CondTy << Cond->getSourceRange();
+}
+
+QualType ATy = A->getType();
+Qu

[llvm-branch-commits] [clang] [ConstantTime][Clang] Add __builtin_ct_select for constant-time selection (PR #166703)

2025-11-06 Thread Julius Alexandre via llvm-branch-commits

https://github.com/wizardengineer updated 
https://github.com/llvm/llvm-project/pull/166703

>From 6ac8221eef92f3e8c615c2218b8db2e3d26cf692 Mon Sep 17 00:00:00 2001
From: wizardengineer 
Date: Wed, 5 Nov 2025 10:56:34 -0500
Subject: [PATCH] [ConstantTime][Clang] Add __builtin_ct_select for
 constant-time selection

---
 clang/include/clang/Basic/Builtins.td |   8 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  37 +-
 clang/lib/Sema/SemaChecking.cpp   |  89 +++
 .../test/Sema/builtin-ct-select-edge-cases.c  | 384 ++
 clang/test/Sema/builtin-ct-select.c   | 683 ++
 5 files changed, 1200 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Sema/builtin-ct-select-edge-cases.c
 create mode 100644 clang/test/Sema/builtin-ct-select.c

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 2b400b012d6ed..13e2a9849bfca 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5278,3 +5278,11 @@ def CountedByRef : Builtin {
   let Attributes = [NoThrow, CustomTypeChecking];
   let Prototype = "int(...)";
 }
+
+// Constant-time select builtin
+def CtSelect : Builtin {
+  let Spellings = ["__builtin_ct_select"];
+  let Attributes = [NoThrow, Const, UnevaluatedArguments,
+ConstIgnoringExceptions, CustomTypeChecking];
+  let Prototype = "void(...)";
+}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index b81e0d02da2c9..3703c9a4ffa79 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -26,8 +26,9 @@
 #include "TargetInfo.h"
 #include "clang/AST/OSLog.h"
 #include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Intrinsics.h"
@@ -6450,6 +6451,40 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 auto Str = CGM.GetAddrOfConstantCString(Name, "");
 return RValue::get(Str.getPointer());
   }
+  case Builtin::BI__builtin_ct_select: {
+if (E->getNumArgs() != 3) {
+  CGM.getDiags().Report(E->getBeginLoc(),
+E->getNumArgs() > 3
+? diag::err_typecheck_call_too_many_args
+: diag::err_typecheck_call_too_few_args);
+  return GetUndefRValue(E->getType());
+}
+
+auto *Cond = EmitScalarExpr(E->getArg(0));
+auto *A = EmitScalarExpr(E->getArg(1));
+auto *B = EmitScalarExpr(E->getArg(2));
+
+// Verify types match
+if (A->getType() != B->getType()) {
+  CGM.getDiags().Report(E->getBeginLoc(),
+diag::err_typecheck_convert_incompatible);
+  return GetUndefRValue(E->getType());
+}
+
+// Verify condition is integer type
+if (!Cond->getType()->isIntegerTy()) {
+  CGM.getDiags().Report(E->getBeginLoc(), diag::err_typecheck_expect_int);
+  return GetUndefRValue(E->getType());
+}
+
+if (Cond->getType()->getIntegerBitWidth() != 1)
+  Cond = Builder.CreateICmpNE(
+  Cond, llvm::ConstantInt::get(Cond->getType(), 0), "cond.bool");
+
+llvm::Function *Fn =
+CGM.getIntrinsic(llvm::Intrinsic::ct_select, {A->getType()});
+return RValue::get(Builder.CreateCall(Fn, {Cond, A, B}));
+  }
   }
 
   // If this is an alias for a lib function (e.g. __builtin_sin), emit
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ad2c2e4a97bb9..026912c859c73 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3494,6 +3494,95 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
 if (BuiltinCountedByRef(TheCall))
   return ExprError();
 break;
+
+  case Builtin::BI__builtin_ct_select: {
+if (TheCall->getNumArgs() != 3) {
+  // Simple argument count check without complex diagnostics
+  if (TheCall->getNumArgs() < 3) {
+return Diag(TheCall->getEndLoc(),
+diag::err_typecheck_call_too_few_args_at_least)
+   << 0 << 3 << TheCall->getNumArgs() << 0
+   << TheCall->getCallee()->getSourceRange();
+  } else {
+return Diag(TheCall->getEndLoc(),
+diag::err_typecheck_call_too_many_args)
+   << 0 << 3 << TheCall->getNumArgs() << 0
+   << TheCall->getCallee()->getSourceRange();
+  }
+}
+auto *Cond = TheCall->getArg(0);
+auto *A = TheCall->getArg(1);
+auto *B = TheCall->getArg(2);
+
+QualType CondTy = Cond->getType();
+if (!CondTy->isIntegerType()) {
+  return Diag(Cond->getBeginLoc(), diag::err_typecheck_cond_expect_scalar)
+ << CondTy << Cond->getSourceRange();
+}
+
+QualType ATy = A->getType();
+Qu