1 //===- CallPromotionUtilsTest.cpp - CallPromotionUtils unit tests ---------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Transforms/Utils/CallPromotionUtils.h" 10 #include "llvm/AsmParser/Parser.h" 11 #include "llvm/IR/Instructions.h" 12 #include "llvm/IR/LLVMContext.h" 13 #include "llvm/IR/Module.h" 14 #include "llvm/Support/SourceMgr.h" 15 #include "gtest/gtest.h" 16 17 using namespace llvm; 18 19 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { 20 SMDiagnostic Err; 21 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); 22 if (!Mod) 23 Err.print("UtilsTests", errs()); 24 return Mod; 25 } 26 27 TEST(CallPromotionUtilsTest, TryPromoteCall) { 28 LLVMContext C; 29 std::unique_ptr<Module> M = parseIR(C, 30 R"IR( 31 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }> 32 %class.Interface = type { i32 (...)** } 33 34 @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%class.Impl*)* @_ZN4Impl3RunEv to i8*)] } 35 36 define void @f() { 37 entry: 38 %o = alloca %class.Impl 39 %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 40 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base 41 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 42 store i32 3, i32* %f 43 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 44 %c = bitcast %class.Interface* %base.i to void (%class.Interface*)*** 45 %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c 46 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i 47 call void %fp(%class.Interface* nonnull %base.i) 48 ret void 49 } 50 51 declare void @_ZN4Impl3RunEv(%class.Impl* %this) 52 )IR"); 53 54 auto *GV = M->getNamedValue("f"); 55 ASSERT_TRUE(GV); 56 auto *F = dyn_cast<Function>(GV); 57 ASSERT_TRUE(F); 58 Instruction *Inst = &F->front().front(); 59 auto *AI = dyn_cast<AllocaInst>(Inst); 60 ASSERT_TRUE(AI); 61 Inst = &*++F->front().rbegin(); 62 auto *CI = dyn_cast<CallInst>(Inst); 63 ASSERT_TRUE(CI); 64 ASSERT_FALSE(CI->getCalledFunction()); 65 bool IsPromoted = tryPromoteCall(*CI); 66 EXPECT_TRUE(IsPromoted); 67 GV = M->getNamedValue("_ZN4Impl3RunEv"); 68 ASSERT_TRUE(GV); 69 auto *F1 = dyn_cast<Function>(GV); 70 EXPECT_EQ(F1, CI->getCalledFunction()); 71 } 72 73 TEST(CallPromotionUtilsTest, TryPromoteCall_NoFPLoad) { 74 LLVMContext C; 75 std::unique_ptr<Module> M = parseIR(C, 76 R"IR( 77 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }> 78 %class.Interface = type { i32 (...)** } 79 80 define void @f(void (%class.Interface*)* %fp, %class.Interface* nonnull %base.i) { 81 entry: 82 call void %fp(%class.Interface* nonnull %base.i) 83 ret void 84 } 85 )IR"); 86 87 auto *GV = M->getNamedValue("f"); 88 ASSERT_TRUE(GV); 89 auto *F = dyn_cast<Function>(GV); 90 ASSERT_TRUE(F); 91 Instruction *Inst = &F->front().front(); 92 auto *CI = dyn_cast<CallInst>(Inst); 93 ASSERT_TRUE(CI); 94 ASSERT_FALSE(CI->getCalledFunction()); 95 bool IsPromoted = tryPromoteCall(*CI); 96 EXPECT_FALSE(IsPromoted); 97 } 98 99 TEST(CallPromotionUtilsTest, TryPromoteCall_NoVTablePtrLoad) { 100 LLVMContext C; 101 std::unique_ptr<Module> M = parseIR(C, 102 R"IR( 103 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }> 104 %class.Interface = type { i32 (...)** } 105 106 define void @f(void (%class.Interface*)** %vtable.i, %class.Interface* nonnull %base.i) { 107 entry: 108 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i 109 call void %fp(%class.Interface* nonnull %base.i) 110 ret void 111 } 112 )IR"); 113 114 auto *GV = M->getNamedValue("f"); 115 ASSERT_TRUE(GV); 116 auto *F = dyn_cast<Function>(GV); 117 ASSERT_TRUE(F); 118 Instruction *Inst = &*++F->front().rbegin(); 119 auto *CI = dyn_cast<CallInst>(Inst); 120 ASSERT_TRUE(CI); 121 ASSERT_FALSE(CI->getCalledFunction()); 122 bool IsPromoted = tryPromoteCall(*CI); 123 EXPECT_FALSE(IsPromoted); 124 } 125 126 TEST(CallPromotionUtilsTest, TryPromoteCall_NoVTableInitFound) { 127 LLVMContext C; 128 std::unique_ptr<Module> M = parseIR(C, 129 R"IR( 130 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }> 131 %class.Interface = type { i32 (...)** } 132 133 define void @f() { 134 entry: 135 %o = alloca %class.Impl 136 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 137 store i32 3, i32* %f 138 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 139 %c = bitcast %class.Interface* %base.i to void (%class.Interface*)*** 140 %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c 141 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i 142 call void %fp(%class.Interface* nonnull %base.i) 143 ret void 144 } 145 146 declare void @_ZN4Impl3RunEv(%class.Impl* %this) 147 )IR"); 148 149 auto *GV = M->getNamedValue("f"); 150 ASSERT_TRUE(GV); 151 auto *F = dyn_cast<Function>(GV); 152 ASSERT_TRUE(F); 153 Instruction *Inst = &*++F->front().rbegin(); 154 auto *CI = dyn_cast<CallInst>(Inst); 155 ASSERT_TRUE(CI); 156 ASSERT_FALSE(CI->getCalledFunction()); 157 bool IsPromoted = tryPromoteCall(*CI); 158 EXPECT_FALSE(IsPromoted); 159 } 160 161 TEST(CallPromotionUtilsTest, TryPromoteCall_EmptyVTable) { 162 LLVMContext C; 163 std::unique_ptr<Module> M = parseIR(C, 164 R"IR( 165 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }> 166 %class.Interface = type { i32 (...)** } 167 168 @_ZTV4Impl = external global { [3 x i8*] } 169 170 define void @f() { 171 entry: 172 %o = alloca %class.Impl 173 %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 174 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base 175 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 176 store i32 3, i32* %f 177 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 178 %c = bitcast %class.Interface* %base.i to void (%class.Interface*)*** 179 %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c 180 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i 181 call void %fp(%class.Interface* nonnull %base.i) 182 ret void 183 } 184 185 declare void @_ZN4Impl3RunEv(%class.Impl* %this) 186 )IR"); 187 188 auto *GV = M->getNamedValue("f"); 189 ASSERT_TRUE(GV); 190 auto *F = dyn_cast<Function>(GV); 191 ASSERT_TRUE(F); 192 Instruction *Inst = &F->front().front(); 193 auto *AI = dyn_cast<AllocaInst>(Inst); 194 ASSERT_TRUE(AI); 195 Inst = &*++F->front().rbegin(); 196 auto *CI = dyn_cast<CallInst>(Inst); 197 ASSERT_TRUE(CI); 198 ASSERT_FALSE(CI->getCalledFunction()); 199 bool IsPromoted = tryPromoteCall(*CI); 200 EXPECT_FALSE(IsPromoted); 201 } 202 203 TEST(CallPromotionUtilsTest, TryPromoteCall_NullFP) { 204 LLVMContext C; 205 std::unique_ptr<Module> M = parseIR(C, 206 R"IR( 207 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }> 208 %class.Interface = type { i32 (...)** } 209 210 @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* null] } 211 212 define void @f() { 213 entry: 214 %o = alloca %class.Impl 215 %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 216 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base 217 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 218 store i32 3, i32* %f 219 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 220 %c = bitcast %class.Interface* %base.i to void (%class.Interface*)*** 221 %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c 222 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i 223 call void %fp(%class.Interface* nonnull %base.i) 224 ret void 225 } 226 227 declare void @_ZN4Impl3RunEv(%class.Impl* %this) 228 )IR"); 229 230 auto *GV = M->getNamedValue("f"); 231 ASSERT_TRUE(GV); 232 auto *F = dyn_cast<Function>(GV); 233 ASSERT_TRUE(F); 234 Instruction *Inst = &F->front().front(); 235 auto *AI = dyn_cast<AllocaInst>(Inst); 236 ASSERT_TRUE(AI); 237 Inst = &*++F->front().rbegin(); 238 auto *CI = dyn_cast<CallInst>(Inst); 239 ASSERT_TRUE(CI); 240 ASSERT_FALSE(CI->getCalledFunction()); 241 bool IsPromoted = tryPromoteCall(*CI); 242 EXPECT_FALSE(IsPromoted); 243 } 244 245 // Based on clang/test/CodeGenCXX/member-function-pointer-calls.cpp 246 TEST(CallPromotionUtilsTest, TryPromoteCall_MemberFunctionCalls) { 247 LLVMContext C; 248 std::unique_ptr<Module> M = parseIR(C, 249 R"IR( 250 %struct.A = type { i32 (...)** } 251 252 @_ZTV1A = linkonce_odr unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i32 (%struct.A*)* @_ZN1A3vf1Ev to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3vf2Ev to i8*)] }, align 8 253 254 define i32 @_Z2g1v() { 255 entry: 256 %a = alloca %struct.A, align 8 257 %0 = bitcast %struct.A* %a to i8* 258 %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0 259 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 260 %2 = bitcast %struct.A* %a to i8* 261 %3 = bitcast i8* %2 to i8** 262 %vtable.i = load i8*, i8** %3, align 8 263 %4 = bitcast i8* %vtable.i to i32 (%struct.A*)** 264 %memptr.virtualfn.i = load i32 (%struct.A*)*, i32 (%struct.A*)** %4, align 8 265 %call.i = call i32 %memptr.virtualfn.i(%struct.A* %a) 266 ret i32 %call.i 267 } 268 269 define i32 @_Z2g2v() { 270 entry: 271 %a = alloca %struct.A, align 8 272 %0 = bitcast %struct.A* %a to i8* 273 %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0 274 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 275 %2 = bitcast %struct.A* %a to i8* 276 %3 = bitcast i8* %2 to i8** 277 %vtable.i = load i8*, i8** %3, align 8 278 %4 = getelementptr i8, i8* %vtable.i, i64 8 279 %5 = bitcast i8* %4 to i32 (%struct.A*)** 280 %memptr.virtualfn.i = load i32 (%struct.A*)*, i32 (%struct.A*)** %5, align 8 281 %call.i = call i32 %memptr.virtualfn.i(%struct.A* %a) 282 ret i32 %call.i 283 } 284 285 declare i32 @_ZN1A3vf1Ev(%struct.A* %this) 286 declare i32 @_ZN1A3vf2Ev(%struct.A* %this) 287 )IR"); 288 289 auto *GV = M->getNamedValue("_Z2g1v"); 290 ASSERT_TRUE(GV); 291 auto *F = dyn_cast<Function>(GV); 292 ASSERT_TRUE(F); 293 Instruction *Inst = &F->front().front(); 294 auto *AI = dyn_cast<AllocaInst>(Inst); 295 ASSERT_TRUE(AI); 296 Inst = &*++F->front().rbegin(); 297 auto *CI = dyn_cast<CallInst>(Inst); 298 ASSERT_TRUE(CI); 299 ASSERT_FALSE(CI->getCalledFunction()); 300 bool IsPromoted1 = tryPromoteCall(*CI); 301 EXPECT_TRUE(IsPromoted1); 302 GV = M->getNamedValue("_ZN1A3vf1Ev"); 303 ASSERT_TRUE(GV); 304 F = dyn_cast<Function>(GV); 305 EXPECT_EQ(F, CI->getCalledFunction()); 306 307 GV = M->getNamedValue("_Z2g2v"); 308 ASSERT_TRUE(GV); 309 F = dyn_cast<Function>(GV); 310 ASSERT_TRUE(F); 311 Inst = &F->front().front(); 312 AI = dyn_cast<AllocaInst>(Inst); 313 ASSERT_TRUE(AI); 314 Inst = &*++F->front().rbegin(); 315 CI = dyn_cast<CallInst>(Inst); 316 ASSERT_TRUE(CI); 317 ASSERT_FALSE(CI->getCalledFunction()); 318 bool IsPromoted2 = tryPromoteCall(*CI); 319 EXPECT_TRUE(IsPromoted2); 320 GV = M->getNamedValue("_ZN1A3vf2Ev"); 321 ASSERT_TRUE(GV); 322 F = dyn_cast<Function>(GV); 323 EXPECT_EQ(F, CI->getCalledFunction()); 324 } 325 326 // Check that it isn't crashing due to missing promotion legality. 327 TEST(CallPromotionUtilsTest, TryPromoteCall_Legality) { 328 LLVMContext C; 329 std::unique_ptr<Module> M = parseIR(C, 330 R"IR( 331 %struct1 = type <{ i32, i64 }> 332 %struct2 = type <{ i32, i64 }> 333 334 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }> 335 %class.Interface = type { i32 (...)** } 336 337 @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (%struct2 (%class.Impl*)* @_ZN4Impl3RunEv to i8*)] } 338 339 define %struct1 @f() { 340 entry: 341 %o = alloca %class.Impl 342 %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 343 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base 344 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 345 store i32 3, i32* %f 346 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 347 %c = bitcast %class.Interface* %base.i to %struct1 (%class.Interface*)*** 348 %vtable.i = load %struct1 (%class.Interface*)**, %struct1 (%class.Interface*)*** %c 349 %fp = load %struct1 (%class.Interface*)*, %struct1 (%class.Interface*)** %vtable.i 350 %rv = call %struct1 %fp(%class.Interface* nonnull %base.i) 351 ret %struct1 %rv 352 } 353 354 declare %struct2 @_ZN4Impl3RunEv(%class.Impl* %this) 355 )IR"); 356 357 auto *GV = M->getNamedValue("f"); 358 ASSERT_TRUE(GV); 359 auto *F = dyn_cast<Function>(GV); 360 ASSERT_TRUE(F); 361 Instruction *Inst = &F->front().front(); 362 auto *AI = dyn_cast<AllocaInst>(Inst); 363 ASSERT_TRUE(AI); 364 Inst = &*++F->front().rbegin(); 365 auto *CI = dyn_cast<CallInst>(Inst); 366 ASSERT_TRUE(CI); 367 ASSERT_FALSE(CI->getCalledFunction()); 368 bool IsPromoted = tryPromoteCall(*CI); 369 EXPECT_FALSE(IsPromoted); 370 } 371