1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK 3 4define i32 @fold_srem_positive_odd(i32 %x) { 5; CHECK-LABEL: fold_srem_positive_odd: 6; CHECK: # %bb.0: 7; CHECK-NEXT: movslq %edi, %rax 8; CHECK-NEXT: imulq $-1401515643, %rax, %rcx # imm = 0xAC769185 9; CHECK-NEXT: shrq $32, %rcx 10; CHECK-NEXT: addl %eax, %ecx 11; CHECK-NEXT: movl %ecx, %edx 12; CHECK-NEXT: shrl $31, %edx 13; CHECK-NEXT: sarl $6, %ecx 14; CHECK-NEXT: addl %edx, %ecx 15; CHECK-NEXT: imull $95, %ecx, %ecx 16; CHECK-NEXT: subl %ecx, %eax 17; CHECK-NEXT: # kill: def $eax killed $eax killed $rax 18; CHECK-NEXT: retq 19 %1 = srem i32 %x, 95 20 ret i32 %1 21} 22 23 24define i32 @fold_srem_positive_even(i32 %x) { 25; CHECK-LABEL: fold_srem_positive_even: 26; CHECK: # %bb.0: 27; CHECK-NEXT: movslq %edi, %rax 28; CHECK-NEXT: imulq $1037275121, %rax, %rcx # imm = 0x3DD38FF1 29; CHECK-NEXT: movq %rcx, %rdx 30; CHECK-NEXT: shrq $63, %rdx 31; CHECK-NEXT: sarq $40, %rcx 32; CHECK-NEXT: addl %edx, %ecx 33; CHECK-NEXT: imull $1060, %ecx, %ecx # imm = 0x424 34; CHECK-NEXT: subl %ecx, %eax 35; CHECK-NEXT: # kill: def $eax killed $eax killed $rax 36; CHECK-NEXT: retq 37 %1 = srem i32 %x, 1060 38 ret i32 %1 39} 40 41 42define i32 @fold_srem_negative_odd(i32 %x) { 43; CHECK-LABEL: fold_srem_negative_odd: 44; CHECK: # %bb.0: 45; CHECK-NEXT: movslq %edi, %rax 46; CHECK-NEXT: imulq $-1520762971, %rax, %rcx # imm = 0xA55AFFA5 47; CHECK-NEXT: movq %rcx, %rdx 48; CHECK-NEXT: shrq $63, %rdx 49; CHECK-NEXT: sarq $40, %rcx 50; CHECK-NEXT: addl %edx, %ecx 51; CHECK-NEXT: imull $-723, %ecx, %ecx # imm = 0xFD2D 52; CHECK-NEXT: subl %ecx, %eax 53; CHECK-NEXT: # kill: def $eax killed $eax killed $rax 54; CHECK-NEXT: retq 55 %1 = srem i32 %x, -723 56 ret i32 %1 57} 58 59 60define i32 @fold_srem_negative_even(i32 %x) { 61; CHECK-LABEL: fold_srem_negative_even: 62; CHECK: # %bb.0: 63; CHECK-NEXT: movslq %edi, %rax 64; CHECK-NEXT: imulq $-47844377, %rax, %rcx # imm = 0xFD25F3E7 65; CHECK-NEXT: movq %rcx, %rdx 66; CHECK-NEXT: shrq $63, %rdx 67; CHECK-NEXT: sarq $40, %rcx 68; CHECK-NEXT: addl %edx, %ecx 69; CHECK-NEXT: imull $-22981, %ecx, %ecx # imm = 0xA63B 70; CHECK-NEXT: subl %ecx, %eax 71; CHECK-NEXT: # kill: def $eax killed $eax killed $rax 72; CHECK-NEXT: retq 73 %1 = srem i32 %x, -22981 74 ret i32 %1 75} 76 77 78; Don't fold if we can combine srem with sdiv. 79define i32 @combine_srem_sdiv(i32 %x) { 80; CHECK-LABEL: combine_srem_sdiv: 81; CHECK: # %bb.0: 82; CHECK-NEXT: movslq %edi, %rax 83; CHECK-NEXT: imulq $-1401515643, %rax, %rcx # imm = 0xAC769185 84; CHECK-NEXT: shrq $32, %rcx 85; CHECK-NEXT: addl %eax, %ecx 86; CHECK-NEXT: movl %ecx, %edx 87; CHECK-NEXT: shrl $31, %edx 88; CHECK-NEXT: sarl $6, %ecx 89; CHECK-NEXT: addl %edx, %ecx 90; CHECK-NEXT: imull $95, %ecx, %edx 91; CHECK-NEXT: subl %edx, %eax 92; CHECK-NEXT: addl %ecx, %eax 93; CHECK-NEXT: # kill: def $eax killed $eax killed $rax 94; CHECK-NEXT: retq 95 %1 = srem i32 %x, 95 96 %2 = sdiv i32 %x, 95 97 %3 = add i32 %1, %2 98 ret i32 %3 99} 100 101; Don't fold for divisors that are a power of two. 102define i32 @dont_fold_srem_power_of_two(i32 %x) { 103; CHECK-LABEL: dont_fold_srem_power_of_two: 104; CHECK: # %bb.0: 105; CHECK-NEXT: movl %edi, %eax 106; CHECK-NEXT: leal 63(%rax), %ecx 107; CHECK-NEXT: testl %edi, %edi 108; CHECK-NEXT: cmovnsl %edi, %ecx 109; CHECK-NEXT: andl $-64, %ecx 110; CHECK-NEXT: subl %ecx, %eax 111; CHECK-NEXT: # kill: def $eax killed $eax killed $rax 112; CHECK-NEXT: retq 113 %1 = srem i32 %x, 64 114 ret i32 %1 115} 116 117; Don't fold if the divisor is one. 118define i32 @dont_fold_srem_one(i32 %x) { 119; CHECK-LABEL: dont_fold_srem_one: 120; CHECK: # %bb.0: 121; CHECK-NEXT: xorl %eax, %eax 122; CHECK-NEXT: retq 123 %1 = srem i32 %x, 1 124 ret i32 %1 125} 126 127; Don't fold if the divisor is 2^31. 128define i32 @dont_fold_srem_i32_smax(i32 %x) { 129; CHECK-LABEL: dont_fold_srem_i32_smax: 130; CHECK: # %bb.0: 131; CHECK-NEXT: # kill: def $edi killed $edi def $rdi 132; CHECK-NEXT: leal 2147483647(%rdi), %eax 133; CHECK-NEXT: testl %edi, %edi 134; CHECK-NEXT: cmovnsl %edi, %eax 135; CHECK-NEXT: andl $-2147483648, %eax # imm = 0x80000000 136; CHECK-NEXT: addl %edi, %eax 137; CHECK-NEXT: retq 138 %1 = srem i32 %x, 2147483648 139 ret i32 %1 140} 141 142; Don't fold i64 srem 143define i64 @dont_fold_srem_i64(i64 %x) { 144; CHECK-LABEL: dont_fold_srem_i64: 145; CHECK: # %bb.0: 146; CHECK-NEXT: movabsq $6023426636313322977, %rcx # imm = 0x5397829CBC14E5E1 147; CHECK-NEXT: movq %rdi, %rax 148; CHECK-NEXT: imulq %rcx 149; CHECK-NEXT: movq %rdx, %rax 150; CHECK-NEXT: shrq $63, %rax 151; CHECK-NEXT: sarq $5, %rdx 152; CHECK-NEXT: addq %rax, %rdx 153; CHECK-NEXT: imulq $98, %rdx, %rax 154; CHECK-NEXT: subq %rax, %rdi 155; CHECK-NEXT: movq %rdi, %rax 156; CHECK-NEXT: retq 157 %1 = srem i64 %x, 98 158 ret i64 %1 159} 160