167 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 62; RUN: llc < %s -mtriple=x86_64 | FileCheck %s3 4; GitHub issue #1610365 6; Positive test : umin(sub(a,b),a) with scalar types should be folded7define i64 @underflow_compare_fold_i64(i64 %a, i64 %b) {8; CHECK-LABEL: underflow_compare_fold_i64:9; CHECK: # %bb.0:10; CHECK-NEXT: movq %rdi, %rax11; CHECK-NEXT: subq %rsi, %rax12; CHECK-NEXT: cmpq %rdi, %rax13; CHECK-NEXT: cmovaeq %rdi, %rax14; CHECK-NEXT: retq15 %sub = sub i64 %a, %b16 %cond = tail call i64 @llvm.umin.i64(i64 %sub, i64 %a)17 ret i64 %cond18}19 20; Positive test : umin(a,sub(a,b)) with scalar types should be folded21define i64 @underflow_compare_fold_i64_commute(i64 %a, i64 %b) {22; CHECK-LABEL: underflow_compare_fold_i64_commute:23; CHECK: # %bb.0:24; CHECK-NEXT: movq %rdi, %rax25; CHECK-NEXT: subq %rsi, %rax26; CHECK-NEXT: cmpq %rax, %rdi27; CHECK-NEXT: cmovbq %rdi, %rax28; CHECK-NEXT: retq29 %sub = sub i64 %a, %b30 %cond = tail call i64 @llvm.umin.i64(i64 %a, i64 %sub)31 ret i64 %cond32}33 34; Positive test : multi-use is OK since the sub instruction still runs once35define i64 @underflow_compare_fold_i64_multi_use(i64 %a, i64 %b, ptr addrspace(1) %ptr) {36; CHECK-LABEL: underflow_compare_fold_i64_multi_use:37; CHECK: # %bb.0:38; CHECK-NEXT: movq %rdi, %rax39; CHECK-NEXT: subq %rsi, %rax40; CHECK-NEXT: movq %rax, (%rdx)41; CHECK-NEXT: cmpq %rdi, %rax42; CHECK-NEXT: cmovaeq %rdi, %rax43; CHECK-NEXT: retq44 %sub = sub i64 %a, %b45 store i64 %sub, ptr addrspace(1) %ptr46 %cond = call i64 @llvm.umin.i64(i64 %sub, i64 %a)47 ret i64 %cond48}49 50; Positive test : i3251define i32 @underflow_compare_fold_i32(i32 %a, i32 %b) {52; CHECK-LABEL: underflow_compare_fold_i32:53; CHECK: # %bb.0:54; CHECK-NEXT: movl %edi, %eax55; CHECK-NEXT: subl %esi, %eax56; CHECK-NEXT: cmpl %edi, %eax57; CHECK-NEXT: cmovael %edi, %eax58; CHECK-NEXT: retq59 %sub = sub i32 %a, %b60 %cond = tail call i32 @llvm.umin.i32(i32 %sub, i32 %a)61 ret i32 %cond62}63 64; Positive test : i3265define i32 @underflow_compare_fold_i32_commute(i32 %a, i32 %b) {66; CHECK-LABEL: underflow_compare_fold_i32_commute:67; CHECK: # %bb.0:68; CHECK-NEXT: movl %edi, %eax69; CHECK-NEXT: subl %esi, %eax70; CHECK-NEXT: cmpl %eax, %edi71; CHECK-NEXT: cmovbl %edi, %eax72; CHECK-NEXT: retq73 %sub = sub i32 %a, %b74 %cond = tail call i32 @llvm.umin.i32(i32 %a, i32 %sub)75 ret i32 %cond76}77 78; Positive test : i3279define i32 @underflow_compare_fold_i32_multi_use(i32 %a, i32 %b, ptr addrspace(1) %ptr) {80; CHECK-LABEL: underflow_compare_fold_i32_multi_use:81; CHECK: # %bb.0:82; CHECK-NEXT: movl %edi, %eax83; CHECK-NEXT: subl %esi, %eax84; CHECK-NEXT: movl %eax, (%rdx)85; CHECK-NEXT: cmpl %edi, %eax86; CHECK-NEXT: cmovael %edi, %eax87; CHECK-NEXT: retq88 %sub = sub i32 %a, %b89 store i32 %sub, ptr addrspace(1) %ptr90 %cond = call i32 @llvm.umin.i32(i32 %sub, i32 %a)91 ret i32 %cond92}93 94; Positive test : i1695define i16 @underflow_compare_fold_i16(i16 %a, i16 %b) {96; CHECK-LABEL: underflow_compare_fold_i16:97; CHECK: # %bb.0:98; CHECK-NEXT: movl %edi, %eax99; CHECK-NEXT: subl %esi, %eax100; CHECK-NEXT: cmpw %di, %ax101; CHECK-NEXT: cmovael %edi, %eax102; CHECK-NEXT: # kill: def $ax killed $ax killed $eax103; CHECK-NEXT: retq104 %sub = sub i16 %a, %b105 %cond = tail call i16 @llvm.umin.i16(i16 %sub, i16 %a)106 ret i16 %cond107}108 109; Positive test : i16110define i16 @underflow_compare_fold_i16_commute(i16 %a, i16 %b) {111; CHECK-LABEL: underflow_compare_fold_i16_commute:112; CHECK: # %bb.0:113; CHECK-NEXT: movl %edi, %eax114; CHECK-NEXT: subl %esi, %eax115; CHECK-NEXT: cmpw %ax, %di116; CHECK-NEXT: cmovbl %edi, %eax117; CHECK-NEXT: # kill: def $ax killed $ax killed $eax118; CHECK-NEXT: retq119 %sub = sub i16 %a, %b120 %cond = tail call i16 @llvm.umin.i16(i16 %a, i16 %sub)121 ret i16 %cond122}123 124; Positive test : i16125define i16 @underflow_compare_fold_i16_multi_use(i16 %a, i16 %b, ptr addrspace(1) %ptr) {126; CHECK-LABEL: underflow_compare_fold_i16_multi_use:127; CHECK: # %bb.0:128; CHECK-NEXT: movl %edi, %eax129; CHECK-NEXT: subl %esi, %eax130; CHECK-NEXT: movw %ax, (%rdx)131; CHECK-NEXT: cmpw %di, %ax132; CHECK-NEXT: cmovael %edi, %eax133; CHECK-NEXT: # kill: def $ax killed $ax killed $eax134; CHECK-NEXT: retq135 %sub = sub i16 %a, %b136 store i16 %sub, ptr addrspace(1) %ptr137 %cond = call i16 @llvm.umin.i16(i16 %sub, i16 %a)138 ret i16 %cond139}140 141 142; Negative test, vector types : umin(sub(a,b),a) but with vectors143define <16 x i8> @underflow_compare_dontfold_vectors(<16 x i8> %a, <16 x i8> %b) {144; CHECK-LABEL: underflow_compare_dontfold_vectors:145; CHECK: # %bb.0:146; CHECK-NEXT: movdqa %xmm0, %xmm2147; CHECK-NEXT: psubb %xmm1, %xmm2148; CHECK-NEXT: pminub %xmm2, %xmm0149; CHECK-NEXT: retq150 %sub = sub <16 x i8> %a, %b151 %cond = tail call <16 x i8> @llvm.umin.v16i8(<16 x i8> %sub, <16 x i8> %a)152 ret <16 x i8> %cond153}154 155; Negative test, pattern mismatch : umin(add(a,b),a)156define i64 @umin_add(i64 %a, i64 %b) {157; CHECK-LABEL: umin_add:158; CHECK: # %bb.0:159; CHECK-NEXT: leaq (%rsi,%rdi), %rax160; CHECK-NEXT: cmpq %rdi, %rax161; CHECK-NEXT: cmovaeq %rdi, %rax162; CHECK-NEXT: retq163 %add = add i64 %a, %b164 %cond = tail call i64 @llvm.umin.i64(i64 %add, i64 %a)165 ret i64 %cond166}167