1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -loop-vectorize -scalable-vectorization=on -mtriple riscv64-linux-gnu -mattr=+v,+f -S 2>%t | FileCheck %s 3 4; Tests specific to div/rem handling - both predicated and not 5 6target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" 7target triple = "riscv64" 8 9define void @vector_udiv(ptr noalias nocapture %a, i64 %v, i64 %n) { 10; CHECK-LABEL: @vector_udiv( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() 13; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP0]] 14; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 15; CHECK: vector.ph: 16; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 17; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP1]] 18; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] 19; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 1 x i64> poison, i64 [[V:%.*]], i32 0 20; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 1 x i64> [[BROADCAST_SPLATINSERT]], <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer 21; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 22; CHECK: vector.body: 23; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 24; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 0 25; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP2]] 26; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[TMP3]], i32 0 27; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 1 x i64>, ptr [[TMP4]], align 8 28; CHECK-NEXT: [[TMP5:%.*]] = udiv <vscale x 1 x i64> [[WIDE_LOAD]], [[BROADCAST_SPLAT]] 29; CHECK-NEXT: store <vscale x 1 x i64> [[TMP5]], ptr [[TMP4]], align 8 30; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 31; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP6]] 32; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 33; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] 34; CHECK: middle.block: 35; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] 36; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]] 37; CHECK: scalar.ph: 38; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 39; CHECK-NEXT: br label [[FOR_BODY:%.*]] 40; CHECK: for.body: 41; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[FOR_BODY]] ] 42; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[IV]] 43; CHECK-NEXT: [[ELEM:%.*]] = load i64, ptr [[ARRAYIDX]], align 8 44; CHECK-NEXT: [[DIVREM:%.*]] = udiv i64 [[ELEM]], [[V]] 45; CHECK-NEXT: store i64 [[DIVREM]], ptr [[ARRAYIDX]], align 8 46; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 47; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 48; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]] 49; CHECK: for.end: 50; CHECK-NEXT: ret void 51; 52entry: 53 br label %for.body 54 55for.body: 56 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 57 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv 58 %elem = load i64, ptr %arrayidx 59 %divrem = udiv i64 %elem, %v 60 store i64 %divrem, ptr %arrayidx 61 %iv.next = add nuw nsw i64 %iv, 1 62 %exitcond.not = icmp eq i64 %iv.next, 1024 63 br i1 %exitcond.not, label %for.end, label %for.body 64 65for.end: 66 ret void 67} 68 69define void @vector_sdiv(ptr noalias nocapture %a, i64 %v, i64 %n) { 70; CHECK-LABEL: @vector_sdiv( 71; CHECK-NEXT: entry: 72; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() 73; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP0]] 74; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 75; CHECK: vector.ph: 76; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 77; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP1]] 78; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] 79; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 1 x i64> poison, i64 [[V:%.*]], i32 0 80; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 1 x i64> [[BROADCAST_SPLATINSERT]], <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer 81; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 82; CHECK: vector.body: 83; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 84; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 0 85; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP2]] 86; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[TMP3]], i32 0 87; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 1 x i64>, ptr [[TMP4]], align 8 88; CHECK-NEXT: [[TMP5:%.*]] = sdiv <vscale x 1 x i64> [[WIDE_LOAD]], [[BROADCAST_SPLAT]] 89; CHECK-NEXT: store <vscale x 1 x i64> [[TMP5]], ptr [[TMP4]], align 8 90; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 91; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP6]] 92; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 93; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] 94; CHECK: middle.block: 95; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] 96; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]] 97; CHECK: scalar.ph: 98; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 99; CHECK-NEXT: br label [[FOR_BODY:%.*]] 100; CHECK: for.body: 101; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[FOR_BODY]] ] 102; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[IV]] 103; CHECK-NEXT: [[ELEM:%.*]] = load i64, ptr [[ARRAYIDX]], align 8 104; CHECK-NEXT: [[DIVREM:%.*]] = sdiv i64 [[ELEM]], [[V]] 105; CHECK-NEXT: store i64 [[DIVREM]], ptr [[ARRAYIDX]], align 8 106; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 107; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 108; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] 109; CHECK: for.end: 110; CHECK-NEXT: ret void 111; 112entry: 113 br label %for.body 114 115for.body: 116 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 117 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv 118 %elem = load i64, ptr %arrayidx 119 %divrem = sdiv i64 %elem, %v 120 store i64 %divrem, ptr %arrayidx 121 %iv.next = add nuw nsw i64 %iv, 1 122 %exitcond.not = icmp eq i64 %iv.next, 1024 123 br i1 %exitcond.not, label %for.end, label %for.body 124 125for.end: 126 ret void 127} 128 129define void @vector_urem(ptr noalias nocapture %a, i64 %v, i64 %n) { 130; CHECK-LABEL: @vector_urem( 131; CHECK-NEXT: entry: 132; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() 133; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP0]] 134; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 135; CHECK: vector.ph: 136; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 137; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP1]] 138; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] 139; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 1 x i64> poison, i64 [[V:%.*]], i32 0 140; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 1 x i64> [[BROADCAST_SPLATINSERT]], <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer 141; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 142; CHECK: vector.body: 143; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 144; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 0 145; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP2]] 146; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[TMP3]], i32 0 147; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 1 x i64>, ptr [[TMP4]], align 8 148; CHECK-NEXT: [[TMP5:%.*]] = urem <vscale x 1 x i64> [[WIDE_LOAD]], [[BROADCAST_SPLAT]] 149; CHECK-NEXT: store <vscale x 1 x i64> [[TMP5]], ptr [[TMP4]], align 8 150; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 151; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP6]] 152; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 153; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] 154; CHECK: middle.block: 155; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] 156; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]] 157; CHECK: scalar.ph: 158; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 159; CHECK-NEXT: br label [[FOR_BODY:%.*]] 160; CHECK: for.body: 161; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[FOR_BODY]] ] 162; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[IV]] 163; CHECK-NEXT: [[ELEM:%.*]] = load i64, ptr [[ARRAYIDX]], align 8 164; CHECK-NEXT: [[DIVREM:%.*]] = urem i64 [[ELEM]], [[V]] 165; CHECK-NEXT: store i64 [[DIVREM]], ptr [[ARRAYIDX]], align 8 166; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 167; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 168; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP7:![0-9]+]] 169; CHECK: for.end: 170; CHECK-NEXT: ret void 171; 172entry: 173 br label %for.body 174 175for.body: 176 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 177 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv 178 %elem = load i64, ptr %arrayidx 179 %divrem = urem i64 %elem, %v 180 store i64 %divrem, ptr %arrayidx 181 %iv.next = add nuw nsw i64 %iv, 1 182 %exitcond.not = icmp eq i64 %iv.next, 1024 183 br i1 %exitcond.not, label %for.end, label %for.body 184 185for.end: 186 ret void 187} 188 189define void @vector_srem(ptr noalias nocapture %a, i64 %v, i64 %n) { 190; CHECK-LABEL: @vector_srem( 191; CHECK-NEXT: entry: 192; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() 193; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP0]] 194; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 195; CHECK: vector.ph: 196; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 197; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP1]] 198; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] 199; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 1 x i64> poison, i64 [[V:%.*]], i32 0 200; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 1 x i64> [[BROADCAST_SPLATINSERT]], <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer 201; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 202; CHECK: vector.body: 203; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 204; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 0 205; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP2]] 206; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[TMP3]], i32 0 207; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 1 x i64>, ptr [[TMP4]], align 8 208; CHECK-NEXT: [[TMP5:%.*]] = srem <vscale x 1 x i64> [[WIDE_LOAD]], [[BROADCAST_SPLAT]] 209; CHECK-NEXT: store <vscale x 1 x i64> [[TMP5]], ptr [[TMP4]], align 8 210; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() 211; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP6]] 212; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 213; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] 214; CHECK: middle.block: 215; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] 216; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]] 217; CHECK: scalar.ph: 218; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 219; CHECK-NEXT: br label [[FOR_BODY:%.*]] 220; CHECK: for.body: 221; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[FOR_BODY]] ] 222; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[IV]] 223; CHECK-NEXT: [[ELEM:%.*]] = load i64, ptr [[ARRAYIDX]], align 8 224; CHECK-NEXT: [[DIVREM:%.*]] = srem i64 [[ELEM]], [[V]] 225; CHECK-NEXT: store i64 [[DIVREM]], ptr [[ARRAYIDX]], align 8 226; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 227; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 228; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]] 229; CHECK: for.end: 230; CHECK-NEXT: ret void 231; 232entry: 233 br label %for.body 234 235for.body: 236 %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.body ] 237 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv 238 %elem = load i64, ptr %arrayidx 239 %divrem = srem i64 %elem, %v 240 store i64 %divrem, ptr %arrayidx 241 %iv.next = add nuw nsw i64 %iv, 1 242 %exitcond.not = icmp eq i64 %iv.next, 1024 243 br i1 %exitcond.not, label %for.end, label %for.body 244 245for.end: 246 ret void 247} 248 249define void @predicated_udiv(ptr noalias nocapture %a, i64 %v, i64 %n) { 250; CHECK-LABEL: @predicated_udiv( 251; CHECK-NEXT: entry: 252; CHECK-NEXT: br label [[FOR_BODY:%.*]] 253; CHECK: for.body: 254; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ] 255; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[IV]] 256; CHECK-NEXT: [[ELEM:%.*]] = load i64, ptr [[ARRAYIDX]], align 8 257; CHECK-NEXT: [[C:%.*]] = icmp ne i64 [[V:%.*]], 0 258; CHECK-NEXT: br i1 [[C]], label [[DO_OP:%.*]], label [[LATCH]] 259; CHECK: do_op: 260; CHECK-NEXT: [[DIVREM:%.*]] = udiv i64 [[ELEM]], [[V]] 261; CHECK-NEXT: br label [[LATCH]] 262; CHECK: latch: 263; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[ELEM]], [[FOR_BODY]] ], [ [[DIVREM]], [[DO_OP]] ] 264; CHECK-NEXT: store i64 [[PHI]], ptr [[ARRAYIDX]], align 8 265; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 266; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 267; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 268; CHECK: for.end: 269; CHECK-NEXT: ret void 270; 271entry: 272 br label %for.body 273 274for.body: 275 %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ] 276 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv 277 %elem = load i64, ptr %arrayidx 278 %c = icmp ne i64 %v, 0 279 br i1 %c, label %do_op, label %latch 280do_op: 281 %divrem = udiv i64 %elem, %v 282 br label %latch 283latch: 284 %phi = phi i64 [%elem, %for.body], [%divrem, %do_op] 285 store i64 %phi, ptr %arrayidx 286 %iv.next = add nuw nsw i64 %iv, 1 287 %exitcond.not = icmp eq i64 %iv.next, 1024 288 br i1 %exitcond.not, label %for.end, label %for.body 289 290for.end: 291 ret void 292} 293 294define void @predicated_sdiv(ptr noalias nocapture %a, i64 %v, i64 %n) { 295; CHECK-LABEL: @predicated_sdiv( 296; CHECK-NEXT: entry: 297; CHECK-NEXT: br label [[FOR_BODY:%.*]] 298; CHECK: for.body: 299; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ] 300; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[IV]] 301; CHECK-NEXT: [[ELEM:%.*]] = load i64, ptr [[ARRAYIDX]], align 8 302; CHECK-NEXT: [[C:%.*]] = icmp ne i64 [[V:%.*]], 0 303; CHECK-NEXT: br i1 [[C]], label [[DO_OP:%.*]], label [[LATCH]] 304; CHECK: do_op: 305; CHECK-NEXT: [[DIVREM:%.*]] = sdiv i64 [[ELEM]], [[V]] 306; CHECK-NEXT: br label [[LATCH]] 307; CHECK: latch: 308; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[ELEM]], [[FOR_BODY]] ], [ [[DIVREM]], [[DO_OP]] ] 309; CHECK-NEXT: store i64 [[PHI]], ptr [[ARRAYIDX]], align 8 310; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 311; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 312; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 313; CHECK: for.end: 314; CHECK-NEXT: ret void 315; 316entry: 317 br label %for.body 318 319for.body: 320 %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ] 321 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv 322 %elem = load i64, ptr %arrayidx 323 %c = icmp ne i64 %v, 0 324 br i1 %c, label %do_op, label %latch 325do_op: 326 %divrem = sdiv i64 %elem, %v 327 br label %latch 328latch: 329 %phi = phi i64 [%elem, %for.body], [%divrem, %do_op] 330 store i64 %phi, ptr %arrayidx 331 %iv.next = add nuw nsw i64 %iv, 1 332 %exitcond.not = icmp eq i64 %iv.next, 1024 333 br i1 %exitcond.not, label %for.end, label %for.body 334 335for.end: 336 ret void 337} 338 339define void @predicated_udiv_by_constant(ptr noalias nocapture %a, i64 %n) { 340; CHECK-LABEL: @predicated_udiv_by_constant( 341; CHECK-NEXT: entry: 342; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() 343; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP0]] 344; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 345; CHECK: vector.ph: 346; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 347; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP1]] 348; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] 349; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 350; CHECK: vector.body: 351; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 352; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 0 353; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP2]] 354; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[TMP3]], i32 0 355; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 1 x i64>, ptr [[TMP4]], align 8 356; CHECK-NEXT: [[TMP5:%.*]] = icmp ne <vscale x 1 x i64> [[WIDE_LOAD]], shufflevector (<vscale x 1 x i64> insertelement (<vscale x 1 x i64> poison, i64 42, i32 0), <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer) 357; CHECK-NEXT: [[TMP6:%.*]] = udiv <vscale x 1 x i64> [[WIDE_LOAD]], shufflevector (<vscale x 1 x i64> insertelement (<vscale x 1 x i64> poison, i64 27, i32 0), <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer) 358; CHECK-NEXT: [[TMP7:%.*]] = xor <vscale x 1 x i1> [[TMP5]], shufflevector (<vscale x 1 x i1> insertelement (<vscale x 1 x i1> poison, i1 true, i32 0), <vscale x 1 x i1> poison, <vscale x 1 x i32> zeroinitializer) 359; CHECK-NEXT: [[PREDPHI:%.*]] = select <vscale x 1 x i1> [[TMP5]], <vscale x 1 x i64> [[TMP6]], <vscale x 1 x i64> [[WIDE_LOAD]] 360; CHECK-NEXT: store <vscale x 1 x i64> [[PREDPHI]], ptr [[TMP4]], align 8 361; CHECK-NEXT: [[TMP8:%.*]] = call i64 @llvm.vscale.i64() 362; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP8]] 363; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 364; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] 365; CHECK: middle.block: 366; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] 367; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]] 368; CHECK: scalar.ph: 369; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 370; CHECK-NEXT: br label [[FOR_BODY:%.*]] 371; CHECK: for.body: 372; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ] 373; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[IV]] 374; CHECK-NEXT: [[ELEM:%.*]] = load i64, ptr [[ARRAYIDX]], align 8 375; CHECK-NEXT: [[C:%.*]] = icmp ne i64 [[ELEM]], 42 376; CHECK-NEXT: br i1 [[C]], label [[DO_OP:%.*]], label [[LATCH]] 377; CHECK: do_op: 378; CHECK-NEXT: [[DIVREM:%.*]] = udiv i64 [[ELEM]], 27 379; CHECK-NEXT: br label [[LATCH]] 380; CHECK: latch: 381; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[ELEM]], [[FOR_BODY]] ], [ [[DIVREM]], [[DO_OP]] ] 382; CHECK-NEXT: store i64 [[PHI]], ptr [[ARRAYIDX]], align 8 383; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 384; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 385; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP11:![0-9]+]] 386; CHECK: for.end: 387; CHECK-NEXT: ret void 388; 389entry: 390 br label %for.body 391 392for.body: 393 %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ] 394 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv 395 %elem = load i64, ptr %arrayidx 396 %c = icmp ne i64 %elem, 42 397 br i1 %c, label %do_op, label %latch 398do_op: 399 %divrem = udiv i64 %elem, 27 400 br label %latch 401latch: 402 %phi = phi i64 [%elem, %for.body], [%divrem, %do_op] 403 store i64 %phi, ptr %arrayidx 404 %iv.next = add nuw nsw i64 %iv, 1 405 %exitcond.not = icmp eq i64 %iv.next, 1024 406 br i1 %exitcond.not, label %for.end, label %for.body 407 408for.end: 409 ret void 410} 411 412define void @predicated_sdiv_by_constant(ptr noalias nocapture %a, i64 %n) { 413; CHECK-LABEL: @predicated_sdiv_by_constant( 414; CHECK-NEXT: entry: 415; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() 416; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1024, [[TMP0]] 417; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 418; CHECK: vector.ph: 419; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 420; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1024, [[TMP1]] 421; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 1024, [[N_MOD_VF]] 422; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 423; CHECK: vector.body: 424; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] 425; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 0 426; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[TMP2]] 427; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i64, ptr [[TMP3]], i32 0 428; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 1 x i64>, ptr [[TMP4]], align 8 429; CHECK-NEXT: [[TMP5:%.*]] = icmp ne <vscale x 1 x i64> [[WIDE_LOAD]], shufflevector (<vscale x 1 x i64> insertelement (<vscale x 1 x i64> poison, i64 42, i32 0), <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer) 430; CHECK-NEXT: [[TMP6:%.*]] = sdiv <vscale x 1 x i64> [[WIDE_LOAD]], shufflevector (<vscale x 1 x i64> insertelement (<vscale x 1 x i64> poison, i64 27, i32 0), <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer) 431; CHECK-NEXT: [[TMP7:%.*]] = xor <vscale x 1 x i1> [[TMP5]], shufflevector (<vscale x 1 x i1> insertelement (<vscale x 1 x i1> poison, i1 true, i32 0), <vscale x 1 x i1> poison, <vscale x 1 x i32> zeroinitializer) 432; CHECK-NEXT: [[PREDPHI:%.*]] = select <vscale x 1 x i1> [[TMP5]], <vscale x 1 x i64> [[TMP6]], <vscale x 1 x i64> [[WIDE_LOAD]] 433; CHECK-NEXT: store <vscale x 1 x i64> [[PREDPHI]], ptr [[TMP4]], align 8 434; CHECK-NEXT: [[TMP8:%.*]] = call i64 @llvm.vscale.i64() 435; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP8]] 436; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 437; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]] 438; CHECK: middle.block: 439; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1024, [[N_VEC]] 440; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END:%.*]], label [[SCALAR_PH]] 441; CHECK: scalar.ph: 442; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] 443; CHECK-NEXT: br label [[FOR_BODY:%.*]] 444; CHECK: for.body: 445; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ] 446; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[IV]] 447; CHECK-NEXT: [[ELEM:%.*]] = load i64, ptr [[ARRAYIDX]], align 8 448; CHECK-NEXT: [[C:%.*]] = icmp ne i64 [[ELEM]], 42 449; CHECK-NEXT: br i1 [[C]], label [[DO_OP:%.*]], label [[LATCH]] 450; CHECK: do_op: 451; CHECK-NEXT: [[DIVREM:%.*]] = sdiv i64 [[ELEM]], 27 452; CHECK-NEXT: br label [[LATCH]] 453; CHECK: latch: 454; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[ELEM]], [[FOR_BODY]] ], [ [[DIVREM]], [[DO_OP]] ] 455; CHECK-NEXT: store i64 [[PHI]], ptr [[ARRAYIDX]], align 8 456; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 457; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 458; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP13:![0-9]+]] 459; CHECK: for.end: 460; CHECK-NEXT: ret void 461; 462entry: 463 br label %for.body 464 465for.body: 466 %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ] 467 %arrayidx = getelementptr inbounds i64, ptr %a, i64 %iv 468 %elem = load i64, ptr %arrayidx 469 %c = icmp ne i64 %elem, 42 470 br i1 %c, label %do_op, label %latch 471do_op: 472 %divrem = sdiv i64 %elem, 27 473 br label %latch 474latch: 475 %phi = phi i64 [%elem, %for.body], [%divrem, %do_op] 476 store i64 %phi, ptr %arrayidx 477 %iv.next = add nuw nsw i64 %iv, 1 478 %exitcond.not = icmp eq i64 %iv.next, 1024 479 br i1 %exitcond.not, label %for.end, label %for.body 480 481for.end: 482 ret void 483} 484 485define void @predicated_sdiv_by_minus_one(ptr noalias nocapture %a, i64 %n) { 486; CHECK-LABEL: @predicated_sdiv_by_minus_one( 487; CHECK-NEXT: entry: 488; CHECK-NEXT: br label [[FOR_BODY:%.*]] 489; CHECK: for.body: 490; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ] 491; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 [[IV]] 492; CHECK-NEXT: [[ELEM:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 493; CHECK-NEXT: [[C:%.*]] = icmp ne i8 [[ELEM]], -128 494; CHECK-NEXT: br i1 [[C]], label [[DO_OP:%.*]], label [[LATCH]] 495; CHECK: do_op: 496; CHECK-NEXT: [[DIVREM:%.*]] = sdiv i8 [[ELEM]], -1 497; CHECK-NEXT: br label [[LATCH]] 498; CHECK: latch: 499; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ [[ELEM]], [[FOR_BODY]] ], [ [[DIVREM]], [[DO_OP]] ] 500; CHECK-NEXT: store i8 [[PHI]], ptr [[ARRAYIDX]], align 1 501; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 502; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 1024 503; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 504; CHECK: for.end: 505; CHECK-NEXT: ret void 506; 507entry: 508 br label %for.body 509 510for.body: 511 %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ] 512 %arrayidx = getelementptr inbounds i8, ptr %a, i64 %iv 513 %elem = load i8, ptr %arrayidx 514 %c = icmp ne i8 %elem, 128 515 br i1 %c, label %do_op, label %latch 516do_op: 517 %divrem = sdiv i8 %elem, -1 ;; UB if %elem = INT_MIN 518 br label %latch 519latch: 520 %phi = phi i8 [%elem, %for.body], [%divrem, %do_op] 521 store i8 %phi, ptr %arrayidx 522 %iv.next = add nuw nsw i64 %iv, 1 523 %exitcond.not = icmp eq i64 %iv.next, 1024 524 br i1 %exitcond.not, label %for.end, label %for.body 525 526for.end: 527 ret void 528} 529