blob: d8b833ced37fbd5f1c274834e20177526aacb374 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+adx,+ndd | FileCheck %s --check-prefixes=CHECK,NDD
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+adx | FileCheck %s --check-prefixes=CHECK,ADX
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=-adx | FileCheck %s --check-prefixes=CHECK,NOADX
define i32 @adox_test_i32(i32 %a, i32 %b, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_i32:
; NDD: # %bb.0:
; NDD-NEXT: cmpb %cl, %dl
; NDD-NEXT: adoxl %esi, %edi, %eax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_i32:
; ADX: # %bb.0:
; ADX-NEXT: movl %edi, %eax
; ADX-NEXT: cmpb %cl, %dl
; ADX-NEXT: adoxl %esi, %eax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_i32:
; NOADX: # %bb.0:
; NOADX-NEXT: # kill: def $esi killed $esi def $rsi
; NOADX-NEXT: # kill: def $edi killed $edi def $rdi
; NOADX-NEXT: xorl %eax, %eax
; NOADX-NEXT: cmpb %cl, %dl
; NOADX-NEXT: seto %al
; NOADX-NEXT: addl %edi, %eax
; NOADX-NEXT: addl %esi, %eax
; NOADX-NEXT: retq
%ssub = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %c, i8 %d)
%ov = extractvalue { i8, i1 } %ssub, 1
%ov.ext = zext i1 %ov to i32
%sum = add i32 %a, %b
%res = add i32 %sum, %ov.ext
ret i32 %res
}
define i64 @adox_test_i64(i64 %a, i64 %b, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_i64:
; NDD: # %bb.0:
; NDD-NEXT: cmpb %cl, %dl
; NDD-NEXT: adoxq %rsi, %rdi, %rax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_i64:
; ADX: # %bb.0:
; ADX-NEXT: movq %rdi, %rax
; ADX-NEXT: cmpb %cl, %dl
; ADX-NEXT: adoxq %rsi, %rax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_i64:
; NOADX: # %bb.0:
; NOADX-NEXT: xorl %eax, %eax
; NOADX-NEXT: cmpb %cl, %dl
; NOADX-NEXT: seto %al
; NOADX-NEXT: addq %rdi, %rax
; NOADX-NEXT: addq %rsi, %rax
; NOADX-NEXT: retq
%ssub = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %c, i8 %d)
%ov = extractvalue { i8, i1 } %ssub, 1
%ov.ext = zext i1 %ov to i64
%sum = add i64 %a, %b
%res = add i64 %sum, %ov.ext
ret i64 %res
}
declare { i8, i1 } @llvm.ssub.with.overflow.i8(i8, i8)
define i32 @adox_test_i32_mem(i32 %a, ptr %b_ptr, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_i32_mem:
; NDD: # %bb.0:
; NDD-NEXT: cmpb %cl, %dl
; NDD-NEXT: adoxl (%rsi), %edi, %eax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_i32_mem:
; ADX: # %bb.0:
; ADX-NEXT: movl %edi, %eax
; ADX-NEXT: cmpb %cl, %dl
; ADX-NEXT: adoxl (%rsi), %eax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_i32_mem:
; NOADX: # %bb.0:
; NOADX-NEXT: xorl %eax, %eax
; NOADX-NEXT: cmpb %cl, %dl
; NOADX-NEXT: seto %al
; NOADX-NEXT: addl (%rsi), %edi
; NOADX-NEXT: addl %edi, %eax
; NOADX-NEXT: retq
%b = load i32, ptr %b_ptr
%ssub = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %c, i8 %d)
%ov = extractvalue { i8, i1 } %ssub, 1
%ov.ext = zext i1 %ov to i32
%add = add i32 %a, %b
%add2 = add i32 %add, %ov.ext
ret i32 %add2
}
define i64 @adox_test_i64_mem(i64 %a, ptr %b_ptr, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_i64_mem:
; NDD: # %bb.0:
; NDD-NEXT: cmpb %cl, %dl
; NDD-NEXT: adoxq (%rsi), %rdi, %rax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_i64_mem:
; ADX: # %bb.0:
; ADX-NEXT: movq %rdi, %rax
; ADX-NEXT: cmpb %cl, %dl
; ADX-NEXT: adoxq (%rsi), %rax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_i64_mem:
; NOADX: # %bb.0:
; NOADX-NEXT: xorl %eax, %eax
; NOADX-NEXT: cmpb %cl, %dl
; NOADX-NEXT: seto %al
; NOADX-NEXT: addq (%rsi), %rdi
; NOADX-NEXT: addq %rdi, %rax
; NOADX-NEXT: retq
%b = load i64, ptr %b_ptr
%ssub = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %c, i8 %d)
%ov = extractvalue { i8, i1 } %ssub, 1
%ov.ext = zext i1 %ov to i64
%add = add i64 %a, %b
%add2 = add i64 %add, %ov.ext
ret i64 %add2
}
define i32 @adox_test_sadd_i32(i32 %a, i32 %b, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_sadd_i32:
; NDD: # %bb.0:
; NDD-NEXT: addb %cl, %dl, %al
; NDD-NEXT: adoxl %esi, %edi, %eax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_sadd_i32:
; ADX: # %bb.0:
; ADX-NEXT: movl %edi, %eax
; ADX-NEXT: addb %cl, %dl
; ADX-NEXT: adoxl %esi, %eax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_sadd_i32:
; NOADX: # %bb.0:
; NOADX-NEXT: # kill: def $esi killed $esi def $rsi
; NOADX-NEXT: # kill: def $edi killed $edi def $rdi
; NOADX-NEXT: xorl %eax, %eax
; NOADX-NEXT: addb %cl, %dl
; NOADX-NEXT: seto %al
; NOADX-NEXT: addl %edi, %eax
; NOADX-NEXT: addl %esi, %eax
; NOADX-NEXT: retq
%sadd = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %c, i8 %d)
%ov = extractvalue { i8, i1 } %sadd, 1
%ov.ext = zext i1 %ov to i32
%add = add i32 %a, %b
%add2 = add i32 %add, %ov.ext
ret i32 %add2
}
declare { i8, i1 } @llvm.sadd.with.overflow.i8(i8, i8)
define i16 @adox_test_i16(i16 %a, i16 %b, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_i16:
; NDD: # %bb.0:
; NDD-NEXT: cmpb %cl, %dl
; NDD-NEXT: adoxl %esi, %edi, %eax
; NDD-NEXT: # kill: def $ax killed $ax killed $eax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_i16:
; ADX: # %bb.0:
; ADX-NEXT: movl %edi, %eax
; ADX-NEXT: cmpb %cl, %dl
; ADX-NEXT: adoxl %esi, %eax
; ADX-NEXT: # kill: def $ax killed $ax killed $eax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_i16:
; NOADX: # %bb.0:
; NOADX-NEXT: # kill: def $esi killed $esi def $rsi
; NOADX-NEXT: # kill: def $edi killed $edi def $rdi
; NOADX-NEXT: xorl %eax, %eax
; NOADX-NEXT: cmpb %cl, %dl
; NOADX-NEXT: seto %al
; NOADX-NEXT: addl %edi, %eax
; NOADX-NEXT: addl %esi, %eax
; NOADX-NEXT: # kill: def $ax killed $ax killed $eax
; NOADX-NEXT: retq
%ssub = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %c, i8 %d)
%ov = extractvalue { i8, i1 } %ssub, 1
%ov.ext = zext i1 %ov to i16
%sum = add i16 %a, %b
%res = add i16 %sum, %ov.ext
ret i16 %res
}
define i8 @adox_test_i8(i8 %a, i8 %b, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_i8:
; NDD: # %bb.0:
; NDD-NEXT: cmpb %cl, %dl
; NDD-NEXT: adoxl %esi, %edi, %eax
; NDD-NEXT: # kill: def $al killed $al killed $eax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_i8:
; ADX: # %bb.0:
; ADX-NEXT: movl %edi, %eax
; ADX-NEXT: cmpb %cl, %dl
; ADX-NEXT: adoxl %esi, %eax
; ADX-NEXT: # kill: def $al killed $al killed $eax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_i8:
; NOADX: # %bb.0:
; NOADX-NEXT: # kill: def $esi killed $esi def $rsi
; NOADX-NEXT: # kill: def $edi killed $edi def $rdi
; NOADX-NEXT: cmpb %cl, %dl
; NOADX-NEXT: seto %cl
; NOADX-NEXT: leal (%rdi,%rsi), %eax
; NOADX-NEXT: addb %cl, %al
; NOADX-NEXT: # kill: def $al killed $al killed $eax
; NOADX-NEXT: retq
%ssub = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %c, i8 %d)
%ov = extractvalue { i8, i1 } %ssub, 1
%ov.ext = zext i1 %ov to i8
%sum = add i8 %a, %b
%res = add i8 %sum, %ov.ext
ret i8 %res
}
define i32 @adox_test_sub_i32(i32 %a, i32 %b, i8 %c, i8 %d) {
; NDD-LABEL: adox_test_sub_i32:
; NDD: # %bb.0:
; NDD-NEXT: xorl %eax, %eax
; NDD-NEXT: cmpb %cl, %dl
; NDD-NEXT: seto %al
; NDD-NEXT: subl %esi, %edi
; NDD-NEXT: subl %eax, %edi, %eax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_sub_i32:
; ADX: # %bb.0:
; ADX-NEXT: movl %edi, %eax
; ADX-NEXT: xorl %edi, %edi
; ADX-NEXT: cmpb %cl, %dl
; ADX-NEXT: seto %dil
; ADX-NEXT: subl %esi, %eax
; ADX-NEXT: subl %edi, %eax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_sub_i32:
; NOADX: # %bb.0:
; NOADX-NEXT: movl %edi, %eax
; NOADX-NEXT: xorl %edi, %edi
; NOADX-NEXT: cmpb %cl, %dl
; NOADX-NEXT: seto %dil
; NOADX-NEXT: subl %esi, %eax
; NOADX-NEXT: subl %edi, %eax
; NOADX-NEXT: retq
%ssub = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %c, i8 %d)
%ov = extractvalue { i8, i1 } %ssub, 1
%ov.ext = zext i1 %ov to i32
%sum = sub i32 %a, %b
%res = sub i32 %sum, %ov.ext
ret i32 %res
}
; Negative test: ADOX modifies OF but does not modify ZF.
; When the result of the addition is checked for equality with zero (using ZF),
; we cannot optimize the addition into an ADOX instruction because the branch
; would read an incorrect/stale ZF value. The compiler must fall back to a
; standard ADD which sets ZF correctly.
define i32 @adox_test_zf(i32 %a, i32 %b, i32 %s) {
; NDD-LABEL: adox_test_zf:
; NDD: # %bb.0:
; NDD-NEXT: xorl %eax, %eax
; NDD-NEXT: addl %edi, %esi
; NDD-NEXT: seto %al
; NDD-NEXT: addl %edx, %eax
; NDD-NEXT: je .LBB8_1
; NDD-NEXT: # %bb.2: # %nonzero
; NDD-NEXT: movl $222, %eax
; NDD-NEXT: retq
; NDD-NEXT: .LBB8_1: # %iszero
; NDD-NEXT: movl $111, %eax
; NDD-NEXT: retq
;
; ADX-LABEL: adox_test_zf:
; ADX: # %bb.0:
; ADX-NEXT: xorl %eax, %eax
; ADX-NEXT: addl %esi, %edi
; ADX-NEXT: seto %al
; ADX-NEXT: addl %edx, %eax
; ADX-NEXT: je .LBB8_1
; ADX-NEXT: # %bb.2: # %nonzero
; ADX-NEXT: movl $222, %eax
; ADX-NEXT: retq
; ADX-NEXT: .LBB8_1: # %iszero
; ADX-NEXT: movl $111, %eax
; ADX-NEXT: retq
;
; NOADX-LABEL: adox_test_zf:
; NOADX: # %bb.0:
; NOADX-NEXT: xorl %eax, %eax
; NOADX-NEXT: addl %esi, %edi
; NOADX-NEXT: seto %al
; NOADX-NEXT: addl %edx, %eax
; NOADX-NEXT: je .LBB8_1
; NOADX-NEXT: # %bb.2: # %nonzero
; NOADX-NEXT: movl $222, %eax
; NOADX-NEXT: retq
; NOADX-NEXT: .LBB8_1: # %iszero
; NOADX-NEXT: movl $111, %eax
; NOADX-NEXT: retq
%o = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
%ov = extractvalue { i32, i1 } %o, 1
%ov.ext = zext i1 %ov to i32
%n = add i32 %s, %ov.ext
%z = icmp eq i32 %n, 0
br i1 %z, label %iszero, label %nonzero
iszero:
ret i32 111
nonzero:
ret i32 222
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}