1 ; RUN: llc -mtriple=thumbv7m -mattr=+dsp %s -o - | FileCheck %s 2 ; RUN: llc -mtriple=armv7a %s -o - | FileCheck %s 3 ; RUN: llc -mtriple=thumbv7m -mattr=-dsp %s -o - | FileCheck --check-prefix=NODSP %s 4 5 define hidden i32 @SMMULR_SMMLAR(i32 %a, i32 %b0, i32 %b1, i32 %Xn, i32 %Xn1) local_unnamed_addr { 6 entry: 7 ; CHECK-LABEL: SMMULR_SMMLAR: 8 ; CHECK: ldr r0, [sp] 9 ; CHECK-NEXT: smmulr r0, {{(r0, r2|r2, r0)}} 10 ; CHECK-NEXT: smmlar r0, {{(r1, r3|r3, r1)}}, r0 11 ; NODSP-LABEL: SMMULR_SMMLAR: 12 ; NODSP-NOT: smmulr 13 ; NODSP-NOT: smmlar 14 %conv = sext i32 %b1 to i64 15 %conv1 = sext i32 %Xn1 to i64 16 %mul = mul nsw i64 %conv1, %conv 17 %add = add nsw i64 %mul, 2147483648 18 %0 = and i64 %add, -4294967296 19 %conv4 = sext i32 %b0 to i64 20 %conv5 = sext i32 %Xn to i64 21 %mul6 = mul nsw i64 %conv5, %conv4 22 %add7 = add i64 %mul6, 2147483648 23 %add8 = add i64 %add7, %0 24 %1 = lshr i64 %add8, 32 25 %conv10 = trunc i64 %1 to i32 26 ret i32 %conv10 27 } 28 29 define hidden i32 @SMMULR(i32 %a, i32 %b) local_unnamed_addr { 30 entry: 31 ; CHECK-LABEL: SMMULR: 32 ; CHECK: smmulr r0, {{(r0, r1|r1, r0)}} 33 ; NODSP-LABEL: SMMULR: 34 ; NODSP-NOT: smmulr 35 %conv = sext i32 %a to i64 36 %conv1 = sext i32 %b to i64 37 %mul = mul nsw i64 %conv1, %conv 38 %add = add nsw i64 %mul, 2147483648 39 %0 = lshr i64 %add, 32 40 %conv2 = trunc i64 %0 to i32 41 ret i32 %conv2 42 } 43 44 define hidden i32 @SMMUL(i32 %a, i32 %b) local_unnamed_addr { 45 entry: 46 ; CHECK-LABEL: SMMUL: 47 ; CHECK: smmul r0, {{(r0, r1|r1, r0)}} 48 ; NODSP-LABEL: SMMUL: 49 ; NODSP-NOT: smmul 50 %conv = sext i32 %a to i64 51 %conv1 = sext i32 %b to i64 52 %mul = mul nsw i64 %conv1, %conv 53 %0 = lshr i64 %mul, 32 54 %conv2 = trunc i64 %0 to i32 55 ret i32 %conv2 56 } 57 58 define hidden i32 @SMMLSR(i32 %a, i32 %b, i32 %c) local_unnamed_addr { 59 entry: 60 ; CHECK-LABEL: SMMLSR: 61 ; CHECK: smmlsr r0, {{(r1, r2|r2, r1)}}, r0 62 ; NODSP-LABEL: SMMLSR: 63 ; NODSP-NOT: smmlsr 64 %conv6 = zext i32 %a to i64 65 %shl = shl nuw i64 %conv6, 32 66 %conv1 = sext i32 %b to i64 67 %conv2 = sext i32 %c to i64 68 %mul = mul nsw i64 %conv2, %conv1 69 %sub = or i64 %shl, 2147483648 70 %add = sub i64 %sub, %mul 71 %0 = lshr i64 %add, 32 72 %conv3 = trunc i64 %0 to i32 73 ret i32 %conv3 74 } 75 76 define hidden i32 @NOT_SMMLSR(i32 %a, i32 %b, i32 %c) local_unnamed_addr { 77 entry: 78 ; CHECK-LABEL: NOT_SMMLSR: 79 ; CHECK-NOT: smmlsr 80 ; NODSP-LABEL: NOT_SMMLSR: 81 ; NODSP-NOT: smmlsr 82 %conv = sext i32 %b to i64 83 %conv1 = sext i32 %c to i64 84 %mul = mul nsw i64 %conv1, %conv 85 %add = add nsw i64 %mul, 2147483648 86 %0 = lshr i64 %add, 32 87 %conv2 = trunc i64 %0 to i32 88 %sub = sub nsw i32 %a, %conv2 89 ret i32 %sub 90 } 91 92 define hidden i32 @SMMLS(i32 %a, i32 %b, i32 %c) local_unnamed_addr { 93 entry: 94 ; CHECK-LABEL: SMMLS: 95 ; CHECK: smmls r0, {{(r1, r2|r2, r1)}}, r0 96 ; NODSP-LABEL: SMMLS: 97 ; NODSP-NOT: smmls 98 %conv5 = zext i32 %a to i64 99 %shl = shl nuw i64 %conv5, 32 100 %conv1 = sext i32 %b to i64 101 %conv2 = sext i32 %c to i64 102 %mul = mul nsw i64 %conv2, %conv1 103 %sub = sub nsw i64 %shl, %mul 104 %0 = lshr i64 %sub, 32 105 %conv3 = trunc i64 %0 to i32 106 ret i32 %conv3 107 } 108 109 define hidden i32 @NOT_SMMLS(i32 %a, i32 %b, i32 %c) local_unnamed_addr { 110 entry: 111 ; CHECK-LABEL: NOT_SMMLS: 112 ; CHECK-NOT: smmls 113 ; NODSP-LABEL: NOT_SMMLS: 114 ; NODSP-NOT: smmls 115 %conv = sext i32 %b to i64 116 %conv1 = sext i32 %c to i64 117 %mul = mul nsw i64 %conv1, %conv 118 %0 = lshr i64 %mul, 32 119 %conv2 = trunc i64 %0 to i32 120 %sub = sub nsw i32 %a, %conv2 121 ret i32 %sub 122 } 123 124 define hidden i32 @SMMLA(i32 %a, i32 %b, i32 %c) local_unnamed_addr { 125 entry: 126 ; CHECK-LABEL: SMMLA: 127 ; CHECK: smmla r0, {{(r1, r2|r2, r1)}}, r0 128 ; NODSP-LABEL: SMMLA: 129 ; NODSP-NOT: smmla 130 %conv = sext i32 %b to i64 131 %conv1 = sext i32 %c to i64 132 %mul = mul nsw i64 %conv1, %conv 133 %0 = lshr i64 %mul, 32 134 %conv2 = trunc i64 %0 to i32 135 %add = add nsw i32 %conv2, %a 136 ret i32 %add 137 } 138 139 define hidden i32 @SMMLAR(i32 %a, i32 %b, i32 %c) local_unnamed_addr { 140 entry: 141 ; CHECK-LABEL: SMMLAR: 142 ; CHECK: smmlar r0, {{(r1, r2|r2, r1)}}, r0 143 ; NODSP-LABEL: SMMLAR: 144 ; NODSP-NOT: smmlar 145 %conv7 = zext i32 %a to i64 146 %shl = shl nuw i64 %conv7, 32 147 %conv1 = sext i32 %b to i64 148 %conv2 = sext i32 %c to i64 149 %mul = mul nsw i64 %conv2, %conv1 150 %add = or i64 %shl, 2147483648 151 %add3 = add i64 %add, %mul 152 %0 = lshr i64 %add3, 32 153 %conv4 = trunc i64 %0 to i32 154 ret i32 %conv4 155 } 156 157 define hidden i32 @NOT_SMMLA(i32 %a, i32 %b, i32 %c) local_unnamed_addr { 158 entry: 159 ; CHECK-LABEL: NOT_SMMLA: 160 ; CHECK-NOT: smmla 161 ; NODSP-LABEL: NOT_SMMLA: 162 ; NODSP-NOT: smmla 163 %conv = sext i32 %b to i64 164 %conv1 = sext i32 %c to i64 165 %mul = mul nsw i64 %conv1, %conv 166 %0 = lshr i64 %mul, 32 167 %conv2 = trunc i64 %0 to i32 168 %add = xor i32 %conv2, -2147483648 169 %add3 = add i32 %add, %a 170 ret i32 %add3 171 } 172