1 ; RUN: opt -S -codegenprepare < %s | FileCheck %s 2 3 target datalayout = 4 "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" 5 target triple = "x86_64-unknown-linux-gnu" 6 7 ; Can we sink single addressing mode computation to use? 8 define void @test1(i1 %cond, i64* %base) { 9 ; CHECK-LABEL: @test1 10 ; CHECK: add i64 {{.+}}, 40 11 entry: 12 %addr = getelementptr inbounds i64, i64* %base, i64 5 13 %casted = bitcast i64* %addr to i32* 14 br i1 %cond, label %if.then, label %fallthrough 15 16 if.then: 17 %v = load i32, i32* %casted, align 4 18 br label %fallthrough 19 20 fallthrough: 21 ret void 22 } 23 24 declare void @foo(i32) 25 26 ; Make sure sinking two copies of addressing mode into different blocks works 27 define void @test2(i1 %cond, i64* %base) { 28 ; CHECK-LABEL: @test2 29 entry: 30 %addr = getelementptr inbounds i64, i64* %base, i64 5 31 %casted = bitcast i64* %addr to i32* 32 br i1 %cond, label %if.then, label %fallthrough 33 34 if.then: 35 ; CHECK-LABEL: if.then: 36 ; CHECK: add i64 {{.+}}, 40 37 %v1 = load i32, i32* %casted, align 4 38 call void @foo(i32 %v1) 39 %cmp = icmp eq i32 %v1, 0 40 br i1 %cmp, label %next, label %fallthrough 41 42 next: 43 ; CHECK-LABEL: next: 44 ; CHECK: add i64 {{.+}}, 40 45 %v2 = load i32, i32* %casted, align 4 46 call void @foo(i32 %v2) 47 br label %fallthrough 48 49 fallthrough: 50 ret void 51 } 52 53 ; If we have two loads in the same block, only need one copy of addressing mode 54 ; - instruction selection will duplicate if needed 55 define void @test3(i1 %cond, i64* %base) { 56 ; CHECK-LABEL: @test3 57 entry: 58 %addr = getelementptr inbounds i64, i64* %base, i64 5 59 %casted = bitcast i64* %addr to i32* 60 br i1 %cond, label %if.then, label %fallthrough 61 62 if.then: 63 ; CHECK-LABEL: if.then: 64 ; CHECK: add i64 {{.+}}, 40 65 %v1 = load i32, i32* %casted, align 4 66 call void @foo(i32 %v1) 67 ; CHECK-NOT: add i64 {{.+}}, 40 68 %v2 = load i32, i32* %casted, align 4 69 call void @foo(i32 %v2) 70 br label %fallthrough 71 72 fallthrough: 73 ret void 74 } 75 76 ; Can we still sink addressing mode if there's a cold use of the 77 ; address itself? 78 define void @test4(i1 %cond, i64* %base) { 79 ; CHECK-LABEL: @test4 80 entry: 81 %addr = getelementptr inbounds i64, i64* %base, i64 5 82 %casted = bitcast i64* %addr to i32* 83 br i1 %cond, label %if.then, label %fallthrough 84 85 if.then: 86 ; CHECK-LABEL: if.then: 87 ; CHECK: add i64 {{.+}}, 40 88 %v1 = load i32, i32* %casted, align 4 89 call void @foo(i32 %v1) 90 %cmp = icmp eq i32 %v1, 0 91 br i1 %cmp, label %rare.1, label %fallthrough 92 93 fallthrough: 94 ret void 95 96 rare.1: 97 ; CHECK-LABEL: rare.1: 98 ; CHECK: add i64 {{.+}}, 40 99 call void @slowpath(i32 %v1, i32* %casted) cold 100 br label %fallthrough 101 } 102 103 ; Negative test - don't want to duplicate addressing into hot path 104 define void @test5(i1 %cond, i64* %base) { 105 ; CHECK-LABEL: @test5 106 entry: 107 ; CHECK: %addr = getelementptr 108 %addr = getelementptr inbounds i64, i64* %base, i64 5 109 %casted = bitcast i64* %addr to i32* 110 br i1 %cond, label %if.then, label %fallthrough 111 112 if.then: 113 ; CHECK-LABEL: if.then: 114 ; CHECK-NOT: add i64 {{.+}}, 40 115 %v1 = load i32, i32* %casted, align 4 116 call void @foo(i32 %v1) 117 %cmp = icmp eq i32 %v1, 0 118 br i1 %cmp, label %rare.1, label %fallthrough 119 120 fallthrough: 121 ret void 122 123 rare.1: 124 call void @slowpath(i32 %v1, i32* %casted) ;; NOT COLD 125 br label %fallthrough 126 } 127 128 ; Negative test - opt for size 129 define void @test6(i1 %cond, i64* %base) minsize { 130 ; CHECK-LABEL: @test6 131 entry: 132 ; CHECK: %addr = getelementptr 133 %addr = getelementptr inbounds i64, i64* %base, i64 5 134 %casted = bitcast i64* %addr to i32* 135 br i1 %cond, label %if.then, label %fallthrough 136 137 if.then: 138 ; CHECK-LABEL: if.then: 139 ; CHECK-NOT: add i64 {{.+}}, 40 140 %v1 = load i32, i32* %casted, align 4 141 call void @foo(i32 %v1) 142 %cmp = icmp eq i32 %v1, 0 143 br i1 %cmp, label %rare.1, label %fallthrough 144 145 fallthrough: 146 ret void 147 148 rare.1: 149 call void @slowpath(i32 %v1, i32* %casted) cold 150 br label %fallthrough 151 } 152 153 154 ; Make sure sinking two copies of addressing mode into different blocks works 155 ; when there are cold paths for each. 156 define void @test7(i1 %cond, i64* %base) { 157 ; CHECK-LABEL: @test7 158 entry: 159 %addr = getelementptr inbounds i64, i64* %base, i64 5 160 %casted = bitcast i64* %addr to i32* 161 br i1 %cond, label %if.then, label %fallthrough 162 163 if.then: 164 ; CHECK-LABEL: if.then: 165 ; CHECK: add i64 {{.+}}, 40 166 %v1 = load i32, i32* %casted, align 4 167 call void @foo(i32 %v1) 168 %cmp = icmp eq i32 %v1, 0 169 br i1 %cmp, label %rare.1, label %next 170 171 next: 172 ; CHECK-LABEL: next: 173 ; CHECK: add i64 {{.+}}, 40 174 %v2 = load i32, i32* %casted, align 4 175 call void @foo(i32 %v2) 176 %cmp2 = icmp eq i32 %v2, 0 177 br i1 %cmp2, label %rare.1, label %fallthrough 178 179 fallthrough: 180 ret void 181 182 rare.1: 183 ; CHECK-LABEL: rare.1: 184 ; CHECK: add i64 {{.+}}, 40 185 call void @slowpath(i32 %v1, i32* %casted) cold 186 br label %next 187 188 rare.2: 189 ; CHECK-LABEL: rare.2: 190 ; CHECK: add i64 {{.+}}, 40 191 call void @slowpath(i32 %v2, i32* %casted) cold 192 br label %fallthrough 193 } 194 195 196 declare void @slowpath(i32, i32*) 197