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 4;------------------------------------------------------------------------------; 5; Odd divisors 6;------------------------------------------------------------------------------; 7 8define i32 @test_srem_odd(i32 %X) nounwind { 9; CHECK-LABEL: test_srem_odd: 10; CHECK: // %bb.0: 11; CHECK-NEXT: mov w8, #52429 12; CHECK-NEXT: mov w9, #39321 13; CHECK-NEXT: movk w8, #52428, lsl #16 14; CHECK-NEXT: movk w9, #6553, lsl #16 15; CHECK-NEXT: madd w8, w0, w8, w9 16; CHECK-NEXT: mov w9, #858993459 17; CHECK-NEXT: cmp w8, w9 18; CHECK-NEXT: cset w0, lo 19; CHECK-NEXT: ret 20 %srem = srem i32 %X, 5 21 %cmp = icmp eq i32 %srem, 0 22 %ret = zext i1 %cmp to i32 23 ret i32 %ret 24} 25 26define i32 @test_srem_odd_25(i32 %X) nounwind { 27; CHECK-LABEL: test_srem_odd_25: 28; CHECK: // %bb.0: 29; CHECK-NEXT: mov w8, #23593 30; CHECK-NEXT: mov w9, #47185 31; CHECK-NEXT: movk w8, #49807, lsl #16 32; CHECK-NEXT: movk w9, #1310, lsl #16 33; CHECK-NEXT: madd w8, w0, w8, w9 34; CHECK-NEXT: mov w9, #28835 35; CHECK-NEXT: movk w9, #2621, lsl #16 36; CHECK-NEXT: cmp w8, w9 37; CHECK-NEXT: cset w0, lo 38; CHECK-NEXT: ret 39 %srem = srem i32 %X, 25 40 %cmp = icmp eq i32 %srem, 0 41 %ret = zext i1 %cmp to i32 42 ret i32 %ret 43} 44 45; This is like test_srem_odd, except the divisor has bit 30 set. 46define i32 @test_srem_odd_bit30(i32 %X) nounwind { 47; CHECK-LABEL: test_srem_odd_bit30: 48; CHECK: // %bb.0: 49; CHECK-NEXT: mov w8, #43691 50; CHECK-NEXT: movk w8, #27306, lsl #16 51; CHECK-NEXT: orr w9, wzr, #0x1 52; CHECK-NEXT: madd w8, w0, w8, w9 53; CHECK-NEXT: cmp w8, #3 // =3 54; CHECK-NEXT: cset w0, lo 55; CHECK-NEXT: ret 56 %srem = srem i32 %X, 1073741827 57 %cmp = icmp eq i32 %srem, 0 58 %ret = zext i1 %cmp to i32 59 ret i32 %ret 60} 61 62; This is like test_srem_odd, except the divisor has bit 31 set. 63define i32 @test_srem_odd_bit31(i32 %X) nounwind { 64; CHECK-LABEL: test_srem_odd_bit31: 65; CHECK: // %bb.0: 66; CHECK-NEXT: mov w8, #21845 67; CHECK-NEXT: movk w8, #54613, lsl #16 68; CHECK-NEXT: orr w9, wzr, #0x1 69; CHECK-NEXT: madd w8, w0, w8, w9 70; CHECK-NEXT: cmp w8, #3 // =3 71; CHECK-NEXT: cset w0, lo 72; CHECK-NEXT: ret 73 %srem = srem i32 %X, 2147483651 74 %cmp = icmp eq i32 %srem, 0 75 %ret = zext i1 %cmp to i32 76 ret i32 %ret 77} 78 79;------------------------------------------------------------------------------; 80; Even divisors 81;------------------------------------------------------------------------------; 82 83define i16 @test_srem_even(i16 %X) nounwind { 84; CHECK-LABEL: test_srem_even: 85; CHECK: // %bb.0: 86; CHECK-NEXT: sxth w8, w0 87; CHECK-NEXT: mov w9, #18725 88; CHECK-NEXT: mul w8, w8, w9 89; CHECK-NEXT: asr w9, w8, #18 90; CHECK-NEXT: add w8, w9, w8, lsr #31 91; CHECK-NEXT: mov w9, #14 92; CHECK-NEXT: msub w8, w8, w9, w0 93; CHECK-NEXT: tst w8, #0xffff 94; CHECK-NEXT: cset w0, ne 95; CHECK-NEXT: ret 96 %srem = srem i16 %X, 14 97 %cmp = icmp ne i16 %srem, 0 98 %ret = zext i1 %cmp to i16 99 ret i16 %ret 100} 101 102define i32 @test_srem_even_100(i32 %X) nounwind { 103; CHECK-LABEL: test_srem_even_100: 104; CHECK: // %bb.0: 105; CHECK-NEXT: mov w8, #23593 106; CHECK-NEXT: mov w9, #47184 107; CHECK-NEXT: movk w8, #49807, lsl #16 108; CHECK-NEXT: movk w9, #1310, lsl #16 109; CHECK-NEXT: madd w8, w0, w8, w9 110; CHECK-NEXT: mov w9, #23593 111; CHECK-NEXT: ror w8, w8, #2 112; CHECK-NEXT: movk w9, #655, lsl #16 113; CHECK-NEXT: cmp w8, w9 114; CHECK-NEXT: cset w0, lo 115; CHECK-NEXT: ret 116 %srem = srem i32 %X, 100 117 %cmp = icmp eq i32 %srem, 0 118 %ret = zext i1 %cmp to i32 119 ret i32 %ret 120} 121 122; This is like test_srem_even, except the divisor has bit 30 set. 123define i32 @test_srem_even_bit30(i32 %X) nounwind { 124; CHECK-LABEL: test_srem_even_bit30: 125; CHECK: // %bb.0: 126; CHECK-NEXT: mov w8, #20165 127; CHECK-NEXT: movk w8, #64748, lsl #16 128; CHECK-NEXT: orr w9, wzr, #0x8 129; CHECK-NEXT: madd w8, w0, w8, w9 130; CHECK-NEXT: ror w8, w8, #3 131; CHECK-NEXT: cmp w8, #3 // =3 132; CHECK-NEXT: cset w0, lo 133; CHECK-NEXT: ret 134 %srem = srem i32 %X, 1073741928 135 %cmp = icmp eq i32 %srem, 0 136 %ret = zext i1 %cmp to i32 137 ret i32 %ret 138} 139 140; This is like test_srem_odd, except the divisor has bit 31 set. 141define i32 @test_srem_even_bit31(i32 %X) nounwind { 142; CHECK-LABEL: test_srem_even_bit31: 143; CHECK: // %bb.0: 144; CHECK-NEXT: mov w8, #1285 145; CHECK-NEXT: movk w8, #50437, lsl #16 146; CHECK-NEXT: orr w9, wzr, #0x2 147; CHECK-NEXT: madd w8, w0, w8, w9 148; CHECK-NEXT: ror w8, w8, #1 149; CHECK-NEXT: cmp w8, #3 // =3 150; CHECK-NEXT: cset w0, lo 151; CHECK-NEXT: ret 152 %srem = srem i32 %X, 2147483750 153 %cmp = icmp eq i32 %srem, 0 154 %ret = zext i1 %cmp to i32 155 ret i32 %ret 156} 157 158;------------------------------------------------------------------------------; 159; Special case 160;------------------------------------------------------------------------------; 161 162; 'NE' predicate is fine too. 163define i32 @test_srem_odd_setne(i32 %X) nounwind { 164; CHECK-LABEL: test_srem_odd_setne: 165; CHECK: // %bb.0: 166; CHECK-NEXT: mov w8, #52429 167; CHECK-NEXT: mov w9, #39321 168; CHECK-NEXT: movk w8, #52428, lsl #16 169; CHECK-NEXT: movk w9, #6553, lsl #16 170; CHECK-NEXT: madd w8, w0, w8, w9 171; CHECK-NEXT: mov w9, #13106 172; CHECK-NEXT: movk w9, #13107, lsl #16 173; CHECK-NEXT: cmp w8, w9 174; CHECK-NEXT: cset w0, hi 175; CHECK-NEXT: ret 176 %srem = srem i32 %X, 5 177 %cmp = icmp ne i32 %srem, 0 178 %ret = zext i1 %cmp to i32 179 ret i32 %ret 180} 181 182; The fold is only valid for positive divisors, negative-ones should be negated. 183define i32 @test_srem_negative_odd(i32 %X) nounwind { 184; CHECK-LABEL: test_srem_negative_odd: 185; CHECK: // %bb.0: 186; CHECK-NEXT: mov w8, #52429 187; CHECK-NEXT: mov w9, #39321 188; CHECK-NEXT: movk w8, #52428, lsl #16 189; CHECK-NEXT: movk w9, #6553, lsl #16 190; CHECK-NEXT: madd w8, w0, w8, w9 191; CHECK-NEXT: mov w9, #13106 192; CHECK-NEXT: movk w9, #13107, lsl #16 193; CHECK-NEXT: cmp w8, w9 194; CHECK-NEXT: cset w0, hi 195; CHECK-NEXT: ret 196 %srem = srem i32 %X, -5 197 %cmp = icmp ne i32 %srem, 0 198 %ret = zext i1 %cmp to i32 199 ret i32 %ret 200} 201define i32 @test_srem_negative_even(i32 %X) nounwind { 202; CHECK-LABEL: test_srem_negative_even: 203; CHECK: // %bb.0: 204; CHECK-NEXT: mov w8, #28087 205; CHECK-NEXT: mov w9, #9362 206; CHECK-NEXT: movk w8, #46811, lsl #16 207; CHECK-NEXT: movk w9, #4681, lsl #16 208; CHECK-NEXT: madd w8, w0, w8, w9 209; CHECK-NEXT: ror w8, w8, #1 210; CHECK-NEXT: cmp w8, w9 211; CHECK-NEXT: cset w0, hi 212; CHECK-NEXT: ret 213 %srem = srem i32 %X, -14 214 %cmp = icmp ne i32 %srem, 0 215 %ret = zext i1 %cmp to i32 216 ret i32 %ret 217} 218 219;------------------------------------------------------------------------------; 220; Negative tests 221;------------------------------------------------------------------------------; 222 223; We can lower remainder of division by one much better elsewhere. 224define i32 @test_srem_one(i32 %X) nounwind { 225; CHECK-LABEL: test_srem_one: 226; CHECK: // %bb.0: 227; CHECK-NEXT: mov w0, #1 228; CHECK-NEXT: ret 229 %srem = srem i32 %X, 1 230 %cmp = icmp eq i32 %srem, 0 231 %ret = zext i1 %cmp to i32 232 ret i32 %ret 233} 234 235; We can lower remainder of division by powers of two much better elsewhere. 236define i32 @test_srem_pow2(i32 %X) nounwind { 237; CHECK-LABEL: test_srem_pow2: 238; CHECK: // %bb.0: 239; CHECK-NEXT: add w8, w0, #15 // =15 240; CHECK-NEXT: cmp w0, #0 // =0 241; CHECK-NEXT: csel w8, w8, w0, lt 242; CHECK-NEXT: and w8, w8, #0xfffffff0 243; CHECK-NEXT: cmp w0, w8 244; CHECK-NEXT: cset w0, eq 245; CHECK-NEXT: ret 246 %srem = srem i32 %X, 16 247 %cmp = icmp eq i32 %srem, 0 248 %ret = zext i1 %cmp to i32 249 ret i32 %ret 250} 251 252; The fold is only valid for positive divisors, and we can't negate INT_MIN. 253define i32 @test_srem_int_min(i32 %X) nounwind { 254; CHECK-LABEL: test_srem_int_min: 255; CHECK: // %bb.0: 256; CHECK-NEXT: mov w8, #2147483647 257; CHECK-NEXT: add w8, w0, w8 258; CHECK-NEXT: cmp w0, #0 // =0 259; CHECK-NEXT: csel w8, w8, w0, lt 260; CHECK-NEXT: and w8, w8, #0x80000000 261; CHECK-NEXT: cmn w0, w8 262; CHECK-NEXT: cset w0, eq 263; CHECK-NEXT: ret 264 %srem = srem i32 %X, 2147483648 265 %cmp = icmp eq i32 %srem, 0 266 %ret = zext i1 %cmp to i32 267 ret i32 %ret 268} 269 270; We can lower remainder of division by all-ones much better elsewhere. 271define i32 @test_srem_allones(i32 %X) nounwind { 272; CHECK-LABEL: test_srem_allones: 273; CHECK: // %bb.0: 274; CHECK-NEXT: cmp w0, #0 // =0 275; CHECK-NEXT: csel w8, w0, w0, lt 276; CHECK-NEXT: cmp w0, w8 277; CHECK-NEXT: cset w0, eq 278; CHECK-NEXT: ret 279 %srem = srem i32 %X, 4294967295 280 %cmp = icmp eq i32 %srem, 0 281 %ret = zext i1 %cmp to i32 282 ret i32 %ret 283} 284