; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt -S -passes='require,function(codegenprepare)' -disable-complex-addr-modes=false -addr-sink-new-phis=true -addr-sink-new-select=true -disable-cgp-delete-phis %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-YES ; RUN: opt -S -passes='require,function(codegenprepare)' -disable-complex-addr-modes=false -addr-sink-new-phis=false -addr-sink-new-select=true -disable-cgp-delete-phis %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" target triple = "x86_64-unknown-linux-gnu" ; Can we sink for different base if there is no phi for base? define i32 @test1(i1 %cond, ptr %b1, ptr %b2) { ; CHECK-YES-LABEL: define i32 @test1( ; CHECK-YES-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI:%.*]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load i32, ptr [[SUNKADDR]], align 4 ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test1( ; CHECK-NO-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[C:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[V:%.*]] = load i32, ptr [[C]], align 4 ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 br i1 %cond, label %if.then, label %fallthrough if.then: %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br label %fallthrough fallthrough: %c = phi ptr [%a1, %entry], [%a2, %if.then] %v = load i32, ptr %c, align 4 ret i32 %v } ; Can we sink for different base if there is phi for base? define i32 @test2(i1 %cond, ptr %b1, ptr %b2) { ; CHECK-LABEL: define i32 @test2( ; CHECK-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK: [[IF_THEN]]: ; CHECK-NEXT: br label %[[FALLTHROUGH]] ; CHECK: [[FALLTHROUGH]]: ; CHECK-NEXT: [[B:%.*]] = phi ptr [ [[B1]], %[[ENTRY]] ], [ [[B2]], %[[IF_THEN]] ] ; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 40 ; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[SUNKADDR]], align 4 ; CHECK-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 br i1 %cond, label %if.then, label %fallthrough if.then: %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br label %fallthrough fallthrough: %b = phi ptr [%b1, %entry], [%b2, %if.then] %c = phi ptr [%a1, %entry], [%a2, %if.then] %v = load i32, ptr %c, align 4 ret i32 %v } ; Can we sink for different base if there is phi for base but not valid one? define i32 @test3(i1 %cond, ptr %b1, ptr %b2) { ; CHECK-YES-LABEL: define i32 @test3( ; CHECK-YES-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[B:%.*]] = phi ptr [ [[B2]], %[[ENTRY]] ], [ [[B1]], %[[IF_THEN]] ] ; CHECK-YES-NEXT: [[SUNK_PHI:%.*]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load i32, ptr [[SUNKADDR]], align 4 ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test3( ; CHECK-NO-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[B:%.*]] = phi ptr [ [[B2]], %[[ENTRY]] ], [ [[B1]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[C:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[V:%.*]] = load i32, ptr [[C]], align 4 ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 br i1 %cond, label %if.then, label %fallthrough if.then: %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br label %fallthrough fallthrough: %b = phi ptr [%b2, %entry], [%b1, %if.then] %c = phi ptr [%a1, %entry], [%a2, %if.then] %v = load i32, ptr %c, align 4 ret i32 %v } ; Can we sink for different base if both addresses are in the same block? define i32 @test4(i1 %cond, ptr %b1, ptr %b2) { ; CHECK-YES-LABEL: define i32 @test4( ; CHECK-YES-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI:%.*]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load i32, ptr [[SUNKADDR]], align 4 ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test4( ; CHECK-NO-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[C:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[V:%.*]] = load i32, ptr [[C]], align 4 ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br i1 %cond, label %if.then, label %fallthrough if.then: br label %fallthrough fallthrough: %c = phi ptr [%a1, %entry], [%a2, %if.then] %v = load i32, ptr %c, align 4 ret i32 %v } ; Can we sink for different base if there is phi for base? ; Both addresses are in the same block. define i32 @test5(i1 %cond, ptr %b1, ptr %b2) { ; CHECK-LABEL: define i32 @test5( ; CHECK-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK: [[IF_THEN]]: ; CHECK-NEXT: br label %[[FALLTHROUGH]] ; CHECK: [[FALLTHROUGH]]: ; CHECK-NEXT: [[B:%.*]] = phi ptr [ [[B1]], %[[ENTRY]] ], [ [[B2]], %[[IF_THEN]] ] ; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 40 ; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[SUNKADDR]], align 4 ; CHECK-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br i1 %cond, label %if.then, label %fallthrough if.then: br label %fallthrough fallthrough: %b = phi ptr [%b1, %entry], [%b2, %if.then] %c = phi ptr [%a1, %entry], [%a2, %if.then] %v = load i32, ptr %c, align 4 ret i32 %v } ; Can we sink for different base if there is phi for base but not valid one? ; Both addresses are in the same block. define i32 @test6(i1 %cond, ptr %b1, ptr %b2) { ; CHECK-YES-LABEL: define i32 @test6( ; CHECK-YES-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[B:%.*]] = phi ptr [ [[B2]], %[[ENTRY]] ], [ [[B1]], %[[IF_THEN]] ] ; CHECK-YES-NEXT: [[SUNK_PHI:%.*]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load i32, ptr [[SUNKADDR]], align 4 ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test6( ; CHECK-NO-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[B:%.*]] = phi ptr [ [[B2]], %[[ENTRY]] ], [ [[B1]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[C:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[V:%.*]] = load i32, ptr [[C]], align 4 ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br i1 %cond, label %if.then, label %fallthrough if.then: br label %fallthrough fallthrough: %b = phi ptr [%b2, %entry], [%b1, %if.then] %c = phi ptr [%a1, %entry], [%a2, %if.then] %v = load i32, ptr %c, align 4 ret i32 %v } ; case with a loop. No phi node. define i32 @test7(i32 %N, i1 %cond, ptr %b1, ptr %b2) { ; CHECK-YES-LABEL: define i32 @test7( ; CHECK-YES-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-YES-NEXT: br label %[[LOOP:.*]] ; CHECK-YES: [[LOOP]]: ; CHECK-YES-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_INC:%.*]], %[[FALLTHROUGH:.*]] ] ; CHECK-YES-NEXT: [[SUNK_PHI1:%.*]] = phi ptr [ [[SUNK_PHI:%.*]], %[[FALLTHROUGH]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[C3:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[C:%.*]], %[[FALLTHROUGH]] ] ; CHECK-YES-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[SUNK_PHI1]], %[[LOOP]] ] ; CHECK-YES-NEXT: [[C]] = phi ptr [ [[C3]], %[[LOOP]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load volatile i32, ptr [[SUNKADDR]], align 4 ; CHECK-YES-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-YES-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-YES-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK-YES: [[EXIT]]: ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test7( ; CHECK-NO-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: br label %[[LOOP:.*]] ; CHECK-NO: [[LOOP]]: ; CHECK-NO-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_INC:%.*]], %[[FALLTHROUGH:.*]] ] ; CHECK-NO-NEXT: [[C3:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[C:%.*]], %[[FALLTHROUGH]] ] ; CHECK-NO-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[C]] = phi ptr [ [[C3]], %[[LOOP]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[V:%.*]] = load volatile i32, ptr [[C]], align 4 ; CHECK-NO-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-NO-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-NO-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK-NO: [[EXIT]]: ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 br label %loop loop: %iv = phi i32 [0, %entry], [%iv.inc, %fallthrough] %c3 = phi ptr [%a1, %entry], [%c, %fallthrough] br i1 %cond, label %if.then, label %fallthrough if.then: %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br label %fallthrough fallthrough: %c = phi ptr [%c3, %loop], [%a2, %if.then] %v = load volatile i32, ptr %c, align 4 %iv.inc = add i32 %iv, 1 %cmp = icmp slt i32 %iv.inc, %N br i1 %cmp, label %loop, label %exit exit: ret i32 %v } ; case with a loop. There is phi node. define i32 @test8(i32 %N, i1 %cond, ptr %b1, ptr %b2) { ; CHECK-LABEL: define i32 @test8( ; CHECK-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_INC:%.*]], %[[FALLTHROUGH:.*]] ] ; CHECK-NEXT: [[C3:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[C:%.*]], %[[FALLTHROUGH]] ] ; CHECK-NEXT: [[B3:%.*]] = phi ptr [ [[B1]], %[[ENTRY]] ], [ [[B:%.*]], %[[FALLTHROUGH]] ] ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH]] ; CHECK: [[IF_THEN]]: ; CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NEXT: br label %[[FALLTHROUGH]] ; CHECK: [[FALLTHROUGH]]: ; CHECK-NEXT: [[C]] = phi ptr [ [[C3]], %[[LOOP]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NEXT: [[B]] = phi ptr [ [[B3]], %[[LOOP]] ], [ [[B2]], %[[IF_THEN]] ] ; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 40 ; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[SUNKADDR]], align 4 ; CHECK-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 br label %loop loop: %iv = phi i32 [0, %entry], [%iv.inc, %fallthrough] %c3 = phi ptr [%a1, %entry], [%c, %fallthrough] %b3 = phi ptr [%b1, %entry], [%b, %fallthrough] br i1 %cond, label %if.then, label %fallthrough if.then: %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br label %fallthrough fallthrough: %c = phi ptr [%c3, %loop], [%a2, %if.then] %b = phi ptr [%b3, %loop], [%b2, %if.then] %v = load volatile i32, ptr %c, align 4 %iv.inc = add i32 %iv, 1 %cmp = icmp slt i32 %iv.inc, %N br i1 %cmp, label %loop, label %exit exit: ret i32 %v } ; case with a loop. There is phi node but it does not fit. define i32 @test9(i32 %N, i1 %cond, ptr %b1, ptr %b2) { ; CHECK-YES-LABEL: define i32 @test9( ; CHECK-YES-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-YES-NEXT: br label %[[LOOP:.*]] ; CHECK-YES: [[LOOP]]: ; CHECK-YES-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_INC:%.*]], %[[FALLTHROUGH:.*]] ] ; CHECK-YES-NEXT: [[SUNK_PHI1:%.*]] = phi ptr [ [[SUNK_PHI:%.*]], %[[FALLTHROUGH]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[C3:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[C:%.*]], %[[FALLTHROUGH]] ] ; CHECK-YES-NEXT: [[B3:%.*]] = phi ptr [ [[B1]], %[[ENTRY]] ], [ [[B2]], %[[FALLTHROUGH]] ] ; CHECK-YES-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[SUNK_PHI1]], %[[LOOP]] ] ; CHECK-YES-NEXT: [[C]] = phi ptr [ [[C3]], %[[LOOP]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-YES-NEXT: [[B:%.*]] = phi ptr [ [[B3]], %[[LOOP]] ], [ [[B2]], %[[IF_THEN]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load volatile i32, ptr [[SUNKADDR]], align 4 ; CHECK-YES-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-YES-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-YES-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK-YES: [[EXIT]]: ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test9( ; CHECK-NO-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: br label %[[LOOP:.*]] ; CHECK-NO: [[LOOP]]: ; CHECK-NO-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_INC:%.*]], %[[FALLTHROUGH:.*]] ] ; CHECK-NO-NEXT: [[C3:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[C:%.*]], %[[FALLTHROUGH]] ] ; CHECK-NO-NEXT: [[B3:%.*]] = phi ptr [ [[B1]], %[[ENTRY]] ], [ [[B2]], %[[FALLTHROUGH]] ] ; CHECK-NO-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[C]] = phi ptr [ [[C3]], %[[LOOP]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[B:%.*]] = phi ptr [ [[B3]], %[[LOOP]] ], [ [[B2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[V:%.*]] = load volatile i32, ptr [[C]], align 4 ; CHECK-NO-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-NO-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-NO-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK-NO: [[EXIT]]: ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 br label %loop loop: %iv = phi i32 [0, %entry], [%iv.inc, %fallthrough] %c3 = phi ptr [%a1, %entry], [%c, %fallthrough] %b3 = phi ptr [%b1, %entry], [%b2, %fallthrough] br i1 %cond, label %if.then, label %fallthrough if.then: %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br label %fallthrough fallthrough: %c = phi ptr [%c3, %loop], [%a2, %if.then] %b = phi ptr [%b3, %loop], [%b2, %if.then] %v = load volatile i32, ptr %c, align 4 %iv.inc = add i32 %iv, 1 %cmp = icmp slt i32 %iv.inc, %N br i1 %cmp, label %loop, label %exit exit: ret i32 %v } ; Case through a loop. No phi node. define i32 @test10(i32 %N, i1 %cond, ptr %b1, ptr %b2) { ; CHECK-YES-LABEL: define i32 @test10( ; CHECK-YES-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI:%.*]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: br label %[[LOOP:.*]] ; CHECK-YES: [[LOOP]]: ; CHECK-YES-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[FALLTHROUGH]] ], [ [[IV_INC:%.*]], %[[LOOP]] ] ; CHECK-YES-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-YES-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-YES-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK-YES: [[EXIT]]: ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load volatile i32, ptr [[SUNKADDR]], align 4 ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test10( ; CHECK-NO-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[C:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: br label %[[LOOP:.*]] ; CHECK-NO: [[LOOP]]: ; CHECK-NO-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[FALLTHROUGH]] ], [ [[IV_INC:%.*]], %[[LOOP]] ] ; CHECK-NO-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-NO-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-NO-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK-NO: [[EXIT]]: ; CHECK-NO-NEXT: [[V:%.*]] = load volatile i32, ptr [[C]], align 4 ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 br i1 %cond, label %if.then, label %fallthrough if.then: %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br label %fallthrough fallthrough: %c = phi ptr [%a1, %entry], [%a2, %if.then] br label %loop loop: %iv = phi i32 [0, %fallthrough], [%iv.inc, %loop] %iv.inc = add i32 %iv, 1 %cmp = icmp slt i32 %iv.inc, %N br i1 %cmp, label %loop, label %exit exit: %v = load volatile i32, ptr %c, align 4 ret i32 %v } ; Case through a loop. There is a phi. define i32 @test11(i32 %N, i1 %cond, ptr %b1, ptr %b2) { ; CHECK-LABEL: define i32 @test11( ; CHECK-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK: [[IF_THEN]]: ; CHECK-NEXT: br label %[[FALLTHROUGH]] ; CHECK: [[FALLTHROUGH]]: ; CHECK-NEXT: [[B:%.*]] = phi ptr [ [[B1]], %[[ENTRY]] ], [ [[B2]], %[[IF_THEN]] ] ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[FALLTHROUGH]] ], [ [[IV_INC:%.*]], %[[LOOP]] ] ; CHECK-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 40 ; CHECK-NEXT: [[V:%.*]] = load volatile i32, ptr [[SUNKADDR]], align 4 ; CHECK-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 br i1 %cond, label %if.then, label %fallthrough if.then: %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br label %fallthrough fallthrough: %c = phi ptr [%a1, %entry], [%a2, %if.then] %b = phi ptr [%b1, %entry], [%b2, %if.then] br label %loop loop: %iv = phi i32 [0, %fallthrough], [%iv.inc, %loop] %iv.inc = add i32 %iv, 1 %cmp = icmp slt i32 %iv.inc, %N br i1 %cmp, label %loop, label %exit exit: %v = load volatile i32, ptr %c, align 4 ret i32 %v } ; Complex case with address value from previous iteration. define i32 @test12(i32 %N, i1 %cond, ptr %b1, ptr %b2, ptr %b3) { ; CHECK-YES-LABEL: define i32 @test12( ; CHECK-YES-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], ptr [[B3:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-YES-NEXT: br label %[[LOOP:.*]] ; CHECK-YES: [[LOOP]]: ; CHECK-YES-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_INC:%.*]], %[[BACKEDGE:.*]] ] ; CHECK-YES-NEXT: [[SUNK_PHI1:%.*]] = phi ptr [ [[SUNK_PHI:%.*]], %[[BACKEDGE]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[C3:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[C:%.*]], %[[BACKEDGE]] ] ; CHECK-YES-NEXT: [[B4:%.*]] = phi ptr [ [[B1]], %[[ENTRY]] ], [ [[B5:%.*]], %[[BACKEDGE]] ] ; CHECK-YES-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[SUNK_PHI1]], %[[LOOP]] ] ; CHECK-YES-NEXT: [[C]] = phi ptr [ [[C3]], %[[LOOP]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-YES-NEXT: [[B6:%.*]] = phi ptr [ [[B4]], %[[LOOP]] ], [ [[B2]], %[[IF_THEN]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load volatile i32, ptr [[SUNKADDR]], align 4 ; CHECK-YES-NEXT: [[A4:%.*]] = getelementptr inbounds i64, ptr [[B4]], i64 5 ; CHECK-YES-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV]], 20 ; CHECK-YES-NEXT: br i1 [[CMP]], label %[[BACKEDGE]], label %[[IF_THEN_2:.*]] ; CHECK-YES: [[IF_THEN_2]]: ; CHECK-YES-NEXT: br label %[[BACKEDGE]] ; CHECK-YES: [[BACKEDGE]]: ; CHECK-YES-NEXT: [[B5]] = phi ptr [ [[B4]], %[[FALLTHROUGH]] ], [ [[B6]], %[[IF_THEN_2]] ] ; CHECK-YES-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-YES-NEXT: [[CMP2:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-YES-NEXT: br i1 [[CMP2]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK-YES: [[EXIT]]: ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test12( ; CHECK-NO-SAME: i32 [[N:%.*]], i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], ptr [[B3:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[A1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: br label %[[LOOP:.*]] ; CHECK-NO: [[LOOP]]: ; CHECK-NO-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_INC:%.*]], %[[BACKEDGE:.*]] ] ; CHECK-NO-NEXT: [[C3:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[C:%.*]], %[[BACKEDGE]] ] ; CHECK-NO-NEXT: [[B4:%.*]] = phi ptr [ [[B1]], %[[ENTRY]] ], [ [[B5:%.*]], %[[BACKEDGE]] ] ; CHECK-NO-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: [[A2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[C]] = phi ptr [ [[C3]], %[[LOOP]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[B6:%.*]] = phi ptr [ [[B4]], %[[LOOP]] ], [ [[B2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[V:%.*]] = load volatile i32, ptr [[C]], align 4 ; CHECK-NO-NEXT: [[A4:%.*]] = getelementptr inbounds i64, ptr [[B4]], i64 5 ; CHECK-NO-NEXT: [[CMP:%.*]] = icmp slt i32 [[IV]], 20 ; CHECK-NO-NEXT: br i1 [[CMP]], label %[[BACKEDGE]], label %[[IF_THEN_2:.*]] ; CHECK-NO: [[IF_THEN_2]]: ; CHECK-NO-NEXT: br label %[[BACKEDGE]] ; CHECK-NO: [[BACKEDGE]]: ; CHECK-NO-NEXT: [[B5]] = phi ptr [ [[B4]], %[[FALLTHROUGH]] ], [ [[B6]], %[[IF_THEN_2]] ] ; CHECK-NO-NEXT: [[IV_INC]] = add i32 [[IV]], 1 ; CHECK-NO-NEXT: [[CMP2:%.*]] = icmp slt i32 [[IV_INC]], [[N]] ; CHECK-NO-NEXT: br i1 [[CMP2]], label %[[LOOP]], label %[[EXIT:.*]] ; CHECK-NO: [[EXIT]]: ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds i64, ptr %b1, i64 5 br label %loop loop: %iv = phi i32 [0, %entry], [%iv.inc, %backedge] %c3 = phi ptr [%a1, %entry], [%c, %backedge] %b4 = phi ptr [%b1, %entry], [%b5, %backedge] br i1 %cond, label %if.then, label %fallthrough if.then: %a2 = getelementptr inbounds i64, ptr %b2, i64 5 br label %fallthrough fallthrough: %c = phi ptr [%c3, %loop], [%a2, %if.then] %b6 = phi ptr [%b4, %loop], [%b2, %if.then] %v = load volatile i32, ptr %c, align 4 %a4 = getelementptr inbounds i64, ptr %b4, i64 5 %cmp = icmp slt i32 %iv, 20 br i1 %cmp, label %backedge, label %if.then.2 if.then.2: br label %backedge backedge: %b5 = phi ptr [%b4, %fallthrough], [%b6, %if.then.2] %iv.inc = add i32 %iv, 1 %cmp2 = icmp slt i32 %iv.inc, %N br i1 %cmp2, label %loop, label %exit exit: ret i32 %v } %struct.S = type {i32, i32} ; Case with index define i32 @test13(i1 %cond, ptr %b1, ptr %b2, i64 %Index) { ; CHECK-YES-LABEL: define i32 @test13( ; CHECK-YES-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], i64 [[INDEX:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: [[I2:%.*]] = mul i64 [[INDEX]], 2 ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI:%.*]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = mul i64 [[INDEX]], 8 ; CHECK-YES-NEXT: [[SUNKADDR1:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 [[SUNKADDR]] ; CHECK-YES-NEXT: [[SUNKADDR2:%.*]] = getelementptr inbounds i8, ptr [[SUNKADDR1]], i64 4 ; CHECK-YES-NEXT: [[V:%.*]] = load i32, ptr [[SUNKADDR2]], align 4 ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test13( ; CHECK-NO-SAME: i1 [[COND:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], i64 [[INDEX:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[A1:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[B1]], i64 [[INDEX]], i32 1 ; CHECK-NO-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: [[I2:%.*]] = mul i64 [[INDEX]], 2 ; CHECK-NO-NEXT: [[A2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[B2]], i64 [[INDEX]], i32 1 ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[A:%.*]] = phi ptr [ [[A1]], %[[ENTRY]] ], [ [[A2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[V:%.*]] = load i32, ptr [[A]], align 4 ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %a1 = getelementptr inbounds %struct.S, ptr %b1, i64 %Index, i32 1 br i1 %cond, label %if.then, label %fallthrough if.then: %i2 = mul i64 %Index, 2 %a2 = getelementptr inbounds %struct.S, ptr %b2, i64 %Index, i32 1 br label %fallthrough fallthrough: %a = phi ptr [%a1, %entry], [%a2, %if.then] %v = load i32, ptr %a, align 4 ret i32 %v } ; Select of Select case. define i64 @test14(i1 %c1, i1 %c2, ptr %b1, ptr %b2, ptr %b3) { ; CHECK-LABEL: define i64 @test14( ; CHECK-SAME: i1 [[C1:%.*]], i1 [[C2:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], ptr [[B3:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[S12:%.*]] = select i1 [[C1]], ptr [[B1]], ptr [[B2]] ; CHECK-NEXT: [[S21:%.*]] = select i1 [[C2]], ptr [[S12]], ptr [[B3]] ; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[S21]], i64 40 ; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[SUNKADDR]], align 8 ; CHECK-NEXT: ret i64 [[V]] ; entry: %g1 = getelementptr inbounds i64, ptr %b1, i64 5 %g2 = getelementptr inbounds i64, ptr %b2, i64 5 %g3 = getelementptr inbounds i64, ptr %b3, i64 5 %s1 = select i1 %c1, ptr %g1, ptr %g2 %s2 = select i1 %c2, ptr %s1, ptr %g3 %v = load i64 , ptr %s2, align 8 ret i64 %v } ; Select of Phi case. define i64 @test15(i1 %c1, i1 %c2, ptr %b1, ptr %b2, ptr %b3) { ; CHECK-YES-LABEL: define i64 @test15( ; CHECK-YES-SAME: i1 [[C1:%.*]], i1 [[C2:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], ptr [[B3:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: br i1 [[C1]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI:%.*]] = phi ptr [ [[B2]], %[[IF_THEN]] ], [ [[B1]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[S11:%.*]] = select i1 [[C2]], ptr [[SUNK_PHI]], ptr [[B3]] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[S11]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load i64, ptr [[SUNKADDR]], align 8 ; CHECK-YES-NEXT: ret i64 [[V]] ; ; CHECK-NO-LABEL: define i64 @test15( ; CHECK-NO-SAME: i1 [[C1:%.*]], i1 [[C2:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], ptr [[B3:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[G1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: [[G2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: [[G3:%.*]] = getelementptr inbounds i64, ptr [[B3]], i64 5 ; CHECK-NO-NEXT: br i1 [[C1]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[P1:%.*]] = phi ptr [ [[G1]], %[[ENTRY]] ], [ [[G2]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[S1:%.*]] = select i1 [[C2]], ptr [[P1]], ptr [[G3]] ; CHECK-NO-NEXT: [[V:%.*]] = load i64, ptr [[S1]], align 8 ; CHECK-NO-NEXT: ret i64 [[V]] ; entry: %g1 = getelementptr inbounds i64, ptr %b1, i64 5 %g2 = getelementptr inbounds i64, ptr %b2, i64 5 %g3 = getelementptr inbounds i64, ptr %b3, i64 5 br i1 %c1, label %if.then, label %fallthrough if.then: br label %fallthrough fallthrough: %p1 = phi ptr [%g1, %entry], [%g2, %if.then] %s1 = select i1 %c2, ptr %p1, ptr %g3 %v = load i64 , ptr %s1, align 8 ret i64 %v } ; Select of Phi case. Phi exists define i64 @test16(i1 %c1, i1 %c2, ptr %b1, ptr %b2, ptr %b3) { ; CHECK-LABEL: define i64 @test16( ; CHECK-SAME: i1 [[C1:%.*]], i1 [[C2:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], ptr [[B3:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br i1 [[C1]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK: [[IF_THEN]]: ; CHECK-NEXT: br label %[[FALLTHROUGH]] ; CHECK: [[FALLTHROUGH]]: ; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[B1]], %[[ENTRY]] ], [ [[B2]], %[[IF_THEN]] ] ; CHECK-NEXT: [[S11:%.*]] = select i1 [[C2]], ptr [[P]], ptr [[B3]] ; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[S11]], i64 40 ; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[SUNKADDR]], align 8 ; CHECK-NEXT: ret i64 [[V]] ; entry: %g1 = getelementptr inbounds i64, ptr %b1, i64 5 %g2 = getelementptr inbounds i64, ptr %b2, i64 5 %g3 = getelementptr inbounds i64, ptr %b3, i64 5 br i1 %c1, label %if.then, label %fallthrough if.then: br label %fallthrough fallthrough: %p = phi ptr [%b1, %entry], [%b2, %if.then] %p1 = phi ptr [%g1, %entry], [%g2, %if.then] %s1 = select i1 %c2, ptr %p1, ptr %g3 %v = load i64 , ptr %s1, align 8 ret i64 %v } ; Phi of Select case. define i64 @test17(i1 %c1, i1 %c2, ptr %b1, ptr %b2, ptr %b3) { ; CHECK-YES-LABEL: define i64 @test17( ; CHECK-YES-SAME: i1 [[C1:%.*]], i1 [[C2:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], ptr [[B3:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*]]: ; CHECK-YES-NEXT: [[S11:%.*]] = select i1 [[C2]], ptr [[B1]], ptr [[B2]] ; CHECK-YES-NEXT: br i1 [[C1]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN]]: ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI:%.*]] = phi ptr [ [[B3]], %[[IF_THEN]] ], [ [[S11]], %[[ENTRY]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V:%.*]] = load i64, ptr [[SUNKADDR]], align 8 ; CHECK-YES-NEXT: ret i64 [[V]] ; ; CHECK-NO-LABEL: define i64 @test17( ; CHECK-NO-SAME: i1 [[C1:%.*]], i1 [[C2:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]], ptr [[B3:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*]]: ; CHECK-NO-NEXT: [[G1:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: [[G2:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: [[G3:%.*]] = getelementptr inbounds i64, ptr [[B3]], i64 5 ; CHECK-NO-NEXT: [[S1:%.*]] = select i1 [[C2]], ptr [[G1]], ptr [[G2]] ; CHECK-NO-NEXT: br i1 [[C1]], label %[[IF_THEN:.*]], label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN]]: ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[P1:%.*]] = phi ptr [ [[S1]], %[[ENTRY]] ], [ [[G3]], %[[IF_THEN]] ] ; CHECK-NO-NEXT: [[V:%.*]] = load i64, ptr [[P1]], align 8 ; CHECK-NO-NEXT: ret i64 [[V]] ; entry: %g1 = getelementptr inbounds i64, ptr %b1, i64 5 %g2 = getelementptr inbounds i64, ptr %b2, i64 5 %g3 = getelementptr inbounds i64, ptr %b3, i64 5 %s1 = select i1 %c2, ptr %g1, ptr %g2 br i1 %c1, label %if.then, label %fallthrough if.then: br label %fallthrough fallthrough: %p1 = phi ptr [%s1, %entry], [%g3, %if.then] %v = load i64 , ptr %p1, align 8 ret i64 %v } ; The same two addr modes by different paths define i32 @test18(i1 %cond1, i1 %cond2, ptr %b1, ptr %b2) { ; CHECK-YES-LABEL: define i32 @test18( ; CHECK-YES-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-YES-NEXT: [[ENTRY:.*:]] ; CHECK-YES-NEXT: br i1 [[COND1]], label %[[IF_THEN1:.*]], label %[[IF_THEN2:.*]] ; CHECK-YES: [[IF_THEN1]]: ; CHECK-YES-NEXT: br label %[[FALLTHROUGH:.*]] ; CHECK-YES: [[IF_THEN2]]: ; CHECK-YES-NEXT: br label %[[FALLTHROUGH]] ; CHECK-YES: [[FALLTHROUGH]]: ; CHECK-YES-NEXT: [[SUNK_PHI:%.*]] = phi ptr [ [[B2]], %[[IF_THEN2]] ], [ [[B1]], %[[IF_THEN1]] ] ; CHECK-YES-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[SUNK_PHI]], i64 40 ; CHECK-YES-NEXT: [[V1:%.*]] = load i32, ptr [[SUNKADDR]], align 4 ; CHECK-YES-NEXT: [[G1_1:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-YES-NEXT: [[V2:%.*]] = load i32, ptr [[G1_1]], align 4 ; CHECK-YES-NEXT: [[V:%.*]] = add i32 [[V1]], [[V2]] ; CHECK-YES-NEXT: ret i32 [[V]] ; ; CHECK-NO-LABEL: define i32 @test18( ; CHECK-NO-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], ptr [[B1:%.*]], ptr [[B2:%.*]]) { ; CHECK-NO-NEXT: [[ENTRY:.*:]] ; CHECK-NO-NEXT: [[G1:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: br i1 [[COND1]], label %[[IF_THEN1:.*]], label %[[IF_THEN2:.*]] ; CHECK-NO: [[IF_THEN1]]: ; CHECK-NO-NEXT: [[G2:%.*]] = getelementptr inbounds i64, ptr [[B1]], i64 5 ; CHECK-NO-NEXT: br label %[[FALLTHROUGH:.*]] ; CHECK-NO: [[IF_THEN2]]: ; CHECK-NO-NEXT: br label %[[FALLTHROUGH]] ; CHECK-NO: [[FALLTHROUGH]]: ; CHECK-NO-NEXT: [[C:%.*]] = phi ptr [ [[G2]], %[[IF_THEN1]] ], [ [[G1]], %[[IF_THEN2]] ] ; CHECK-NO-NEXT: [[V1:%.*]] = load i32, ptr [[C]], align 4 ; CHECK-NO-NEXT: [[G1_1:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NO-NEXT: [[V2:%.*]] = load i32, ptr [[G1_1]], align 4 ; CHECK-NO-NEXT: [[V:%.*]] = add i32 [[V1]], [[V2]] ; CHECK-NO-NEXT: ret i32 [[V]] ; entry: %g1 = getelementptr inbounds i64, ptr %b2, i64 5 br i1 %cond1, label %if.then1, label %if.then2 if.then1: %g2 = getelementptr inbounds i64, ptr %b1, i64 5 br label %fallthrough if.then2: br i1 %cond2, label %fallthrough, label %if.then3 if.then3: br label %fallthrough fallthrough: %c = phi ptr [%g2, %if.then1], [%g1, %if.then2], [%g1, %if.then3] %v1 = load i32, ptr %c, align 4 %g1_1 = getelementptr inbounds i64, ptr %b2, i64 5 %v2 = load i32, ptr %g1_1, align 4 %v = add i32 %v1, %v2 ret i32 %v } ; Different types but null is the first? define i32 @test19(i1 %cond1, i1 %cond2, ptr %b2, ptr %b1) { ; CHECK-LABEL: define i32 @test19( ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], ptr [[B2:%.*]], ptr [[B1:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[G1:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NEXT: br i1 [[COND1]], label %[[IF_THEN1:.*]], label %[[IF_THEN2:.*]] ; CHECK: [[IF_THEN1]]: ; CHECK-NEXT: [[G2:%.*]] = getelementptr inbounds i8, ptr [[B1]], i64 40 ; CHECK-NEXT: [[BC2:%.*]] = bitcast ptr [[G2]] to ptr ; CHECK-NEXT: br label %[[FALLTHROUGH:.*]] ; CHECK: [[IF_THEN2]]: ; CHECK-NEXT: [[BC1_1:%.*]] = bitcast ptr [[G1]] to ptr ; CHECK-NEXT: br i1 [[COND2]], label %[[FALLTHROUGH]], label %[[IF_THEN3:.*]] ; CHECK: [[IF_THEN3]]: ; CHECK-NEXT: [[G3:%.*]] = getelementptr inbounds i64, ptr null, i64 5 ; CHECK-NEXT: [[BC1_2:%.*]] = bitcast ptr [[G3]] to ptr ; CHECK-NEXT: br label %[[FALLTHROUGH]] ; CHECK: [[FALLTHROUGH]]: ; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[BC2]], %[[IF_THEN1]] ], [ [[BC1_1]], %[[IF_THEN2]] ], [ [[BC1_2]], %[[IF_THEN3]] ] ; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[C]], align 4 ; CHECK-NEXT: [[G1_1:%.*]] = getelementptr inbounds i64, ptr [[B2]], i64 5 ; CHECK-NEXT: [[BC1_1_1:%.*]] = bitcast ptr [[G1_1]] to ptr ; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[BC1_1_1]], align 4 ; CHECK-NEXT: [[V:%.*]] = add i32 [[V1]], [[V2]] ; CHECK-NEXT: ret i32 [[V]] ; entry: %g1 = getelementptr inbounds i64, ptr %b2, i64 5 %bc1 = bitcast ptr %g1 to ptr br i1 %cond1, label %if.then1, label %if.then2 if.then1: %g2 = getelementptr inbounds i8, ptr %b1, i64 40 %bc2 = bitcast ptr %g2 to ptr br label %fallthrough if.then2: %bc1_1 = bitcast ptr %g1 to ptr br i1 %cond2, label %fallthrough, label %if.then3 if.then3: %g3 = getelementptr inbounds i64, ptr null, i64 5 %bc1_2 = bitcast ptr %g3 to ptr br label %fallthrough fallthrough: %c = phi ptr [%bc2, %if.then1], [%bc1_1, %if.then2], [%bc1_2, %if.then3] %v1 = load i32, ptr %c, align 4 %g1_1 = getelementptr inbounds i64, ptr %b2, i64 5 %bc1_1_1 = bitcast ptr %g1_1 to ptr %v2 = load i32, ptr %bc1_1_1, align 4 %v = add i32 %v1, %v2 ret i32 %v }