306 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; RUN: opt < %s -passes=tailcallelim -verify-dom-info -S | FileCheck %s3 4%struct.ListNode = type { i32, ptr }5 6define i32 @umin(ptr readonly %a) {7; CHECK-LABEL: define i32 @umin8; CHECK-SAME: (ptr readonly [[A:%.*]]) {9; CHECK-NEXT: entry:10; CHECK-NEXT: br label [[TAILRECURSE:%.*]]11; CHECK: tailrecurse:12; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]13; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]14; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null15; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]16; CHECK: common.ret6:17; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.umin.i32(i32 -1, i32 [[ACCUMULATOR_TR]])18; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]19; CHECK: if.end:20; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 421; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 122; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 823; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.umin.i32(i32 [[TMP0]], i32 [[ACCUMULATOR_TR]])24; CHECK-NEXT: br label [[TAILRECURSE]]25;26entry:27 %tobool.not = icmp eq ptr %a, null28 br i1 %tobool.not, label %common.ret6, label %if.end29 30common.ret6: ; preds = %entry, %if.end31 %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ -1, %entry ]32 ret i32 %common.ret6.op33 34if.end: ; preds = %entry35 %0 = load i32, ptr %a36 %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 137 %1 = load ptr, ptr %next38 %call = tail call i32 @umin(ptr %1)39 %.sroa.speculated = tail call i32 @llvm.umin.i32(i32 %0, i32 %call)40 br label %common.ret641}42 43define i32 @umin2(ptr readonly %a) {44; CHECK-LABEL: define i32 @umin245; CHECK-SAME: (ptr readonly [[A:%.*]]) {46; CHECK-NEXT: entry:47; CHECK-NEXT: br label [[TAILRECURSE:%.*]]48; CHECK: tailrecurse:49; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]50; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]51; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null52; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]53; CHECK: common.ret6:54; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.umin.i32(i32 [[ACCUMULATOR_TR]], i32 -1)55; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]56; CHECK: if.end:57; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 458; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 159; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 860; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.umin.i32(i32 [[ACCUMULATOR_TR]], i32 [[TMP0]])61; CHECK-NEXT: br label [[TAILRECURSE]]62;63entry:64 %tobool.not = icmp eq ptr %a, null65 br i1 %tobool.not, label %common.ret6, label %if.end66 67common.ret6: ; preds = %entry, %if.end68 %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ -1, %entry ]69 ret i32 %common.ret6.op70 71if.end: ; preds = %entry72 %0 = load i32, ptr %a73 %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 174 %1 = load ptr, ptr %next75 %call = tail call i32 @umin2(ptr %1)76 %.sroa.speculated = tail call i32 @llvm.umin.i32(i32 %call, i32 %0)77 br label %common.ret678}79 80define i32 @umax(ptr readonly %a) {81; CHECK-LABEL: define i32 @umax82; CHECK-SAME: (ptr readonly [[A:%.*]]) {83; CHECK-NEXT: entry:84; CHECK-NEXT: br label [[TAILRECURSE:%.*]]85; CHECK: tailrecurse:86; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]87; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]88; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null89; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]90; CHECK: common.ret6:91; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.umax.i32(i32 0, i32 [[ACCUMULATOR_TR]])92; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]93; CHECK: if.end:94; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 495; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 196; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 897; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.umax.i32(i32 [[TMP0]], i32 [[ACCUMULATOR_TR]])98; CHECK-NEXT: br label [[TAILRECURSE]]99;100entry:101 %tobool.not = icmp eq ptr %a, null102 br i1 %tobool.not, label %common.ret6, label %if.end103 104common.ret6: ; preds = %entry, %if.end105 %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ 0, %entry ]106 ret i32 %common.ret6.op107 108if.end: ; preds = %entry109 %0 = load i32, ptr %a110 %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1111 %1 = load ptr, ptr %next112 %call = tail call i32 @umax(ptr %1)113 %.sroa.speculated = tail call i32 @llvm.umax.i32(i32 %0, i32 %call)114 br label %common.ret6115}116 117define i32 @umax2(ptr readonly %a) {118; CHECK-LABEL: define i32 @umax2119; CHECK-SAME: (ptr readonly [[A:%.*]]) {120; CHECK-NEXT: entry:121; CHECK-NEXT: br label [[TAILRECURSE:%.*]]122; CHECK: tailrecurse:123; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]124; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]125; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null126; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]127; CHECK: common.ret6:128; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.umax.i32(i32 [[ACCUMULATOR_TR]], i32 0)129; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]130; CHECK: if.end:131; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 4132; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 1133; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 8134; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.umax.i32(i32 [[ACCUMULATOR_TR]], i32 [[TMP0]])135; CHECK-NEXT: br label [[TAILRECURSE]]136;137entry:138 %tobool.not = icmp eq ptr %a, null139 br i1 %tobool.not, label %common.ret6, label %if.end140 141common.ret6: ; preds = %entry, %if.end142 %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ 0, %entry ]143 ret i32 %common.ret6.op144 145if.end: ; preds = %entry146 %0 = load i32, ptr %a147 %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1148 %1 = load ptr, ptr %next149 %call = tail call i32 @umax2(ptr %1)150 %.sroa.speculated = tail call i32 @llvm.umax.i32(i32 %call, i32 %0)151 br label %common.ret6152}153 154define i32 @smin(ptr readonly %a) {155; CHECK-LABEL: define i32 @smin156; CHECK-SAME: (ptr readonly [[A:%.*]]) {157; CHECK-NEXT: entry:158; CHECK-NEXT: br label [[TAILRECURSE:%.*]]159; CHECK: tailrecurse:160; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ 2147483647, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]161; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]162; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null163; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]164; CHECK: common.ret6:165; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.smin.i32(i32 2147483647, i32 [[ACCUMULATOR_TR]])166; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]167; CHECK: if.end:168; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 4169; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 1170; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 8171; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.smin.i32(i32 [[TMP0]], i32 [[ACCUMULATOR_TR]])172; CHECK-NEXT: br label [[TAILRECURSE]]173;174entry:175 %tobool.not = icmp eq ptr %a, null176 br i1 %tobool.not, label %common.ret6, label %if.end177 178common.ret6: ; preds = %entry, %if.end179 %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ 2147483647, %entry ]180 ret i32 %common.ret6.op181 182if.end: ; preds = %entry183 %0 = load i32, ptr %a184 %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1185 %1 = load ptr, ptr %next186 %call = tail call i32 @smin(ptr %1)187 %.sroa.speculated = tail call i32 @llvm.smin.i32(i32 %0, i32 %call)188 br label %common.ret6189}190 191define i32 @smin2(ptr readonly %a) {192; CHECK-LABEL: define i32 @smin2193; CHECK-SAME: (ptr readonly [[A:%.*]]) {194; CHECK-NEXT: entry:195; CHECK-NEXT: br label [[TAILRECURSE:%.*]]196; CHECK: tailrecurse:197; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ 2147483647, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]198; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]199; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null200; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]201; CHECK: common.ret6:202; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.smin.i32(i32 [[ACCUMULATOR_TR]], i32 2147483647)203; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]204; CHECK: if.end:205; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 4206; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 1207; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 8208; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.smin.i32(i32 [[ACCUMULATOR_TR]], i32 [[TMP0]])209; CHECK-NEXT: br label [[TAILRECURSE]]210;211entry:212 %tobool.not = icmp eq ptr %a, null213 br i1 %tobool.not, label %common.ret6, label %if.end214 215common.ret6: ; preds = %entry, %if.end216 %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ 2147483647, %entry ]217 ret i32 %common.ret6.op218 219if.end: ; preds = %entry220 %0 = load i32, ptr %a221 %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1222 %1 = load ptr, ptr %next223 %call = tail call i32 @smin2(ptr %1)224 %.sroa.speculated = tail call i32 @llvm.smin.i32(i32 %call, i32 %0)225 br label %common.ret6226}227 228define i32 @smax(ptr readonly %a) {229; CHECK-LABEL: define i32 @smax230; CHECK-SAME: (ptr readonly [[A:%.*]]) {231; CHECK-NEXT: entry:232; CHECK-NEXT: br label [[TAILRECURSE:%.*]]233; CHECK: tailrecurse:234; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]235; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]236; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null237; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]238; CHECK: common.ret6:239; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.smax.i32(i32 -2147483648, i32 [[ACCUMULATOR_TR]])240; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]241; CHECK: if.end:242; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 4243; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 1244; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 8245; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.smax.i32(i32 [[TMP0]], i32 [[ACCUMULATOR_TR]])246; CHECK-NEXT: br label [[TAILRECURSE]]247;248entry:249 %tobool.not = icmp eq ptr %a, null250 br i1 %tobool.not, label %common.ret6, label %if.end251 252common.ret6: ; preds = %entry, %if.end253 %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ -2147483648, %entry ]254 ret i32 %common.ret6.op255 256if.end: ; preds = %entry257 %0 = load i32, ptr %a258 %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1259 %1 = load ptr, ptr %next260 %call = tail call i32 @smax(ptr %1)261 %.sroa.speculated = tail call i32 @llvm.smax.i32(i32 %0, i32 %call)262 br label %common.ret6263}264 265define i32 @smax2(ptr readonly %a) {266; CHECK-LABEL: define i32 @smax2267; CHECK-SAME: (ptr readonly [[A:%.*]]) {268; CHECK-NEXT: entry:269; CHECK-NEXT: br label [[TAILRECURSE:%.*]]270; CHECK: tailrecurse:271; CHECK-NEXT: [[ACCUMULATOR_TR:%.*]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[DOTSROA_SPECULATED:%.*]], [[IF_END:%.*]] ]272; CHECK-NEXT: [[A_TR:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[TMP1:%.*]], [[IF_END]] ]273; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr [[A_TR]], null274; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[COMMON_RET6:%.*]], label [[IF_END]]275; CHECK: common.ret6:276; CHECK-NEXT: [[ACCUMULATOR_RET_TR:%.*]] = tail call i32 @llvm.smax.i32(i32 [[ACCUMULATOR_TR]], i32 -2147483648)277; CHECK-NEXT: ret i32 [[ACCUMULATOR_RET_TR]]278; CHECK: if.end:279; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_TR]], align 4280; CHECK-NEXT: [[NEXT:%.*]] = getelementptr inbounds [[STRUCT_LISTNODE:%.*]], ptr [[A_TR]], i64 0, i32 1281; CHECK-NEXT: [[TMP1]] = load ptr, ptr [[NEXT]], align 8282; CHECK-NEXT: [[DOTSROA_SPECULATED]] = tail call i32 @llvm.smax.i32(i32 [[ACCUMULATOR_TR]], i32 [[TMP0]])283; CHECK-NEXT: br label [[TAILRECURSE]]284;285entry:286 %tobool.not = icmp eq ptr %a, null287 br i1 %tobool.not, label %common.ret6, label %if.end288 289common.ret6: ; preds = %entry, %if.end290 %common.ret6.op = phi i32 [ %.sroa.speculated, %if.end ], [ -2147483648, %entry ]291 ret i32 %common.ret6.op292 293if.end: ; preds = %entry294 %0 = load i32, ptr %a295 %next = getelementptr inbounds %struct.ListNode, ptr %a, i64 0, i32 1296 %1 = load ptr, ptr %next297 %call = tail call i32 @smax2(ptr %1)298 %.sroa.speculated = tail call i32 @llvm.smax.i32(i32 %call, i32 %0)299 br label %common.ret6300}301 302declare i32 @llvm.umin.i32(i32, i32)303declare i32 @llvm.umax.i32(i32, i32)304declare i32 @llvm.smin.i32(i32, i32)305declare i32 @llvm.smax.i32(i32, i32)306