1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -codegenprepare -S < %s -mtriple=aarch64-none-linux-gnu -mattr=+sve | FileCheck %s 3 4define i64 @select_or_reduce_v2i1(ptr nocapture noundef readonly %src) { 5; CHECK-LABEL: define i64 @select_or_reduce_v2i1( 6; CHECK-SAME: ptr noundef readonly captures(none) [[SRC:%.*]]) #[[ATTR0:[0-9]+]] { 7; CHECK-NEXT: [[ENTRY:.*]]: 8; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] 9; CHECK: [[VECTOR_BODY]]: 10; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] 11; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[INDEX]] 12; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x ptr>, ptr [[ARRAYIDX]], align 8 13; CHECK-NEXT: [[COND:%.*]] = icmp eq <2 x ptr> [[WIDE_LOAD]], zeroinitializer 14; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 15; CHECK-NEXT: [[OR_REDUC:%.*]] = tail call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[COND]]) 16; CHECK-NEXT: [[IV_CMP:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4 17; CHECK-NEXT: [[EXIT_COND:%.*]] = or i1 [[OR_REDUC]], [[IV_CMP]] 18; CHECK-NEXT: br i1 [[EXIT_COND]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]] 19; CHECK: [[MIDDLE_SPLIT]]: 20; CHECK-NEXT: [[SEL:%.*]] = select i1 [[OR_REDUC]], i64 1, i64 0 21; CHECK-NEXT: ret i64 [[SEL]] 22; 23entry: 24 br label %vector.body 25 26vector.body: 27 %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ] 28 %arrayidx = getelementptr inbounds ptr, ptr %src, i64 %index 29 %wide.load = load <2 x ptr>, ptr %arrayidx, align 8 30 %cond = icmp eq <2 x ptr> %wide.load, splat(ptr zeroinitializer) 31 %index.next = add nuw i64 %index, 2 32 %or.reduc = tail call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> %cond) 33 %iv.cmp = icmp eq i64 %index.next, 4 34 %exit.cond = or i1 %or.reduc, %iv.cmp 35 br i1 %exit.cond, label %middle.split, label %vector.body 36 37middle.split: 38 %sel = select i1 %or.reduc, i64 1, i64 0 39 ret i64 %sel 40} 41 42define i64 @br_or_reduce_v2i1(ptr nocapture noundef readonly %src, ptr noundef readnone %p) { 43; CHECK-LABEL: define i64 @br_or_reduce_v2i1( 44; CHECK-SAME: ptr noundef readonly captures(none) [[SRC:%.*]], ptr noundef readnone [[P:%.*]]) #[[ATTR0]] { 45; CHECK-NEXT: [[ENTRY:.*]]: 46; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] 47; CHECK: [[VECTOR_BODY]]: 48; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] 49; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[INDEX]] 50; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x ptr>, ptr [[ARRAYIDX]], align 8 51; CHECK-NEXT: [[COND:%.*]] = icmp eq <2 x ptr> [[WIDE_LOAD]], zeroinitializer 52; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 53; CHECK-NEXT: [[OR_REDUC:%.*]] = tail call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[COND]]) 54; CHECK-NEXT: [[IV_CMP:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4 55; CHECK-NEXT: [[EXIT_COND:%.*]] = or i1 [[OR_REDUC]], [[IV_CMP]] 56; CHECK-NEXT: br i1 [[EXIT_COND]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]] 57; CHECK: [[MIDDLE_SPLIT]]: 58; CHECK-NEXT: br i1 [[OR_REDUC]], label %[[FOUND:.*]], label %[[NOTFOUND:.*]] 59; CHECK: [[FOUND]]: 60; CHECK-NEXT: store i64 56, ptr [[P]], align 8 61; CHECK-NEXT: ret i64 1 62; CHECK: [[NOTFOUND]]: 63; CHECK-NEXT: ret i64 0 64; 65entry: 66 br label %vector.body 67 68vector.body: 69 %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ] 70 %arrayidx = getelementptr inbounds ptr, ptr %src, i64 %index 71 %wide.load = load <2 x ptr>, ptr %arrayidx, align 8 72 %cond = icmp eq <2 x ptr> %wide.load, splat(ptr zeroinitializer) 73 %index.next = add nuw i64 %index, 2 74 %or.reduc = tail call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> %cond) 75 %iv.cmp = icmp eq i64 %index.next, 4 76 %exit.cond = or i1 %or.reduc, %iv.cmp 77 br i1 %exit.cond, label %middle.split, label %vector.body 78 79middle.split: 80 br i1 %or.reduc, label %found, label %notfound 81 82found: 83 store i64 56, ptr %p, align 8 84 ret i64 1 85 86notfound: 87 ret i64 0 88} 89 90define i64 @select_or_reduce_nxv2i1(ptr nocapture noundef readonly %src) { 91; CHECK-LABEL: define i64 @select_or_reduce_nxv2i1( 92; CHECK-SAME: ptr noundef readonly captures(none) [[SRC:%.*]]) #[[ATTR0]] { 93; CHECK-NEXT: [[ENTRY:.*]]: 94; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] 95; CHECK: [[VECTOR_BODY]]: 96; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] 97; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[INDEX]] 98; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 2 x ptr>, ptr [[ARRAYIDX]], align 8 99; CHECK-NEXT: [[COND:%.*]] = icmp eq <vscale x 2 x ptr> [[WIDE_LOAD]], zeroinitializer 100; CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.vscale.i64() 101; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 1 102; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]] 103; CHECK-NEXT: [[OR_REDUC:%.*]] = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> [[COND]]) 104; CHECK-NEXT: [[IV_CMP:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4 105; CHECK-NEXT: [[EXIT_COND:%.*]] = or i1 [[OR_REDUC]], [[IV_CMP]] 106; CHECK-NEXT: br i1 [[EXIT_COND]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]] 107; CHECK: [[MIDDLE_SPLIT]]: 108; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <vscale x 2 x ptr> [[WIDE_LOAD]], zeroinitializer 109; CHECK-NEXT: [[TMP3:%.*]] = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> [[TMP2]]) 110; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP3]], i64 1, i64 0 111; CHECK-NEXT: ret i64 [[SEL]] 112; 113entry: 114 %vscale = tail call i64 @llvm.vscale.i64() 115 %vf = shl nuw nsw i64 %vscale, 1 116 br label %vector.body 117 118vector.body: 119 %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ] 120 %arrayidx = getelementptr inbounds ptr, ptr %src, i64 %index 121 %wide.load = load <vscale x 2 x ptr>, ptr %arrayidx, align 8 122 %cond = icmp eq <vscale x 2 x ptr> %wide.load, splat(ptr zeroinitializer) 123 %index.next = add nuw i64 %index, %vf 124 %or.reduc = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> %cond) 125 %iv.cmp = icmp eq i64 %index.next, 4 126 %exit.cond = or i1 %or.reduc, %iv.cmp 127 br i1 %exit.cond, label %middle.split, label %vector.body 128 129middle.split: 130 %sel = select i1 %or.reduc, i64 1, i64 0 131 ret i64 %sel 132} 133 134define i64 @br_or_reduce_nxv2i1(ptr nocapture noundef readonly %src, ptr noundef readnone %p) { 135; CHECK-LABEL: define i64 @br_or_reduce_nxv2i1( 136; CHECK-SAME: ptr noundef readonly captures(none) [[SRC:%.*]], ptr noundef readnone [[P:%.*]]) #[[ATTR0]] { 137; CHECK-NEXT: [[ENTRY:.*]]: 138; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] 139; CHECK: [[VECTOR_BODY]]: 140; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] 141; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[SRC]], i64 [[INDEX]] 142; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 2 x ptr>, ptr [[ARRAYIDX]], align 8 143; CHECK-NEXT: [[COND:%.*]] = icmp eq <vscale x 2 x ptr> [[WIDE_LOAD]], zeroinitializer 144; CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.vscale.i64() 145; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 1 146; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP1]] 147; CHECK-NEXT: [[OR_REDUC:%.*]] = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> [[COND]]) 148; CHECK-NEXT: [[IV_CMP:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4 149; CHECK-NEXT: [[EXIT_COND:%.*]] = or i1 [[OR_REDUC]], [[IV_CMP]] 150; CHECK-NEXT: br i1 [[EXIT_COND]], label %[[MIDDLE_SPLIT:.*]], label %[[VECTOR_BODY]] 151; CHECK: [[MIDDLE_SPLIT]]: 152; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <vscale x 2 x ptr> [[WIDE_LOAD]], zeroinitializer 153; CHECK-NEXT: [[TMP3:%.*]] = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> [[TMP2]]) 154; CHECK-NEXT: br i1 [[TMP3]], label %[[FOUND:.*]], label %[[NOTFOUND:.*]] 155; CHECK: [[FOUND]]: 156; CHECK-NEXT: store i64 56, ptr [[P]], align 8 157; CHECK-NEXT: ret i64 1 158; CHECK: [[NOTFOUND]]: 159; CHECK-NEXT: ret i64 0 160; 161entry: 162 %vscale = tail call i64 @llvm.vscale.i64() 163 %vf = shl nuw nsw i64 %vscale, 1 164 br label %vector.body 165 166vector.body: 167 %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ] 168 %arrayidx = getelementptr inbounds ptr, ptr %src, i64 %index 169 %wide.load = load <vscale x 2 x ptr>, ptr %arrayidx, align 8 170 %cond = icmp eq <vscale x 2 x ptr> %wide.load, splat(ptr zeroinitializer) 171 %index.next = add nuw i64 %index, %vf 172 %or.reduc = tail call i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1> %cond) 173 %iv.cmp = icmp eq i64 %index.next, 4 174 %exit.cond = or i1 %or.reduc, %iv.cmp 175 br i1 %exit.cond, label %middle.split, label %vector.body 176 177middle.split: 178 br i1 %or.reduc, label %found, label %notfound 179 180found: 181 store i64 56, ptr %p, align 8 182 ret i64 1 183 184notfound: 185 ret i64 0 186} 187 188declare i1 @llvm.vector.reduce.or.v2i1(<2 x i1>) 189declare i1 @llvm.vector.reduce.or.nxv2i1(<vscale x 2 x i1>) 190