brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.9 KiB · bd43daa Raw
492 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S < %s | FileCheck %s3 4; Function Attrs: noinline uwtable5define i32 @foo(ptr nocapture writeonly %arg) {6; CHECK-LABEL: @foo(7; CHECK-NEXT:  bb:8; CHECK-NEXT:    [[VAR:%.*]] = call i32 @baz()9; CHECK-NEXT:    store i32 [[VAR]], ptr [[ARG:%.*]], align 410; CHECK-NEXT:    [[VAR1:%.*]] = call i32 @baz()11; CHECK-NEXT:    ret i32 [[VAR1]]12;13bb:14  %var = call i32 @baz()15  store i32 %var, ptr %arg, align 416  %var1 = call i32 @baz()17  ret i32 %var118}19declare i32 @baz()20 21; Function Attrs: uwtable22; This is an equivalent IR for a c-style example with a large function (foo)23; with out-params which are unused in the caller(test8). Note that foo is24; marked noinline to prevent IPO transforms.25; int foo();26;27; extern int foo(int *out) __attribute__((noinline));28; int foo(int *out) {29;   *out = baz();30;   return baz();31; }32;33; int test() {34;35;   int notdead;36;   if (foo(&notdead))37;     return 0;38;39;   int dead;40;   int tmp = foo(&dead);41;   if (notdead)42;     return tmp;43;   return bar();44; }45 46; TODO: We should be able to sink the second call @foo at bb5 down to bb_crit_edge47define i32 @test() {48; CHECK-LABEL: @test(49; CHECK-NEXT:  bb:50; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 451; CHECK-NEXT:    [[VAR1:%.*]] = alloca i32, align 452; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[VAR]])53; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @foo(ptr nonnull writeonly [[VAR]])54; CHECK-NEXT:    [[VAR4:%.*]] = icmp eq i32 [[VAR3]], 055; CHECK-NEXT:    br i1 [[VAR4]], label [[BB5:%.*]], label [[BB14:%.*]]56; CHECK:       bb5:57; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[VAR1]])58; CHECK-NEXT:    [[VAR8:%.*]] = load i32, ptr [[VAR]], align 459; CHECK-NEXT:    [[VAR9:%.*]] = icmp eq i32 [[VAR8]], 060; CHECK-NEXT:    [[VAR7:%.*]] = call i32 @foo(ptr nonnull writeonly [[VAR1]])61; CHECK-NEXT:    br i1 [[VAR9]], label [[BB10:%.*]], label [[BB_CRIT_EDGE:%.*]]62; CHECK:       bb10:63; CHECK-NEXT:    [[VAR11:%.*]] = call i32 @bar()64; CHECK-NEXT:    br label [[BB12:%.*]]65; CHECK:       bb_crit_edge:66; CHECK-NEXT:    br label [[BB12]]67; CHECK:       bb12:68; CHECK-NEXT:    [[VAR13:%.*]] = phi i32 [ [[VAR11]], [[BB10]] ], [ [[VAR7]], [[BB_CRIT_EDGE]] ]69; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[VAR1]])70; CHECK-NEXT:    br label [[BB14]]71; CHECK:       bb14:72; CHECK-NEXT:    [[VAR15:%.*]] = phi i32 [ [[VAR13]], [[BB12]] ], [ 0, [[BB:%.*]] ]73; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[VAR]])74; CHECK-NEXT:    ret i32 [[VAR15]]75;76bb:77  %var = alloca i32, align 478  %var1 = alloca i32, align 479  call void @llvm.lifetime.start.p0(ptr nonnull %var) #480  %var3 = call i32 @foo(ptr nonnull writeonly %var)81  %var4 = icmp eq i32 %var3, 082  br i1 %var4, label %bb5, label %bb1483 84bb5:                                              ; preds = %bb85  call void @llvm.lifetime.start.p0(ptr nonnull %var1) #486  %var8 = load i32, ptr %var, align 487  %var9 = icmp eq i32 %var8, 088  %var7 = call i32 @foo(ptr nonnull writeonly %var1)89  br i1 %var9, label %bb10, label %bb_crit_edge90 91bb10:                                             ; preds = %bb592  %var11 = call i32 @bar()93  br label %bb1294 95bb_crit_edge:96  br label %bb1297 98bb12:                                             ; preds = %bb10, %bb599  %var13 = phi i32 [ %var11, %bb10 ], [ %var7, %bb_crit_edge ]100  call void @llvm.lifetime.end.p0(ptr nonnull %var1) #4101  br label %bb14102 103bb14:                                             ; preds = %bb12, %bb104  %var15 = phi i32 [ %var13, %bb12 ], [ 0, %bb ]105  call void @llvm.lifetime.end.p0(ptr nonnull %var)106  ret i32 %var15107}108 109declare i32 @unknown(ptr %dest)110declare i32 @unknown.as2(ptr addrspace(2) %dest)111 112define i32 @sink_write_to_use(i1 %c) {113; CHECK-LABEL: @sink_write_to_use(114; CHECK-NEXT:  entry:115; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4116; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]117; CHECK:       early_return:118; CHECK-NEXT:    ret i32 0119; CHECK:       use_block:120; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull writeonly [[VAR]]) #[[ATTR1:[0-9]+]]121; CHECK-NEXT:    ret i32 [[VAR3]]122;123entry:124  %var = alloca i32, align 4125  %var3 = call i32 @unknown(ptr writeonly %var) argmemonly nounwind willreturn126  br i1 %c, label %early_return, label %use_block127 128early_return:129  ret i32 0130 131use_block:132  ret i32 %var3133}134 135define i32 @sink_readwrite_to_use(i1 %c) {136; CHECK-LABEL: @sink_readwrite_to_use(137; CHECK-NEXT:  entry:138; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4139; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]140; CHECK:       early_return:141; CHECK-NEXT:    ret i32 0142; CHECK:       use_block:143; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR1]]144; CHECK-NEXT:    ret i32 [[VAR3]]145;146entry:147  %var = alloca i32, align 4148  %var3 = call i32 @unknown(ptr %var) argmemonly nounwind willreturn149  br i1 %c, label %early_return, label %use_block150 151early_return:152  ret i32 0153 154use_block:155  ret i32 %var3156}157 158define i32 @sink_bitcast(i1 %c) {159; CHECK-LABEL: @sink_bitcast(160; CHECK-NEXT:  entry:161; CHECK-NEXT:    [[VAR:%.*]] = alloca i8, align 8162; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]163; CHECK:       early_return:164; CHECK-NEXT:    ret i32 0165; CHECK:       use_block:166; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR1]]167; CHECK-NEXT:    ret i32 [[VAR3]]168;169entry:170  %var = alloca i8, align 8171  %var3 = call i32 @unknown(ptr %var) argmemonly nounwind willreturn172  br i1 %c, label %early_return, label %use_block173 174early_return:175  ret i32 0176 177use_block:178  ret i32 %var3179}180 181 182define i32 @sink_gep1(i1 %c) {183; CHECK-LABEL: @sink_gep1(184; CHECK-NEXT:  entry:185; CHECK-NEXT:    [[VAR:%.*]] = alloca i64, align 8186; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]187; CHECK:       early_return:188; CHECK-NEXT:    ret i32 0189; CHECK:       use_block:190; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[VAR]], i64 4191; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[GEP]]) #[[ATTR1]]192; CHECK-NEXT:    ret i32 [[VAR3]]193;194entry:195  %var = alloca i64, align 8196  %gep = getelementptr i32, ptr %var, i32 1197  %var3 = call i32 @unknown(ptr %gep) argmemonly nounwind willreturn198  br i1 %c, label %early_return, label %use_block199 200early_return:201  ret i32 0202 203use_block:204  ret i32 %var3205}206 207define i32 @sink_gep2(i1 %c) {208; CHECK-LABEL: @sink_gep2(209; CHECK-NEXT:  entry:210; CHECK-NEXT:    [[VAR:%.*]] = alloca i64, align 8211; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]212; CHECK:       early_return:213; CHECK-NEXT:    ret i32 0214; CHECK:       use_block:215; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR1]]216; CHECK-NEXT:    ret i32 [[VAR3]]217;218entry:219  %var = alloca i64, align 8220  %var3 = call i32 @unknown(ptr %var) argmemonly nounwind willreturn221  br i1 %c, label %early_return, label %use_block222 223early_return:224  ret i32 0225 226use_block:227  ret i32 %var3228}229 230define i32 @sink_addrspacecast(i1 %c) {231; CHECK-LABEL: @sink_addrspacecast(232; CHECK-NEXT:  entry:233; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 8234; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]235; CHECK:       early_return:236; CHECK-NEXT:    ret i32 0237; CHECK:       use_block:238; CHECK-NEXT:    [[CAST:%.*]] = addrspacecast ptr [[VAR]] to ptr addrspace(2)239; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown.as2(ptr addrspace(2) [[CAST]]) #[[ATTR1]]240; CHECK-NEXT:    ret i32 [[VAR3]]241;242entry:243  %var = alloca i32, align 8244  %cast = addrspacecast ptr %var to ptr addrspace(2)245  %var3 = call i32 @unknown.as2(ptr addrspace(2) %cast) argmemonly nounwind willreturn246  br i1 %c, label %early_return, label %use_block247 248early_return:249  ret i32 0250 251use_block:252  ret i32 %var3253}254 255define i32 @neg_infinite_loop(i1 %c) {256; CHECK-LABEL: @neg_infinite_loop(257; CHECK-NEXT:  entry:258; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4259; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR2:[0-9]+]]260; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]261; CHECK:       early_return:262; CHECK-NEXT:    ret i32 0263; CHECK:       use_block:264; CHECK-NEXT:    ret i32 [[VAR3]]265;266entry:267  %var = alloca i32, align 4268  %var3 = call i32 @unknown(ptr %var) argmemonly nounwind269  br i1 %c, label %early_return, label %use_block270 271early_return:272  ret i32 0273 274use_block:275  ret i32 %var3276}277 278define i32 @neg_throw(i1 %c) {279; CHECK-LABEL: @neg_throw(280; CHECK-NEXT:  entry:281; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4282; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR3:[0-9]+]]283; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]284; CHECK:       early_return:285; CHECK-NEXT:    ret i32 0286; CHECK:       use_block:287; CHECK-NEXT:    ret i32 [[VAR3]]288;289entry:290  %var = alloca i32, align 4291  %var3 = call i32 @unknown(ptr %var) argmemonly willreturn292  br i1 %c, label %early_return, label %use_block293 294early_return:295  ret i32 0296 297use_block:298  ret i32 %var3299}300 301define i32 @neg_unknown_write(i1 %c) {302; CHECK-LABEL: @neg_unknown_write(303; CHECK-NEXT:  entry:304; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4305; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR4:[0-9]+]]306; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]307; CHECK:       early_return:308; CHECK-NEXT:    ret i32 0309; CHECK:       use_block:310; CHECK-NEXT:    ret i32 [[VAR3]]311;312entry:313  %var = alloca i32, align 4314  %var3 = call i32 @unknown(ptr %var) nounwind willreturn315  br i1 %c, label %early_return, label %use_block316 317early_return:318  ret i32 0319 320use_block:321  ret i32 %var3322}323 324define i32 @sink_lifetime1(i1 %c) {325; CHECK-LABEL: @sink_lifetime1(326; CHECK-NEXT:  entry:327; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4328; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[VAR]])329; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR1]]330; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]331; CHECK:       early_return:332; CHECK-NEXT:    ret i32 0333; CHECK:       use_block:334; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[VAR]])335; CHECK-NEXT:    ret i32 [[VAR3]]336;337entry:338  %var = alloca i32, align 4339  call void @llvm.lifetime.start.p0(ptr %var)340  %var3 = call i32 @unknown(ptr %var) argmemonly nounwind willreturn341  br i1 %c, label %early_return, label %use_block342 343early_return:344  ret i32 0345 346use_block:347  call void @llvm.lifetime.end.p0(ptr %var)348  ret i32 %var3349}350 351define i32 @sink_lifetime2(i1 %c) {352; CHECK-LABEL: @sink_lifetime2(353; CHECK-NEXT:  entry:354; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4355; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[VAR]])356; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR1]]357; CHECK-NEXT:    br i1 [[C:%.*]], label [[MERGE:%.*]], label [[USE_BLOCK:%.*]]358; CHECK:       merge:359; CHECK-NEXT:    [[RET:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAR3]], [[USE_BLOCK]] ]360; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[VAR]])361; CHECK-NEXT:    ret i32 [[RET]]362; CHECK:       use_block:363; CHECK-NEXT:    br label [[MERGE]]364;365entry:366  %var = alloca i32, align 4367  call void @llvm.lifetime.start.p0(ptr %var)368  %var3 = call i32 @unknown(ptr %var) argmemonly nounwind willreturn369  br i1 %c, label %merge, label %use_block370 371merge:372  %ret = phi i32 [0, %entry], [%var3, %use_block]373  call void @llvm.lifetime.end.p0(ptr %var)374  ret i32 %ret375 376use_block:377  br label %merge378}379 380define i32 @sink_lifetime3(i1 %c) {381; CHECK-LABEL: @sink_lifetime3(382; CHECK-NEXT:  entry:383; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4384; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]385; CHECK:       early_return:386; CHECK-NEXT:    ret i32 0387; CHECK:       use_block:388; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR1]]389; CHECK-NEXT:    ret i32 [[VAR3]]390;391entry:392  %var = alloca i32, align 4393  call void @llvm.lifetime.start.p0(ptr %var)394  call void @llvm.lifetime.end.p0(ptr %var)395  ; If unknown accesses %var, that's UB396  %var3 = call i32 @unknown(ptr %var) argmemonly nounwind willreturn397  br i1 %c, label %early_return, label %use_block398 399early_return:400  ret i32 0401 402use_block:403  ret i32 %var3404}405 406define i32 @sink_lifetime4a(i1 %c) {407; CHECK-LABEL: @sink_lifetime4a(408; CHECK-NEXT:  entry:409; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4410; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[VAR]])411; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull [[VAR]]) #[[ATTR1]]412; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[VAR]])413; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]414; CHECK:       early_return:415; CHECK-NEXT:    ret i32 0416; CHECK:       use_block:417; CHECK-NEXT:    ret i32 [[VAR3]]418;419entry:420  %var = alloca i32, align 4421  call void @llvm.lifetime.start.p0(ptr %var)422  %var3 = call i32 @unknown(ptr %var) argmemonly nounwind willreturn423  call void @llvm.lifetime.end.p0(ptr %var)424  br i1 %c, label %early_return, label %use_block425 426early_return:427  ret i32 0428 429use_block:430  ret i32 %var3431}432 433; Version which only writes to var, and thus can't rely on may-read scan for434; clobbers to prevent the transform435define i32 @sink_lifetime4b(i1 %c) {436; CHECK-LABEL: @sink_lifetime4b(437; CHECK-NEXT:  entry:438; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4439; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr nonnull [[VAR]])440; CHECK-NEXT:    [[VAR3:%.*]] = call i32 @unknown(ptr nonnull writeonly [[VAR]]) #[[ATTR1]]441; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr nonnull [[VAR]])442; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]443; CHECK:       early_return:444; CHECK-NEXT:    ret i32 0445; CHECK:       use_block:446; CHECK-NEXT:    ret i32 [[VAR3]]447;448entry:449  %var = alloca i32, align 4450  call void @llvm.lifetime.start.p0(ptr %var)451  %var3 = call i32 @unknown(ptr writeonly %var) argmemonly nounwind willreturn452  call void @llvm.lifetime.end.p0(ptr %var)453  br i1 %c, label %early_return, label %use_block454 455early_return:456  ret i32 0457 458use_block:459  ret i32 %var3460}461; Mostly checking that trying to sink a non-call doesn't crash (i.e. prior bug)462define i32 @sink_atomicrmw_to_use(i1 %c) {463; CHECK-LABEL: @sink_atomicrmw_to_use(464; CHECK-NEXT:  entry:465; CHECK-NEXT:    [[VAR:%.*]] = alloca i32, align 4466; CHECK-NEXT:    store i32 0, ptr [[VAR]], align 4467; CHECK-NEXT:    [[VAR3:%.*]] = atomicrmw add ptr [[VAR]], i32 1 seq_cst, align 4468; CHECK-NEXT:    br i1 [[C:%.*]], label [[EARLY_RETURN:%.*]], label [[USE_BLOCK:%.*]]469; CHECK:       early_return:470; CHECK-NEXT:    ret i32 0471; CHECK:       use_block:472; CHECK-NEXT:    ret i32 [[VAR3]]473;474entry:475  %var = alloca i32, align 4476  store i32 0, ptr %var477  %var3 = atomicrmw add ptr %var, i32 1 seq_cst, align 4478  br i1 %c, label %early_return, label %use_block479 480early_return:481  ret i32 0482 483use_block:484  ret i32 %var3485}486 487 488declare i32 @bar()489declare void @llvm.lifetime.start.p0(ptr nocapture)490declare void @llvm.lifetime.end.p0(ptr nocapture)491 492