1; RUN: llc -mtriple armv7a-none-eabi -mattr=-neon < %s -verify-machineinstrs -o - | FileCheck %s 2 3; Thumb1 (thumbv6m) is tested in tests/Thumb 4 5@a = external global i32* 6@b = external global i32* 7 8; Function Attrs: nounwind 9define void @foo24() #0 { 10entry: 11; CHECK-LABEL: foo24: 12; We use '[rl0-9]*' to allow 'r0'..'r12', 'lr' 13; CHECK: movt [[LB:[rl0-9]+]], :upper16:b 14; CHECK: movt [[SB:[rl0-9]+]], :upper16:a 15; CHECK: add [[NLB:[rl0-9]+]], [[LB]], #4 16; CHECK: add [[NSB:[rl0-9]+]], [[SB]], #4 17; CHECK-NEXT: ldm [[NLB]], {[[R1:[rl0-9]+]], [[R2:[rl0-9]+]], [[R3:[rl0-9]+]], [[R4:[rl0-9]+]], [[R5:[rl0-9]+]], [[R6:[rl0-9]+]]} 18; CHECK-NEXT: stm [[NSB]], {[[R1]], [[R2]], [[R3]], [[R4]], [[R5]], [[R6]]} 19 %0 = load i32*, i32** @a, align 4 20 %arrayidx = getelementptr inbounds i32, i32* %0, i32 1 21 %1 = bitcast i32* %arrayidx to i8* 22 %2 = load i32*, i32** @b, align 4 23 %arrayidx1 = getelementptr inbounds i32, i32* %2, i32 1 24 %3 = bitcast i32* %arrayidx1 to i8* 25 tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %1, i8* align 4 %3, i32 24, i1 false) 26 ret void 27} 28 29define void @foo28() #0 { 30entry: 31; CHECK-LABEL: foo28: 32; CHECK: movt [[LB:[rl0-9]+]], :upper16:b 33; CHECK: movt [[SB:[rl0-9]+]], :upper16:a 34; CHECK: add [[NLB:[rl0-9]+]], [[LB]], #4 35; CHECK: add [[NSB:[rl0-9]+]], [[SB]], #4 36; CHECK-NEXT: ldm [[NLB]]!, {[[R1:[rl0-9]+]], [[R2:[rl0-9]+]], [[R3:[rl0-9]+]]} 37; CHECK-NEXT: stm [[NSB]]!, {[[R1]], [[R2]], [[R3]]} 38; CHECK-NEXT: ldm [[NLB]], {[[R1:[rl0-9]+]], [[R2:[rl0-9]+]], [[R3:[rl0-9]+]], [[R4:[rl0-9]+]]} 39; CHECK-NEXT: stm [[NSB]], {[[R1]], [[R2]], [[R3]], [[R4]]} 40 %0 = load i32*, i32** @a, align 4 41 %arrayidx = getelementptr inbounds i32, i32* %0, i32 1 42 %1 = bitcast i32* %arrayidx to i8* 43 %2 = load i32*, i32** @b, align 4 44 %arrayidx1 = getelementptr inbounds i32, i32* %2, i32 1 45 %3 = bitcast i32* %arrayidx1 to i8* 46 tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %1, i8* align 4 %3, i32 28, i1 false) 47 ret void 48} 49 50define void @foo32() #0 { 51entry: 52; CHECK-LABEL: foo32: 53; CHECK: movt [[LB:[rl0-9]+]], :upper16:b 54; CHECK: movt [[SB:[rl0-9]+]], :upper16:a 55; CHECK: add [[NLB:[rl0-9]+]], [[LB]], #4 56; CHECK: add [[NSB:[rl0-9]+]], [[SB]], #4 57; CHECK-NEXT: ldm [[NLB]]!, {[[R1:[rl0-9]+]], [[R2:[rl0-9]+]], [[R3:[rl0-9]+]], [[R4:[rl0-9]+]]} 58; CHECK-NEXT: stm [[NSB]]!, {[[R1]], [[R2]], [[R3]], [[R4]]} 59; CHECK-NEXT: ldm [[NLB]], {[[R1:[rl0-9]+]], [[R2:[rl0-9]+]], [[R3:[rl0-9]+]], [[R4:[rl0-9]+]]} 60; CHECK-NEXT: stm [[NSB]], {[[R1]], [[R2]], [[R3]], [[R4]]} 61 %0 = load i32*, i32** @a, align 4 62 %arrayidx = getelementptr inbounds i32, i32* %0, i32 1 63 %1 = bitcast i32* %arrayidx to i8* 64 %2 = load i32*, i32** @b, align 4 65 %arrayidx1 = getelementptr inbounds i32, i32* %2, i32 1 66 %3 = bitcast i32* %arrayidx1 to i8* 67 tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %1, i8* align 4 %3, i32 32, i1 false) 68 ret void 69} 70 71define void @foo36() #0 { 72entry: 73; CHECK-LABEL: foo36: 74; CHECK: movt [[LB:[rl0-9]+]], :upper16:b 75; CHECK: movt [[SB:[rl0-9]+]], :upper16:a 76; CHECK: add [[NLB:[rl0-9]+]], [[LB]], #4 77; CHECK: add [[NSB:[rl0-9]+]], [[SB]], #4 78; CHECK-NEXT: ldm [[NLB]]!, {[[R1:[rl0-9]+]], [[R2:[rl0-9]+]], [[R3:[rl0-9]+]], [[R4:[rl0-9]+]]} 79; CHECK-NEXT: stm [[NSB]]!, {[[R1]], [[R2]], [[R3]], [[R4]]} 80; CHECK-NEXT: ldm [[NLB]], {[[R1:[rl0-9]+]], [[R2:[rl0-9]+]], [[R3:[rl0-9]+]], [[R4:[rl0-9]+]], [[R5:[rl0-9]+]]} 81; CHECK-NEXT: stm [[NSB]], {[[R1]], [[R2]], [[R3]], [[R4]], [[R5]]} 82 %0 = load i32*, i32** @a, align 4 83 %arrayidx = getelementptr inbounds i32, i32* %0, i32 1 84 %1 = bitcast i32* %arrayidx to i8* 85 %2 = load i32*, i32** @b, align 4 86 %arrayidx1 = getelementptr inbounds i32, i32* %2, i32 1 87 %3 = bitcast i32* %arrayidx1 to i8* 88 tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %1, i8* align 4 %3, i32 36, i1 false) 89 ret void 90} 91 92; Function Attrs: nounwind 93declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) #1 94