[PATCH] D108782: [MergeICmps] Ignore clobbering instructions before the loads

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 17 14:30:24 PDT 2021


nikic added a comment.

Thanks for the report! This seems to have exposed a pre-existing problem. Here's a variant that fails also prior to this patch (note the commented init calls):

  target triple = "x86_64-unknown-linux-gnu"
  
  %"struct.a::c" = type { i32, i32*, i8* }
  
  define i1 @test() {
  entry:
    %h = alloca %"struct.a::c", align 8
    %i = alloca %"struct.a::c", align 8
    ;call void @init(%"struct.a::c"* %h)
    ;call void @init(%"struct.a::c"* %i)
    %e = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %h, i64 0, i32 2
    %v3 = load i8*, i8** %e, align 8
    %e2 = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %i, i64 0, i32 2
    %v4 = load i8*, i8** %e2, align 8
    %cmp = icmp eq i8* %v3, %v4
    br i1 %cmp, label %land.lhs.true, label %land.end
  
  land.lhs.true:                                    ; preds = %entry
    %d = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %h, i64 0, i32 1
    %v5 = load i32*, i32** %d, align 8
    %d3 = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %i, i64 0, i32 1
    %v6 = load i32*, i32** %d3, align 8
    %cmp4 = icmp eq i32* %v5, %v6
    br i1 %cmp4, label %land.rhs, label %land.end
  
  land.rhs:                                         ; preds = %land.lhs.true
    %j = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %h, i64 0, i32 0
    %v7 = load i32, i32* %j, align 8
    %j5 = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %i, i64 0, i32 0
    %v8 = load i32, i32* %j5, align 8
    %cmp6 = icmp eq i32 %v7, %v8
    br label %land.end
  
  land.end:                                         ; preds = %land.rhs, %land.lhs.true, %entry
    %v9 = phi i1 [ false, %land.lhs.true ], [ false, %entry ], [ %cmp6, %land.rhs ]
    ret i1 %v9
  }
  
  declare void @init(%"struct.a::c"*)

The result of the transform looks like this:

  define i1 @test() {
  land.rhs2:
    %0 = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %h, i64 0, i32 0
    %1 = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %i, i64 0, i32 0
    %2 = load i32, i32* %0, align 4
    %3 = load i32, i32* %1, align 4
    %4 = icmp eq i32 %2, %3
    br i1 %4, label %"land.lhs.true+entry", label %land.end
  
  "land.lhs.true+entry":                            ; preds = %land.rhs2
    %h = alloca %"struct.a::c", align 8
    %i = alloca %"struct.a::c", align 8
    %5 = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %h, i64 0, i32 1
    %6 = getelementptr inbounds %"struct.a::c", %"struct.a::c"* %i, i64 0, i32 1
    %cstr = bitcast i32** %5 to i8*
    %cstr1 = bitcast i32** %6 to i8*
    %memcmp = call i32 @memcmp(i8* %cstr, i8* %cstr1, i64 16)
    %7 = icmp eq i32 %memcmp, 0
    br label %land.end
  
  land.end:                                         ; preds = %land.rhs2, %"land.lhs.true+entry"
    %v9 = phi i1 [ %7, %"land.lhs.true+entry" ], [ false, %land.rhs2 ]
    ret i1 %v9
  }

The comparison at offset 0 doesn't get merged as it's non-contiguous, but for some reason it also gets moved to the start, such that the allocas are effectively sunk,


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D108782/new/

https://reviews.llvm.org/D108782



More information about the llvm-commits mailing list