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_urem_odd(i32 %X) nounwind { 9; CHECK-LABEL: test_urem_odd: 10; CHECK: // %bb.0: 11; CHECK-NEXT: mov w8, #52429 // =0xcccd 12; CHECK-NEXT: mov w9, #13108 // =0x3334 13; CHECK-NEXT: movk w8, #52428, lsl #16 14; CHECK-NEXT: movk w9, #13107, lsl #16 15; CHECK-NEXT: mul w8, w0, w8 16; CHECK-NEXT: cmp w8, w9 17; CHECK-NEXT: cset w0, lo 18; CHECK-NEXT: ret 19 %urem = urem i32 %X, 5 20 %cmp = icmp eq i32 %urem, 0 21 %ret = zext i1 %cmp to i32 22 ret i32 %ret 23} 24 25define i32 @test_urem_odd_25(i32 %X) nounwind { 26; CHECK-LABEL: test_urem_odd_25: 27; CHECK: // %bb.0: 28; CHECK-NEXT: mov w8, #23593 // =0x5c29 29; CHECK-NEXT: mov w9, #28836 // =0x70a4 30; CHECK-NEXT: movk w8, #49807, lsl #16 31; CHECK-NEXT: movk w9, #2621, lsl #16 32; CHECK-NEXT: mul w8, w0, w8 33; CHECK-NEXT: cmp w8, w9 34; CHECK-NEXT: cset w0, lo 35; CHECK-NEXT: ret 36 %urem = urem i32 %X, 25 37 %cmp = icmp eq i32 %urem, 0 38 %ret = zext i1 %cmp to i32 39 ret i32 %ret 40} 41 42; This is like test_urem_odd, except the divisor has bit 30 set. 43define i32 @test_urem_odd_bit30(i32 %X) nounwind { 44; CHECK-LABEL: test_urem_odd_bit30: 45; CHECK: // %bb.0: 46; CHECK-NEXT: mov w8, #43691 // =0xaaab 47; CHECK-NEXT: movk w8, #27306, lsl #16 48; CHECK-NEXT: mul w8, w0, w8 49; CHECK-NEXT: cmp w8, #4 50; CHECK-NEXT: cset w0, lo 51; CHECK-NEXT: ret 52 %urem = urem i32 %X, 1073741827 53 %cmp = icmp eq i32 %urem, 0 54 %ret = zext i1 %cmp to i32 55 ret i32 %ret 56} 57 58; This is like test_urem_odd, except the divisor has bit 31 set. 59define i32 @test_urem_odd_bit31(i32 %X) nounwind { 60; CHECK-LABEL: test_urem_odd_bit31: 61; CHECK: // %bb.0: 62; CHECK-NEXT: mov w8, #43691 // =0xaaab 63; CHECK-NEXT: movk w8, #10922, lsl #16 64; CHECK-NEXT: mul w8, w0, w8 65; CHECK-NEXT: cmp w8, #2 66; CHECK-NEXT: cset w0, lo 67; CHECK-NEXT: ret 68 %urem = urem i32 %X, 2147483651 69 %cmp = icmp eq i32 %urem, 0 70 %ret = zext i1 %cmp to i32 71 ret i32 %ret 72} 73 74;------------------------------------------------------------------------------; 75; Even divisors 76;------------------------------------------------------------------------------; 77 78define i16 @test_urem_even(i16 %X) nounwind { 79; CHECK-LABEL: test_urem_even: 80; CHECK: // %bb.0: 81; CHECK-NEXT: mov w8, #28087 // =0x6db7 82; CHECK-NEXT: mul w8, w0, w8 83; CHECK-NEXT: and w9, w8, #0xfffc 84; CHECK-NEXT: lsr w9, w9, #1 85; CHECK-NEXT: orr w8, w9, w8, lsl #15 86; CHECK-NEXT: ubfx w8, w8, #1, #15 87; CHECK-NEXT: cmp w8, #2340 88; CHECK-NEXT: cset w0, hi 89; CHECK-NEXT: ret 90 %urem = urem i16 %X, 14 91 %cmp = icmp ne i16 %urem, 0 92 %ret = zext i1 %cmp to i16 93 ret i16 %ret 94} 95 96define i32 @test_urem_even_100(i32 %X) nounwind { 97; CHECK-LABEL: test_urem_even_100: 98; CHECK: // %bb.0: 99; CHECK-NEXT: mov w8, #23593 // =0x5c29 100; CHECK-NEXT: mov w9, #23593 // =0x5c29 101; CHECK-NEXT: movk w8, #49807, lsl #16 102; CHECK-NEXT: movk w9, #655, lsl #16 103; CHECK-NEXT: mul w8, w0, w8 104; CHECK-NEXT: ror w8, w8, #2 105; CHECK-NEXT: cmp w8, w9 106; CHECK-NEXT: cset w0, lo 107; CHECK-NEXT: ret 108 %urem = urem i32 %X, 100 109 %cmp = icmp eq i32 %urem, 0 110 %ret = zext i1 %cmp to i32 111 ret i32 %ret 112} 113 114; This is like test_urem_even, except the divisor has bit 30 set. 115define i32 @test_urem_even_bit30(i32 %X) nounwind { 116; CHECK-LABEL: test_urem_even_bit30: 117; CHECK: // %bb.0: 118; CHECK-NEXT: mov w8, #20165 // =0x4ec5 119; CHECK-NEXT: movk w8, #64748, lsl #16 120; CHECK-NEXT: mul w8, w0, w8 121; CHECK-NEXT: ror w8, w8, #3 122; CHECK-NEXT: cmp w8, #4 123; CHECK-NEXT: cset w0, lo 124; CHECK-NEXT: ret 125 %urem = urem i32 %X, 1073741928 126 %cmp = icmp eq i32 %urem, 0 127 %ret = zext i1 %cmp to i32 128 ret i32 %ret 129} 130 131; This is like test_urem_odd, except the divisor has bit 31 set. 132define i32 @test_urem_even_bit31(i32 %X) nounwind { 133; CHECK-LABEL: test_urem_even_bit31: 134; CHECK: // %bb.0: 135; CHECK-NEXT: mov w8, #64251 // =0xfafb 136; CHECK-NEXT: movk w8, #47866, lsl #16 137; CHECK-NEXT: mul w8, w0, w8 138; CHECK-NEXT: ror w8, w8, #1 139; CHECK-NEXT: cmp w8, #2 140; CHECK-NEXT: cset w0, lo 141; CHECK-NEXT: ret 142 %urem = urem i32 %X, 2147483750 143 %cmp = icmp eq i32 %urem, 0 144 %ret = zext i1 %cmp to i32 145 ret i32 %ret 146} 147 148;------------------------------------------------------------------------------; 149; Special case 150;------------------------------------------------------------------------------; 151 152; 'NE' predicate is fine too. 153define i32 @test_urem_odd_setne(i32 %X) nounwind { 154; CHECK-LABEL: test_urem_odd_setne: 155; CHECK: // %bb.0: 156; CHECK-NEXT: mov w8, #52429 // =0xcccd 157; CHECK-NEXT: mov w9, #858993459 // =0x33333333 158; CHECK-NEXT: movk w8, #52428, lsl #16 159; CHECK-NEXT: mul w8, w0, w8 160; CHECK-NEXT: cmp w8, w9 161; CHECK-NEXT: cset w0, hi 162; CHECK-NEXT: ret 163 %urem = urem i32 %X, 5 164 %cmp = icmp ne i32 %urem, 0 165 %ret = zext i1 %cmp to i32 166 ret i32 %ret 167} 168 169; The fold is only valid for positive divisors, negative-ones should be negated. 170define i32 @test_urem_negative_odd(i32 %X) nounwind { 171; CHECK-LABEL: test_urem_negative_odd: 172; CHECK: // %bb.0: 173; CHECK-NEXT: mov w8, #858993459 // =0x33333333 174; CHECK-NEXT: mul w8, w0, w8 175; CHECK-NEXT: cmp w8, #1 176; CHECK-NEXT: cset w0, hi 177; CHECK-NEXT: ret 178 %urem = urem i32 %X, -5 179 %cmp = icmp ne i32 %urem, 0 180 %ret = zext i1 %cmp to i32 181 ret i32 %ret 182} 183define i32 @test_urem_negative_even(i32 %X) nounwind { 184; CHECK-LABEL: test_urem_negative_even: 185; CHECK: // %bb.0: 186; CHECK-NEXT: mov w8, #37449 // =0x9249 187; CHECK-NEXT: movk w8, #51492, lsl #16 188; CHECK-NEXT: mul w8, w0, w8 189; CHECK-NEXT: ror w8, w8, #1 190; CHECK-NEXT: cmp w8, #1 191; CHECK-NEXT: cset w0, hi 192; CHECK-NEXT: ret 193 %urem = urem i32 %X, -14 194 %cmp = icmp ne i32 %urem, 0 195 %ret = zext i1 %cmp to i32 196 ret i32 %ret 197} 198 199;------------------------------------------------------------------------------; 200; Negative tests 201;------------------------------------------------------------------------------; 202 203; We can lower remainder of division by one much better elsewhere. 204define i32 @test_urem_one(i32 %X) nounwind { 205; CHECK-LABEL: test_urem_one: 206; CHECK: // %bb.0: 207; CHECK-NEXT: mov w0, #1 // =0x1 208; CHECK-NEXT: ret 209 %urem = urem i32 %X, 1 210 %cmp = icmp eq i32 %urem, 0 211 %ret = zext i1 %cmp to i32 212 ret i32 %ret 213} 214 215; We can lower remainder of division by powers of two much better elsewhere. 216define i32 @test_urem_pow2(i32 %X) nounwind { 217; CHECK-LABEL: test_urem_pow2: 218; CHECK: // %bb.0: 219; CHECK-NEXT: tst w0, #0xf 220; CHECK-NEXT: cset w0, eq 221; CHECK-NEXT: ret 222 %urem = urem i32 %X, 16 223 %cmp = icmp eq i32 %urem, 0 224 %ret = zext i1 %cmp to i32 225 ret i32 %ret 226} 227 228; The fold is only valid for positive divisors, and we can't negate INT_MIN. 229define i32 @test_urem_int_min(i32 %X) nounwind { 230; CHECK-LABEL: test_urem_int_min: 231; CHECK: // %bb.0: 232; CHECK-NEXT: tst w0, #0x7fffffff 233; CHECK-NEXT: cset w0, eq 234; CHECK-NEXT: ret 235 %urem = urem i32 %X, 2147483648 236 %cmp = icmp eq i32 %urem, 0 237 %ret = zext i1 %cmp to i32 238 ret i32 %ret 239} 240 241; We can lower remainder of division by all-ones much better elsewhere. 242define i32 @test_urem_allones(i32 %X) nounwind { 243; CHECK-LABEL: test_urem_allones: 244; CHECK: // %bb.0: 245; CHECK-NEXT: neg w8, w0 246; CHECK-NEXT: cmp w8, #2 247; CHECK-NEXT: cset w0, lo 248; CHECK-NEXT: ret 249 %urem = urem i32 %X, 4294967295 250 %cmp = icmp eq i32 %urem, 0 251 %ret = zext i1 %cmp to i32 252 ret i32 %ret 253} 254