Marking volatile accesses as !unordered seems excessively conservative. For instance, LLVM is not able to optimize declare void @escape(i32*) declare i32 @read_only(i32) readonly define i32 @f(i1* %c) { entry: %a = alloca i32 %b = alloca i32 call void @escape(i32* %a) call void @escape(i32* %b) %a0 = load i32, i32* %b, align 4 %lv = load volatile i32, i32* %b %a1 = load i32, i32* %a, align 4 %result = add i32 %a0, %a1 ret i32 %result } to "%result = %a0 << 1" via -O3. NB: changing the volatile load to a volatile store triggers the optimization (via -instcombine) -- llvm::FindAvailableLoadedValue just skips over noalias ordered stores. -- Sanjoy
Chandler Carruth
2015-Apr-03 01:09 UTC
[LLVMdev] why are volatile memory accesses ordered?
Could you explain why you think it is worthwhile to optimize code involving a volatile access? On Thu, Apr 2, 2015 at 6:08 PM Sanjoy Das <sanjoy at playingwithpointers.com> wrote:> Marking volatile accesses as !unordered seems excessively > conservative. For instance, LLVM is not able to optimize > > declare void @escape(i32*) > declare i32 @read_only(i32) readonly > > define i32 @f(i1* %c) { > entry: > %a = alloca i32 > %b = alloca i32 > call void @escape(i32* %a) > call void @escape(i32* %b) > > %a0 = load i32, i32* %b, align 4 > %lv = load volatile i32, i32* %b > %a1 = load i32, i32* %a, align 4 > > %result = add i32 %a0, %a1 > ret i32 %result > } > > to "%result = %a0 << 1" via -O3. > > NB: changing the volatile load to a volatile store triggers the > optimization (via -instcombine) -- llvm::FindAvailableLoadedValue just > skips over noalias ordered stores. > > -- Sanjoy > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150403/dd525b55/attachment.html>
On Thu, Apr 2, 2015 at 6:04 PM, Sanjoy Das <sanjoy at playingwithpointers.com> wrote:> Marking volatile accesses as !unordered seems excessively > conservative. For instance, LLVM is not able to optimize > > declare void @escape(i32*) > declare i32 @read_only(i32) readonly > > define i32 @f(i1* %c) { > entry: > %a = alloca i32 > %b = alloca i32 > call void @escape(i32* %a) > call void @escape(i32* %b) > > %a0 = load i32, i32* %b, align 4 > %lv = load volatile i32, i32* %b > %a1 = load i32, i32* %a, align 4 > > %result = add i32 %a0, %a1 > ret i32 %result > } > > to "%result = %a0 << 1" via -O3.Maybe it's just late, but what am i missing that makes you think this optimizes to %a0 << 1? In particular, how do you know what %a1 is, since %a0 and %a1 are loads of different pointers? GVN otherwise optimizes volatile loads (as does everything using memdep). The volatile load will not be a barrier to eliminating two loads. You can see a testcase like yours in transforms/GVN/volatile.ll If you replace %a with %b in %a1, it should do with %result = add i32 %a0, %a0, which i presume will transform the way you want it.>> NB: changing the volatile load to a volatile store triggers the > optimization (via -instcombine) -- llvm::FindAvailableLoadedValue just > skips over noalias ordered stores. > > -- Sanjoy > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Dunno whether it's worthwhile, but we definitely test for it, and if his two non-volatile loads were identical, we'd definitely eliminate them in GVN. On Thu, Apr 2, 2015 at 6:09 PM, Chandler Carruth <chandlerc at google.com> wrote:> Could you explain why you think it is worthwhile to optimize code involving > a volatile access? > > On Thu, Apr 2, 2015 at 6:08 PM Sanjoy Das <sanjoy at playingwithpointers.com> > wrote: >> >> Marking volatile accesses as !unordered seems excessively >> conservative. For instance, LLVM is not able to optimize >> >> declare void @escape(i32*) >> declare i32 @read_only(i32) readonly >> >> define i32 @f(i1* %c) { >> entry: >> %a = alloca i32 >> %b = alloca i32 >> call void @escape(i32* %a) >> call void @escape(i32* %b) >> >> %a0 = load i32, i32* %b, align 4 >> %lv = load volatile i32, i32* %b >> %a1 = load i32, i32* %a, align 4 >> >> %result = add i32 %a0, %a1 >> ret i32 %result >> } >> >> to "%result = %a0 << 1" via -O3. >> >> NB: changing the volatile load to a volatile store triggers the >> optimization (via -instcombine) -- llvm::FindAvailableLoadedValue just >> skips over noalias ordered stores. >> >> -- Sanjoy >> _______________________________________________ >> LLVM Developers mailing list >> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >