diff --git a/llvm/include/llvm/Transforms/IPO.h b/llvm/include/llvm/Transforms/IPO.h --- a/llvm/include/llvm/Transforms/IPO.h +++ b/llvm/include/llvm/Transforms/IPO.h @@ -29,6 +29,10 @@ class GlobalValue; class raw_ostream; +//Global variable to capture user input from optional OPT flag 'argpromotion-max-elements-to-promote' +//see ArgumentPromotion{.cpp,.h} +extern unsigned MaxElemsToPromote; + //===----------------------------------------------------------------------===// // // These functions removes symbols from functions and modules. If OnlyDebugInfo @@ -149,7 +153,7 @@ /// be passed by value if the number of elements passed is smaller or /// equal to maxElements (maxElements == 0 means always promote). /// -Pass *createArgumentPromotionPass(unsigned maxElements = 3); +Pass *createArgumentPromotionPass(unsigned maxElements = MaxElemsToPromote); //===----------------------------------------------------------------------===// /// createOpenMPOptLegacyPass - OpenMP specific optimizations. diff --git a/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h b/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h --- a/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h +++ b/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h @@ -14,9 +14,7 @@ #include "llvm/IR/PassManager.h" namespace llvm { -//opt flag (if supplied) populates this Global Variable in the llvm namespace. Default value is set to 3, as was existing before. -//This global value can be changed via user input to set the maximum number of members that can be promoted with an aggregate. -static unsigned GL_NUMPROMARGS = 3; + class TargetTransformInfo; /// Argument promotion pass. diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -90,8 +90,15 @@ #define DEBUG_TYPE "argpromotion" -//opt flag to capture user supplied value for GV: GL_NUMPROMARGS -cl::opt argmax("numargspromoted", cl::desc("Specify number of args to promote"), cl::value_desc("numargs"), cl::location(llvm::GL_NUMPROMARGS)); +//opt flag to capture user supplied value for global variable MaxElemsToPromote +cl::opt argmax("argpromotion-max-elements-to-promote", \ + cl::desc("Specify maximum number of elements of an aggregate to promote. \ + Currently, promotion of aggregates is limited to only promote up to three elements of the aggregate "), \ + cl::location(llvm::MaxElemsToPromote)); + +//global variable (declared in IPO.h file) captures user input from optional OPT flag 'argpromotion-max-elements-to-promote' +//When flag is NOT set, the global variable defaults to 3. +unsigned llvm::MaxElemsToPromote = 3; STATISTIC(NumArgumentsPromoted, "Number of pointer arguments promoted"); STATISTIC(NumAggregatesPromoted, "Number of aggregate arguments promoted"); @@ -1072,7 +1079,7 @@ // Pass identification, replacement for typeid static char ID; - explicit ArgPromotion(unsigned MaxElements = GL_NUMPROMARGS) + explicit ArgPromotion(unsigned MaxElements = MaxElemsToPromote) : CallGraphSCCPass(ID), MaxElements(MaxElements) { initializeArgPromotionPass(*PassRegistry::getPassRegistry()); } @@ -1111,7 +1118,7 @@ "Promote 'by reference' arguments to scalars", false, false) Pass *llvm::createArgumentPromotionPass(unsigned MaxElements) { - return new ArgPromotion(GL_NUMPROMARGS); + return new ArgPromotion(MaxElements); } bool ArgPromotion::runOnSCC(CallGraphSCC &SCC) { diff --git a/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-DEFAULT.ll b/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-DEFAULT.ll --- a/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-DEFAULT.ll +++ b/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-DEFAULT.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basic-aa -mem2reg -argpromotion -mem2reg -S | FileCheck %s +; RUN: opt < %s -argpromotion -S | FileCheck %s target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" @@ -29,10 +29,7 @@ ; CHECK-NEXT: ret i32 0 ; entry: - %retval = alloca i32, align 4 %four = alloca %struct.fourmem, align 4 - %T = alloca i32, align 4 - store i32 0, i32* %retval, align 4 %a = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 0 store i32 1, i32* %a, align 4 %b = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 1 @@ -42,7 +39,6 @@ %d = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 3 store i32 4, i32* %d, align 4 %call = call i32 @_ZL6calleeP7fourmem(%struct.fourmem* %four) - store i32 %call, i32* %T, align 4 ret i32 0 } @@ -57,27 +53,18 @@ ; CHECK-NEXT: ret i32 %{{.*}} ; entry: - %t.addr = alloca %struct.fourmem*, align 8 - %S = alloca i32, align 4 - store %struct.fourmem* %t, %struct.fourmem** %t.addr, align 8 - %0 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %a = getelementptr inbounds %struct.fourmem, %struct.fourmem* %0, i32 0, i32 0 - %1 = load i32, i32* %a, align 4 - %2 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %b = getelementptr inbounds %struct.fourmem, %struct.fourmem* %2, i32 0, i32 1 - %3 = load i32, i32* %b, align 4 - %add = add nsw i32 %1, %3 - %4 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %c = getelementptr inbounds %struct.fourmem, %struct.fourmem* %4, i32 0, i32 2 - %5 = load i32, i32* %c, align 4 - %add1 = add nsw i32 %add, %5 - %6 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %d = getelementptr inbounds %struct.fourmem, %struct.fourmem* %6, i32 0, i32 3 - %7 = load i32, i32* %d, align 4 - %add2 = add nsw i32 %add1, %7 - store i32 %add2, i32* %S, align 4 - %8 = load i32, i32* %S, align 4 - ret i32 %8 + %a = getelementptr inbounds %struct.fourmem, %struct.fourmem* %t, i32 0, i32 0 + %0 = load i32, i32* %a, align 4 + %b = getelementptr inbounds %struct.fourmem, %struct.fourmem* %t, i32 0, i32 1 + %1 = load i32, i32* %b, align 4 + %add = add nsw i32 %0, %1 + %c = getelementptr inbounds %struct.fourmem, %struct.fourmem* %t, i32 0, i32 2 + %2 = load i32, i32* %c, align 4 + %add1 = add nsw i32 %add, %2 + %d = getelementptr inbounds %struct.fourmem, %struct.fourmem* %t, i32 0, i32 3 + %3 = load i32, i32* %d, align 4 + %add2 = add nsw i32 %add1, %3 + ret i32 %add2 } attributes #0 = { noinline norecurse ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-INTMAX.ll b/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-INTMAX.ll --- a/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-INTMAX.ll +++ b/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-INTMAX.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basic-aa -mem2reg -argpromotion -mem2reg -numargspromoted=2147483647 -S | FileCheck %s +; RUN: opt < %s -argpromotion -argpromotion-max-elements-to-promote=2147483647 -S | FileCheck %s target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" @@ -17,22 +17,19 @@ ; CHECK-NEXT: store {{.*}} ; CHECK-NEXT: {{%.*}} = getelementptr {{.*}} ; CHECK-NEXT: store {{.*}} -; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 0 -; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 -; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 1 -; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 -; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 2 -; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 -; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 3 -; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 -; CHECK-NEXT: %{{.*}} = call i32 @{{.*}}fourmem(i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val) -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 0 +; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 +; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 1 +; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 +; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 2 +; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 +; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 3 +; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 +; CHECK-NEXT: %{{.*}} = call i32 @{{.*}}fourmem(i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val) +; CHECK-NEXT: ret i32 0 ; entry: - %retval = alloca i32, align 4 %four = alloca %struct.fourmem, align 4 - %T = alloca i32, align 4 - store i32 0, i32* %retval, align 4 %a = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 0 store i32 1, i32* %a, align 4 %b = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 1 @@ -41,43 +38,33 @@ store i32 3, i32* %c, align 4 %d = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 3 store i32 4, i32* %d, align 4 - %call = call i32 @_ZL6calleeP7fourmem(%struct.fourmem* %four) - store i32 %call, i32* %T, align 4 + %four.idx = getelementptr %struct.fourmem, %struct.fourmem* %four, i64 0, i32 0 + %four.idx.val = load i32, i32* %four.idx, align 4 + %four.idx1 = getelementptr %struct.fourmem, %struct.fourmem* %four, i64 0, i32 1 + %four.idx1.val = load i32, i32* %four.idx1, align 4 + %four.idx2 = getelementptr %struct.fourmem, %struct.fourmem* %four, i64 0, i32 2 + %four.idx2.val = load i32, i32* %four.idx2, align 4 + %four.idx3 = getelementptr %struct.fourmem, %struct.fourmem* %four, i64 0, i32 3 + %four.idx3.val = load i32, i32* %four.idx3, align 4 + %0 = call i32 @_ZL6calleeP7fourmem(i32 %four.idx.val, i32 %four.idx1.val, i32 %four.idx2.val, i32 %four.idx3.val) ret i32 0 } ; Function Attrs: noinline nounwind ssp uwtable -define internal i32 @_ZL6calleeP7fourmem(%struct.fourmem* %t) #1 { +define internal i32 @_ZL6calleeP7fourmem(i32 %t.0.0.val, i32 %t.0.1.val, i32 %t.0.2.val, i32 %t.0.3.val) #1 { ; CHECK-LABEL: define {{[^@]+}}@{{.*}}fourmem ; CHECK-SAME: (i32 %t.0.{{.*}}.val, i32 %t.0.{{.*}}.val, i32 %t.0.{{.*}}.val, i32 %t.0.{{.*}}.val) -; CHECK-NEXT: entry: +; CHECK-NEXT: entry: ; CHECK-NEXT: %add{{.*}} = add nsw i32 {{.*}}, {{.*}} ; CHECK-NEXT: %add{{.*}} = add nsw i32 {{.*}}, {{.*}} ; CHECK-NEXT: %add{{.*}} = add nsw i32 {{.*}}, {{.*}} -; CHECK-NEXT: ret i32 %{{.*}} +; CHECK-NEXT: ret i32 %{{.*}} ; entry: - %t.addr = alloca %struct.fourmem*, align 8 - %S = alloca i32, align 4 - store %struct.fourmem* %t, %struct.fourmem** %t.addr, align 8 - %0 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %a = getelementptr inbounds %struct.fourmem, %struct.fourmem* %0, i32 0, i32 0 - %1 = load i32, i32* %a, align 4 - %2 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %b = getelementptr inbounds %struct.fourmem, %struct.fourmem* %2, i32 0, i32 1 - %3 = load i32, i32* %b, align 4 - %add = add nsw i32 %1, %3 - %4 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %c = getelementptr inbounds %struct.fourmem, %struct.fourmem* %4, i32 0, i32 2 - %5 = load i32, i32* %c, align 4 - %add1 = add nsw i32 %add, %5 - %6 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %d = getelementptr inbounds %struct.fourmem, %struct.fourmem* %6, i32 0, i32 3 - %7 = load i32, i32* %d, align 4 - %add2 = add nsw i32 %add1, %7 - store i32 %add2, i32* %S, align 4 - %8 = load i32, i32* %S, align 4 - ret i32 %8 + %add = add nsw i32 %t.0.0.val, %t.0.1.val + %add1 = add nsw i32 %add, %t.0.2.val + %add2 = add nsw i32 %add1, %t.0.3.val + ret i32 %add2 } attributes #0 = { noinline norecurse ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-ZERO.ll b/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-ZERO.ll --- a/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-ZERO.ll +++ b/llvm/test/Transforms/ArgumentPromotion/fourmember-struct-promote-ZERO.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -basic-aa -mem2reg -argpromotion -mem2reg -numargspromoted=0 -S | FileCheck %s +; RUN: opt < %s -argpromotion -argpromotion-max-elements-to-promote=0 -S | FileCheck %s target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" @@ -17,67 +17,51 @@ ; CHECK-NEXT: store {{.*}} ; CHECK-NEXT: {{%.*}} = getelementptr {{.*}} ; CHECK-NEXT: store {{.*}} -; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 0 -; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 -; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 1 -; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 -; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 2 -; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 -; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 3 -; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 -; CHECK-NEXT: %{{.*}} = call i32 @{{.*}}fourmem(i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val) -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 0 +; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 +; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 1 +; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 +; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 2 +; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 +; CHECK-NEXT: [[F]].idx{{.*}} = getelementptr %struct.fourmem, %struct.fourmem* [[F]], i64 0, i32 3 +; CHECK-NEXT: [[F]].idx{{.*}}.val = load i32, i32* [[F]].idx{{.*}}, align 4 +; CHECK-NEXT: %{{.*}} = call i32 @{{.*}}fourmem(i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val, i32 [[F]].idx{{.*}}.val) +; CHECK-NEXT: ret i32 0 ; -entry: - %retval = alloca i32, align 4 - %four = alloca %struct.fourmem, align 4 - %T = alloca i32, align 4 - store i32 0, i32* %retval, align 4 - %a = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 0 - store i32 1, i32* %a, align 4 - %b = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 1 - store i32 2, i32* %b, align 4 +entry: + %four = alloca %struct.fourmem, align 4 %a = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 0 + store i32 1, i32* %a, align 4 %b = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 1 store i32 2, i32* %b, align 4 %c = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 2 store i32 3, i32* %c, align 4 %d = getelementptr inbounds %struct.fourmem, %struct.fourmem* %four, i32 0, i32 3 store i32 4, i32* %d, align 4 - %call = call i32 @_ZL6calleeP7fourmem(%struct.fourmem* %four) - store i32 %call, i32* %T, align 4 + %four.idx = getelementptr %struct.fourmem, %struct.fourmem* %four, i64 0, i32 0 + %four.idx.val = load i32, i32* %four.idx, align 4 + %four.idx1 = getelementptr %struct.fourmem, %struct.fourmem* %four, i64 0, i32 1 + %four.idx1.val = load i32, i32* %four.idx1, align 4 + %four.idx2 = getelementptr %struct.fourmem, %struct.fourmem* %four, i64 0, i32 2 + %four.idx2.val = load i32, i32* %four.idx2, align 4 + %four.idx3 = getelementptr %struct.fourmem, %struct.fourmem* %four, i64 0, i32 3 + %four.idx3.val = load i32, i32* %four.idx3, align 4 + %0 = call i32 @_ZL6calleeP7fourmem(i32 %four.idx.val, i32 %four.idx1.val, i32 %four.idx2.val, i32 %four.idx3.val) ret i32 0 } ; Function Attrs: noinline nounwind ssp uwtable -define internal i32 @_ZL6calleeP7fourmem(%struct.fourmem* %t) #1 { +define internal i32 @_ZL6calleeP7fourmem(i32 %t.0.0.val, i32 %t.0.1.val, i32 %t.0.2.val, i32 %t.0.3.val) #1 { ; CHECK-LABEL: define {{[^@]+}}@{{.*}}fourmem ; CHECK-SAME: (i32 %t.0.{{.*}}.val, i32 %t.0.{{.*}}.val, i32 %t.0.{{.*}}.val, i32 %t.0.{{.*}}.val) -; CHECK-NEXT: entry: +; CHECK-NEXT: entry: ; CHECK-NEXT: %add{{.*}} = add nsw i32 {{.*}}, {{.*}} ; CHECK-NEXT: %add{{.*}} = add nsw i32 {{.*}}, {{.*}} ; CHECK-NEXT: %add{{.*}} = add nsw i32 {{.*}}, {{.*}} -; CHECK-NEXT: ret i32 %{{.*}} +; CHECK-NEXT: ret i32 %{{.*}} ; entry: - %t.addr = alloca %struct.fourmem*, align 8 - %S = alloca i32, align 4 - store %struct.fourmem* %t, %struct.fourmem** %t.addr, align 8 - %0 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %a = getelementptr inbounds %struct.fourmem, %struct.fourmem* %0, i32 0, i32 0 - %1 = load i32, i32* %a, align 4 - %2 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %b = getelementptr inbounds %struct.fourmem, %struct.fourmem* %2, i32 0, i32 1 - %3 = load i32, i32* %b, align 4 - %add = add nsw i32 %1, %3 - %4 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %c = getelementptr inbounds %struct.fourmem, %struct.fourmem* %4, i32 0, i32 2 - %5 = load i32, i32* %c, align 4 - %add1 = add nsw i32 %add, %5 - %6 = load %struct.fourmem*, %struct.fourmem** %t.addr, align 8 - %d = getelementptr inbounds %struct.fourmem, %struct.fourmem* %6, i32 0, i32 3 - %7 = load i32, i32* %d, align 4 - %add2 = add nsw i32 %add1, %7 - store i32 %add2, i32* %S, align 4 - %8 = load i32, i32* %S, align 4 - ret i32 %8 + %add = add nsw i32 %t.0.0.val, %t.0.1.val + %add1 = add nsw i32 %add, %t.0.2.val + %add2 = add nsw i32 %add1, %t.0.3.val + ret i32 %add2 } attributes #0 = { noinline norecurse ssp uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="penryn" "target-features"="+cx16,+cx8,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }