| ; 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 basic ct.select functionality for scalar types |
| define i8 @test_ctselect_i8(i1 %cond, i8 %a, i8 %b) { |
| ; M32-LABEL: test_ctselect_i8: |
| ; M32: # %bb.0: |
| ; M32-NEXT: andi $2, $4, 1 |
| ; M32-NEXT: xor $1, $5, $6 |
| ; 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_i8: |
| ; M64: # %bb.0: |
| ; M64-NEXT: sll $1, $4, 0 |
| ; M64-NEXT: xor $2, $5, $6 |
| ; M64-NEXT: andi $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 |
| %result = call i8 @llvm.ct.select.i8(i1 %cond, i8 %a, i8 %b) |
| ret i8 %result |
| } |
| |
| define i16 @test_ctselect_i16(i1 %cond, i16 %a, i16 %b) { |
| ; M32-LABEL: test_ctselect_i16: |
| ; M32: # %bb.0: |
| ; M32-NEXT: andi $2, $4, 1 |
| ; M32-NEXT: xor $1, $5, $6 |
| ; 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_i16: |
| ; M64: # %bb.0: |
| ; M64-NEXT: sll $1, $4, 0 |
| ; M64-NEXT: xor $2, $5, $6 |
| ; M64-NEXT: andi $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 |
| %result = call i16 @llvm.ct.select.i16(i1 %cond, i16 %a, i16 %b) |
| ret i16 %result |
| } |
| |
| define i32 @test_ctselect_i32(i1 %cond, i32 %a, i32 %b) { |
| ; M32-LABEL: test_ctselect_i32: |
| ; M32: # %bb.0: |
| ; M32-NEXT: andi $2, $4, 1 |
| ; M32-NEXT: xor $1, $5, $6 |
| ; 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_i32: |
| ; M64: # %bb.0: |
| ; M64-NEXT: sll $1, $4, 0 |
| ; M64-NEXT: xor $2, $5, $6 |
| ; M64-NEXT: andi $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 |
| %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 %a, i32 %b) |
| ret i32 %result |
| } |
| |
| define i64 @test_ctselect_i64(i1 %cond, i64 %a, i64 %b) { |
| ; M32-LABEL: test_ctselect_i64: |
| ; M32: # %bb.0: |
| ; M32-NEXT: lw $1, 16($sp) |
| ; M32-NEXT: andi $3, $4, 1 |
| ; M32-NEXT: negu $3, $3 |
| ; M32-NEXT: xor $2, $6, $1 |
| ; M32-NEXT: and $2, $2, $3 |
| ; M32-NEXT: xor $2, $1, $2 |
| ; M32-NEXT: lw $1, 20($sp) |
| ; M32-NEXT: xor $4, $7, $1 |
| ; M32-NEXT: and $3, $4, $3 |
| ; M32-NEXT: jr $ra |
| ; M32-NEXT: xor $3, $1, $3 |
| ; |
| ; M64-LABEL: test_ctselect_i64: |
| ; M64: # %bb.0: |
| ; M64-NEXT: andi $2, $4, 1 |
| ; M64-NEXT: xor $1, $5, $6 |
| ; M64-NEXT: dnegu $2, $2 |
| ; M64-NEXT: and $1, $1, $2 |
| ; M64-NEXT: jr $ra |
| ; M64-NEXT: xor $2, $6, $1 |
| %result = call i64 @llvm.ct.select.i64(i1 %cond, i64 %a, i64 %b) |
| ret i64 %result |
| } |
| |
| define ptr @test_ctselect_ptr(i1 %cond, ptr %a, ptr %b) { |
| ; M32-LABEL: test_ctselect_ptr: |
| ; M32: # %bb.0: |
| ; M32-NEXT: andi $2, $4, 1 |
| ; M32-NEXT: xor $1, $5, $6 |
| ; 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_ptr: |
| ; M64: # %bb.0: |
| ; M64-NEXT: andi $2, $4, 1 |
| ; M64-NEXT: xor $1, $5, $6 |
| ; M64-NEXT: dnegu $2, $2 |
| ; M64-NEXT: and $1, $1, $2 |
| ; M64-NEXT: jr $ra |
| ; M64-NEXT: xor $2, $6, $1 |
| %result = call ptr @llvm.ct.select.p0(i1 %cond, ptr %a, ptr %b) |
| ret ptr %result |
| } |
| |
| ; Test with constant conditions |
| define i32 @test_ctselect_const_true(i32 %a, i32 %b) { |
| ; M32-LABEL: test_ctselect_const_true: |
| ; M32: # %bb.0: |
| ; M32-NEXT: jr $ra |
| ; M32-NEXT: move $2, $4 |
| ; |
| ; M64-LABEL: test_ctselect_const_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_const_false(i32 %a, i32 %b) { |
| ; M32-LABEL: test_ctselect_const_false: |
| ; M32: # %bb.0: |
| ; M32-NEXT: jr $ra |
| ; M32-NEXT: move $2, $5 |
| ; |
| ; M64-LABEL: test_ctselect_const_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 comparison conditions |
| define i32 @test_ctselect_icmp_eq(i32 %x, i32 %y, i32 %a, i32 %b) { |
| ; M32-LABEL: test_ctselect_icmp_eq: |
| ; M32: # %bb.0: |
| ; M32-NEXT: xor $2, $4, $5 |
| ; M32-NEXT: xor $1, $6, $7 |
| ; 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, $7, $1 |
| ; |
| ; M64-LABEL: test_ctselect_icmp_eq: |
| ; 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, $6, $7 |
| ; 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, $7, 0 |
| ; M64-NEXT: jr $ra |
| ; M64-NEXT: xor $2, $2, $1 |
| %cond = icmp eq i32 %x, %y |
| %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 %a, i32 %b) |
| ret i32 %result |
| } |
| |
| define i32 @test_ctselect_icmp_ne(i32 %x, i32 %y, i32 %a, i32 %b) { |
| ; M32-LABEL: test_ctselect_icmp_ne: |
| ; M32: # %bb.0: |
| ; M32-NEXT: xor $2, $4, $5 |
| ; M32-NEXT: xor $1, $6, $7 |
| ; M32-NEXT: sltu $2, $zero, $2 |
| ; M32-NEXT: negu $2, $2 |
| ; M32-NEXT: and $1, $1, $2 |
| ; M32-NEXT: jr $ra |
| ; M32-NEXT: xor $2, $7, $1 |
| ; |
| ; M64-LABEL: test_ctselect_icmp_ne: |
| ; 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, $6, $7 |
| ; M64-NEXT: sltu $1, $zero, $1 |
| ; M64-NEXT: sll $2, $2, 0 |
| ; M64-NEXT: negu $1, $1 |
| ; M64-NEXT: and $1, $2, $1 |
| ; M64-NEXT: sll $2, $7, 0 |
| ; M64-NEXT: jr $ra |
| ; M64-NEXT: xor $2, $2, $1 |
| %cond = icmp ne i32 %x, %y |
| %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 %a, i32 %b) |
| ret i32 %result |
| } |
| |
| define i32 @test_ctselect_icmp_slt(i32 %x, i32 %y, i32 %a, i32 %b) { |
| ; M32-LABEL: test_ctselect_icmp_slt: |
| ; M32: # %bb.0: |
| ; M32-NEXT: slt $2, $4, $5 |
| ; M32-NEXT: xor $1, $6, $7 |
| ; M32-NEXT: negu $2, $2 |
| ; M32-NEXT: and $1, $1, $2 |
| ; M32-NEXT: jr $ra |
| ; M32-NEXT: xor $2, $7, $1 |
| ; |
| ; M64-LABEL: test_ctselect_icmp_slt: |
| ; M64: # %bb.0: |
| ; M64-NEXT: sll $1, $5, 0 |
| ; M64-NEXT: sll $2, $4, 0 |
| ; M64-NEXT: slt $1, $2, $1 |
| ; M64-NEXT: xor $2, $6, $7 |
| ; M64-NEXT: negu $1, $1 |
| ; M64-NEXT: sll $2, $2, 0 |
| ; M64-NEXT: and $1, $2, $1 |
| ; M64-NEXT: sll $2, $7, 0 |
| ; M64-NEXT: jr $ra |
| ; M64-NEXT: xor $2, $2, $1 |
| %cond = icmp slt i32 %x, %y |
| %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 %a, i32 %b) |
| ret i32 %result |
| } |
| |
| define i32 @test_ctselect_icmp_ult(i32 %x, i32 %y, i32 %a, i32 %b) { |
| ; M32-LABEL: test_ctselect_icmp_ult: |
| ; M32: # %bb.0: |
| ; M32-NEXT: sltu $2, $4, $5 |
| ; M32-NEXT: xor $1, $6, $7 |
| ; M32-NEXT: negu $2, $2 |
| ; M32-NEXT: and $1, $1, $2 |
| ; M32-NEXT: jr $ra |
| ; M32-NEXT: xor $2, $7, $1 |
| ; |
| ; M64-LABEL: test_ctselect_icmp_ult: |
| ; M64: # %bb.0: |
| ; M64-NEXT: sll $1, $5, 0 |
| ; M64-NEXT: sll $2, $4, 0 |
| ; M64-NEXT: sltu $1, $2, $1 |
| ; M64-NEXT: xor $2, $6, $7 |
| ; M64-NEXT: negu $1, $1 |
| ; M64-NEXT: sll $2, $2, 0 |
| ; M64-NEXT: and $1, $2, $1 |
| ; M64-NEXT: sll $2, $7, 0 |
| ; M64-NEXT: jr $ra |
| ; M64-NEXT: xor $2, $2, $1 |
| %cond = icmp ult i32 %x, %y |
| %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 %a, i32 %b) |
| ret i32 %result |
| } |
| |
| ; Test with memory operands |
| define i32 @test_ctselect_load(i1 %cond, ptr %p1, ptr %p2) { |
| ; M32-LABEL: test_ctselect_load: |
| ; M32: # %bb.0: |
| ; M32-NEXT: lw $2, 0($6) |
| ; M32-NEXT: lw $3, 0($5) |
| ; M32-NEXT: andi $1, $4, 1 |
| ; M32-NEXT: negu $1, $1 |
| ; M32-NEXT: xor $3, $3, $2 |
| ; M32-NEXT: and $1, $3, $1 |
| ; M32-NEXT: jr $ra |
| ; M32-NEXT: xor $2, $2, $1 |
| ; |
| ; M64-LABEL: test_ctselect_load: |
| ; M64: # %bb.0: |
| ; M64-NEXT: sll $3, $4, 0 |
| ; M64-NEXT: lw $1, 0($6) |
| ; M64-NEXT: lw $2, 0($5) |
| ; M64-NEXT: andi $3, $3, 1 |
| ; M64-NEXT: xor $2, $2, $1 |
| ; M64-NEXT: negu $3, $3 |
| ; M64-NEXT: and $2, $2, $3 |
| ; M64-NEXT: jr $ra |
| ; M64-NEXT: xor $2, $1, $2 |
| %a = load i32, ptr %p1 |
| %b = load i32, ptr %p2 |
| %result = call i32 @llvm.ct.select.i32(i1 %cond, i32 %a, i32 %b) |
| ret i32 %result |
| } |
| |
| ; Test nested ctselect calls |
| define i32 @test_ctselect_nested(i1 %cond1, i1 %cond2, i32 %a, i32 %b, i32 %c) { |
| ; M32-LABEL: test_ctselect_nested: |
| ; M32: # %bb.0: |
| ; M32-NEXT: andi $2, $5, 1 |
| ; M32-NEXT: xor $1, $6, $7 |
| ; M32-NEXT: andi $3, $4, 1 |
| ; M32-NEXT: negu $2, $2 |
| ; M32-NEXT: negu $3, $3 |
| ; M32-NEXT: and $1, $1, $2 |
| ; M32-NEXT: lw $2, 16($sp) |
| ; M32-NEXT: xor $1, $7, $1 |
| ; M32-NEXT: xor $1, $1, $2 |
| ; M32-NEXT: and $1, $1, $3 |
| ; M32-NEXT: jr $ra |
| ; M32-NEXT: xor $2, $2, $1 |
| ; |
| ; M64-LABEL: test_ctselect_nested: |
| ; M64: # %bb.0: |
| ; M64-NEXT: sll $1, $5, 0 |
| ; M64-NEXT: xor $2, $6, $7 |
| ; M64-NEXT: sll $3, $4, 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, $7, 0 |
| ; M64-NEXT: xor $1, $2, $1 |
| ; M64-NEXT: sll $2, $8, 0 |
| ; M64-NEXT: xor $1, $1, $2 |
| ; M64-NEXT: and $1, $1, $3 |
| ; M64-NEXT: jr $ra |
| ; M64-NEXT: xor $2, $2, $1 |
| %inner = call i32 @llvm.ct.select.i32(i1 %cond2, i32 %a, i32 %b) |
| %result = call i32 @llvm.ct.select.i32(i1 %cond1, i32 %inner, i32 %c) |
| ret i32 %result |
| } |
| |
| ; Declare the intrinsics |
| declare i8 @llvm.ct.select.i8(i1, i8, i8) |
| declare i16 @llvm.ct.select.i16(i1, i16, i16) |
| declare i32 @llvm.ct.select.i32(i1, i32, i32) |
| declare i64 @llvm.ct.select.i64(i1, i64, i64) |
| declare ptr @llvm.ct.select.p0(i1, ptr, ptr) |