1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes 2; RUN: opt -attributor --attributor-disable=false -attributor-annotate-decl-cs -S < %s | FileCheck %s 3; TODO: Add max-iteration check 4 5; Disable update test checks and enable it where required. 6; UTC_ARGS: --disable 7 8; ModuleID = 'value-simplify.ll' 9source_filename = "value-simplify.ll" 10target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 11declare void @f(i32) 12 13; Test1: Replace argument with constant 14define internal void @test1(i32 %a) { 15; CHECK: tail call void @f(i32 1) 16 tail call void @f(i32 %a) 17 ret void 18} 19 20define void @test1_helper() { 21 tail call void @test1(i32 1) 22 ret void 23} 24 25; TEST 2 : Simplify return value 26define i32 @return0() { 27 ret i32 0 28} 29 30define i32 @return1() { 31 ret i32 1 32} 33 34; CHECK: define i32 @test2_1(i1 %c) 35define i32 @test2_1(i1 %c) { 36 br i1 %c, label %if.true, label %if.false 37if.true: 38 %call = tail call i32 @return0() 39 %ret0 = add i32 %call, 1 40 br label %end 41if.false: 42 %ret1 = tail call i32 @return1() 43 br label %end 44end: 45 46; CHECK: %ret = phi i32 [ %ret0, %if.true ], [ 1, %if.false ] 47 %ret = phi i32 [ %ret0, %if.true ], [ %ret1, %if.false ] 48 49; CHECK: ret i32 1 50 ret i32 1 51} 52 53 54 55; CHECK: define i32 @test2_2(i1 %c) 56define i32 @test2_2(i1 %c) { 57 %ret = tail call i32 @test2_1(i1 %c) 58; CHECK: ret i32 1 59 ret i32 %ret 60} 61 62declare void @use(i32) 63; CHECK: define void @test3(i1 %c) 64define void @test3(i1 %c) { 65 br i1 %c, label %if.true, label %if.false 66if.true: 67 br label %end 68if.false: 69 %ret1 = tail call i32 @return1() 70 br label %end 71end: 72 73; CHECK: %r = phi i32 [ 1, %if.true ], [ 1, %if.false ] 74 %r = phi i32 [ 1, %if.true ], [ %ret1, %if.false ] 75 76; CHECK: tail call void @use(i32 1) 77 tail call void @use(i32 %r) 78 ret void 79} 80 81define void @test-select-phi(i1 %c) { 82 %select-same = select i1 %c, i32 1, i32 1 83 ; CHECK: tail call void @use(i32 1) 84 tail call void @use(i32 %select-same) 85 86 %select-not-same = select i1 %c, i32 1, i32 0 87 ; CHECK: tail call void @use(i32 %select-not-same) 88 tail call void @use(i32 %select-not-same) 89 br i1 %c, label %if-true, label %if-false 90if-true: 91 br label %end 92if-false: 93 br label %end 94end: 95 %phi-same = phi i32 [ 1, %if-true ], [ 1, %if-false ] 96 %phi-not-same = phi i32 [ 0, %if-true ], [ 1, %if-false ] 97 %phi-same-prop = phi i32 [ 1, %if-true ], [ %select-same, %if-false ] 98 %phi-same-undef = phi i32 [ 1, %if-true ], [ undef, %if-false ] 99 %select-not-same-undef = select i1 %c, i32 %phi-not-same, i32 undef 100 101 102 ; CHECK: tail call void @use(i32 1) 103 tail call void @use(i32 %phi-same) 104 105 ; CHECK: tail call void @use(i32 %phi-not-same) 106 tail call void @use(i32 %phi-not-same) 107 108 ; CHECK: tail call void @use(i32 1) 109 tail call void @use(i32 %phi-same-prop) 110 111 ; CHECK: tail call void @use(i32 1) 112 tail call void @use(i32 %phi-same-undef) 113 114 ; CHECK: tail call void @use(i32 %select-not-same-undef) 115 tail call void @use(i32 %select-not-same-undef) 116 117 ret void 118 119} 120 121define i32 @ipccp1(i32 %a) { 122; CHECK-LABEL: define {{[^@]+}}@ipccp1 123; CHECK-SAME: (i32 returned [[A:%.*]]) 124; CHECK-NEXT: br i1 true, label [[T:%.*]], label [[F:%.*]] 125; CHECK: t: 126; CHECK-NEXT: ret i32 [[A:%.*]] 127; CHECK: f: 128; CHECK-NEXT: unreachable 129; 130 br i1 true, label %t, label %f 131t: 132 ret i32 %a 133f: 134 %r = call i32 @ipccp1(i32 5) 135 ret i32 %r 136} 137 138define internal i1 @ipccp2i(i1 %a) { 139 br i1 %a, label %t, label %f 140t: 141 ret i1 %a 142f: 143 %r = call i1 @ipccp2i(i1 false) 144 ret i1 %r 145} 146 147define i1 @ipccp2() { 148; CHECK-LABEL: define {{[^@]+}}@ipccp2() 149; CHECK-NEXT: ret i1 true 150; 151 %r = call i1 @ipccp2i(i1 true) 152 ret i1 %r 153} 154 155define internal i1 @ipccp2ib(i1 %a) { 156 br i1 %a, label %t, label %f 157t: 158 ret i1 true 159f: 160 %r = call i1 @ipccp2ib(i1 false) 161 ret i1 %r 162} 163 164define i1 @ipccp2b() { 165; CHECK-LABEL: define {{[^@]+}}@ipccp2b() 166; CHECK-NEXT: ret i1 true 167; 168 %r = call i1 @ipccp2ib(i1 true) 169 ret i1 %r 170} 171 172define internal i32 @ipccp3i(i32 %a) { 173 %c = icmp eq i32 %a, 7 174 br i1 %c, label %t, label %f 175t: 176 ret i32 %a 177f: 178 %r = call i32 @ipccp3i(i32 5) 179 ret i32 %r 180} 181 182define i32 @ipccp3() { 183; CHECK-LABEL: define {{[^@]+}}@ipccp3() 184; CHECK-NEXT: ret i32 7 185 %r = call i32 @ipccp3i(i32 7) 186 ret i32 %r 187} 188 189; UTC_ARGS: --enable 190 191; Do not touch complicated arguments (for now) 192%struct.X = type { i8* } 193define internal i32* @test_inalloca(i32* inalloca %a) { 194; CHECK-LABEL: define {{[^@]+}}@test_inalloca 195; CHECK-SAME: (i32* inalloca noalias nofree returned writeonly align 536870912 [[A:%.*]]) 196; CHECK-NEXT: ret i32* [[A]] 197; 198 ret i32* %a 199} 200define i32* @complicated_args_inalloca() { 201; CHECK-LABEL: define {{[^@]+}}@complicated_args_inalloca() 202; CHECK-NEXT: [[CALL:%.*]] = call i32* @test_inalloca(i32* noalias nofree writeonly align 536870912 null) 203; CHECK-NEXT: ret i32* [[CALL]] 204; 205 %call = call i32* @test_inalloca(i32* null) 206 ret i32* %call 207} 208 209define internal void @test_sret(%struct.X* sret %a, %struct.X** %b) { 210; CHECK-LABEL: define {{[^@]+}}@test_sret 211; CHECK-SAME: (%struct.X* noalias nofree sret writeonly align 536870912 [[A:%.*]], %struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B:%.*]]) 212; CHECK-NEXT: store %struct.X* [[A]], %struct.X** [[B]], align 8 213; CHECK-NEXT: ret void 214; 215 store %struct.X* %a, %struct.X** %b 216 ret void 217} 218; FIXME: Alignment and dereferenceability are not propagated to the argument 219define void @complicated_args_sret(%struct.X** %b) { 220; CHECK-LABEL: define {{[^@]+}}@complicated_args_sret 221; CHECK-SAME: (%struct.X** nocapture nofree writeonly [[B:%.*]]) 222; CHECK-NEXT: call void @test_sret(%struct.X* noalias nofree writeonly align 536870912 null, %struct.X** nocapture nofree writeonly align 8 [[B]]) 223; CHECK-NEXT: ret void 224; 225 call void @test_sret(%struct.X* null, %struct.X** %b) 226 ret void 227} 228 229define internal %struct.X* @test_nest(%struct.X* nest %a) { 230; CHECK-LABEL: define {{[^@]+}}@test_nest 231; CHECK-SAME: (%struct.X* nest noalias nofree readnone returned align 536870912 [[A:%.*]]) 232; CHECK-NEXT: ret %struct.X* [[A]] 233; 234 ret %struct.X* %a 235} 236define %struct.X* @complicated_args_nest() { 237; CHECK-LABEL: define {{[^@]+}}@complicated_args_nest() 238; CHECK-NEXT: [[CALL:%.*]] = call %struct.X* @test_nest(%struct.X* noalias nofree readnone align 536870912 null) 239; CHECK-NEXT: ret %struct.X* [[CALL]] 240; 241 %call = call %struct.X* @test_nest(%struct.X* null) 242 ret %struct.X* %call 243} 244 245@S = external global %struct.X 246define internal void @test_byval(%struct.X* byval %a) { 247 %g0 = getelementptr %struct.X, %struct.X* %a, i32 0, i32 0 248 store i8* null, i8** %g0 249 ret void 250} 251define void @complicated_args_byval() { 252; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval() 253; CHECK-NEXT: ret void 254; 255 call void @test_byval(%struct.X* @S) 256 ret void 257} 258 259define internal i8*@test_byval2(%struct.X* byval %a) { 260; CHECK-LABEL: define {{[^@]+}}@test_byval2() 261; CHECK-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0 262; CHECK-NEXT: [[L:%.*]] = load i8*, i8** [[G0]], align 8 263; CHECK-NEXT: ret i8* [[L]] 264; 265 %g0 = getelementptr %struct.X, %struct.X* %a, i32 0, i32 0 266 %l = load i8*, i8** %g0 267 ret i8* %l 268} 269define i8* @complicated_args_byval2() { 270; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval2() 271; CHECK-NEXT: [[C:%.*]] = call i8* @test_byval2() 272; CHECK-NEXT: ret i8* [[C]] 273; 274 %c = call i8* @test_byval2(%struct.X* @S) 275 ret i8* %c 276} 277 278define void @fixpoint_changed(i32* %p) { 279; CHECK-LABEL: define {{[^@]+}}@fixpoint_changed 280; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) 281; CHECK-NEXT: entry: 282; CHECK-NEXT: br label [[FOR_COND:%.*]] 283; CHECK: for.cond: 284; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_EPILOG:%.*]] ] 285; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[J_0]], 30 286; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 287; CHECK: for.body: 288; CHECK-NEXT: switch i32 [[J_0]], label [[SW_EPILOG]] [ 289; CHECK-NEXT: i32 1, label [[SW_BB:%.*]] 290; CHECK-NEXT: ] 291; CHECK: sw.bb: 292; CHECK-NEXT: br label [[SW_EPILOG]] 293; CHECK: sw.epilog: 294; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 255, [[FOR_BODY]] ], [ 253, [[SW_BB]] ] 295; CHECK-NEXT: store i32 [[X_0]], i32* [[P]] 296; CHECK-NEXT: [[INC]] = add nsw i32 [[J_0]], 1 297; CHECK-NEXT: br label [[FOR_COND]] 298; CHECK: for.end: 299; CHECK-NEXT: ret void 300; 301entry: 302 br label %for.cond 303 304for.cond: 305 %j.0 = phi i32 [ 0, %entry ], [ %inc, %sw.epilog ] 306 %cmp = icmp slt i32 %j.0, 30 307 br i1 %cmp, label %for.body, label %for.end 308 309for.body: 310 switch i32 %j.0, label %sw.epilog [ 311 i32 1, label %sw.bb 312 ] 313 314sw.bb: 315 br label %sw.epilog 316 317sw.epilog: 318 %x.0 = phi i32 [ 255, %for.body ], [ 253, %sw.bb ] 319 store i32 %x.0, i32* %p 320 %inc = add nsw i32 %j.0, 1 321 br label %for.cond 322 323for.end: 324 ret void 325} 326 327; Check we merge undef and a constant properly. 328; FIXME fold the addition and return the constant. 329define i8 @caller0() { 330; CHECK-LABEL: define {{[^@]+}}@caller0() 331; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 332; CHECK-NEXT: ret i8 [[C]] 333; 334 %c = call i8 @callee(i8 undef) 335 ret i8 %c 336} 337define i8 @caller1() { 338; CHECK-LABEL: define {{[^@]+}}@caller1() 339; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 340; CHECK-NEXT: ret i8 [[C]] 341; 342 %c = call i8 @callee(i8 undef) 343 ret i8 %c 344} 345define i8 @caller2() { 346; CHECK-LABEL: define {{[^@]+}}@caller2() 347; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 348; CHECK-NEXT: ret i8 [[C]] 349; 350 %c = call i8 @callee(i8 undef) 351 ret i8 %c 352} 353define i8 @caller_middle() { 354; CHECK-LABEL: define {{[^@]+}}@caller_middle() 355; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 356; CHECK-NEXT: ret i8 [[C]] 357; 358 %c = call i8 @callee(i8 42) 359 ret i8 %c 360} 361define i8 @caller3() { 362; CHECK-LABEL: define {{[^@]+}}@caller3() 363; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 364; CHECK-NEXT: ret i8 [[C]] 365; 366 %c = call i8 @callee(i8 undef) 367 ret i8 %c 368} 369define i8 @caller4() { 370; CHECK-LABEL: define {{[^@]+}}@caller4() 371; CHECK-NEXT: [[C:%.*]] = call i8 @callee() 372; CHECK-NEXT: ret i8 [[C]] 373; 374 %c = call i8 @callee(i8 undef) 375 ret i8 %c 376} 377define internal i8 @callee(i8 %a) { 378; CHECK-LABEL: define {{[^@]+}}@callee() 379; CHECK-NEXT: [[C:%.*]] = add i8 42, 7 380; CHECK-NEXT: ret i8 [[C]] 381; 382 %c = add i8 %a, 7 383 ret i8 %c 384} 385 386; UTC_ARGS: --disable 387