1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; Test memset 0 with variable length 3; 4; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 5 6define void @fun0(ptr %Addr, i64 %Len) { 7; CHECK-LABEL: fun0: 8; CHECK: # %bb.0: 9; CHECK-NEXT: aghi %r3, -1 10; CHECK-NEXT: cgibe %r3, -1, 0(%r14) 11; CHECK-NEXT: .LBB0_1: 12; CHECK-NEXT: srlg %r0, %r3, 8 13; CHECK-NEXT: cgije %r0, 0, .LBB0_3 14; CHECK-NEXT: .LBB0_2: # =>This Inner Loop Header: Depth=1 15; CHECK-NEXT: xc 0(256,%r2), 0(%r2) 16; CHECK-NEXT: la %r2, 256(%r2) 17; CHECK-NEXT: brctg %r0, .LBB0_2 18; CHECK-NEXT: .LBB0_3: 19; CHECK-NEXT: exrl %r3, .Ltmp0 20; CHECK-NEXT: br %r14 21 tail call void @llvm.memset.p0.i64(ptr %Addr, i8 0, i64 %Len, i1 false) 22 ret void 23} 24 25define void @fun1(ptr %Addr, i32 %Len) { 26; CHECK-LABEL: fun1: 27; CHECK: # %bb.0: 28; CHECK-NEXT: llgfr %r1, %r3 29; CHECK-NEXT: aghi %r1, -1 30; CHECK-NEXT: cgibe %r1, -1, 0(%r14) 31; CHECK-NEXT: .LBB1_1: 32; CHECK-NEXT: srlg %r0, %r1, 8 33; CHECK-NEXT: cgije %r0, 0, .LBB1_3 34; CHECK-NEXT: .LBB1_2: # =>This Inner Loop Header: Depth=1 35; CHECK-NEXT: xc 0(256,%r2), 0(%r2) 36; CHECK-NEXT: la %r2, 256(%r2) 37; CHECK-NEXT: brctg %r0, .LBB1_2 38; CHECK-NEXT: .LBB1_3: 39; CHECK-NEXT: exrl %r1, .Ltmp0 40; CHECK-NEXT: br %r14 41 tail call void @llvm.memset.p0.i32(ptr %Addr, i8 0, i32 %Len, i1 false) 42 ret void 43} 44 45; Test that identical target instructions get reused. 46define void @fun2(ptr %Addr, i32 %Len) { 47; CHECK-LABEL: fun2: 48; CHECK: # %bb.0: 49; CHECK-NEXT: llgfr %r1, %r3 50; CHECK-NEXT: aghi %r1, -1 51; CHECK-NEXT: cgije %r1, -1, .LBB2_4 52; CHECK-NEXT: # %bb.1: 53; CHECK-NEXT: srlg %r0, %r1, 8 54; CHECK-NEXT: lgr %r3, %r2 55; CHECK-NEXT: cgije %r0, 0, .LBB2_3 56; CHECK-NEXT: .LBB2_2: # =>This Inner Loop Header: Depth=1 57; CHECK-NEXT: xc 0(256,%r3), 0(%r3) 58; CHECK-NEXT: la %r3, 256(%r3) 59; CHECK-NEXT: brctg %r0, .LBB2_2 60; CHECK-NEXT: .LBB2_3: 61; CHECK-NEXT: exrl %r1, .Ltmp1 62; CHECK-NEXT: .LBB2_4: 63; CHECK-NEXT: cgije %r1, -1, .LBB2_8 64; CHECK-NEXT: # %bb.5: 65; CHECK-NEXT: srlg %r0, %r1, 8 66; CHECK-NEXT: lgr %r3, %r2 67; CHECK-NEXT: cgije %r0, 0, .LBB2_7 68; CHECK-NEXT: .LBB2_6: # =>This Inner Loop Header: Depth=1 69; CHECK-NEXT: xc 0(256,%r3), 0(%r3) 70; CHECK-NEXT: la %r3, 256(%r3) 71; CHECK-NEXT: brctg %r0, .LBB2_6 72; CHECK-NEXT: .LBB2_7: 73; CHECK-NEXT: exrl %r1, .Ltmp1 74; CHECK-NEXT: .LBB2_8: 75; CHECK-NEXT: cgibe %r1, -1, 0(%r14) 76; CHECK-NEXT: .LBB2_9: 77; CHECK-NEXT: srlg %r0, %r1, 8 78; CHECK-NEXT: cgije %r0, 0, .LBB2_11 79; CHECK-NEXT: .LBB2_10: # =>This Inner Loop Header: Depth=1 80; CHECK-NEXT: xc 0(256,%r2), 0(%r2) 81; CHECK-NEXT: la %r2, 256(%r2) 82; CHECK-NEXT: brctg %r0, .LBB2_10 83; CHECK-NEXT: .LBB2_11: 84; CHECK-NEXT: exrl %r1, .Ltmp0 85; CHECK-NEXT: br %r14 86 tail call void @llvm.memset.p0.i32(ptr %Addr, i8 0, i32 %Len, i1 false) 87 tail call void @llvm.memset.p0.i32(ptr %Addr, i8 0, i32 %Len, i1 false) 88 tail call void @llvm.memset.p0.i32(ptr %Addr, i8 0, i32 %Len, i1 false) 89 ret void 90} 91 92; Test that a memset to nullptr compiles. 93define void @fun3(i64 %Len) { 94; CHECK-LABEL: fun3: 95; CHECK: # %bb.0: 96; CHECK-NEXT: aghi %r2, -1 97; CHECK-NEXT: cgibe %r2, -1, 0(%r14) 98; CHECK-NEXT: .LBB3_1: 99; CHECK-NEXT: srlg %r0, %r2, 8 100; CHECK-NEXT: lghi %r1, 0 101; CHECK-NEXT: cgije %r0, 0, .LBB3_3 102; CHECK-NEXT: .LBB3_2: # =>This Inner Loop Header: Depth=1 103; CHECK-NEXT: xc 0(256,%r1), 0(%r1) 104; CHECK-NEXT: la %r1, 256(%r1) 105; CHECK-NEXT: brctg %r0, .LBB3_2 106; CHECK-NEXT: .LBB3_3: 107; CHECK-NEXT: exrl %r2, .Ltmp2 108; CHECK-NEXT: br %r14 109 call void @llvm.memset.p0.i64(ptr null, i8 0, i64 %Len, i1 false) 110 ret void 111} 112 113; Test that a memset with a length argument that DAGCombiner will convert 114; into a constant get the correct number of bytes set. 115@Data = external hidden constant [1024 x i8], align 2 116define void @fun4() { 117; CHECK-LABEL: fun4: 118; CHECK: # %bb.0: 119; CHECK-NEXT: larl %r1, Data 120; CHECK-NEXT: xc 35(256,%r1), 35(%r1) 121; CHECK-NEXT: xc 291(256,%r1), 291(%r1) 122; CHECK-NEXT: xc 547(256,%r1), 547(%r1) 123; CHECK-NEXT: xc 803(221,%r1), 803(%r1) 124; CHECK-NEXT: mvghi 0(%r1), 989 125; CHECK-NEXT: br %r14 126 call void @llvm.memset.p0.i64( 127 ptr getelementptr inbounds ([1024 x i8], ptr @Data, i64 0, i64 35), 128 i8 0, 129 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 130 ptr @Data, i64 1, i64 0) to i64), i64 1), 131 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 132 ptr @Data, i64 0, i64 35) to i64), i64 1)), 133 i1 false) 134 %i11 = getelementptr i8, ptr null, 135 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 136 ptr @Data, i64 1, i64 0) to i64), i64 1), 137 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 138 ptr @Data, i64 0, i64 35) to i64), i64 1)) 139 store ptr %i11, ptr undef, align 8 140 ret void 141} 142 143; The same, with a resulting constant length of 0. 144define void @fun5() { 145; CHECK-LABEL: fun5: 146; CHECK: # %bb.0: 147; CHECK-NEXT: mvghi 0(%r1), 0 148; CHECK-NEXT: br %r14 149 call void @llvm.memset.p0.i64( 150 ptr getelementptr inbounds ([1024 x i8], ptr @Data, i64 0, i64 35), 151 i8 0, 152 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 153 ptr @Data, i64 1, i64 35) to i64), i64 1), 154 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 155 ptr @Data, i64 1, i64 35) to i64), i64 1)), 156 i1 false) 157 %i11 = getelementptr i8, ptr null, 158 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 159 ptr @Data, i64 1, i64 35) to i64), i64 1), 160 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 161 ptr @Data, i64 1, i64 35) to i64), i64 1)) 162 store ptr %i11, ptr undef, align 8 163 ret void 164} 165 166; The same, with a resulting constant length of 1. 167define void @fun6() { 168; CHECK-LABEL: fun6: 169; CHECK: # %bb.0: 170; CHECK-NEXT: larl %r1, Data 171; CHECK-NEXT: xc 35(1,%r1), 35(%r1) 172; CHECK-NEXT: mvghi 0(%r1), 1 173; CHECK-NEXT: br %r14 174 call void @llvm.memset.p0.i64( 175 ptr getelementptr inbounds ([1024 x i8], ptr @Data, i64 0, i64 35), 176 i8 0, 177 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 178 ptr @Data, i64 1, i64 36) to i64), i64 1), 179 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 180 ptr @Data, i64 1, i64 35) to i64), i64 1)), 181 i1 false) 182 %i11 = getelementptr i8, ptr null, 183 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 184 ptr @Data, i64 1, i64 36) to i64), i64 1), 185 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 186 ptr @Data, i64 1, i64 35) to i64), i64 1)) 187 store ptr %i11, ptr undef, align 8 188 ret void 189} 190 191; The same, with a resulting constant length of 256. 192define void @fun7() { 193; CHECK-LABEL: fun7: 194; CHECK: # %bb.0: 195; CHECK-NEXT: larl %r1, Data 196; CHECK-NEXT: xc 35(256,%r1), 35(%r1) 197; CHECK-NEXT: mvghi 0(%r1), 256 198; CHECK-NEXT: br %r14 199 call void @llvm.memset.p0.i64( 200 ptr getelementptr inbounds ([1024 x i8], ptr @Data, i64 0, i64 35), 201 i8 0, 202 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 203 ptr @Data, i64 1, i64 291) to i64), i64 1), 204 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 205 ptr @Data, i64 1, i64 35) to i64), i64 1)), 206 i1 false) 207 %i11 = getelementptr i8, ptr null, 208 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 209 ptr @Data, i64 1, i64 291) to i64), i64 1), 210 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 211 ptr @Data, i64 1, i64 35) to i64), i64 1)) 212 store ptr %i11, ptr undef, align 8 213 ret void 214} 215 216; The same, with a resulting constant length of 257. 217define void @fun8() { 218; CHECK-LABEL: fun8: 219; CHECK: # %bb.0: 220; CHECK-NEXT: larl %r1, Data 221; CHECK-NEXT: xc 35(256,%r1), 35(%r1) 222; CHECK-NEXT: xc 291(1,%r1), 291(%r1) 223; CHECK-NEXT: mvghi 0(%r1), 257 224; CHECK-NEXT: br %r14 225 call void @llvm.memset.p0.i64( 226 ptr getelementptr inbounds ([1024 x i8], ptr @Data, i64 0, i64 35), 227 i8 0, 228 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 229 ptr @Data, i64 1, i64 292) to i64), i64 1), 230 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 231 ptr @Data, i64 1, i64 35) to i64), i64 1)), 232 i1 false) 233 %i11 = getelementptr i8, ptr null, 234 i64 sub (i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 235 ptr @Data, i64 1, i64 292) to i64), i64 1), 236 i64 add (i64 ptrtoint (ptr getelementptr inbounds ([1024 x i8], 237 ptr @Data, i64 1, i64 35) to i64), i64 1)) 238 store ptr %i11, ptr undef, align 8 239 ret void 240} 241 242; CHECK: .Ltmp2: 243; CHECK-NEXT: xc 0(1,%r1), 0(%r1) 244; CHECK-NEXT: .Ltmp0: 245; CHECK-NEXT: xc 0(1,%r2), 0(%r2) 246; CHECK-NEXT: .Ltmp1: 247; CHECK-NEXT: xc 0(1,%r3), 0(%r3) 248 249declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) 250declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) 251