; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes='require,function(codegenprepare)' -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s ; REQUIRES: aarch64-registered-target %struct.S = type { i8 } %struct.X = type { i32 } @g_getS = internal global %struct.S zeroinitializer, align 1 @g_getX = internal global %struct.X zeroinitializer, align 1 @guard = internal global i64 0, align 8 declare ptr @getS_dec() declare extern_weak dllimport ptr @getS_dllimport_function() define ptr @getS() personality ptr @__gxx_personality_v0 { entry: %guard = load atomic i8, ptr @guard acquire, align 8 %mask = and i8 %guard, 1 %cond = icmp eq i8 %mask, 0 br i1 %cond, label %to_be_init, label %return to_be_init: ; preds = %entry %is_init = call i32 @__cxa_guard_acquire(ptr @guard) %cond.2 = icmp ne i32 %is_init, 0 br i1 %cond.2, label %ctor, label %return ctor: ; preds = %to_be_init invoke void @S_ctor(ptr @g_getS) to label %continue unwind label %landing_pad continue: ; preds = %ctor call void @__cxa_guard_release(ptr @guard) br label %return return: ; preds = %continue, %to_be_init, %entry ret ptr @g_getS landing_pad: ; preds = %ctor %lp = landingpad { ptr, i32 } cleanup call void @__cxa_guard_abort(ptr @guard) resume { ptr, i32 } %lp } define ptr @getS_or_getX(i1 %cond) { entry: %result = select i1 %cond, ptr @g_getS, ptr @g_getX ret ptr %result } define weak ptr @getS_weak_function() { entry: ret ptr @g_getS } define linkonce_odr ptr @getS_linkonce_odr_function() { entry: ret ptr @g_getS } ; May revert propagation. define i32 @caller_1() { ; CHECK-LABEL: @caller_1( ; CHECK-NEXT: [[GETS_PTR:%.*]] = call ptr @getS() ; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr [[GETS_PTR]]) ; CHECK-NEXT: ret i32 [[GETI]] ; %getS_ptr = call ptr @getS() %getI = call i32 @S_getI(ptr @g_getS) ret i32 %getI } ; Cannot revert propagation due to use appearing in a different basic block. define i32 @caller_2() { ; CHECK-LABEL: @caller_2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[GETS_PTR:%.*]] = call ptr @getS() ; CHECK-NEXT: br label [[USE:%.*]] ; CHECK: use: ; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr [[GETS_PTR]]) ; CHECK-NEXT: ret i32 [[GETI]] ; entry: %getS_ptr = call ptr @getS() br label %use use: ; preds = %entry %getI = call i32 @S_getI(ptr %getS_ptr) ret i32 %getI } ; Cannot revert propagation due to use before call. define i32 @caller_3() { ; CHECK-LABEL: @caller_3( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr @g_getS) ; CHECK-NEXT: [[GETS_PTR:%.*]] = call ptr @getS() ; CHECK-NEXT: ret i32 [[GETI]] ; entry: %getI = call i32 @S_getI(ptr @g_getS) %getS_ptr = call ptr @getS() ret i32 %getI } ; Cannot revert propagation due to non-uniform returned constant. define i32 @caller_4(i1 %cond) { ; CHECK-LABEL: @caller_4( ; CHECK-NEXT: [[GETS_OR_GETX_PTR:%.*]] = call ptr @getS_or_getX(i1 [[COND:%.*]]) ; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr @g_getS) ; CHECK-NEXT: ret i32 [[GETI]] ; %getS_or_getX_ptr = call ptr @getS_or_getX(i1 %cond) %getI = call i32 @S_getI(ptr @g_getS) ret i32 %getI } ; Cannot revert propagation due to weak-linkage callee. define i32 @caller_5() { ; CHECK-LABEL: @caller_5( ; CHECK-NEXT: [[GETS_PTR:%.*]] = call ptr @getS_weak_function() ; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr @g_getS) ; CHECK-NEXT: ret i32 [[GETI]] ; %getS_ptr = call ptr @getS_weak_function() %getI = call i32 @S_getI(ptr @g_getS) ret i32 %getI } ; Cannot revert propagation due to callee with external function definition. define i32 @caller_6() { ; CHECK-LABEL: @caller_6( ; CHECK-NEXT: [[GETS_PTR:%.*]] = call ptr @getS_dec() ; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr @g_getS) ; CHECK-NEXT: ret i32 [[GETI]] ; %getS_ptr = call ptr @getS_dec() %getI = call i32 @S_getI(ptr @g_getS) ret i32 %getI } ; Cannot revert propagation due to callee with DLLImport storage class. define i32 @caller_7() { ; CHECK-LABEL: @caller_7( ; CHECK-NEXT: [[GETS_PTR:%.*]] = call ptr @getS_dllimport_function() ; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr @g_getS) ; CHECK-NEXT: ret i32 [[GETI]] ; %getS_ptr = call ptr @getS_dllimport_function() %getI = call i32 @S_getI(ptr @g_getS) ret i32 %getI } ; Cannot revert propagation due to callee whose definition may be overridden. define i32 @caller_8() { ; CHECK-LABEL: @caller_8( ; CHECK-NEXT: [[GETS_PTR:%.*]] = call ptr @getS_linkonce_odr_function() ; CHECK-NEXT: [[GETI:%.*]] = call i32 @S_getI(ptr @g_getS) ; CHECK-NEXT: ret i32 [[GETI]] ; %getS_ptr = call ptr @getS_linkonce_odr_function() %getI = call i32 @S_getI(ptr @g_getS) ret i32 %getI } declare i32 @__cxa_guard_acquire(ptr) declare void @S_ctor(ptr) declare i32 @S_getI(ptr) declare void @__cxa_guard_abort(ptr) declare void @__cxa_guard_release(ptr) declare i32 @__gxx_personality_v0(...)