क्लैंग का एक हालिया निर्माण getelementptr
निर्देश का वर्णन नहीं करता है जो आप वर्णन करते हैं। यह सामान्य अनुक्रमण का उपयोग करता है।
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
%struct.foo = type { [16 x %struct.bar] }
%struct.bar = type { i32, i32, i8, i8, i8 }
define i32 @func(%struct.foo* nocapture %f, i32 %num) {
entry:
%cmp25 = icmp sgt i32 %num, 0
br i1 %cmp25, label %for.body.preheader, label %for.cond.cleanup
for.body.preheader: ; preds = %entry
%xtraiter = and i32 %num, 1
%0 = icmp eq i32 %num, 1
br i1 %0, label %for.cond.cleanup.loopexit.unr-lcssa, label %for.body.preheader.new
for.body.preheader.new: ; preds = %for.body.preheader
%unroll_iter = sub i32 %num, %xtraiter
br label %for.body
for.cond.cleanup.loopexit.unr-lcssa.loopexit: ; preds = %for.body
%indvars.iv.next.1.lcssa = phi i64 [ %indvars.iv.next.1, %for.body ]
br label %for.cond.cleanup.loopexit.unr-lcssa
for.cond.cleanup.loopexit.unr-lcssa: ; preds = %for.cond.cleanup.loopexit.unr-lcssa.loopexit, %for.body.preheader
%indvars.iv.unr = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next.1.lcssa, %for.cond.cleanup.loopexit.unr-lcssa.loopexit ]
%lcmp.mod = icmp eq i32 %xtraiter, 0
br i1 %lcmp.mod, label %for.cond.cleanup.loopexit, label %for.body.epil.preheader
for.body.epil.preheader: ; preds = %for.cond.cleanup.loopexit.unr-lcssa
br label %for.body.epil
for.body.epil: ; preds = %for.body.epil.preheader
%int1.epil = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.unr, i32 0
store i32 1, i32* %int1.epil, align 4, !tbaa !1
%int2.epil = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.unr, i32 1
store i32 2, i32* %int2.epil, align 4, !tbaa !6
%char1.epil = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.unr, i32 2
store i8 97, i8* %char1.epil, align 4, !tbaa !7
%char2.epil = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.unr, i32 3
store i8 98, i8* %char2.epil, align 1, !tbaa !8
%char3.epil = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.unr, i32 4
store i8 99, i8* %char3.epil, align 2, !tbaa !9
br label %for.cond.cleanup.loopexit.epilog-lcssa
for.cond.cleanup.loopexit.epilog-lcssa: ; preds = %for.body.epil
br label %for.cond.cleanup.loopexit
for.cond.cleanup.loopexit: ; preds = %for.cond.cleanup.loopexit.unr-lcssa, %for.cond.cleanup.loopexit.epilog-lcssa
br label %for.cond.cleanup
for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry
ret i32 %num
for.body: ; preds = %for.body, %for.body.preheader.new
%indvars.iv = phi i64 [ 0, %for.body.preheader.new ], [ %indvars.iv.next.1, %for.body ]
%niter = phi i32 [ %unroll_iter, %for.body.preheader.new ], [ %niter.nsub.1, %for.body ]
%int1 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv, i32 0
store i32 1, i32* %int1, align 4, !tbaa !1
%int2 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv, i32 1
store i32 2, i32* %int2, align 4, !tbaa !6
%char1 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv, i32 2
store i8 97, i8* %char1, align 4, !tbaa !7
%char2 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv, i32 3
store i8 98, i8* %char2, align 1, !tbaa !8
%char3 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv, i32 4
store i8 99, i8* %char3, align 2, !tbaa !9
%indvars.iv.next = or i64 %indvars.iv, 1
%int1.1 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.next, i32 0
store i32 1, i32* %int1.1, align 4, !tbaa !1
%int2.1 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.next, i32 1
store i32 2, i32* %int2.1, align 4, !tbaa !6
%char1.1 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.next, i32 2
store i8 97, i8* %char1.1, align 4, !tbaa !7
%char2.1 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.next, i32 3
store i8 98, i8* %char2.1, align 1, !tbaa !8
%char3.1 = getelementptr inbounds %struct.foo, %struct.foo* %f, i64 0, i32 0, i64 %indvars.iv.next, i32 4
store i8 99, i8* %char3.1, align 2, !tbaa !9
%indvars.iv.next.1 = add nsw i64 %indvars.iv, 2
%niter.nsub.1 = add i32 %niter, -2
%niter.ncmp.1 = icmp eq i32 %niter.nsub.1, 0
br i1 %niter.ncmp.1, label %for.cond.cleanup.loopexit.unr-lcssa.loopexit, label %for.body
}
आप आईआर आपने देखा ठीक करने के चरण के साथ आपके सवाल का अद्यतन करते हैं, मैं समझाने के लिए क्यों LLVM यह उत्पादन खुश हूँ: अजीब बात यह है unrolled पाश के शरीर में दो बार के साथ एक संस्करण का उत्पादन होता है , लेकिन मैं निर्देश के नाम पर आधारित अनुमान नहीं लेना चाहता हूं।
पढ़ें http://llvm.org/docs/GetElementPtr.html –
'scev' स्केलर विकास के लिए खड़ा है। मुझे नहीं पता कि यह अनुकूलन क्यों होता है, लेकिन आप वहां से शुरू कर सकते हैं। –
क्या आप अपने बिल्ड विकल्प और पूरे llvm ir पोस्ट कर सकते हैं? कम से कम स्टोर हिस्से के लिए? –