blob: a1c5d524c69391e2f83105ce4105cf721fcab70f [file] [log] [blame] [edit]
; 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
; Test smin(x, 0) pattern
define i32 @test_ctselect_smin_zero(i32 %x) {
; M32-LABEL: test_ctselect_smin_zero:
; M32: # %bb.0:
; M32-NEXT: slti $1, $4, 0
; M32-NEXT: negu $1, $1
; M32-NEXT: jr $ra
; M32-NEXT: and $2, $4, $1
;
; M64-LABEL: test_ctselect_smin_zero:
; M64: # %bb.0:
; M64-NEXT: sll $1, $4, 0
; M64-NEXT: slti $2, $1, 0
; M64-NEXT: negu $2, $2
; M64-NEXT: jr $ra
; M64-NEXT: and $2, $1, $2
%cmp = icmp slt i32 %x, 0
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 0)
ret i32 %result
}
; Test smax(x, 0) pattern
define i32 @test_ctselect_smax_zero(i32 %x) {
; M32-LABEL: test_ctselect_smax_zero:
; M32: # %bb.0:
; M32-NEXT: slt $1, $zero, $4
; M32-NEXT: negu $1, $1
; M32-NEXT: jr $ra
; M32-NEXT: and $2, $4, $1
;
; M64-LABEL: test_ctselect_smax_zero:
; M64: # %bb.0:
; M64-NEXT: sll $1, $4, 0
; M64-NEXT: slt $2, $zero, $1
; M64-NEXT: negu $2, $2
; M64-NEXT: jr $ra
; M64-NEXT: and $2, $1, $2
%cmp = icmp sgt i32 %x, 0
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 0)
ret i32 %result
}
; Test generic smin pattern
define i32 @test_ctselect_smin_generic(i32 %x, i32 %y) {
; M32-LABEL: test_ctselect_smin_generic:
; M32: # %bb.0:
; M32-NEXT: slt $2, $4, $5
; M32-NEXT: xor $1, $4, $5
; M32-NEXT: negu $2, $2
; M32-NEXT: and $1, $1, $2
; M32-NEXT: jr $ra
; M32-NEXT: xor $2, $5, $1
;
; M64-LABEL: test_ctselect_smin_generic:
; M64: # %bb.0:
; M64-NEXT: sll $1, $5, 0
; M64-NEXT: sll $2, $4, 0
; M64-NEXT: xor $3, $2, $1
; M64-NEXT: slt $2, $2, $1
; M64-NEXT: negu $2, $2
; M64-NEXT: and $2, $3, $2
; M64-NEXT: jr $ra
; M64-NEXT: xor $2, $1, $2
%cmp = icmp slt i32 %x, %y
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %y)
ret i32 %result
}
; Test generic smax pattern
define i32 @test_ctselect_smax_generic(i32 %x, i32 %y) {
; M32-LABEL: test_ctselect_smax_generic:
; M32: # %bb.0:
; M32-NEXT: slt $2, $5, $4
; M32-NEXT: xor $1, $4, $5
; M32-NEXT: negu $2, $2
; M32-NEXT: and $1, $1, $2
; M32-NEXT: jr $ra
; M32-NEXT: xor $2, $5, $1
;
; M64-LABEL: test_ctselect_smax_generic:
; M64: # %bb.0:
; M64-NEXT: sll $1, $5, 0
; M64-NEXT: sll $2, $4, 0
; M64-NEXT: xor $3, $2, $1
; M64-NEXT: slt $2, $1, $2
; M64-NEXT: negu $2, $2
; M64-NEXT: and $2, $3, $2
; M64-NEXT: jr $ra
; M64-NEXT: xor $2, $1, $2
%cmp = icmp sgt i32 %x, %y
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %y)
ret i32 %result
}
; Test umin pattern
define i32 @test_ctselect_umin_generic(i32 %x, i32 %y) {
; M32-LABEL: test_ctselect_umin_generic:
; M32: # %bb.0:
; M32-NEXT: sltu $2, $4, $5
; M32-NEXT: xor $1, $4, $5
; M32-NEXT: negu $2, $2
; M32-NEXT: and $1, $1, $2
; M32-NEXT: jr $ra
; M32-NEXT: xor $2, $5, $1
;
; M64-LABEL: test_ctselect_umin_generic:
; M64: # %bb.0:
; M64-NEXT: sll $1, $5, 0
; M64-NEXT: sll $2, $4, 0
; M64-NEXT: xor $3, $2, $1
; M64-NEXT: sltu $2, $2, $1
; M64-NEXT: negu $2, $2
; M64-NEXT: and $2, $3, $2
; M64-NEXT: jr $ra
; M64-NEXT: xor $2, $1, $2
%cmp = icmp ult i32 %x, %y
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %y)
ret i32 %result
}
; Test umax pattern
define i32 @test_ctselect_umax_generic(i32 %x, i32 %y) {
; M32-LABEL: test_ctselect_umax_generic:
; M32: # %bb.0:
; M32-NEXT: sltu $2, $5, $4
; M32-NEXT: xor $1, $4, $5
; M32-NEXT: negu $2, $2
; M32-NEXT: and $1, $1, $2
; M32-NEXT: jr $ra
; M32-NEXT: xor $2, $5, $1
;
; M64-LABEL: test_ctselect_umax_generic:
; M64: # %bb.0:
; M64-NEXT: sll $1, $5, 0
; M64-NEXT: sll $2, $4, 0
; M64-NEXT: xor $3, $2, $1
; M64-NEXT: sltu $2, $1, $2
; M64-NEXT: negu $2, $2
; M64-NEXT: and $2, $3, $2
; M64-NEXT: jr $ra
; M64-NEXT: xor $2, $1, $2
%cmp = icmp ugt i32 %x, %y
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %y)
ret i32 %result
}
; Test abs pattern
define i32 @test_ctselect_abs(i32 %x) {
; M32-LABEL: test_ctselect_abs:
; M32: # %bb.0:
; M32-NEXT: slti $1, $4, 0
; M32-NEXT: negu $2, $4
; M32-NEXT: negu $1, $1
; M32-NEXT: xor $2, $2, $4
; M32-NEXT: and $1, $2, $1
; M32-NEXT: jr $ra
; M32-NEXT: xor $2, $4, $1
;
; M64-LABEL: test_ctselect_abs:
; M64: # %bb.0:
; M64-NEXT: sll $1, $4, 0
; M64-NEXT: slti $2, $1, 0
; M64-NEXT: negu $3, $1
; M64-NEXT: negu $2, $2
; M64-NEXT: xor $3, $3, $1
; M64-NEXT: and $2, $3, $2
; M64-NEXT: jr $ra
; M64-NEXT: xor $2, $1, $2
%neg = sub i32 0, %x
%cmp = icmp slt i32 %x, 0
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %neg, i32 %x)
ret i32 %result
}
; Test nabs pattern (negative abs)
define i32 @test_ctselect_nabs(i32 %x) {
; M32-LABEL: test_ctselect_nabs:
; M32: # %bb.0:
; M32-NEXT: slti $1, $4, 0
; M32-NEXT: negu $2, $4
; M32-NEXT: negu $1, $1
; M32-NEXT: xor $3, $4, $2
; M32-NEXT: and $1, $3, $1
; M32-NEXT: jr $ra
; M32-NEXT: xor $2, $2, $1
;
; M64-LABEL: test_ctselect_nabs:
; M64: # %bb.0:
; M64-NEXT: sll $1, $4, 0
; M64-NEXT: slti $2, $1, 0
; M64-NEXT: negu $3, $1
; M64-NEXT: negu $2, $2
; M64-NEXT: xor $1, $1, $3
; M64-NEXT: and $1, $1, $2
; M64-NEXT: jr $ra
; M64-NEXT: xor $2, $3, $1
%neg = sub i32 0, %x
%cmp = icmp slt i32 %x, 0
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 %x, i32 %neg)
ret i32 %result
}
; Test sign extension pattern
define i32 @test_ctselect_sign_extend(i32 %x) {
; M32-LABEL: test_ctselect_sign_extend:
; M32: # %bb.0:
; M32-NEXT: slti $1, $4, 0
; M32-NEXT: jr $ra
; M32-NEXT: negu $2, $1
;
; M64-LABEL: test_ctselect_sign_extend:
; M64: # %bb.0:
; M64-NEXT: sll $1, $4, 0
; M64-NEXT: slti $1, $1, 0
; M64-NEXT: jr $ra
; M64-NEXT: negu $2, $1
%cmp = icmp slt i32 %x, 0
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 -1, i32 0)
ret i32 %result
}
; Test zero extension pattern
define i32 @test_ctselect_zero_extend(i32 %x) {
; M32-LABEL: test_ctselect_zero_extend:
; M32: # %bb.0:
; M32-NEXT: jr $ra
; M32-NEXT: sltu $2, $zero, $4
;
; M64-LABEL: test_ctselect_zero_extend:
; M64: # %bb.0:
; M64-NEXT: sll $1, $4, 0
; M64-NEXT: jr $ra
; M64-NEXT: sltu $2, $zero, $1
%cmp = icmp ne i32 %x, 0
%result = call i32 @llvm.ct.select.i32(i1 %cmp, i32 1, i32 0)
ret i32 %result
}
; Test constant folding with known condition
define i32 @test_ctselect_constant_folding_true(i32 %a, i32 %b) {
; M32-LABEL: test_ctselect_constant_folding_true:
; M32: # %bb.0:
; M32-NEXT: jr $ra
; M32-NEXT: move $2, $4
;
; M64-LABEL: test_ctselect_constant_folding_true:
; M64: # %bb.0:
; M64-NEXT: jr $ra
; M64-NEXT: sll $2, $4, 0
%result = call i32 @llvm.ct.select.i32(i1 true, i32 %a, i32 %b)
ret i32 %result
}
define i32 @test_ctselect_constant_folding_false(i32 %a, i32 %b) {
; M32-LABEL: test_ctselect_constant_folding_false:
; M32: # %bb.0:
; M32-NEXT: jr $ra
; M32-NEXT: move $2, $5
;
; M64-LABEL: test_ctselect_constant_folding_false:
; M64: # %bb.0:
; M64-NEXT: jr $ra
; M64-NEXT: sll $2, $5, 0
%result = call i32 @llvm.ct.select.i32(i1 false, i32 %a, i32 %b)
ret i32 %result
}
; Test with identical operands
define i32 @test_ctselect_identical_operands(i1 %cond, i32 %x) {
; M32-LABEL: test_ctselect_identical_operands:
; M32: # %bb.0:
; M32-NEXT: jr $ra
; M32-NEXT: move $2, $5
;
; M64-LABEL: test_ctselect_identical_operands:
; M64: # %bb.0:
; M64-NEXT: jr $ra
; M64-NEXT: sll $2, $5, 0
%result = call i32 @llvm.ct.select.i32(i1 %cond, i32 %x, i32 %x)
ret i32 %result
}
; Test with inverted condition
define i32 @test_ctselect_inverted_condition(i32 %x, i32 %y, i32 %a, i32 %b) {
; M32-LABEL: test_ctselect_inverted_condition:
; M32: # %bb.0:
; M32-NEXT: xor $2, $4, $5
; M32-NEXT: xor $1, $7, $6
; M32-NEXT: sltiu $2, $2, 1
; M32-NEXT: negu $2, $2
; M32-NEXT: and $1, $1, $2
; M32-NEXT: jr $ra
; M32-NEXT: xor $2, $6, $1
;
; M64-LABEL: test_ctselect_inverted_condition:
; M64: # %bb.0:
; M64-NEXT: sll $1, $5, 0
; M64-NEXT: sll $2, $4, 0
; M64-NEXT: xor $1, $2, $1
; M64-NEXT: xor $2, $7, $6
; M64-NEXT: sltiu $1, $1, 1
; M64-NEXT: sll $2, $2, 0
; M64-NEXT: negu $1, $1
; M64-NEXT: and $1, $2, $1
; M64-NEXT: sll $2, $6, 0
; M64-NEXT: jr $ra
; M64-NEXT: xor $2, $2, $1
%cmp = icmp eq i32 %x, %y
%not_cmp = xor i1 %cmp, true
%result = call i32 @llvm.ct.select.i32(i1 %not_cmp, i32 %a, i32 %b)
ret i32 %result
}
; Test chain of ct.select operations
define i32 @test_ctselect_chain(i1 %c1, i1 %c2, i1 %c3, i32 %a, i32 %b, i32 %c, i32 %d) {
; M32-LABEL: test_ctselect_chain:
; M32: # %bb.0:
; M32-NEXT: lw $1, 16($sp)
; M32-NEXT: andi $3, $4, 1
; M32-NEXT: negu $3, $3
; M32-NEXT: xor $2, $7, $1
; M32-NEXT: and $2, $2, $3
; M32-NEXT: andi $3, $5, 1
; M32-NEXT: xor $1, $1, $2
; M32-NEXT: lw $2, 20($sp)
; M32-NEXT: negu $3, $3
; M32-NEXT: xor $1, $1, $2
; M32-NEXT: and $1, $1, $3
; M32-NEXT: lw $3, 24($sp)
; M32-NEXT: xor $1, $2, $1
; M32-NEXT: andi $2, $6, 1
; M32-NEXT: xor $1, $1, $3
; M32-NEXT: negu $2, $2
; M32-NEXT: and $1, $1, $2
; M32-NEXT: jr $ra
; M32-NEXT: xor $2, $3, $1
;
; M64-LABEL: test_ctselect_chain:
; M64: # %bb.0:
; M64-NEXT: sll $1, $4, 0
; M64-NEXT: xor $2, $7, $8
; M64-NEXT: sll $3, $5, 0
; M64-NEXT: andi $1, $1, 1
; M64-NEXT: sll $2, $2, 0
; M64-NEXT: andi $3, $3, 1
; M64-NEXT: negu $1, $1
; M64-NEXT: negu $3, $3
; M64-NEXT: and $1, $2, $1
; M64-NEXT: sll $2, $8, 0
; M64-NEXT: xor $1, $2, $1
; M64-NEXT: sll $2, $9, 0
; M64-NEXT: xor $1, $1, $2
; M64-NEXT: and $1, $1, $3
; M64-NEXT: sll $3, $6, 0
; M64-NEXT: xor $1, $2, $1
; M64-NEXT: andi $2, $3, 1
; M64-NEXT: sll $3, $10, 0
; M64-NEXT: xor $1, $1, $3
; M64-NEXT: negu $2, $2
; M64-NEXT: and $1, $1, $2
; M64-NEXT: jr $ra
; M64-NEXT: xor $2, $3, $1
%sel1 = call i32 @llvm.ct.select.i32(i1 %c1, i32 %a, i32 %b)
%sel2 = call i32 @llvm.ct.select.i32(i1 %c2, i32 %sel1, i32 %c)
%sel3 = call i32 @llvm.ct.select.i32(i1 %c3, i32 %sel2, i32 %d)
ret i32 %sel3
}
; Test for 64-bit operations (supported on all 64-bit architectures)
define i64 @test_ctselect_i64_smin_zero(i64 %x) {
; M32-LABEL: test_ctselect_i64_smin_zero:
; M32: # %bb.0:
; M32-NEXT: slti $1, $5, 0
; M32-NEXT: negu $1, $1
; M32-NEXT: and $2, $4, $1
; M32-NEXT: jr $ra
; M32-NEXT: and $3, $5, $1
;
; M64-LABEL: test_ctselect_i64_smin_zero:
; M64: # %bb.0:
; M64-NEXT: dsra $1, $4, 63
; M64-NEXT: jr $ra
; M64-NEXT: and $2, $4, $1
%cmp = icmp slt i64 %x, 0
%result = call i64 @llvm.ct.select.i64(i1 %cmp, i64 %x, i64 0)
ret i64 %result
}
; Declare the intrinsics
declare i32 @llvm.ct.select.i32(i1, i32, i32)
declare i64 @llvm.ct.select.i64(i1, i64, i64)