1; RUN: llc -mtriple=thumbv7em -mattr=+fp-armv8 %s -o - | \ 2; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DEFAULT 3 4; RUN: llc -mtriple=thumbv8m.main -mattr=+fp-armv8,+dsp %s -o - | \ 5; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DEFAULT 6 7; -lsr-backedge-indexing=false 8 9; RUN: llc -mtriple=thumbv8m.main -mattr=+fp-armv8,+dsp -lsr-preferred-addressing-mode=postindexed %s -o - | \ 10; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=DISABLED 11 12; RUN: llc -mtriple=thumbv8 %s -o - | \ 13; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=DISABLED 14 15; RUN: llc -mtriple=thumbv8m.main -mattr=+fp-armv8,+dsp -lsr-complexity-limit=2147483647 %s -o - | \ 16; RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-COMPLEX 17 18; CHECK-LABEL: test_qadd_2 19; CHECK: @ %loop 20 21; CHECK-DEFAULT: ldr{{.*}}, #4] 22; CHECK-DEFAULT: ldr{{.*}}, #4] 23; CHECK-DEFAULT: str{{.*}}, #4] 24; CHECK-DEFAULT: ldr{{.*}}, #8]! 25; CHECK-DEAFULT: ldr{{.*}}, #8]! 26; CHECK-DEFAULT: str{{.*}}, #8]! 27 28; CHECK-COMPLEX: ldr{{.*}}, #8]! 29; CHECK-COMPLEX: ldr{{.*}}, #8]! 30; CHECK-COMPLEX: str{{.*}}, #8]! 31; CHECK-COMPLEX: ldr{{.*}}, #4] 32; CHECK-COMPLEX: ldr{{.*}}, #4] 33; CHECK-COMPLEX: str{{.*}}, #4] 34 35; DISABLED-NOT: ldr{{.*}}]! 36; DISABLED-NOT: str{{.*}}]! 37 38define void @test_qadd_2(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) { 39entry: 40 br label %loop 41 42loop: 43 %i = phi i32 [ 0, %entry ], [ %i.next, %loop ] 44 %idx.1 = phi i32 [ 0, %entry ], [ %idx.next, %loop ] 45 %gep.a.1 = getelementptr inbounds i32, ptr %a.array, i32 %idx.1 46 %a.1 = load i32, ptr %gep.a.1 47 %gep.b.1 = getelementptr inbounds i32, ptr %b.array, i32 %idx.1 48 %b.1 = load i32, ptr %gep.b.1 49 %qadd.1 = call i32 @llvm.arm.qadd(i32 %a.1, i32 %b.1) 50 %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1 51 store i32 %qadd.1, ptr %addr.1 52 %idx.2 = or disjoint i32 %idx.1, 1 53 %gep.a.2 = getelementptr inbounds i32, ptr %a.array, i32 %idx.2 54 %a.2 = load i32, ptr %gep.a.2 55 %gep.b.2 = getelementptr inbounds i32, ptr %b.array, i32 %idx.2 56 %b.2 = load i32, ptr %gep.b.2 57 %qadd.2 = call i32 @llvm.arm.qadd(i32 %a.2, i32 %b.2) 58 %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2 59 store i32 %qadd.2, ptr %addr.2 60 %i.next = add nsw nuw i32 %i, -2 61 %idx.next = add nsw nuw i32 %idx.1, 2 62 %cmp = icmp ult i32 %i.next, %N 63 br i1 %cmp, label %loop, label %exit 64 65exit: 66 ret void 67} 68 69; CHECK-LABEL: test_qadd_2_backwards 70; TODO: Indexes should be generated. 71 72; CHECK: @ %loop 73 74; CHECK-DEFAULT: ldr{{.*}}, 75; CHECK-DEFAULT: ldr{{.*}}, 76; CHECK-DEFAULT: str{{.*}}, 77; CHECK-DEFAULT: ldr{{.*}}, #-4] 78; CHECK-DEFAULT: ldr{{.*}}, #-4] 79; CHECK-DEFAULT: sub{{.*}}, #8 80; CHECK-DEFAULT: str{{.*}}, #-4] 81; CHECK-DEFAULT: sub{{.*}}, #8 82 83; CHECK-COMPLEX: ldr{{.*}} lsl #2] 84; CHECK-COMPLEX: ldr{{.*}} lsl #2] 85; CHECK-COMPLEX: str{{.*}} lsl #2] 86; CHECK-COMPLEX: ldr{{.*}} lsl #2] 87; CHECK-COMPLEX: ldr{{.*}} lsl #2] 88; CHECK-COMPLEX: str{{.*}} lsl #2] 89 90; DISABLED-NOT: ldr{{.*}}]! 91; DISABLED-NOT: str{{.*}}]! 92 93define void @test_qadd_2_backwards(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) { 94entry: 95 br label %loop 96 97loop: 98 %i = phi i32 [ 0, %entry ], [ %i.next, %loop ] 99 %idx.1 = phi i32 [ %N, %entry ], [ %idx.next, %loop ] 100 %gep.a.1 = getelementptr inbounds i32, ptr %a.array, i32 %idx.1 101 %a.1 = load i32, ptr %gep.a.1 102 %gep.b.1 = getelementptr inbounds i32, ptr %b.array, i32 %idx.1 103 %b.1 = load i32, ptr %gep.b.1 104 %qadd.1 = call i32 @llvm.arm.qadd(i32 %a.1, i32 %b.1) 105 %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1 106 store i32 %qadd.1, ptr %addr.1 107 %idx.2 = sub nsw nuw i32 %idx.1, 1 108 %gep.a.2 = getelementptr inbounds i32, ptr %a.array, i32 %idx.2 109 %a.2 = load i32, ptr %gep.a.2 110 %gep.b.2 = getelementptr inbounds i32, ptr %b.array, i32 %idx.2 111 %b.2 = load i32, ptr %gep.b.2 112 %qadd.2 = call i32 @llvm.arm.qadd(i32 %a.2, i32 %b.2) 113 %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2 114 store i32 %qadd.2, ptr %addr.2 115 %i.next = add nsw nuw i32 %i, -2 116 %idx.next = sub nsw nuw i32 %idx.1, 2 117 %cmp = icmp ult i32 %i.next, %N 118 br i1 %cmp, label %loop, label %exit 119 120exit: 121 ret void 122} 123 124; CHECK-LABEL: test_qadd_3 125; CHECK: @ %loop 126 127; CHECK-DEFAULT: ldr{{.*}}, #8] 128; CHECK-DEFAULT: ldr{{.*}}, #8] 129; CHECK-DEFAULT: str{{.*}}, #8] 130; CHECK-DEFAULT: ldr{{.*}}, #12]! 131; CHECK-DEFAULT: ldr{{.*}}, #12]! 132; CHECK-DEFAULT: str{{.*}}, #12]! 133 134; CHECK-COMPLEX: ldr{{.*}}, #12]! 135; CHECK-COMPLEX: ldr{{.*}}, #12]! 136; CHECK-COMPLEX: str{{.*}}, #12]! 137; CHECK-COMPLEX: ldr{{.*}}, #4] 138; CHECK-COMPLEX: ldr{{.*}}, #4] 139; CHECK-COMPLEX: str{{.*}}, #4] 140; CHECK-COMPLEX: ldr{{.*}}, #8] 141; CHECK-COMPLEX: ldr{{.*}}, #8] 142; CHECK-COMPLEX: str{{.*}}, #8] 143 144; DISABLED-NOT: ldr{{.*}}]! 145; DISABLED-NOT: str{{.*}}]! 146 147define void @test_qadd_3(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) { 148entry: 149 br label %loop 150 151loop: 152 %i = phi i32 [ 0, %entry ], [ %i.next, %loop ] 153 %idx.1 = phi i32 [ 0, %entry ], [ %idx.next, %loop ] 154 %gep.a.1 = getelementptr inbounds i32, ptr %a.array, i32 %idx.1 155 %a.1 = load i32, ptr %gep.a.1 156 %gep.b.1 = getelementptr inbounds i32, ptr %b.array, i32 %idx.1 157 %b.1 = load i32, ptr %gep.b.1 158 %qadd.1 = call i32 @llvm.arm.qadd(i32 %a.1, i32 %b.1) 159 %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1 160 store i32 %qadd.1, ptr %addr.1 161 %idx.2 = add nuw nsw i32 %idx.1, 1 162 %gep.a.2 = getelementptr inbounds i32, ptr %a.array, i32 %idx.2 163 %a.2 = load i32, ptr %gep.a.2 164 %gep.b.2 = getelementptr inbounds i32, ptr %b.array, i32 %idx.2 165 %b.2 = load i32, ptr %gep.b.2 166 %qadd.2 = call i32 @llvm.arm.qadd(i32 %a.2, i32 %b.2) 167 %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2 168 store i32 %qadd.2, ptr %addr.2 169 %idx.3 = add nuw nsw i32 %idx.1, 2 170 %gep.a.3 = getelementptr inbounds i32, ptr %a.array, i32 %idx.3 171 %a.3 = load i32, ptr %gep.a.3 172 %gep.b.3 = getelementptr inbounds i32, ptr %b.array, i32 %idx.3 173 %b.3 = load i32, ptr %gep.b.3 174 %qadd.3 = call i32 @llvm.arm.qadd(i32 %a.3, i32 %b.3) 175 %addr.3 = getelementptr inbounds i32, ptr %out.array, i32 %idx.3 176 store i32 %qadd.3, ptr %addr.3 177 %i.next = add nsw nuw i32 %i, -3 178 %idx.next = add nsw nuw i32 %idx.1, 3 179 %cmp = icmp ult i32 %i.next, %N 180 br i1 %cmp, label %loop, label %exit 181 182exit: 183 ret void 184} 185 186; CHECK-LABEL: test_qadd_4 187; CHECK: @ %loop 188 189; TODO: pre-inc store 190 191; CHECK-DEFAULT: ldr{{.*}}, #4] 192; CHECK-DEFAULT: ldr{{.*}}, #4] 193; CHECK-DEFAULT: str{{.*}}, #4] 194; CHECK-DEFAULT: ldr{{.*}}, #8] 195; CHECK-DEFAULT: ldr{{.*}}, #8] 196; CHECK-DEFAULT: str{{.*}}, #8] 197; CHECK-DEFAULT: ldr{{.*}}, #12] 198; CHECK-DEFAULT: ldr{{.*}}, #12] 199; CHECK-DEFAULT: str{{.*}}, #12] 200 201; CHECK-COMPLEX: ldr{{.*}}, #16]! 202; CHECK-COMPLEX: ldr{{.*}}, #16]! 203; CHECK-COMPLEX: str{{.*}}, #16]! 204; CHECK-COMPLEX: ldr{{.*}}, #4] 205; CHECK-COMPLEX: ldr{{.*}}, #4] 206; CHECK-COMPLEX: str{{.*}}, #4] 207; CHECK-COMPLEX: ldr{{.*}}, #8] 208; CHECK-COMPLEX: ldr{{.*}}, #8] 209; CHECK-COMPLEX: str{{.*}}, #8] 210; CHECK-COMPLEX: ldr{{.*}}, #12] 211; CHECK-COMPLEX: ldr{{.*}}, #12] 212; CHECK-COMPLEX: str{{.*}}, #12] 213 214; DISABLED-NOT: ldr{{.*}}]! 215; DISABLED-NOT: str{{.*}}]! 216 217define void @test_qadd_4(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) { 218entry: 219 br label %loop 220 221loop: 222 %i = phi i32 [ 0, %entry ], [ %i.next, %loop ] 223 %idx.1 = phi i32 [ 0, %entry ], [ %idx.next, %loop ] 224 %gep.a.1 = getelementptr inbounds i32, ptr %a.array, i32 %idx.1 225 %a.1 = load i32, ptr %gep.a.1 226 %gep.b.1 = getelementptr inbounds i32, ptr %b.array, i32 %idx.1 227 %b.1 = load i32, ptr %gep.b.1 228 %qadd.1 = call i32 @llvm.arm.qadd(i32 %a.1, i32 %b.1) 229 %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1 230 store i32 %qadd.1, ptr %addr.1 231 %idx.2 = or disjoint i32 %idx.1, 1 232 %gep.a.2 = getelementptr inbounds i32, ptr %a.array, i32 %idx.2 233 %a.2 = load i32, ptr %gep.a.2 234 %gep.b.2 = getelementptr inbounds i32, ptr %b.array, i32 %idx.2 235 %b.2 = load i32, ptr %gep.b.2 236 %qadd.2 = call i32 @llvm.arm.qadd(i32 %a.2, i32 %b.2) 237 %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2 238 store i32 %qadd.2, ptr %addr.2 239 %idx.3 = or disjoint i32 %idx.1, 2 240 %gep.a.3 = getelementptr inbounds i32, ptr %a.array, i32 %idx.3 241 %a.3 = load i32, ptr %gep.a.3 242 %gep.b.3 = getelementptr inbounds i32, ptr %b.array, i32 %idx.3 243 %b.3 = load i32, ptr %gep.b.3 244 %qadd.3 = call i32 @llvm.arm.qadd(i32 %a.3, i32 %b.3) 245 %addr.3 = getelementptr inbounds i32, ptr %out.array, i32 %idx.3 246 store i32 %qadd.3, ptr %addr.3 247 %idx.4 = or disjoint i32 %idx.1, 3 248 %gep.a.4 = getelementptr inbounds i32, ptr %a.array, i32 %idx.4 249 %a.4 = load i32, ptr %gep.a.4 250 %gep.b.4 = getelementptr inbounds i32, ptr %b.array, i32 %idx.4 251 %b.4 = load i32, ptr %gep.b.4 252 %qadd.4 = call i32 @llvm.arm.qadd(i32 %a.4, i32 %b.4) 253 %addr.4 = getelementptr inbounds i32, ptr %out.array, i32 %idx.4 254 store i32 %qadd.4, ptr %addr.4 255 %i.next = add nsw nuw i32 %i, -4 256 %idx.next = add nsw nuw i32 %idx.1, 4 257 %cmp = icmp ult i32 %i.next, %N 258 br i1 %cmp, label %loop, label %exit 259 260exit: 261 ret void 262} 263 264; CHECK-LABEL: test_qadd16_2 265; CHECK: @ %loop 266; TODO: pre-inc store. 267 268; CHECK-DEFAULT: ldr{{.*}}, #4] 269; CHECK-DEFAULT: ldr{{.*}}, #4] 270; CHECK-DEFAULT: str{{.*}}, #8] 271; CHECK-DEFAULT: ldr{{.*}}, #8]! 272; CHECK-DEFAULT: ldr{{.*}}, #8]! 273; CHECK-DEFAULT: str{{.*}}, #16]! 274 275; CHECK-COMPLEX: ldr{{.*}}, #8]! 276; CHECK-COMPLEX: ldr{{.*}}, #8]! 277; CHECK-COMPLEX: str{{.*}}, #16]! 278; CHECK-COMPLEX: ldr{{.*}}, #4] 279; CHECK-COMPLEX: ldr{{.*}}, #4] 280; CHECK-COMPLEX: str{{.*}}, #8] 281 282; DISABLED-NOT: ldr{{.*}}]! 283; DISABLED-NOT: str{{.*}}]! 284 285define void @test_qadd16_2(ptr %a.array, ptr %b.array, ptr %out.array, i32 %N) { 286entry: 287 br label %loop 288 289loop: 290 %i = phi i32 [ 0, %entry ], [ %i.next, %loop ] 291 %idx.1 = phi i32 [ 0, %entry ], [ %idx.next, %loop ] 292 %gep.a.1 = getelementptr inbounds i16, ptr %a.array, i32 %idx.1 293 %a.1 = load i32, ptr %gep.a.1 294 %gep.b.1 = getelementptr inbounds i16, ptr %b.array, i32 %idx.1 295 %b.1 = load i32, ptr %gep.b.1 296 %qadd.1 = call i32 @llvm.arm.qadd16(i32 %a.1, i32 %b.1) 297 %addr.1 = getelementptr inbounds i32, ptr %out.array, i32 %idx.1 298 store i32 %qadd.1, ptr %addr.1 299 %idx.2 = add nsw nuw i32 %idx.1, 2 300 %gep.a.2 = getelementptr inbounds i16, ptr %a.array, i32 %idx.2 301 %a.2 = load i32, ptr %gep.a.2 302 %gep.b.2 = getelementptr inbounds i16, ptr %b.array, i32 %idx.2 303 %b.2 = load i32, ptr %gep.b.2 304 %qadd.2 = call i32 @llvm.arm.qadd16(i32 %a.2, i32 %b.2) 305 %addr.2 = getelementptr inbounds i32, ptr %out.array, i32 %idx.2 306 store i32 %qadd.2, ptr %addr.2 307 %i.next = add nsw nuw i32 %i, -2 308 %idx.next = add nsw nuw i32 %idx.1, 4 309 %cmp = icmp ult i32 %i.next, %N 310 br i1 %cmp, label %loop, label %exit 311 312exit: 313 ret void 314} 315 316declare i32 @llvm.arm.qadd(i32, i32) 317declare i32 @llvm.arm.qadd16(i32, i32) 318