1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM 4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM 5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM 6; 7; Test cases specifically designed for the "returned" argument attribute. 8; We use FIXME's to indicate problems and missing attributes. 9; 10 11; TEST SCC test returning an integer value argument 12; 13; int scc_r1(int a, int b, int r); 14; int scc_r2(int a, int b, int r); 15; 16; __attribute__((noinline)) int sink_r0(int r) { 17; return r; 18; } 19; 20; __attribute__((noinline)) int scc_r1(int a, int r, int b) { 21; return scc_r2(r, a, sink_r0(r)); 22; } 23; 24; __attribute__((noinline)) int scc_r2(int a, int b, int r) { 25; if (a > b) 26; return scc_r2(b, a, sink_r0(r)); 27; if (a < b) 28; return scc_r1(sink_r0(b), scc_r2(scc_r1(a, b, r), scc_r1(a, scc_r2(r, r, r), r), scc_r2(a, b, r)), scc_r1(a, b, r)); 29; return a == b ? r : scc_r2(a, b, r); 30; } 31; __attribute__((noinline)) int scc_rX(int a, int b, int r) { 32; if (a > b) 33; return scc_r2(b, a, sink_r0(r)); 34; if (a < b) // V Diff to scc_r2 35; return scc_r1(sink_r0(b), scc_r2(scc_r1(a, b, r), scc_r1(a, scc_r2(r, r, r), r), scc_r1(a, b, r)), scc_r1(a, b, r)); 36; return a == b ? r : scc_r2(a, b, r); 37; } 38target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 39 40;. 41; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = external global i8 42; CHECK: @[[_ZTI1X:[a-zA-Z0-9_$"\\.-]+]] = external dso_local constant { i8*, i8* }, align 8 43; CHECK: @[[_ZTI1Y:[a-zA-Z0-9_$"\\.-]+]] = external dso_local constant { i8*, i8*, i8* }, align 8 44;. 45define i32 @sink_r0(i32 %r) #0 { 46; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 47; CHECK-LABEL: define {{[^@]+}}@sink_r0 48; CHECK-SAME: (i32 returned [[R:%.*]]) #[[ATTR0:[0-9]+]] { 49; CHECK-NEXT: entry: 50; CHECK-NEXT: ret i32 [[R]] 51; 52entry: 53 ret i32 %r 54} 55 56define i32 @scc_r1(i32 %a, i32 %r, i32 %b) #0 { 57; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 58; IS__TUNIT____-LABEL: define {{[^@]+}}@scc_r1 59; IS__TUNIT____-SAME: (i32 [[A:%.*]], i32 returned [[R:%.*]], i32 [[B:%.*]]) #[[ATTR1:[0-9]+]] { 60; IS__TUNIT____-NEXT: entry: 61; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[A]], i32 [[R]]) #[[ATTR10:[0-9]+]] 62; IS__TUNIT____-NEXT: ret i32 [[R]] 63; 64; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 65; IS__CGSCC____-LABEL: define {{[^@]+}}@scc_r1 66; IS__CGSCC____-SAME: (i32 [[A:%.*]], i32 returned [[R:%.*]], i32 [[B:%.*]]) #[[ATTR1:[0-9]+]] { 67; IS__CGSCC____-NEXT: entry: 68; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[A]], i32 [[R]]) #[[ATTR7:[0-9]+]] 69; IS__CGSCC____-NEXT: ret i32 [[R]] 70; 71entry: 72 %call = call i32 @sink_r0(i32 %r) 73 %call1 = call i32 @scc_r2(i32 %r, i32 %a, i32 %call) 74 ret i32 %call1 75} 76 77define i32 @scc_r2(i32 %a, i32 %b, i32 %r) #0 { 78; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 79; IS__TUNIT____-LABEL: define {{[^@]+}}@scc_r2 80; IS__TUNIT____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 returned [[R:%.*]]) #[[ATTR1]] { 81; IS__TUNIT____-NEXT: entry: 82; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]] 83; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 84; IS__TUNIT____: if.then: 85; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR10]] 86; IS__TUNIT____-NEXT: br label [[RETURN:%.*]] 87; IS__TUNIT____: if.end: 88; IS__TUNIT____-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]] 89; IS__TUNIT____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] 90; IS__TUNIT____: if.then3: 91; IS__TUNIT____-NEXT: [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR10]] 92; IS__TUNIT____-NEXT: [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR10]] 93; IS__TUNIT____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 undef) #[[ATTR10]] 94; IS__TUNIT____-NEXT: [[CALL8:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR10]] 95; IS__TUNIT____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[R]]) #[[ATTR10]] 96; IS__TUNIT____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[R]], i32 undef) #[[ATTR10]] 97; IS__TUNIT____-NEXT: br label [[RETURN]] 98; IS__TUNIT____: if.end12: 99; IS__TUNIT____-NEXT: [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]] 100; IS__TUNIT____-NEXT: br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 101; IS__TUNIT____: cond.true: 102; IS__TUNIT____-NEXT: br label [[COND_END:%.*]] 103; IS__TUNIT____: cond.false: 104; IS__TUNIT____-NEXT: [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR10]] 105; IS__TUNIT____-NEXT: br label [[COND_END]] 106; IS__TUNIT____: cond.end: 107; IS__TUNIT____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] 108; IS__TUNIT____-NEXT: br label [[RETURN]] 109; IS__TUNIT____: return: 110; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] 111; IS__TUNIT____-NEXT: ret i32 [[R]] 112; 113; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 114; IS__CGSCC____-LABEL: define {{[^@]+}}@scc_r2 115; IS__CGSCC____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 returned [[R:%.*]]) #[[ATTR1]] { 116; IS__CGSCC____-NEXT: entry: 117; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]] 118; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 119; IS__CGSCC____: if.then: 120; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR7]] 121; IS__CGSCC____-NEXT: br label [[RETURN:%.*]] 122; IS__CGSCC____: if.end: 123; IS__CGSCC____-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]] 124; IS__CGSCC____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] 125; IS__CGSCC____: if.then3: 126; IS__CGSCC____-NEXT: [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR7]] 127; IS__CGSCC____-NEXT: [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR7]] 128; IS__CGSCC____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 undef) #[[ATTR7]] 129; IS__CGSCC____-NEXT: [[CALL8:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]] 130; IS__CGSCC____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[R]]) #[[ATTR7]] 131; IS__CGSCC____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[R]], i32 undef) #[[ATTR7]] 132; IS__CGSCC____-NEXT: br label [[RETURN]] 133; IS__CGSCC____: if.end12: 134; IS__CGSCC____-NEXT: [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]] 135; IS__CGSCC____-NEXT: br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 136; IS__CGSCC____: cond.true: 137; IS__CGSCC____-NEXT: br label [[COND_END:%.*]] 138; IS__CGSCC____: cond.false: 139; IS__CGSCC____-NEXT: [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]] 140; IS__CGSCC____-NEXT: br label [[COND_END]] 141; IS__CGSCC____: cond.end: 142; IS__CGSCC____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] 143; IS__CGSCC____-NEXT: br label [[RETURN]] 144; IS__CGSCC____: return: 145; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] 146; IS__CGSCC____-NEXT: ret i32 [[R]] 147; 148entry: 149 %cmp = icmp sgt i32 %a, %b 150 br i1 %cmp, label %if.then, label %if.end 151 152if.then: ; preds = %entry 153 %call = call i32 @sink_r0(i32 %r) 154 %call1 = call i32 @scc_r2(i32 %b, i32 %a, i32 %call) 155 br label %return 156 157if.end: ; preds = %entry 158 %cmp2 = icmp slt i32 %a, %b 159 br i1 %cmp2, label %if.then3, label %if.end12 160 161if.then3: ; preds = %if.end 162 %call4 = call i32 @sink_r0(i32 %b) 163 %call5 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r) 164 %call6 = call i32 @scc_r2(i32 %r, i32 %r, i32 %r) 165 %call7 = call i32 @scc_r1(i32 %a, i32 %call6, i32 %r) 166 %call8 = call i32 @scc_r2(i32 %a, i32 %b, i32 %r) 167 %call9 = call i32 @scc_r2(i32 %call5, i32 %call7, i32 %call8) 168 %call10 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r) 169 %call11 = call i32 @scc_r1(i32 %call4, i32 %call9, i32 %call10) 170 br label %return 171 172if.end12: ; preds = %if.end 173 %cmp13 = icmp eq i32 %a, %b 174 br i1 %cmp13, label %cond.true, label %cond.false 175 176cond.true: ; preds = %if.end12 177 br label %cond.end 178 179cond.false: ; preds = %if.end12 180 %call14 = call i32 @scc_r2(i32 %a, i32 %b, i32 %r) 181 br label %cond.end 182 183cond.end: ; preds = %cond.false, %cond.true 184 %cond = phi i32 [ %r, %cond.true ], [ %call14, %cond.false ] 185 br label %return 186 187return: ; preds = %cond.end, %if.then3, %if.then 188 %retval.0 = phi i32 [ %call1, %if.then ], [ %call11, %if.then3 ], [ %cond, %cond.end ] 189 ret i32 %retval.0 190} 191 192define i32 @scc_rX(i32 %a, i32 %b, i32 %r) #0 { 193; IS__TUNIT____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable 194; IS__TUNIT____-LABEL: define {{[^@]+}}@scc_rX 195; IS__TUNIT____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[R:%.*]]) #[[ATTR2:[0-9]+]] { 196; IS__TUNIT____-NEXT: entry: 197; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]] 198; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 199; IS__TUNIT____: if.then: 200; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR10]] 201; IS__TUNIT____-NEXT: br label [[RETURN:%.*]] 202; IS__TUNIT____: if.end: 203; IS__TUNIT____-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]] 204; IS__TUNIT____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] 205; IS__TUNIT____: if.then3: 206; IS__TUNIT____-NEXT: [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR10]] 207; IS__TUNIT____-NEXT: [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR10]] 208; IS__TUNIT____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 undef) #[[ATTR10]] 209; IS__TUNIT____-NEXT: [[CALL8:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR10]] 210; IS__TUNIT____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[B]]) #[[ATTR10]] 211; IS__TUNIT____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[B]], i32 undef) #[[ATTR10]] 212; IS__TUNIT____-NEXT: br label [[RETURN]] 213; IS__TUNIT____: if.end12: 214; IS__TUNIT____-NEXT: [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]] 215; IS__TUNIT____-NEXT: br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 216; IS__TUNIT____: cond.true: 217; IS__TUNIT____-NEXT: br label [[COND_END:%.*]] 218; IS__TUNIT____: cond.false: 219; IS__TUNIT____-NEXT: [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR10]] 220; IS__TUNIT____-NEXT: br label [[COND_END]] 221; IS__TUNIT____: cond.end: 222; IS__TUNIT____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] 223; IS__TUNIT____-NEXT: br label [[RETURN]] 224; IS__TUNIT____: return: 225; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[B]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] 226; IS__TUNIT____-NEXT: ret i32 [[RETVAL_0]] 227; 228; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 229; IS__CGSCC____-LABEL: define {{[^@]+}}@scc_rX 230; IS__CGSCC____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[R:%.*]]) #[[ATTR1]] { 231; IS__CGSCC____-NEXT: entry: 232; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]] 233; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 234; IS__CGSCC____: if.then: 235; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR8:[0-9]+]] 236; IS__CGSCC____-NEXT: br label [[RETURN:%.*]] 237; IS__CGSCC____: if.end: 238; IS__CGSCC____-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]] 239; IS__CGSCC____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] 240; IS__CGSCC____: if.then3: 241; IS__CGSCC____-NEXT: [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR8]] 242; IS__CGSCC____-NEXT: [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR8]] 243; IS__CGSCC____-NEXT: [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 [[R]]) #[[ATTR8]] 244; IS__CGSCC____-NEXT: [[CALL8:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR8]] 245; IS__CGSCC____-NEXT: [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[B]]) #[[ATTR8]] 246; IS__CGSCC____-NEXT: [[CALL10:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR8]] 247; IS__CGSCC____-NEXT: [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[B]], i32 [[B]]) #[[ATTR8]] 248; IS__CGSCC____-NEXT: br label [[RETURN]] 249; IS__CGSCC____: if.end12: 250; IS__CGSCC____-NEXT: [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]] 251; IS__CGSCC____-NEXT: br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 252; IS__CGSCC____: cond.true: 253; IS__CGSCC____-NEXT: br label [[COND_END:%.*]] 254; IS__CGSCC____: cond.false: 255; IS__CGSCC____-NEXT: [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR8]] 256; IS__CGSCC____-NEXT: br label [[COND_END]] 257; IS__CGSCC____: cond.end: 258; IS__CGSCC____-NEXT: [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[CALL14]], [[COND_FALSE]] ] 259; IS__CGSCC____-NEXT: br label [[RETURN]] 260; IS__CGSCC____: return: 261; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] 262; IS__CGSCC____-NEXT: ret i32 [[RETVAL_0]] 263; 264entry: 265 %cmp = icmp sgt i32 %a, %b 266 br i1 %cmp, label %if.then, label %if.end 267 268if.then: ; preds = %entry 269 %call = call i32 @sink_r0(i32 %r) 270 %call1 = call i32 @scc_r2(i32 %b, i32 %a, i32 %call) 271 br label %return 272 273if.end: ; preds = %entry 274 %cmp2 = icmp slt i32 %a, %b 275 br i1 %cmp2, label %if.then3, label %if.end12 276 277if.then3: ; preds = %if.end 278 %call4 = call i32 @sink_r0(i32 %b) 279 %call5 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r) 280 %call6 = call i32 @scc_r2(i32 %r, i32 %r, i32 %r) 281 %call7 = call i32 @scc_r1(i32 %a, i32 %call6, i32 %r) 282 %call8 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r) 283 %call9 = call i32 @scc_r2(i32 %call5, i32 %call7, i32 %call8) 284 %call10 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r) 285 %call11 = call i32 @scc_r1(i32 %call4, i32 %call9, i32 %call10) 286 br label %return 287 288if.end12: ; preds = %if.end 289 %cmp13 = icmp eq i32 %a, %b 290 br i1 %cmp13, label %cond.true, label %cond.false 291 292cond.true: ; preds = %if.end12 293 br label %cond.end 294 295cond.false: ; preds = %if.end12 296 %call14 = call i32 @scc_r2(i32 %a, i32 %b, i32 %r) 297 br label %cond.end 298 299cond.end: ; preds = %cond.false, %cond.true 300 %cond = phi i32 [ %r, %cond.true ], [ %call14, %cond.false ] 301 br label %return 302 303return: ; preds = %cond.end, %if.then3, %if.then 304 %retval.0 = phi i32 [ %call1, %if.then ], [ %call11, %if.then3 ], [ %cond, %cond.end ] 305 ret i32 %retval.0 306} 307 308 309; TEST SCC test returning a pointer value argument 310; 311; double* ptr_scc_r1(double* a, double* b, double* r); 312; double* ptr_scc_r2(double* a, double* b, double* r); 313; 314; __attribute__((noinline)) double* ptr_sink_r0(double* r) { 315; return r; 316; } 317; 318; __attribute__((noinline)) double* ptr_scc_r1(double* a, double* r, double* b) { 319; return ptr_scc_r2(r, a, ptr_sink_r0(r)); 320; } 321; 322; __attribute__((noinline)) double* ptr_scc_r2(double* a, double* b, double* r) { 323; if (a > b) 324; return ptr_scc_r2(b, a, ptr_sink_r0(r)); 325; if (a < b) 326; return ptr_scc_r1(ptr_sink_r0(b), ptr_scc_r2(ptr_scc_r1(a, b, r), ptr_scc_r1(a, ptr_scc_r2(r, r, r), r), ptr_scc_r2(a, b, r)), ptr_scc_r1(a, b, r)); 327; return a == b ? r : ptr_scc_r2(a, b, r); 328; } 329define double* @ptr_sink_r0(double* %r) #0 { 330; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 331; CHECK-LABEL: define {{[^@]+}}@ptr_sink_r0 332; CHECK-SAME: (double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR0]] { 333; CHECK-NEXT: entry: 334; CHECK-NEXT: ret double* [[R]] 335; 336entry: 337 ret double* %r 338} 339 340define double* @ptr_scc_r1(double* %a, double* %r, double* %b) #0 { 341; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 342; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr_scc_r1 343; IS__TUNIT____-SAME: (double* nocapture nofree readnone [[A:%.*]], double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]], double* nocapture nofree readnone [[B:%.*]]) #[[ATTR1]] { 344; IS__TUNIT____-NEXT: entry: 345; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[R]], double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR10]] 346; IS__TUNIT____-NEXT: ret double* [[R]] 347; 348; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 349; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_scc_r1 350; IS__CGSCC____-SAME: (double* nocapture nofree readnone [[A:%.*]], double* nofree readnone returned [[R:%.*]], double* nocapture nofree readnone [[B:%.*]]) #[[ATTR1]] { 351; IS__CGSCC____-NEXT: entry: 352; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[R]], double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone [[R]]) #[[ATTR7]] 353; IS__CGSCC____-NEXT: ret double* [[R]] 354; 355entry: 356 %call = call double* @ptr_sink_r0(double* %r) 357 %call1 = call double* @ptr_scc_r2(double* %r, double* %a, double* %call) 358 ret double* %call1 359} 360 361define double* @ptr_scc_r2(double* %a, double* %b, double* %r) #0 { 362; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 363; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr_scc_r2 364; IS__TUNIT____-SAME: (double* nocapture nofree readnone [[A:%.*]], double* nocapture nofree readnone [[B:%.*]], double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR1]] { 365; IS__TUNIT____-NEXT: entry: 366; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp ugt double* [[A]], [[B]] 367; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 368; IS__TUNIT____: if.then: 369; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[B]], double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR10]] 370; IS__TUNIT____-NEXT: br label [[RETURN:%.*]] 371; IS__TUNIT____: if.end: 372; IS__TUNIT____-NEXT: [[CMP2:%.*]] = icmp ult double* [[A]], [[B]] 373; IS__TUNIT____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] 374; IS__TUNIT____: if.then3: 375; IS__TUNIT____-NEXT: [[CALL5:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[B]], double* noalias nocapture nofree readnone undef) #[[ATTR10]] 376; IS__TUNIT____-NEXT: [[CALL6:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[R]], double* noalias nocapture nofree readnone [[R]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR10]] 377; IS__TUNIT____-NEXT: [[CALL7:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]], double* noalias nocapture nofree readnone undef) #[[ATTR10]] 378; IS__TUNIT____-NEXT: [[CALL8:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[A]], double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR10]] 379; IS__TUNIT____-NEXT: [[CALL9:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[B]], double* noalias nocapture nofree readnone [[R]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR10]] 380; IS__TUNIT____-NEXT: [[CALL11:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]], double* noalias nocapture nofree readnone undef) #[[ATTR10]] 381; IS__TUNIT____-NEXT: br label [[RETURN]] 382; IS__TUNIT____: if.end12: 383; IS__TUNIT____-NEXT: [[CMP13:%.*]] = icmp eq double* [[A]], [[B]] 384; IS__TUNIT____-NEXT: br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 385; IS__TUNIT____: cond.true: 386; IS__TUNIT____-NEXT: br label [[COND_END:%.*]] 387; IS__TUNIT____: cond.false: 388; IS__TUNIT____-NEXT: [[CALL14:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[A]], double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR10]] 389; IS__TUNIT____-NEXT: br label [[COND_END]] 390; IS__TUNIT____: cond.end: 391; IS__TUNIT____-NEXT: [[COND:%.*]] = phi double* [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] 392; IS__TUNIT____-NEXT: br label [[RETURN]] 393; IS__TUNIT____: return: 394; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi double* [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] 395; IS__TUNIT____-NEXT: ret double* [[R]] 396; 397; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 398; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_scc_r2 399; IS__CGSCC____-SAME: (double* nocapture nofree readnone [[A:%.*]], double* nocapture nofree readnone [[B:%.*]], double* nofree readnone returned [[R:%.*]]) #[[ATTR1]] { 400; IS__CGSCC____-NEXT: entry: 401; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp ugt double* [[A]], [[B]] 402; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 403; IS__CGSCC____: if.then: 404; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[B]], double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone [[R]]) #[[ATTR7]] 405; IS__CGSCC____-NEXT: br label [[RETURN:%.*]] 406; IS__CGSCC____: if.end: 407; IS__CGSCC____-NEXT: [[CMP2:%.*]] = icmp ult double* [[A]], [[B]] 408; IS__CGSCC____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]] 409; IS__CGSCC____: if.then3: 410; IS__CGSCC____-NEXT: [[CALL5:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone [[B]], double* noalias nocapture nofree readnone undef) #[[ATTR7]] 411; IS__CGSCC____-NEXT: [[CALL6:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[R]], double* noalias nocapture nofree readnone [[R]], double* noalias nofree readnone [[R]]) #[[ATTR7]] 412; IS__CGSCC____-NEXT: [[CALL7:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[A]], double* noalias nofree readnone [[R]], double* noalias nocapture nofree readnone undef) #[[ATTR7]] 413; IS__CGSCC____-NEXT: [[CALL8:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[A]], double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone [[R]]) #[[ATTR7]] 414; IS__CGSCC____-NEXT: [[CALL9:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[B]], double* noalias nocapture nofree readnone [[R]], double* noalias nofree readnone [[R]]) #[[ATTR7]] 415; IS__CGSCC____-NEXT: [[CALL11:%.*]] = call double* @ptr_scc_r1(double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone [[R]], double* noalias nocapture nofree readnone undef) #[[ATTR7]] 416; IS__CGSCC____-NEXT: br label [[RETURN]] 417; IS__CGSCC____: if.end12: 418; IS__CGSCC____-NEXT: [[CMP13:%.*]] = icmp eq double* [[A]], [[B]] 419; IS__CGSCC____-NEXT: br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] 420; IS__CGSCC____: cond.true: 421; IS__CGSCC____-NEXT: br label [[COND_END:%.*]] 422; IS__CGSCC____: cond.false: 423; IS__CGSCC____-NEXT: [[CALL14:%.*]] = call double* @ptr_scc_r2(double* noalias nocapture nofree readnone [[A]], double* noalias nocapture nofree readnone [[B]], double* noalias nofree readnone [[R]]) #[[ATTR7]] 424; IS__CGSCC____-NEXT: br label [[COND_END]] 425; IS__CGSCC____: cond.end: 426; IS__CGSCC____-NEXT: [[COND:%.*]] = phi double* [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ] 427; IS__CGSCC____-NEXT: br label [[RETURN]] 428; IS__CGSCC____: return: 429; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi double* [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] 430; IS__CGSCC____-NEXT: ret double* [[R]] 431; 432entry: 433 %cmp = icmp ugt double* %a, %b 434 br i1 %cmp, label %if.then, label %if.end 435 436if.then: ; preds = %entry 437 %call = call double* @ptr_sink_r0(double* %r) 438 %call1 = call double* @ptr_scc_r2(double* %b, double* %a, double* %call) 439 br label %return 440 441if.end: ; preds = %entry 442 %cmp2 = icmp ult double* %a, %b 443 br i1 %cmp2, label %if.then3, label %if.end12 444 445if.then3: ; preds = %if.end 446 %call4 = call double* @ptr_sink_r0(double* %b) 447 %call5 = call double* @ptr_scc_r1(double* %a, double* %b, double* %r) 448 %call6 = call double* @ptr_scc_r2(double* %r, double* %r, double* %r) 449 %call7 = call double* @ptr_scc_r1(double* %a, double* %call6, double* %r) 450 %call8 = call double* @ptr_scc_r2(double* %a, double* %b, double* %r) 451 %call9 = call double* @ptr_scc_r2(double* %call5, double* %call7, double* %call8) 452 %call10 = call double* @ptr_scc_r1(double* %a, double* %b, double* %r) 453 %call11 = call double* @ptr_scc_r1(double* %call4, double* %call9, double* %call10) 454 br label %return 455 456if.end12: ; preds = %if.end 457 %cmp13 = icmp eq double* %a, %b 458 br i1 %cmp13, label %cond.true, label %cond.false 459 460cond.true: ; preds = %if.end12 461 br label %cond.end 462 463cond.false: ; preds = %if.end12 464 %call14 = call double* @ptr_scc_r2(double* %a, double* %b, double* %r) 465 br label %cond.end 466 467cond.end: ; preds = %cond.false, %cond.true 468 %cond = phi double* [ %r, %cond.true ], [ %call14, %cond.false ] 469 br label %return 470 471return: ; preds = %cond.end, %if.then3, %if.then 472 %retval.0 = phi double* [ %call1, %if.then ], [ %call11, %if.then3 ], [ %cond, %cond.end ] 473 ret double* %retval.0 474} 475 476 477; TEST a no-return singleton SCC 478; 479; int* rt0(int *a) { 480; return *a ? a : rt0(a); 481; } 482; 483define i32* @rt0(i32* %a) #0 { 484; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable 485; IS__TUNIT____-LABEL: define {{[^@]+}}@rt0 486; IS__TUNIT____-SAME: (i32* nofree noundef nonnull readonly returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR3:[0-9]+]] { 487; IS__TUNIT____-NEXT: entry: 488; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt0(i32* nofree noundef nonnull readonly align 4 dereferenceable(4) "no-capture-maybe-returned" [[A]]) #[[ATTR11:[0-9]+]] 489; IS__TUNIT____-NEXT: ret i32* [[A]] 490; 491; IS__CGSCC____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable 492; IS__CGSCC____-LABEL: define {{[^@]+}}@rt0 493; IS__CGSCC____-SAME: (i32* nofree noundef nonnull readonly returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2:[0-9]+]] { 494; IS__CGSCC____-NEXT: entry: 495; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt0(i32* nofree noundef nonnull readonly align 4 dereferenceable(4) "no-capture-maybe-returned" [[A]]) #[[ATTR9:[0-9]+]] 496; IS__CGSCC____-NEXT: ret i32* [[A]] 497; 498entry: 499 %v = load i32, i32* %a, align 4 500 %tobool = icmp ne i32 %v, 0 501 %call = call i32* @rt0(i32* %a) 502 %sel = select i1 %tobool, i32* %a, i32* %call 503 ret i32* %sel 504} 505 506; TEST a no-return singleton SCC 507; 508; int* rt1(int *a) { 509; return *a ? undef : rt1(a); 510; } 511; 512define i32* @rt1(i32* %a) #0 { 513; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable 514; IS__TUNIT____-LABEL: define {{[^@]+}}@rt1 515; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR4:[0-9]+]] { 516; IS__TUNIT____-NEXT: entry: 517; IS__TUNIT____-NEXT: ret i32* undef 518; 519; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable 520; IS__CGSCC____-LABEL: define {{[^@]+}}@rt1 521; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR3:[0-9]+]] { 522; IS__CGSCC____-NEXT: entry: 523; IS__CGSCC____-NEXT: ret i32* undef 524; 525entry: 526 %v = load i32, i32* %a, align 4 527 %tobool = icmp ne i32 %v, 0 528 %call = call i32* @rt1(i32* %a) 529 %sel = select i1 %tobool, i32* undef, i32* %call 530 ret i32* %sel 531} 532 533; TEST another SCC test 534; 535define i32* @rt2_helper(i32* %a) #0 { 536; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 537; IS__TUNIT____-LABEL: define {{[^@]+}}@rt2_helper 538; IS__TUNIT____-SAME: (i32* nofree readnone returned [[A:%.*]]) #[[ATTR1]] { 539; IS__TUNIT____-NEXT: entry: 540; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt2(i32* noalias nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[A]]) #[[ATTR10]] 541; IS__TUNIT____-NEXT: ret i32* [[A]] 542; 543; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 544; IS__CGSCC____-LABEL: define {{[^@]+}}@rt2_helper 545; IS__CGSCC____-SAME: (i32* nofree readnone returned [[A:%.*]]) #[[ATTR1]] { 546; IS__CGSCC____-NEXT: entry: 547; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt2(i32* noalias nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[A]]) #[[ATTR7]] 548; IS__CGSCC____-NEXT: ret i32* [[A]] 549; 550entry: 551 %call = call i32* @rt2(i32* %a, i32* %a) 552 ret i32* %call 553} 554 555define i32* @rt2(i32* %a, i32 *%b) #0 { 556; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 557; IS__TUNIT____-LABEL: define {{[^@]+}}@rt2 558; IS__TUNIT____-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { 559; IS__TUNIT____-NEXT: entry: 560; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32* [[A]], null 561; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 562; IS__TUNIT____: if.then: 563; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt2_helper(i32* noalias nofree readnone [[A]]) #[[ATTR10]] 564; IS__TUNIT____-NEXT: br label [[IF_END]] 565; IS__TUNIT____: if.end: 566; IS__TUNIT____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[A]], [[IF_THEN]] ] 567; IS__TUNIT____-NEXT: ret i32* [[SEL]] 568; 569; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 570; IS__CGSCC____-LABEL: define {{[^@]+}}@rt2 571; IS__CGSCC____-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { 572; IS__CGSCC____-NEXT: entry: 573; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[A]], null 574; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 575; IS__CGSCC____: if.then: 576; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt2_helper(i32* noalias nofree readnone [[A]]) #[[ATTR7]] 577; IS__CGSCC____-NEXT: br label [[IF_END]] 578; IS__CGSCC____: if.end: 579; IS__CGSCC____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[A]], [[IF_THEN]] ] 580; IS__CGSCC____-NEXT: ret i32* [[SEL]] 581; 582entry: 583 %cmp = icmp eq i32* %a, null 584 br i1 %cmp, label %if.then, label %if.end 585 586if.then: 587 %call = call i32* @rt2_helper(i32* %a) 588 br label %if.end 589 590if.end: 591 %sel = phi i32* [ %b, %entry], [%call, %if.then] 592 ret i32* %sel 593} 594 595; TEST another SCC test 596; 597define i32* @rt3_helper(i32* %a, i32* %b) #0 { 598; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 599; IS__TUNIT____-LABEL: define {{[^@]+}}@rt3_helper 600; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { 601; IS__TUNIT____-NEXT: entry: 602; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt3(i32* noalias nocapture nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR10]] 603; IS__TUNIT____-NEXT: ret i32* [[B]] 604; 605; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 606; IS__CGSCC____-LABEL: define {{[^@]+}}@rt3_helper 607; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { 608; IS__CGSCC____-NEXT: entry: 609; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt3(i32* noalias nocapture nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR7]] 610; IS__CGSCC____-NEXT: ret i32* [[B]] 611; 612entry: 613 %call = call i32* @rt3(i32* %a, i32* %b) 614 ret i32* %call 615} 616 617define i32* @rt3(i32* %a, i32 *%b) #0 { 618; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 619; IS__TUNIT____-LABEL: define {{[^@]+}}@rt3 620; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { 621; IS__TUNIT____-NEXT: entry: 622; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32* [[A]], null 623; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 624; IS__TUNIT____: if.then: 625; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @rt3_helper(i32* noalias nocapture nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR10]] 626; IS__TUNIT____-NEXT: br label [[IF_END]] 627; IS__TUNIT____: if.end: 628; IS__TUNIT____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ] 629; IS__TUNIT____-NEXT: ret i32* [[B]] 630; 631; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 632; IS__CGSCC____-LABEL: define {{[^@]+}}@rt3 633; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] { 634; IS__CGSCC____-NEXT: entry: 635; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[A]], null 636; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 637; IS__CGSCC____: if.then: 638; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @rt3_helper(i32* noalias nocapture nofree readnone [[A]], i32* noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR7]] 639; IS__CGSCC____-NEXT: br label [[IF_END]] 640; IS__CGSCC____: if.end: 641; IS__CGSCC____-NEXT: [[SEL:%.*]] = phi i32* [ [[B]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ] 642; IS__CGSCC____-NEXT: ret i32* [[B]] 643; 644entry: 645 %cmp = icmp eq i32* %a, null 646 br i1 %cmp, label %if.then, label %if.end 647 648if.then: 649 %call = call i32* @rt3_helper(i32* %a, i32* %b) 650 br label %if.end 651 652if.end: 653 %sel = phi i32* [ %b, %entry], [%call, %if.then] 654 ret i32* %sel 655} 656 657; TEST address taken function with call to an external functions 658; 659; void unknown_fn(void *); 660; 661; int* calls_unknown_fn(int *r) { 662; unknown_fn(&calls_unknown_fn); 663; return r; 664; } 665; 666declare void @unknown_fn(i32* (i32*)*) #0 667 668define i32* @calls_unknown_fn(i32* %r) #0 { 669; IS__TUNIT____: Function Attrs: noinline nounwind uwtable 670; IS__TUNIT____-LABEL: define {{[^@]+}}@calls_unknown_fn 671; IS__TUNIT____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR5:[0-9]+]] { 672; IS__TUNIT____-NEXT: tail call void @unknown_fn(i32* (i32*)* noundef nonnull @calls_unknown_fn) #[[ATTR12:[0-9]+]] 673; IS__TUNIT____-NEXT: ret i32* [[R]] 674; 675; IS__CGSCC____: Function Attrs: noinline nounwind uwtable 676; IS__CGSCC____-LABEL: define {{[^@]+}}@calls_unknown_fn 677; IS__CGSCC____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR4:[0-9]+]] { 678; IS__CGSCC____-NEXT: tail call void @unknown_fn(i32* (i32*)* noundef nonnull @calls_unknown_fn) #[[ATTR10:[0-9]+]] 679; IS__CGSCC____-NEXT: ret i32* [[R]] 680; 681 tail call void @unknown_fn(i32* (i32*)* nonnull @calls_unknown_fn) 682 ret i32* %r 683} 684 685 686; TEST call to a function that might be redifined at link time 687; 688; int *maybe_redefined_fn(int *r) { 689; return r; 690; } 691; 692; int *calls_maybe_redefined_fn(int *r) { 693; maybe_redefined_fn(r); 694; return r; 695; } 696; 697; Verify the maybe-redefined function is not annotated: 698; 699define linkonce_odr i32* @maybe_redefined_fn(i32* %r) #0 { 700; IS__TUNIT____: Function Attrs: noinline nounwind uwtable 701; IS__TUNIT____-LABEL: define {{[^@]+}}@maybe_redefined_fn 702; IS__TUNIT____-SAME: (i32* [[R:%.*]]) #[[ATTR5]] { 703; IS__TUNIT____-NEXT: entry: 704; IS__TUNIT____-NEXT: ret i32* [[R]] 705; 706; IS__CGSCC____: Function Attrs: noinline nounwind uwtable 707; IS__CGSCC____-LABEL: define {{[^@]+}}@maybe_redefined_fn 708; IS__CGSCC____-SAME: (i32* [[R:%.*]]) #[[ATTR4]] { 709; IS__CGSCC____-NEXT: entry: 710; IS__CGSCC____-NEXT: ret i32* [[R]] 711; 712entry: 713 ret i32* %r 714} 715 716define i32* @calls_maybe_redefined_fn(i32* %r) #0 { 717; IS__TUNIT____: Function Attrs: noinline norecurse nounwind uwtable 718; IS__TUNIT____-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn 719; IS__TUNIT____-SAME: (i32* returned [[R:%.*]]) #[[ATTR6:[0-9]+]] { 720; IS__TUNIT____-NEXT: entry: 721; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @maybe_redefined_fn(i32* [[R]]) #[[ATTR12]] 722; IS__TUNIT____-NEXT: ret i32* [[R]] 723; 724; IS__CGSCC____: Function Attrs: noinline nounwind uwtable 725; IS__CGSCC____-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn 726; IS__CGSCC____-SAME: (i32* returned [[R:%.*]]) #[[ATTR4]] { 727; IS__CGSCC____-NEXT: entry: 728; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @maybe_redefined_fn(i32* [[R]]) #[[ATTR10]] 729; IS__CGSCC____-NEXT: ret i32* [[R]] 730; 731entry: 732 %call = call i32* @maybe_redefined_fn(i32* %r) 733 ret i32* %r 734} 735 736; TEST return call to a function that might be redifined at link time 737; 738; int *maybe_redefined_fn2(int *r) { 739; return r; 740; } 741; 742; int *calls_maybe_redefined_fn2(int *r) { 743; return maybe_redefined_fn2(r); 744; } 745; 746; Verify the maybe-redefined function is not annotated: 747; 748define linkonce_odr i32* @maybe_redefined_fn2(i32* %r) #0 { 749; IS__TUNIT____: Function Attrs: noinline nounwind uwtable 750; IS__TUNIT____-LABEL: define {{[^@]+}}@maybe_redefined_fn2 751; IS__TUNIT____-SAME: (i32* [[R:%.*]]) #[[ATTR5]] { 752; IS__TUNIT____-NEXT: entry: 753; IS__TUNIT____-NEXT: ret i32* [[R]] 754; 755; IS__CGSCC____: Function Attrs: noinline nounwind uwtable 756; IS__CGSCC____-LABEL: define {{[^@]+}}@maybe_redefined_fn2 757; IS__CGSCC____-SAME: (i32* [[R:%.*]]) #[[ATTR4]] { 758; IS__CGSCC____-NEXT: entry: 759; IS__CGSCC____-NEXT: ret i32* [[R]] 760; 761entry: 762 ret i32* %r 763} 764 765define i32* @calls_maybe_redefined_fn2(i32* %r) #0 { 766; IS__TUNIT____: Function Attrs: noinline norecurse nounwind uwtable 767; IS__TUNIT____-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn2 768; IS__TUNIT____-SAME: (i32* [[R:%.*]]) #[[ATTR6]] { 769; IS__TUNIT____-NEXT: entry: 770; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @maybe_redefined_fn2(i32* [[R]]) #[[ATTR12]] 771; IS__TUNIT____-NEXT: ret i32* [[CALL]] 772; 773; IS__CGSCC____: Function Attrs: noinline nounwind uwtable 774; IS__CGSCC____-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn2 775; IS__CGSCC____-SAME: (i32* [[R:%.*]]) #[[ATTR4]] { 776; IS__CGSCC____-NEXT: entry: 777; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @maybe_redefined_fn2(i32* [[R]]) #[[ATTR10]] 778; IS__CGSCC____-NEXT: ret i32* [[CALL]] 779; 780entry: 781 %call = call i32* @maybe_redefined_fn2(i32* %r) 782 ret i32* %call 783} 784 785 786; TEST returned argument goes through select and phi 787; 788; double select_and_phi(double b) { 789; double x = b; 790; if (b > 0) 791; x = b; 792; return b == 0? b : x; 793; } 794; 795define double @select_and_phi(double %b) #0 { 796; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 797; CHECK-LABEL: define {{[^@]+}}@select_and_phi 798; CHECK-SAME: (double returned [[B:%.*]]) #[[ATTR0]] { 799; CHECK-NEXT: entry: 800; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[B]], 0.000000e+00 801; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 802; CHECK: if.then: 803; CHECK-NEXT: br label [[IF_END]] 804; CHECK: if.end: 805; CHECK-NEXT: ret double [[B]] 806; 807entry: 808 %cmp = fcmp ogt double %b, 0.000000e+00 809 br i1 %cmp, label %if.then, label %if.end 810 811if.then: ; preds = %entry 812 br label %if.end 813 814if.end: ; preds = %if.then, %entry 815 %phi = phi double [ %b, %if.then ], [ %b, %entry ] 816 %cmp1 = fcmp oeq double %b, 0.000000e+00 817 %sel = select i1 %cmp1, double %b, double %phi 818 ret double %sel 819} 820 821 822; TEST returned argument goes through recursion, select, and phi 823; 824; double recursion_select_and_phi(int a, double b) { 825; double x = b; 826; if (a-- > 0) 827; x = recursion_select_and_phi(a, b); 828; return b == 0? b : x; 829; } 830; 831define double @recursion_select_and_phi(i32 %a, double %b) #0 { 832; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 833; IS__TUNIT____-LABEL: define {{[^@]+}}@recursion_select_and_phi 834; IS__TUNIT____-SAME: (i32 [[A:%.*]], double returned [[B:%.*]]) #[[ATTR1]] { 835; IS__TUNIT____-NEXT: entry: 836; IS__TUNIT____-NEXT: [[DEC:%.*]] = add nsw i32 [[A]], -1 837; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 0 838; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 839; IS__TUNIT____: if.then: 840; IS__TUNIT____-NEXT: [[CALL:%.*]] = call double @recursion_select_and_phi(i32 [[DEC]], double [[B]]) #[[ATTR10]] 841; IS__TUNIT____-NEXT: br label [[IF_END]] 842; IS__TUNIT____: if.end: 843; IS__TUNIT____-NEXT: ret double [[B]] 844; 845; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable 846; IS__CGSCC____-LABEL: define {{[^@]+}}@recursion_select_and_phi 847; IS__CGSCC____-SAME: (i32 [[A:%.*]], double returned [[B:%.*]]) #[[ATTR1]] { 848; IS__CGSCC____-NEXT: entry: 849; IS__CGSCC____-NEXT: [[DEC:%.*]] = add nsw i32 [[A]], -1 850; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 0 851; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 852; IS__CGSCC____: if.then: 853; IS__CGSCC____-NEXT: [[CALL:%.*]] = call double @recursion_select_and_phi(i32 [[DEC]], double [[B]]) #[[ATTR7]] 854; IS__CGSCC____-NEXT: br label [[IF_END]] 855; IS__CGSCC____: if.end: 856; IS__CGSCC____-NEXT: ret double [[B]] 857; 858entry: 859 %dec = add nsw i32 %a, -1 860 %cmp = icmp sgt i32 %a, 0 861 br i1 %cmp, label %if.then, label %if.end 862 863if.then: ; preds = %entry 864 %call = call double @recursion_select_and_phi(i32 %dec, double %b) 865 br label %if.end 866 867if.end: ; preds = %if.then, %entry 868 %phi = phi double [ %call, %if.then ], [ %b, %entry ] 869 %cmp1 = fcmp oeq double %b, 0.000000e+00 870 %sel = select i1 %cmp1, double %b, double %phi 871 ret double %sel 872} 873 874 875; TEST returned argument goes through bitcasts 876; 877; double* bitcast(int* b) { 878; return (double*)b; 879; } 880; 881define double* @bitcast(i32* %b) #0 { 882; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 883; CHECK-LABEL: define {{[^@]+}}@bitcast 884; CHECK-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR0]] { 885; CHECK-NEXT: entry: 886; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* 887; CHECK-NEXT: ret double* [[BC0]] 888; 889entry: 890 %bc0 = bitcast i32* %b to double* 891 ret double* %bc0 892} 893 894 895; TEST returned argument goes through select and phi interleaved with bitcasts 896; 897; double* bitcasts_select_and_phi(int* b) { 898; double* x = b; 899; if (b == 0) 900; x = b; 901; return b != 0 ? b : x; 902; } 903; 904define double* @bitcasts_select_and_phi(i32* %b) #0 { 905; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 906; CHECK-LABEL: define {{[^@]+}}@bitcasts_select_and_phi 907; CHECK-SAME: (i32* nofree readnone [[B:%.*]]) #[[ATTR0]] { 908; CHECK-NEXT: entry: 909; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* 910; CHECK-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null 911; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 912; CHECK: if.then: 913; CHECK-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* 914; CHECK-NEXT: br label [[IF_END]] 915; CHECK: if.end: 916; CHECK-NEXT: [[PHI:%.*]] = phi double* [ [[BC1]], [[IF_THEN]] ], [ [[BC0]], [[ENTRY:%.*]] ] 917; CHECK-NEXT: [[BC2:%.*]] = bitcast double* [[PHI]] to i8* 918; CHECK-NEXT: [[BC3:%.*]] = bitcast i32* [[B]] to i8* 919; CHECK-NEXT: [[CMP2:%.*]] = icmp ne double* [[BC0]], null 920; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP2]], i8* [[BC2]], i8* [[BC3]] 921; CHECK-NEXT: [[BC4:%.*]] = bitcast i8* [[SEL]] to double* 922; CHECK-NEXT: ret double* [[BC4]] 923; 924entry: 925 %bc0 = bitcast i32* %b to double* 926 %cmp = icmp eq double* %bc0, null 927 br i1 %cmp, label %if.then, label %if.end 928 929if.then: ; preds = %entry 930 %bc1 = bitcast i32* %b to double* 931 br label %if.end 932 933if.end: ; preds = %if.then, %entry 934 %phi = phi double* [ %bc1, %if.then ], [ %bc0, %entry ] 935 %bc2 = bitcast double* %phi to i8* 936 %bc3 = bitcast i32* %b to i8* 937 %cmp2 = icmp ne double* %bc0, null 938 %sel = select i1 %cmp2, i8* %bc2, i8* %bc3 939 %bc4 = bitcast i8* %sel to double* 940 ret double* %bc4 941} 942 943 944; TEST return argument or argument or undef 945; 946; double* ret_arg_arg_undef(int* b) { 947; if (b == 0) 948; return (double*)b; 949; if (b == 0) 950; return (double*)b; 951; /* return undef */ 952; } 953; 954define double* @ret_arg_arg_undef(i32* %b) #0 { 955; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 956; CHECK-LABEL: define {{[^@]+}}@ret_arg_arg_undef 957; CHECK-SAME: (i32* nofree readnone [[B:%.*]]) #[[ATTR0]] { 958; CHECK-NEXT: entry: 959; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* 960; CHECK-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null 961; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[IF_END:%.*]] 962; CHECK: ret_arg0: 963; CHECK-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* 964; CHECK-NEXT: ret double* [[BC1]] 965; CHECK: if.end: 966; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG1:%.*]], label [[RET_UNDEF:%.*]] 967; CHECK: ret_arg1: 968; CHECK-NEXT: ret double* [[BC0]] 969; CHECK: ret_undef: 970; CHECK-NEXT: ret double* undef 971; 972entry: 973 %bc0 = bitcast i32* %b to double* 974 %cmp = icmp eq double* %bc0, null 975 br i1 %cmp, label %ret_arg0, label %if.end 976 977ret_arg0: 978 %bc1 = bitcast i32* %b to double* 979 ret double* %bc1 980 981if.end: 982 br i1 %cmp, label %ret_arg1, label %ret_undef 983 984ret_arg1: 985 ret double* %bc0 986 987ret_undef: 988 ret double *undef 989} 990 991 992; TEST return undef or argument or argument 993; 994; double* ret_undef_arg_arg(int* b) { 995; if (b == 0) 996; return (double*)b; 997; if (b == 0) 998; return (double*)b; 999; /* return undef */ 1000; } 1001; 1002define double* @ret_undef_arg_arg(i32* %b) #0 { 1003; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 1004; CHECK-LABEL: define {{[^@]+}}@ret_undef_arg_arg 1005; CHECK-SAME: (i32* nofree readnone [[B:%.*]]) #[[ATTR0]] { 1006; CHECK-NEXT: entry: 1007; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* 1008; CHECK-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null 1009; CHECK-NEXT: br i1 [[CMP]], label [[RET_UNDEF:%.*]], label [[IF_END:%.*]] 1010; CHECK: ret_undef: 1011; CHECK-NEXT: ret double* undef 1012; CHECK: if.end: 1013; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[RET_ARG1:%.*]] 1014; CHECK: ret_arg0: 1015; CHECK-NEXT: ret double* [[BC0]] 1016; CHECK: ret_arg1: 1017; CHECK-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* 1018; CHECK-NEXT: ret double* [[BC1]] 1019; 1020entry: 1021 %bc0 = bitcast i32* %b to double* 1022 %cmp = icmp eq double* %bc0, null 1023 br i1 %cmp, label %ret_undef, label %if.end 1024 1025ret_undef: 1026 ret double *undef 1027 1028if.end: 1029 br i1 %cmp, label %ret_arg0, label %ret_arg1 1030 1031ret_arg0: 1032 ret double* %bc0 1033 1034ret_arg1: 1035 %bc1 = bitcast i32* %b to double* 1036 ret double* %bc1 1037} 1038 1039 1040; TEST return undef or argument or undef 1041; 1042; double* ret_undef_arg_undef(int* b) { 1043; if (b == 0) 1044; /* return undef */ 1045; if (b == 0) 1046; return (double*)b; 1047; /* return undef */ 1048; } 1049; 1050define double* @ret_undef_arg_undef(i32* %b) #0 { 1051; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 1052; CHECK-LABEL: define {{[^@]+}}@ret_undef_arg_undef 1053; CHECK-SAME: (i32* nofree readnone [[B:%.*]]) #[[ATTR0]] { 1054; CHECK-NEXT: entry: 1055; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* 1056; CHECK-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null 1057; CHECK-NEXT: br i1 [[CMP]], label [[RET_UNDEF0:%.*]], label [[IF_END:%.*]] 1058; CHECK: ret_undef0: 1059; CHECK-NEXT: ret double* undef 1060; CHECK: if.end: 1061; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNDEF1:%.*]] 1062; CHECK: ret_arg: 1063; CHECK-NEXT: ret double* [[BC0]] 1064; CHECK: ret_undef1: 1065; CHECK-NEXT: ret double* undef 1066; 1067entry: 1068 %bc0 = bitcast i32* %b to double* 1069 %cmp = icmp eq double* %bc0, null 1070 br i1 %cmp, label %ret_undef0, label %if.end 1071 1072ret_undef0: 1073 ret double *undef 1074 1075if.end: 1076 br i1 %cmp, label %ret_arg, label %ret_undef1 1077 1078ret_arg: 1079 ret double* %bc0 1080 1081ret_undef1: 1082 ret double *undef 1083} 1084 1085; TEST return argument or unknown call result 1086; 1087; int* ret_arg_or_unknown(int* b) { 1088; if (b == 0) 1089; return b; 1090; return unknown(); 1091; } 1092; 1093; Verify we do not assume b is returned 1094; 1095declare i32* @unknown(i32*) 1096 1097define i32* @ret_arg_or_unknown(i32* %b) #0 { 1098; IS__TUNIT____: Function Attrs: noinline nounwind uwtable 1099; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_arg_or_unknown 1100; IS__TUNIT____-SAME: (i32* [[B:%.*]]) #[[ATTR5]] { 1101; IS__TUNIT____-NEXT: entry: 1102; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null 1103; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] 1104; IS__TUNIT____: ret_arg: 1105; IS__TUNIT____-NEXT: ret i32* [[B]] 1106; IS__TUNIT____: ret_unknown: 1107; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) 1108; IS__TUNIT____-NEXT: ret i32* [[CALL]] 1109; 1110; IS__CGSCC____: Function Attrs: noinline nounwind uwtable 1111; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_arg_or_unknown 1112; IS__CGSCC____-SAME: (i32* [[B:%.*]]) #[[ATTR4]] { 1113; IS__CGSCC____-NEXT: entry: 1114; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null 1115; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] 1116; IS__CGSCC____: ret_arg: 1117; IS__CGSCC____-NEXT: ret i32* [[B]] 1118; IS__CGSCC____: ret_unknown: 1119; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) 1120; IS__CGSCC____-NEXT: ret i32* [[CALL]] 1121; 1122entry: 1123 %cmp = icmp eq i32* %b, null 1124 br i1 %cmp, label %ret_arg, label %ret_unknown 1125 1126ret_arg: 1127 ret i32* %b 1128 1129ret_unknown: 1130 %call = call i32* @unknown(i32* %b) 1131 ret i32* %call 1132} 1133 1134define i32* @ret_arg_or_unknown_through_phi(i32* %b) #0 { 1135; IS__TUNIT____: Function Attrs: noinline nounwind uwtable 1136; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_arg_or_unknown_through_phi 1137; IS__TUNIT____-SAME: (i32* [[B:%.*]]) #[[ATTR5]] { 1138; IS__TUNIT____-NEXT: entry: 1139; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null 1140; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] 1141; IS__TUNIT____: ret_arg: 1142; IS__TUNIT____-NEXT: br label [[R:%.*]] 1143; IS__TUNIT____: ret_unknown: 1144; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) 1145; IS__TUNIT____-NEXT: br label [[R]] 1146; IS__TUNIT____: r: 1147; IS__TUNIT____-NEXT: [[PHI:%.*]] = phi i32* [ [[B]], [[RET_ARG]] ], [ [[CALL]], [[RET_UNKNOWN]] ] 1148; IS__TUNIT____-NEXT: ret i32* [[PHI]] 1149; 1150; IS__CGSCC____: Function Attrs: noinline nounwind uwtable 1151; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_arg_or_unknown_through_phi 1152; IS__CGSCC____-SAME: (i32* [[B:%.*]]) #[[ATTR4]] { 1153; IS__CGSCC____-NEXT: entry: 1154; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null 1155; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] 1156; IS__CGSCC____: ret_arg: 1157; IS__CGSCC____-NEXT: br label [[R:%.*]] 1158; IS__CGSCC____: ret_unknown: 1159; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @unknown(i32* [[B]]) 1160; IS__CGSCC____-NEXT: br label [[R]] 1161; IS__CGSCC____: r: 1162; IS__CGSCC____-NEXT: [[PHI:%.*]] = phi i32* [ [[B]], [[RET_ARG]] ], [ [[CALL]], [[RET_UNKNOWN]] ] 1163; IS__CGSCC____-NEXT: ret i32* [[PHI]] 1164; 1165entry: 1166 %cmp = icmp eq i32* %b, null 1167 br i1 %cmp, label %ret_arg, label %ret_unknown 1168 1169ret_arg: 1170 br label %r 1171 1172ret_unknown: 1173 %call = call i32* @unknown(i32* %b) 1174 br label %r 1175 1176r: 1177 %phi = phi i32* [ %b, %ret_arg ], [ %call, %ret_unknown ] 1178 ret i32* %phi 1179} 1180 1181; TEST inconsistent IR in dead code. 1182; 1183define i32 @deadblockcall1(i32 %A) #0 { 1184; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 1185; CHECK-LABEL: define {{[^@]+}}@deadblockcall1 1186; CHECK-SAME: (i32 returned [[A:%.*]]) #[[ATTR0]] { 1187; CHECK-NEXT: entry: 1188; CHECK-NEXT: ret i32 [[A]] 1189; CHECK: unreachableblock: 1190; CHECK-NEXT: unreachable 1191; 1192entry: 1193 ret i32 %A 1194unreachableblock: 1195 %B = call i32 @deadblockcall1(i32 %B) 1196 ret i32 %B 1197} 1198 1199declare i32 @deadblockcall_helper(i32 returned %A); 1200 1201define i32 @deadblockcall2(i32 %A) #0 { 1202; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 1203; CHECK-LABEL: define {{[^@]+}}@deadblockcall2 1204; CHECK-SAME: (i32 returned [[A:%.*]]) #[[ATTR0]] { 1205; CHECK-NEXT: entry: 1206; CHECK-NEXT: ret i32 [[A]] 1207; CHECK: unreachableblock1: 1208; CHECK-NEXT: unreachable 1209; CHECK: unreachableblock2: 1210; CHECK-NEXT: unreachable 1211; 1212entry: 1213 ret i32 %A 1214unreachableblock1: 1215 %B = call i32 @deadblockcall_helper(i32 %B) 1216 ret i32 %B 1217unreachableblock2: 1218 %C = call i32 @deadblockcall1(i32 %C) 1219 ret i32 %C 1220} 1221 1222define i32 @deadblockphi1(i32 %A) #0 { 1223; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 1224; CHECK-LABEL: define {{[^@]+}}@deadblockphi1 1225; CHECK-SAME: (i32 returned [[A:%.*]]) #[[ATTR0]] { 1226; CHECK-NEXT: entry: 1227; CHECK-NEXT: br label [[R:%.*]] 1228; CHECK: unreachableblock1: 1229; CHECK-NEXT: unreachable 1230; CHECK: unreachableblock2: 1231; CHECK-NEXT: unreachable 1232; CHECK: r: 1233; CHECK-NEXT: ret i32 [[A]] 1234; 1235entry: 1236 br label %r 1237unreachableblock1: 1238 %B = call i32 @deadblockcall_helper(i32 %B) 1239 ret i32 %B 1240unreachableblock2: 1241 %C = call i32 @deadblockcall1(i32 %C) 1242 br label %r 1243r: 1244 %PHI = phi i32 [%A, %entry], [%C, %unreachableblock2] 1245 ret i32 %PHI 1246} 1247 1248define i32 @deadblockphi2(i32 %A) #0 { 1249; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 1250; CHECK-LABEL: define {{[^@]+}}@deadblockphi2 1251; CHECK-SAME: (i32 returned [[A:%.*]]) #[[ATTR0]] { 1252; CHECK-NEXT: entry: 1253; CHECK-NEXT: br label [[R:%.*]] 1254; CHECK: unreachableblock1: 1255; CHECK-NEXT: unreachable 1256; CHECK: unreachableblock2: 1257; CHECK-NEXT: unreachable 1258; CHECK: unreachableblock3: 1259; CHECK-NEXT: unreachable 1260; CHECK: r: 1261; CHECK-NEXT: ret i32 [[A]] 1262; 1263entry: 1264 br label %r 1265unreachableblock1: 1266 %B = call i32 @deadblockcall_helper(i32 %B) 1267 br label %unreachableblock3 1268unreachableblock2: 1269 %C = call i32 @deadblockcall1(i32 %C) 1270 br label %unreachableblock3 1271unreachableblock3: 1272 %PHI1 = phi i32 [%B, %unreachableblock1], [%C, %unreachableblock2] 1273 br label %r 1274r: 1275 %PHI2 = phi i32 [%A, %entry], [%PHI1, %unreachableblock3] 1276 ret i32 %PHI2 1277} 1278 1279declare void @noreturn() noreturn; 1280 1281define i32 @deadblockphi3(i32 %A, i1 %c) #0 { 1282; IS__TUNIT____: Function Attrs: noinline nounwind uwtable 1283; IS__TUNIT____-LABEL: define {{[^@]+}}@deadblockphi3 1284; IS__TUNIT____-SAME: (i32 returned [[A:%.*]], i1 [[C:%.*]]) #[[ATTR5]] { 1285; IS__TUNIT____-NEXT: entry: 1286; IS__TUNIT____-NEXT: br i1 [[C]], label [[R:%.*]], label [[UNREACHABLECALL:%.*]] 1287; IS__TUNIT____: unreachablecall: 1288; IS__TUNIT____-NEXT: call void @noreturn() #[[ATTR7:[0-9]+]] 1289; IS__TUNIT____-NEXT: unreachable 1290; IS__TUNIT____: unreachableblock2: 1291; IS__TUNIT____-NEXT: unreachable 1292; IS__TUNIT____: unreachableblock3: 1293; IS__TUNIT____-NEXT: unreachable 1294; IS__TUNIT____: r: 1295; IS__TUNIT____-NEXT: ret i32 [[A]] 1296; 1297; IS__CGSCC____: Function Attrs: noinline nounwind uwtable 1298; IS__CGSCC____-LABEL: define {{[^@]+}}@deadblockphi3 1299; IS__CGSCC____-SAME: (i32 returned [[A:%.*]], i1 [[C:%.*]]) #[[ATTR4]] { 1300; IS__CGSCC____-NEXT: entry: 1301; IS__CGSCC____-NEXT: br i1 [[C]], label [[R:%.*]], label [[UNREACHABLECALL:%.*]] 1302; IS__CGSCC____: unreachablecall: 1303; IS__CGSCC____-NEXT: call void @noreturn() #[[ATTR5:[0-9]+]] 1304; IS__CGSCC____-NEXT: unreachable 1305; IS__CGSCC____: unreachableblock2: 1306; IS__CGSCC____-NEXT: unreachable 1307; IS__CGSCC____: unreachableblock3: 1308; IS__CGSCC____-NEXT: unreachable 1309; IS__CGSCC____: r: 1310; IS__CGSCC____-NEXT: ret i32 [[A]] 1311; 1312entry: 1313 br i1 %c, label %r, label %unreachablecall 1314unreachablecall: 1315 call void @noreturn(); 1316 %B = call i32 @deadblockcall_helper(i32 0) 1317 br label %unreachableblock3 1318unreachableblock2: 1319 %C = call i32 @deadblockcall1(i32 %C) 1320 br label %unreachableblock3 1321unreachableblock3: 1322 %PHI1 = phi i32 [%B, %unreachablecall], [%C, %unreachableblock2] 1323 br label %r 1324r: 1325 %PHI2 = phi i32 [%A, %entry], [%PHI1, %unreachableblock3] 1326 ret i32 %PHI2 1327} 1328 1329define weak_odr i32 @non_exact_0() { 1330; CHECK-LABEL: define {{[^@]+}}@non_exact_0() { 1331; CHECK-NEXT: ret i32 0 1332; 1333 ret i32 0 1334} 1335define weak_odr i32 @non_exact_1(i32 %a) { 1336; CHECK-LABEL: define {{[^@]+}}@non_exact_1 1337; CHECK-SAME: (i32 [[A:%.*]]) { 1338; CHECK-NEXT: ret i32 [[A]] 1339; 1340 ret i32 %a 1341} 1342define weak_odr i32 @non_exact_2(i32 returned %a) { 1343; CHECK-LABEL: define {{[^@]+}}@non_exact_2 1344; CHECK-SAME: (i32 returned [[A:%.*]]) { 1345; CHECK-NEXT: ret i32 [[A]] 1346; 1347 ret i32 %a 1348} 1349define weak_odr align 16 i32* @non_exact_3(i32* align 32 returned %a) { 1350; CHECK-LABEL: define {{[^@]+}}@non_exact_3 1351; CHECK-SAME: (i32* returned align 32 [[A:%.*]]) { 1352; CHECK-NEXT: ret i32* [[A]] 1353; 1354 ret i32* %a 1355} 1356define weak_odr align 16 i32* @non_exact_4(i32* align 32 %a) { 1357; CHECK-LABEL: define {{[^@]+}}@non_exact_4 1358; CHECK-SAME: (i32* align 32 [[A:%.*]]) { 1359; CHECK-NEXT: ret i32* [[A]] 1360; 1361 ret i32* %a 1362} 1363; We can use the alignment information of the weak function non_exact_3 argument 1364; because it was given to us and not derived. 1365; We can use the return information of the weak function non_exact_4. 1366; FIXME: %c2 and %c3 should be replaced but not %c0 or %c1! 1367define i32 @exact(i32* align 8 %a, i32* align 8 %b) { 1368; IS__TUNIT____: Function Attrs: norecurse 1369; IS__TUNIT____-LABEL: define {{[^@]+}}@exact 1370; IS__TUNIT____-SAME: (i32* align 8 [[A:%.*]], i32* align 8 [[B:%.*]]) #[[ATTR8:[0-9]+]] { 1371; IS__TUNIT____-NEXT: [[C0:%.*]] = call i32 @non_exact_0() 1372; IS__TUNIT____-NEXT: [[C1:%.*]] = call i32 @non_exact_1(i32 noundef 1) 1373; IS__TUNIT____-NEXT: [[C2:%.*]] = call i32 @non_exact_2(i32 noundef 2) 1374; IS__TUNIT____-NEXT: [[C3:%.*]] = call align 32 i32* @non_exact_3(i32* align 32 [[A]]) 1375; IS__TUNIT____-NEXT: [[C4:%.*]] = call align 16 i32* @non_exact_4(i32* align 32 [[B]]) 1376; IS__TUNIT____-NEXT: [[C3L:%.*]] = load i32, i32* [[A]], align 32 1377; IS__TUNIT____-NEXT: [[C4L:%.*]] = load i32, i32* [[C4]], align 16 1378; IS__TUNIT____-NEXT: [[ADD1:%.*]] = add i32 [[C0]], [[C1]] 1379; IS__TUNIT____-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], 2 1380; IS__TUNIT____-NEXT: [[ADD3:%.*]] = add i32 [[ADD2]], [[C3L]] 1381; IS__TUNIT____-NEXT: [[ADD4:%.*]] = add i32 [[ADD3]], [[C4L]] 1382; IS__TUNIT____-NEXT: ret i32 [[ADD4]] 1383; 1384; IS__CGSCC____-LABEL: define {{[^@]+}}@exact 1385; IS__CGSCC____-SAME: (i32* align 8 [[A:%.*]], i32* align 8 [[B:%.*]]) { 1386; IS__CGSCC____-NEXT: [[C0:%.*]] = call i32 @non_exact_0() 1387; IS__CGSCC____-NEXT: [[C1:%.*]] = call i32 @non_exact_1(i32 noundef 1) 1388; IS__CGSCC____-NEXT: [[C2:%.*]] = call i32 @non_exact_2(i32 noundef 2) 1389; IS__CGSCC____-NEXT: [[C3:%.*]] = call align 32 i32* @non_exact_3(i32* align 32 [[A]]) 1390; IS__CGSCC____-NEXT: [[C4:%.*]] = call align 16 i32* @non_exact_4(i32* align 32 [[B]]) 1391; IS__CGSCC____-NEXT: [[C3L:%.*]] = load i32, i32* [[C3]], align 32 1392; IS__CGSCC____-NEXT: [[C4L:%.*]] = load i32, i32* [[C4]], align 16 1393; IS__CGSCC____-NEXT: [[ADD1:%.*]] = add i32 [[C0]], [[C1]] 1394; IS__CGSCC____-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], [[C2]] 1395; IS__CGSCC____-NEXT: [[ADD3:%.*]] = add i32 [[ADD2]], [[C3L]] 1396; IS__CGSCC____-NEXT: [[ADD4:%.*]] = add i32 [[ADD3]], [[C4L]] 1397; IS__CGSCC____-NEXT: ret i32 [[ADD4]] 1398; 1399 %c0 = call i32 @non_exact_0() 1400 %c1 = call i32 @non_exact_1(i32 1) 1401 %c2 = call i32 @non_exact_2(i32 2) 1402 %c3 = call i32* @non_exact_3(i32* %a) 1403 %c4 = call i32* @non_exact_4(i32* %b) 1404 %c3l = load i32, i32* %c3 1405 %c4l = load i32, i32* %c4 1406 %add1 = add i32 %c0, %c1 1407 %add2 = add i32 %add1, %c2 1408 %add3 = add i32 %add2, %c3l 1409 %add4 = add i32 %add3, %c4l 1410 ret i32 %add4 1411} 1412 1413@G = external global i8 1414define i32* @ret_const() #0 { 1415; CHECK: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 1416; CHECK-LABEL: define {{[^@]+}}@ret_const 1417; CHECK-SAME: () #[[ATTR0]] { 1418; CHECK-NEXT: ret i32* bitcast (i8* @G to i32*) 1419; 1420 %bc = bitcast i8* @G to i32* 1421 ret i32* %bc 1422} 1423define i32* @use_const() #0 { 1424; IS__TUNIT____: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 1425; IS__TUNIT____-LABEL: define {{[^@]+}}@use_const 1426; IS__TUNIT____-SAME: () #[[ATTR0]] { 1427; IS__TUNIT____-NEXT: ret i32* bitcast (i8* @G to i32*) 1428; 1429; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable 1430; IS__CGSCC____-LABEL: define {{[^@]+}}@use_const 1431; IS__CGSCC____-SAME: () #[[ATTR3]] { 1432; IS__CGSCC____-NEXT: [[C:%.*]] = call noundef nonnull dereferenceable(1) i32* @ret_const() #[[ATTR11:[0-9]+]] 1433; IS__CGSCC____-NEXT: ret i32* [[C]] 1434; 1435 %c = call i32* @ret_const() 1436 ret i32* %c 1437} 1438define i32* @dont_use_const() #0 { 1439; IS__TUNIT____: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable 1440; IS__TUNIT____-LABEL: define {{[^@]+}}@dont_use_const 1441; IS__TUNIT____-SAME: () #[[ATTR0]] { 1442; IS__TUNIT____-NEXT: ret i32* bitcast (i8* @G to i32*) 1443; 1444; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone willreturn uwtable 1445; IS__CGSCC____-LABEL: define {{[^@]+}}@dont_use_const 1446; IS__CGSCC____-SAME: () #[[ATTR3]] { 1447; IS__CGSCC____-NEXT: [[C:%.*]] = musttail call noundef nonnull dereferenceable(1) i32* @ret_const() #[[ATTR11]] 1448; IS__CGSCC____-NEXT: ret i32* [[C]] 1449; 1450 %c = musttail call i32* @ret_const() 1451 ret i32* %c 1452} 1453 1454; UTC_ARGS: --disable 1455; 1456; Verify we do not derive constraints for @_Z3fooP1X as if it was returning `null`. 1457; 1458; CHEKC-NOT: noalias 1459; CHECK-NOT: align 536870912 1460 1461%struct.Y = type { %struct.X } 1462%struct.X = type { i32 (...)** } 1463 1464@_ZTI1X = external dso_local constant { i8*, i8* }, align 8 1465@_ZTI1Y = external dso_local constant { i8*, i8*, i8* }, align 8 1466 1467define internal i8* @_ZN1Y3barEv(%struct.Y* %this) align 2 { 1468entry: 1469 %0 = bitcast %struct.Y* %this to i8* 1470 ret i8* %0 1471} 1472 1473define dso_local i8* @_Z3fooP1X(%struct.X* %x) { 1474entry: 1475 %0 = icmp eq %struct.X* %x, null 1476 br i1 %0, label %dynamic_cast.null, label %dynamic_cast.notnull 1477 1478dynamic_cast.notnull: ; preds = %entry 1479 %1 = bitcast %struct.X* %x to i8* 1480 %2 = call i8* @__dynamic_cast(i8* %1, i8* bitcast ({ i8*, i8* }* @_ZTI1X to i8*), i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1Y to i8*), i64 0) #2 1481 %3 = bitcast i8* %2 to %struct.Y* 1482 br label %dynamic_cast.end 1483 1484dynamic_cast.null: ; preds = %entry 1485 br label %dynamic_cast.end 1486 1487dynamic_cast.end: ; preds = %dynamic_cast.null, %dynamic_cast.notnull 1488 %QQ5 = phi %struct.Y* [ %3, %dynamic_cast.notnull ], [ null, %dynamic_cast.null ] 1489 %call = call i8* @_ZN1Y3barEv(%struct.Y* %QQ5) 1490 ret i8* %call 1491} 1492 1493declare dso_local i8* @__dynamic_cast(i8*, i8*, i8*, i64) 1494 1495; UTC_ARGS: --enable 1496 1497attributes #0 = { noinline nounwind uwtable } 1498;. 1499; IS__TUNIT____: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable } 1500; IS__TUNIT____: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable } 1501; IS__TUNIT____: attributes #[[ATTR2]] = { nofree noinline norecurse nosync nounwind readnone uwtable } 1502; IS__TUNIT____: attributes #[[ATTR3]] = { argmemonly nofree noinline nosync nounwind readonly uwtable } 1503; IS__TUNIT____: attributes #[[ATTR4]] = { nofree noinline nosync nounwind readnone willreturn uwtable } 1504; IS__TUNIT____: attributes #[[ATTR5]] = { noinline nounwind uwtable } 1505; IS__TUNIT____: attributes #[[ATTR6]] = { noinline norecurse nounwind uwtable } 1506; IS__TUNIT____: attributes #[[ATTR7]] = { noreturn } 1507; IS__TUNIT____: attributes #[[ATTR8]] = { norecurse } 1508; IS__TUNIT____: attributes #[[ATTR9:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn } 1509; IS__TUNIT____: attributes #[[ATTR10]] = { nofree nosync nounwind readnone } 1510; IS__TUNIT____: attributes #[[ATTR11]] = { nofree nosync nounwind readonly } 1511; IS__TUNIT____: attributes #[[ATTR12]] = { nounwind } 1512; IS__TUNIT____: attributes #[[ATTR13:[0-9]+]] = { nounwind readnone } 1513;. 1514; IS__CGSCC____: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable } 1515; IS__CGSCC____: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone uwtable } 1516; IS__CGSCC____: attributes #[[ATTR2]] = { argmemonly nofree noinline nosync nounwind readonly uwtable } 1517; IS__CGSCC____: attributes #[[ATTR3]] = { nofree noinline nosync nounwind readnone willreturn uwtable } 1518; IS__CGSCC____: attributes #[[ATTR4]] = { noinline nounwind uwtable } 1519; IS__CGSCC____: attributes #[[ATTR5]] = { noreturn } 1520; IS__CGSCC____: attributes #[[ATTR6:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn } 1521; IS__CGSCC____: attributes #[[ATTR7]] = { nofree nosync nounwind readnone } 1522; IS__CGSCC____: attributes #[[ATTR8]] = { nounwind readnone } 1523; IS__CGSCC____: attributes #[[ATTR9]] = { nofree nosync nounwind readonly } 1524; IS__CGSCC____: attributes #[[ATTR10]] = { nounwind } 1525; IS__CGSCC____: attributes #[[ATTR11]] = { readnone willreturn } 1526;. 1527