1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s 3 4define i32 @fold_srem_positive_odd(i32 %x) { 5; CHECK-LABEL: fold_srem_positive_odd: 6; CHECK: // %bb.0: 7; CHECK-NEXT: mov w8, #37253 8; CHECK-NEXT: movk w8, #44150, lsl #16 9; CHECK-NEXT: smull x8, w0, w8 10; CHECK-NEXT: lsr x8, x8, #32 11; CHECK-NEXT: add w8, w8, w0 12; CHECK-NEXT: asr w9, w8, #6 13; CHECK-NEXT: add w8, w9, w8, lsr #31 14; CHECK-NEXT: mov w9, #95 15; CHECK-NEXT: msub w0, w8, w9, w0 16; CHECK-NEXT: ret 17 %1 = srem i32 %x, 95 18 ret i32 %1 19} 20 21 22define i32 @fold_srem_positive_even(i32 %x) { 23; CHECK-LABEL: fold_srem_positive_even: 24; CHECK: // %bb.0: 25; CHECK-NEXT: mov w8, #36849 26; CHECK-NEXT: movk w8, #15827, lsl #16 27; CHECK-NEXT: smull x8, w0, w8 28; CHECK-NEXT: lsr x9, x8, #63 29; CHECK-NEXT: asr x8, x8, #40 30; CHECK-NEXT: add w8, w8, w9 31; CHECK-NEXT: mov w9, #1060 32; CHECK-NEXT: msub w0, w8, w9, w0 33; CHECK-NEXT: ret 34 %1 = srem i32 %x, 1060 35 ret i32 %1 36} 37 38 39define i32 @fold_srem_negative_odd(i32 %x) { 40; CHECK-LABEL: fold_srem_negative_odd: 41; CHECK: // %bb.0: 42; CHECK-NEXT: mov w8, #65445 43; CHECK-NEXT: movk w8, #42330, lsl #16 44; CHECK-NEXT: smull x8, w0, w8 45; CHECK-NEXT: lsr x9, x8, #63 46; CHECK-NEXT: asr x8, x8, #40 47; CHECK-NEXT: add w8, w8, w9 48; CHECK-NEXT: mov w9, #-723 49; CHECK-NEXT: msub w0, w8, w9, w0 50; CHECK-NEXT: ret 51 %1 = srem i32 %x, -723 52 ret i32 %1 53} 54 55 56define i32 @fold_srem_negative_even(i32 %x) { 57; CHECK-LABEL: fold_srem_negative_even: 58; CHECK: // %bb.0: 59; CHECK-NEXT: mov w8, #62439 60; CHECK-NEXT: movk w8, #64805, lsl #16 61; CHECK-NEXT: smull x8, w0, w8 62; CHECK-NEXT: lsr x9, x8, #63 63; CHECK-NEXT: asr x8, x8, #40 64; CHECK-NEXT: add w8, w8, w9 65; CHECK-NEXT: mov w9, #-22981 66; CHECK-NEXT: msub w0, w8, w9, w0 67; CHECK-NEXT: ret 68 %1 = srem i32 %x, -22981 69 ret i32 %1 70} 71 72 73; Don't fold if we can combine srem with sdiv. 74define i32 @combine_srem_sdiv(i32 %x) { 75; CHECK-LABEL: combine_srem_sdiv: 76; CHECK: // %bb.0: 77; CHECK-NEXT: mov w8, #37253 78; CHECK-NEXT: movk w8, #44150, lsl #16 79; CHECK-NEXT: smull x8, w0, w8 80; CHECK-NEXT: lsr x8, x8, #32 81; CHECK-NEXT: add w8, w8, w0 82; CHECK-NEXT: asr w9, w8, #6 83; CHECK-NEXT: add w8, w9, w8, lsr #31 84; CHECK-NEXT: mov w9, #95 85; CHECK-NEXT: msub w9, w8, w9, w0 86; CHECK-NEXT: add w0, w9, w8 87; CHECK-NEXT: ret 88 %1 = srem i32 %x, 95 89 %2 = sdiv i32 %x, 95 90 %3 = add i32 %1, %2 91 ret i32 %3 92} 93 94; Don't fold for divisors that are a power of two. 95define i32 @dont_fold_srem_power_of_two(i32 %x) { 96; CHECK-LABEL: dont_fold_srem_power_of_two: 97; CHECK: // %bb.0: 98; CHECK-NEXT: add w8, w0, #63 // =63 99; CHECK-NEXT: cmp w0, #0 // =0 100; CHECK-NEXT: csel w8, w8, w0, lt 101; CHECK-NEXT: and w8, w8, #0xffffffc0 102; CHECK-NEXT: sub w0, w0, w8 103; CHECK-NEXT: ret 104 %1 = srem i32 %x, 64 105 ret i32 %1 106} 107 108; Don't fold if the divisor is one. 109define i32 @dont_fold_srem_one(i32 %x) { 110; CHECK-LABEL: dont_fold_srem_one: 111; CHECK: // %bb.0: 112; CHECK-NEXT: mov w0, wzr 113; CHECK-NEXT: ret 114 %1 = srem i32 %x, 1 115 ret i32 %1 116} 117 118; Don't fold if the divisor is 2^31. 119define i32 @dont_fold_srem_i32_smax(i32 %x) { 120; CHECK-LABEL: dont_fold_srem_i32_smax: 121; CHECK: // %bb.0: 122; CHECK-NEXT: mov w8, #2147483647 123; CHECK-NEXT: add w8, w0, w8 124; CHECK-NEXT: cmp w0, #0 // =0 125; CHECK-NEXT: csel w8, w8, w0, lt 126; CHECK-NEXT: and w8, w8, #0x80000000 127; CHECK-NEXT: add w0, w0, w8 128; CHECK-NEXT: ret 129 %1 = srem i32 %x, 2147483648 130 ret i32 %1 131} 132 133; Don't fold i64 srem 134define i64 @dont_fold_srem_i64(i64 %x) { 135; CHECK-LABEL: dont_fold_srem_i64: 136; CHECK: // %bb.0: 137; CHECK-NEXT: mov x8, #58849 138; CHECK-NEXT: movk x8, #48148, lsl #16 139; CHECK-NEXT: movk x8, #33436, lsl #32 140; CHECK-NEXT: movk x8, #21399, lsl #48 141; CHECK-NEXT: smulh x8, x0, x8 142; CHECK-NEXT: asr x9, x8, #5 143; CHECK-NEXT: add x8, x9, x8, lsr #63 144; CHECK-NEXT: mov w9, #98 145; CHECK-NEXT: msub x0, x8, x9, x0 146; CHECK-NEXT: ret 147 %1 = srem i64 %x, 98 148 ret i64 %1 149} 150