1; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux | FileCheck %s 2 3; The Peephole optimizer should fold the load into the cmp even with debug info. 4; CHECK-LABEL: _ZN3Foo3batEv 5; CHECK-NOT: movq pfoo 6; CHECK: cmpq {{%[a-z]+}}, pfoo(%rip) 7; 8; CHECK-LABEL: _Z3bazv 9; CHECK-NOT: movq wibble2 10; CHECK: cmpq {{%[a-z]+}}, wibble2(%rip) 11 12; Regenerate test with this command: 13; clang -emit-llvm -S -O2 -g 14; from this source: 15; struct Foo { 16; bool bat(); 17; bool operator==(Foo &arg) { return (this == &arg); } 18; }; 19; Foo *pfoo; 20; bool Foo::bat() { return (*this == *pfoo); } 21; 22; struct Wibble { 23; int x; 24; } *wibble1, *wibble2; 25; struct Flibble { 26; void bar(Wibble *c) { 27; if (c < wibble2) 28; wibble2 = 0; 29; c->x = 0; 30; } 31; } flibble; 32; void baz() { flibble.bar(wibble1); } 33 34%struct.Foo = type { i8 } 35%struct.Wibble = type { i32 } 36%struct.Flibble = type { i8 } 37 38@pfoo = global %struct.Foo* null, align 8 39@wibble1 = global %struct.Wibble* null, align 8 40@wibble2 = global %struct.Wibble* null, align 8 41@flibble = global %struct.Flibble zeroinitializer, align 1 42 43; Function Attrs: nounwind readonly uwtable 44define zeroext i1 @_ZN3Foo3batEv(%struct.Foo* %this) #0 align 2 { 45entry: 46 %0 = load %struct.Foo*, %struct.Foo** @pfoo, align 8 47 tail call void @llvm.dbg.value(metadata %struct.Foo* %0, i64 0, metadata !62, metadata !MDExpression()), !dbg !MDLocation(scope: !MDSubprogram()) 48 %cmp.i = icmp eq %struct.Foo* %0, %this 49 ret i1 %cmp.i 50} 51 52; Function Attrs: nounwind uwtable 53define void @_Z3bazv() #1 { 54entry: 55 %0 = load %struct.Wibble*, %struct.Wibble** @wibble1, align 8 56 tail call void @llvm.dbg.value(metadata %struct.Flibble* undef, i64 0, metadata !65, metadata !MDExpression()), !dbg !MDLocation(scope: !MDSubprogram()) 57 %1 = load %struct.Wibble*, %struct.Wibble** @wibble2, align 8 58 %cmp.i = icmp ugt %struct.Wibble* %1, %0 59 br i1 %cmp.i, label %if.then.i, label %_ZN7Flibble3barEP6Wibble.exit 60 61if.then.i: ; preds = %entry 62 store %struct.Wibble* null, %struct.Wibble** @wibble2, align 8 63 br label %_ZN7Flibble3barEP6Wibble.exit 64 65_ZN7Flibble3barEP6Wibble.exit: ; preds = %entry, %if.then.i 66 %x.i = getelementptr inbounds %struct.Wibble, %struct.Wibble* %0, i64 0, i32 0 67 store i32 0, i32* %x.i, align 4 68 ret void 69} 70 71; Function Attrs: nounwind readnone 72declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2 73 74attributes #0 = { nounwind readonly uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } 75attributes #1 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } 76attributes #2 = { nounwind readnone } 77 78 79!17 = !MDDerivedType(tag: DW_TAG_reference_type, baseType: null) 80!45 = !MDDerivedType(tag: DW_TAG_pointer_type, size: 64, align: 64, baseType: null) 81!62 = !MDLocalVariable(tag: DW_TAG_arg_variable, name: "arg", line: 4, arg: 2, scope: !MDSubprogram(), type: !17) 82!64 = !{%struct.Flibble* undef} 83!65 = !MDLocalVariable(tag: DW_TAG_arg_variable, name: "this", line: 13, arg: 1, flags: DIFlagArtificial | DIFlagObjectPointer, scope: !MDSubprogram(), type: !45) 84