1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; REQUIRES: aarch64-registered-target 3 4; RUN: opt < %s -licm -S | FileCheck %s 5 6target triple = "aarch64--linux-gnueabi" 7 8define i8** @test1(i32 %j, i8** readonly %P, i8* readnone %Q) { 9; CHECK-LABEL: @test1( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[CMP0:%.*]] = icmp slt i32 0, [[J:%.*]] 12; CHECK-NEXT: br i1 [[CMP0]], label [[FOR_BODY_LR_PH:%.*]], label [[RETURN:%.*]] 13; CHECK: for.body.lr.ph: 14; CHECK-NEXT: br label [[FOR_BODY:%.*]] 15; CHECK: for.body: 16; CHECK-NEXT: [[P_ADDR:%.*]] = phi i8** [ [[P:%.*]], [[FOR_BODY_LR_PH]] ], [ [[ARRAYIDX0:%.*]], [[IF_END:%.*]] ] 17; CHECK-NEXT: [[I0:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH]] ], [ [[I_ADD:%.*]], [[IF_END]] ] 18; CHECK-NEXT: [[I0_EXT:%.*]] = sext i32 [[I0]] to i64 19; CHECK-NEXT: [[ARRAYIDX0]] = getelementptr inbounds i8*, i8** [[P_ADDR]], i64 [[I0_EXT]] 20; CHECK-NEXT: [[L0:%.*]] = load i8*, i8** [[ARRAYIDX0]], align 8 21; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8* [[L0]], [[Q:%.*]] 22; CHECK-NEXT: br i1 [[CMP1]], label [[LOOPEXIT0:%.*]], label [[IF_END]] 23; CHECK: if.end: 24; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8*, i8** [[ARRAYIDX0]], i64 1 25; CHECK-NEXT: [[L1:%.*]] = load i8*, i8** [[ARRAYIDX1]], align 8 26; CHECK-NEXT: [[CMP4:%.*]] = icmp ugt i8* [[L1]], [[Q]] 27; CHECK-NEXT: [[I_ADD]] = add nsw i32 [[I0]], 2 28; CHECK-NEXT: br i1 [[CMP4]], label [[LOOPEXIT1:%.*]], label [[FOR_BODY]] 29; CHECK: loopexit0: 30; CHECK-NEXT: [[P1:%.*]] = phi i8** [ [[ARRAYIDX0]], [[FOR_BODY]] ] 31; CHECK-NEXT: br label [[RETURN]] 32; CHECK: loopexit1: 33; CHECK-NEXT: [[ARRAYIDX0_LCSSA:%.*]] = phi i8** [ [[ARRAYIDX0]], [[IF_END]] ] 34; CHECK-NEXT: [[ARRAYIDX1_LE:%.*]] = getelementptr inbounds i8*, i8** [[ARRAYIDX0_LCSSA]], i64 1 35; CHECK-NEXT: br label [[RETURN]] 36; CHECK: return: 37; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8** [ [[P1]], [[LOOPEXIT0]] ], [ [[ARRAYIDX1_LE]], [[LOOPEXIT1]] ], [ null, [[ENTRY:%.*]] ] 38; CHECK-NEXT: ret i8** [[RETVAL_0]] 39; 40entry: 41 %cmp0 = icmp slt i32 0, %j 42 br i1 %cmp0, label %for.body.lr.ph, label %return 43 44for.body.lr.ph: 45 br label %for.body 46 47for.body: 48 %P.addr = phi i8** [ %P, %for.body.lr.ph ], [ %arrayidx0, %if.end ] 49 %i0 = phi i32 [ 0, %for.body.lr.ph ], [ %i.add, %if.end] 50 51 %i0.ext = sext i32 %i0 to i64 52 %arrayidx0 = getelementptr inbounds i8*, i8** %P.addr, i64 %i0.ext 53 %l0 = load i8*, i8** %arrayidx0, align 8 54 %cmp1 = icmp ugt i8* %l0, %Q 55 br i1 %cmp1, label %loopexit0, label %if.end 56 57if.end: ; preds = %for.body 58 %arrayidx1 = getelementptr inbounds i8*, i8** %arrayidx0, i64 1 59 %l1 = load i8*, i8** %arrayidx1, align 8 60 %cmp4 = icmp ugt i8* %l1, %Q 61 %i.add = add nsw i32 %i0, 2 62 br i1 %cmp4, label %loopexit1, label %for.body 63 64loopexit0: 65 %p1 = phi i8** [%arrayidx0, %for.body] 66 br label %return 67 68loopexit1: 69 %p2 = phi i8** [%arrayidx1, %if.end] 70 br label %return 71 72return: 73 %retval.0 = phi i8** [ %p1, %loopexit0 ], [%p2, %loopexit1], [ null, %entry ] 74 ret i8** %retval.0 75} 76 77define i8** @test2(i32 %j, i8** readonly %P, i8* readnone %Q) { 78; CHECK-LABEL: @test2( 79; CHECK-NEXT: entry: 80; CHECK-NEXT: br label [[FOR_BODY:%.*]] 81; CHECK: for.cond: 82; CHECK-NEXT: [[I_ADDR_0:%.*]] = phi i32 [ [[ADD:%.*]], [[IF_END:%.*]] ] 83; CHECK-NEXT: [[P_ADDR_0:%.*]] = phi i8** [ [[ADD_PTR:%.*]], [[IF_END]] ] 84; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_ADDR_0]], [[J:%.*]] 85; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[LOOPEXIT0:%.*]] 86; CHECK: for.body: 87; CHECK-NEXT: [[P_ADDR:%.*]] = phi i8** [ [[P:%.*]], [[ENTRY:%.*]] ], [ [[P_ADDR_0]], [[FOR_COND:%.*]] ] 88; CHECK-NEXT: [[I_ADDR:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I_ADDR_0]], [[FOR_COND]] ] 89; CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[I_ADDR]] to i64 90; CHECK-NEXT: [[ADD_PTR]] = getelementptr inbounds i8*, i8** [[P_ADDR]], i64 [[IDX_EXT]] 91; CHECK-NEXT: [[L0:%.*]] = load i8*, i8** [[ADD_PTR]], align 8 92; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8* [[L0]], [[Q:%.*]] 93; CHECK-NEXT: br i1 [[CMP1]], label [[LOOPEXIT1:%.*]], label [[IF_END]] 94; CHECK: if.end: 95; CHECK-NEXT: [[ADD_I:%.*]] = add i32 [[I_ADDR]], 1 96; CHECK-NEXT: [[IDX2_EXT:%.*]] = sext i32 [[ADD_I]] to i64 97; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i8*, i8** [[ADD_PTR]], i64 [[IDX2_EXT]] 98; CHECK-NEXT: [[L1:%.*]] = load i8*, i8** [[ARRAYIDX2]], align 8 99; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8* [[L1]], [[Q]] 100; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD_I]], 1 101; CHECK-NEXT: br i1 [[CMP2]], label [[LOOPEXIT2:%.*]], label [[FOR_COND]] 102; CHECK: loopexit0: 103; CHECK-NEXT: [[P0:%.*]] = phi i8** [ null, [[FOR_COND]] ] 104; CHECK-NEXT: br label [[RETURN:%.*]] 105; CHECK: loopexit1: 106; CHECK-NEXT: [[P1:%.*]] = phi i8** [ [[ADD_PTR]], [[FOR_BODY]] ] 107; CHECK-NEXT: br label [[RETURN]] 108; CHECK: loopexit2: 109; CHECK-NEXT: [[IDX2_EXT_LCSSA:%.*]] = phi i64 [ [[IDX2_EXT]], [[IF_END]] ] 110; CHECK-NEXT: [[ADD_PTR_LCSSA:%.*]] = phi i8** [ [[ADD_PTR]], [[IF_END]] ] 111; CHECK-NEXT: [[ARRAYIDX2_LE:%.*]] = getelementptr inbounds i8*, i8** [[ADD_PTR_LCSSA]], i64 [[IDX2_EXT_LCSSA]] 112; CHECK-NEXT: br label [[RETURN]] 113; CHECK: return: 114; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8** [ [[P1]], [[LOOPEXIT1]] ], [ [[ARRAYIDX2_LE]], [[LOOPEXIT2]] ], [ [[P0]], [[LOOPEXIT0]] ] 115; CHECK-NEXT: ret i8** [[RETVAL_0]] 116; 117entry: 118 br label %for.body 119 120for.cond: 121 %i.addr.0 = phi i32 [ %add, %if.end ] 122 %P.addr.0 = phi i8** [ %add.ptr, %if.end ] 123 %cmp = icmp slt i32 %i.addr.0, %j 124 br i1 %cmp, label %for.body, label %loopexit0 125 126for.body: 127 %P.addr = phi i8** [ %P, %entry ], [ %P.addr.0, %for.cond ] 128 %i.addr = phi i32 [ 0, %entry ], [ %i.addr.0, %for.cond ] 129 130 %idx.ext = sext i32 %i.addr to i64 131 %add.ptr = getelementptr inbounds i8*, i8** %P.addr, i64 %idx.ext 132 %l0 = load i8*, i8** %add.ptr, align 8 133 134 %cmp1 = icmp ugt i8* %l0, %Q 135 br i1 %cmp1, label %loopexit1, label %if.end 136 137if.end: 138 %add.i = add i32 %i.addr, 1 139 %idx2.ext = sext i32 %add.i to i64 140 %arrayidx2 = getelementptr inbounds i8*, i8** %add.ptr, i64 %idx2.ext 141 %l1 = load i8*, i8** %arrayidx2, align 8 142 %cmp2 = icmp ugt i8* %l1, %Q 143 %add = add nsw i32 %add.i, 1 144 br i1 %cmp2, label %loopexit2, label %for.cond 145 146loopexit0: 147 %p0 = phi i8** [ null, %for.cond ] 148 br label %return 149 150loopexit1: 151 %p1 = phi i8** [ %add.ptr, %for.body ] 152 br label %return 153 154loopexit2: 155 %p2 = phi i8** [ %arrayidx2, %if.end ] 156 br label %return 157 158return: 159 %retval.0 = phi i8** [ %p1, %loopexit1 ], [ %p2, %loopexit2 ], [ %p0, %loopexit0 ] 160 ret i8** %retval.0 161} 162 163 164define i8** @test3(i64 %j, i8** readonly %P, i8* readnone %Q) { 165; CHECK-LABEL: @test3( 166; CHECK-NEXT: entry: 167; CHECK-NEXT: [[CMP0:%.*]] = icmp slt i64 0, [[J:%.*]] 168; CHECK-NEXT: br i1 [[CMP0]], label [[FOR_BODY_LR_PH:%.*]], label [[RETURN:%.*]] 169; CHECK: for.body.lr.ph: 170; CHECK-NEXT: br label [[FOR_BODY:%.*]] 171; CHECK: for.body: 172; CHECK-NEXT: [[P_ADDR:%.*]] = phi i8** [ [[P:%.*]], [[FOR_BODY_LR_PH]] ], [ [[ARRAYIDX0:%.*]], [[IF_END:%.*]] ] 173; CHECK-NEXT: [[I0:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH]] ], [ [[I_ADD:%.*]], [[IF_END]] ] 174; CHECK-NEXT: [[I0_EXT:%.*]] = sext i32 [[I0]] to i64 175; CHECK-NEXT: [[ARRAYIDX0]] = getelementptr inbounds i8*, i8** [[P_ADDR]], i64 [[I0_EXT]] 176; CHECK-NEXT: [[L0:%.*]] = load i8*, i8** [[ARRAYIDX0]], align 8 177; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8* [[L0]], [[Q:%.*]] 178; CHECK-NEXT: br i1 [[CMP1]], label [[LOOPEXIT0:%.*]], label [[IF_END]] 179; CHECK: if.end: 180; CHECK-NEXT: [[ADD:%.*]] = add i64 [[I0_EXT]], 1 181; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[ADD]] to i32 182; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8*, i8** [[P_ADDR]], i32 [[TRUNC]] 183; CHECK-NEXT: [[L1:%.*]] = load i8*, i8** [[ARRAYIDX1]], align 8 184; CHECK-NEXT: [[CMP4:%.*]] = icmp ugt i8* [[L1]], [[Q]] 185; CHECK-NEXT: [[I_ADD]] = add nsw i32 [[I0]], 2 186; CHECK-NEXT: br i1 [[CMP4]], label [[LOOPEXIT1:%.*]], label [[FOR_BODY]] 187; CHECK: loopexit0: 188; CHECK-NEXT: [[P1:%.*]] = phi i8** [ [[ARRAYIDX0]], [[FOR_BODY]] ] 189; CHECK-NEXT: br label [[RETURN]] 190; CHECK: loopexit1: 191; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i64 [ [[ADD]], [[IF_END]] ] 192; CHECK-NEXT: [[P_ADDR_LCSSA:%.*]] = phi i8** [ [[P_ADDR]], [[IF_END]] ] 193; CHECK-NEXT: [[TRUNC_LE:%.*]] = trunc i64 [[ADD_LCSSA]] to i32 194; CHECK-NEXT: [[ARRAYIDX1_LE:%.*]] = getelementptr inbounds i8*, i8** [[P_ADDR_LCSSA]], i32 [[TRUNC_LE]] 195; CHECK-NEXT: call void @dummy(i32 [[TRUNC_LE]]) 196; CHECK-NEXT: br label [[RETURN]] 197; CHECK: return: 198; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i8** [ [[P1]], [[LOOPEXIT0]] ], [ [[ARRAYIDX1_LE]], [[LOOPEXIT1]] ], [ null, [[ENTRY:%.*]] ] 199; CHECK-NEXT: ret i8** [[RETVAL_0]] 200; 201entry: 202 %cmp0 = icmp slt i64 0, %j 203 br i1 %cmp0, label %for.body.lr.ph, label %return 204 205for.body.lr.ph: 206 br label %for.body 207 208for.body: 209 %P.addr = phi i8** [ %P, %for.body.lr.ph ], [ %arrayidx0, %if.end ] 210 %i0 = phi i32 [ 0, %for.body.lr.ph ], [ %i.add, %if.end] 211 212 %i0.ext = sext i32 %i0 to i64 213 %arrayidx0 = getelementptr inbounds i8*, i8** %P.addr, i64 %i0.ext 214 %l0 = load i8*, i8** %arrayidx0, align 8 215 %cmp1 = icmp ugt i8* %l0, %Q 216 br i1 %cmp1, label %loopexit0, label %if.end 217 218if.end: ; preds = %for.body 219 %add = add i64 %i0.ext, 1 220 %trunc = trunc i64 %add to i32 221 %arrayidx1 = getelementptr inbounds i8*, i8** %P.addr, i32 %trunc 222 %l1 = load i8*, i8** %arrayidx1, align 8 223 %cmp4 = icmp ugt i8* %l1, %Q 224 %i.add = add nsw i32 %i0, 2 225 br i1 %cmp4, label %loopexit1, label %for.body 226 227loopexit0: 228 %p1 = phi i8** [%arrayidx0, %for.body] 229 br label %return 230 231loopexit1: 232 %p2 = phi i8** [%arrayidx1, %if.end] 233 call void @dummy(i32 %trunc) 234 br label %return 235 236return: 237 %retval.0 = phi i8** [ %p1, %loopexit0 ], [%p2, %loopexit1], [ null, %entry ] 238 ret i8** %retval.0 239} 240 241declare void @dummy(i32) 242