1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=arm64-eabi | FileCheck %s --check-prefixes=CHECK,CHECK-SD 3; RUN: llc < %s -mtriple=arm64-eabi -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI 4 5; rdar://9296808 6; rdar://9349137 7 8define i128 @t1(i64 %a, i64 %b) nounwind readnone ssp { 9; CHECK-LABEL: t1: 10; CHECK: // %bb.0: // %entry 11; CHECK-NEXT: mul x8, x0, x1 12; CHECK-NEXT: umulh x1, x0, x1 13; CHECK-NEXT: mov x0, x8 14; CHECK-NEXT: ret 15entry: 16 %tmp1 = zext i64 %a to i128 17 %tmp2 = zext i64 %b to i128 18 %tmp3 = mul i128 %tmp1, %tmp2 19 ret i128 %tmp3 20} 21 22define i128 @t2(i64 %a, i64 %b) nounwind readnone ssp { 23; CHECK-SD-LABEL: t2: 24; CHECK-SD: // %bb.0: // %entry 25; CHECK-SD-NEXT: mul x8, x0, x1 26; CHECK-SD-NEXT: smulh x1, x0, x1 27; CHECK-SD-NEXT: mov x0, x8 28; CHECK-SD-NEXT: ret 29; 30; CHECK-GI-LABEL: t2: 31; CHECK-GI: // %bb.0: // %entry 32; CHECK-GI-NEXT: asr x9, x1, #63 33; CHECK-GI-NEXT: asr x10, x0, #63 34; CHECK-GI-NEXT: mul x8, x0, x1 35; CHECK-GI-NEXT: mul x9, x0, x9 36; CHECK-GI-NEXT: umulh x11, x0, x1 37; CHECK-GI-NEXT: mov x0, x8 38; CHECK-GI-NEXT: madd x9, x10, x1, x9 39; CHECK-GI-NEXT: add x1, x9, x11 40; CHECK-GI-NEXT: ret 41entry: 42 %tmp1 = sext i64 %a to i128 43 %tmp2 = sext i64 %b to i128 44 %tmp3 = mul i128 %tmp1, %tmp2 45 ret i128 %tmp3 46} 47 48define i64 @t3(i32 %a, i32 %b) nounwind { 49; CHECK-LABEL: t3: 50; CHECK: // %bb.0: // %entry 51; CHECK-NEXT: umull x0, w0, w1 52; CHECK-NEXT: ret 53entry: 54 %tmp1 = zext i32 %a to i64 55 %tmp2 = zext i32 %b to i64 56 %tmp3 = mul i64 %tmp1, %tmp2 57 ret i64 %tmp3 58} 59 60define i64 @t4(i32 %a, i32 %b) nounwind { 61; CHECK-LABEL: t4: 62; CHECK: // %bb.0: // %entry 63; CHECK-NEXT: smull x0, w0, w1 64; CHECK-NEXT: ret 65entry: 66 %tmp1 = sext i32 %a to i64 67 %tmp2 = sext i32 %b to i64 68 %tmp3 = mul i64 %tmp1, %tmp2 69 ret i64 %tmp3 70} 71 72define i64 @t5(i32 %a, i32 %b, i64 %c) nounwind { 73; CHECK-LABEL: t5: 74; CHECK: // %bb.0: // %entry 75; CHECK-NEXT: umaddl x0, w0, w1, x2 76; CHECK-NEXT: ret 77entry: 78 %tmp1 = zext i32 %a to i64 79 %tmp2 = zext i32 %b to i64 80 %tmp3 = mul i64 %tmp1, %tmp2 81 %tmp4 = add i64 %c, %tmp3 82 ret i64 %tmp4 83} 84 85define i64 @t6(i32 %a, i32 %b, i64 %c) nounwind { 86; CHECK-LABEL: t6: 87; CHECK: // %bb.0: // %entry 88; CHECK-NEXT: smsubl x0, w0, w1, x2 89; CHECK-NEXT: ret 90entry: 91 %tmp1 = sext i32 %a to i64 92 %tmp2 = sext i32 %b to i64 93 %tmp3 = mul i64 %tmp1, %tmp2 94 %tmp4 = sub i64 %c, %tmp3 95 ret i64 %tmp4 96} 97 98define i64 @t7(i32 %a, i32 %b) nounwind { 99; CHECK-LABEL: t7: 100; CHECK: // %bb.0: // %entry 101; CHECK-NEXT: umnegl x0, w0, w1 102; CHECK-NEXT: ret 103entry: 104 %tmp1 = zext i32 %a to i64 105 %tmp2 = zext i32 %b to i64 106 %tmp3 = mul i64 %tmp1, %tmp2 107 %tmp4 = sub i64 0, %tmp3 108 ret i64 %tmp4 109} 110 111define i64 @t8(i32 %a, i32 %b) nounwind { 112; CHECK-LABEL: t8: 113; CHECK: // %bb.0: // %entry 114; CHECK-NEXT: smnegl x0, w0, w1 115; CHECK-NEXT: ret 116entry: 117 %tmp1 = sext i32 %a to i64 118 %tmp2 = sext i32 %b to i64 119 %tmp3 = mul i64 %tmp1, %tmp2 120 %tmp4 = sub i64 0, %tmp3 121 ret i64 %tmp4 122} 123 124define i64 @t9(i32 %a) nounwind { 125; CHECK-LABEL: t9: 126; CHECK: // %bb.0: // %entry 127; CHECK-NEXT: mov w8, #8896 // =0x22c0 128; CHECK-NEXT: movk w8, #2, lsl #16 129; CHECK-NEXT: umull x0, w0, w8 130; CHECK-NEXT: ret 131entry: 132 %tmp1 = zext i32 %a to i64 133 %tmp2 = mul i64 %tmp1, 139968 134 ret i64 %tmp2 135} 136 137; Check 64-bit multiplication is used for constants > 32 bits. 138define i64 @t10(i32 %a) nounwind { 139; CHECK-LABEL: t10: 140; CHECK: // %bb.0: // %entry 141; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 142; CHECK-NEXT: sxtw x8, w0 143; CHECK-NEXT: mov w9, #2 // =0x2 144; CHECK-NEXT: movk w9, #32768, lsl #16 145; CHECK-NEXT: mul x0, x8, x9 146; CHECK-NEXT: ret 147entry: 148 %tmp1 = sext i32 %a to i64 149 %tmp2 = mul i64 %tmp1, 2147483650 ; = 2^31 + 2 150 ret i64 %tmp2 151} 152 153; Check the sext_inreg case. 154define i64 @t11(i64 %a) nounwind { 155; CHECK-LABEL: t11: 156; CHECK: // %bb.0: // %entry 157; CHECK-NEXT: mov w8, #29594 // =0x739a 158; CHECK-NEXT: movk w8, #65499, lsl #16 159; CHECK-NEXT: smnegl x0, w0, w8 160; CHECK-NEXT: ret 161entry: 162 %tmp1 = trunc i64 %a to i32 163 %tmp2 = sext i32 %tmp1 to i64 164 %tmp3 = mul i64 %tmp2, -2395238 165 %tmp4 = sub i64 0, %tmp3 166 ret i64 %tmp4 167} 168 169define i64 @t12(i64 %a, i64 %b) nounwind { 170; CHECK-LABEL: t12: 171; CHECK: // %bb.0: // %entry 172; CHECK-NEXT: mov w8, #35118 // =0x892e 173; CHECK-NEXT: movk w8, #65008, lsl #16 174; CHECK-NEXT: smaddl x0, w0, w8, x1 175; CHECK-NEXT: ret 176entry: 177 %tmp1 = trunc i64 %a to i32 178 %tmp2 = sext i32 %tmp1 to i64 179 %tmp3 = mul i64 %tmp2, -34567890 180 %tmp4 = add i64 %b, %tmp3 181 ret i64 %tmp4 182} 183 184define i64 @t13(i32 %a, i64 %b) nounwind { 185; CHECK-LABEL: t13: 186; CHECK: // %bb.0: // %entry 187; CHECK-NEXT: mov w8, #24910 // =0x614e 188; CHECK-NEXT: movk w8, #188, lsl #16 189; CHECK-NEXT: umsubl x0, w0, w8, x1 190; CHECK-NEXT: ret 191entry: 192 %tmp1 = zext i32 %a to i64 193 %tmp3 = mul i64 %tmp1, 12345678 194 %tmp4 = sub i64 %b, %tmp3 195 ret i64 %tmp4 196} 197 198define i64 @t14(i32 %a, i64 %b) nounwind { 199; CHECK-LABEL: t14: 200; CHECK: // %bb.0: // %entry 201; CHECK-NEXT: mov w8, #40626 // =0x9eb2 202; CHECK-NEXT: movk w8, #65347, lsl #16 203; CHECK-NEXT: smsubl x0, w0, w8, x1 204; CHECK-NEXT: ret 205entry: 206 %tmp1 = sext i32 %a to i64 207 %tmp3 = mul i64 %tmp1, -12345678 208 %tmp4 = sub i64 %b, %tmp3 209 ret i64 %tmp4 210} 211