1 ; RUN: llc < %s -mtriple=x86_64-linux -enable-x86-lea-opt | FileCheck %s 2 3 %struct.anon1 = type { i32, i32, i32 } 4 %struct.anon2 = type { i32, [32 x i32], i32 } 5 6 @arr1 = external global [65 x %struct.anon1], align 16 7 @arr2 = external global [65 x %struct.anon2], align 16 8 9 define void @test1(i64 %x) nounwind { 10 entry: 11 %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0 12 %tmp = load i32, i32* %a, align 4 13 %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1 14 %tmp1 = load i32, i32* %b, align 4 15 %sub = sub i32 %tmp, %tmp1 16 %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2 17 %tmp2 = load i32, i32* %c, align 4 18 %add = add nsw i32 %sub, %tmp2 19 switch i32 %add, label %sw.epilog [ 20 i32 1, label %sw.bb.1 21 i32 2, label %sw.bb.2 22 ] 23 24 sw.bb.1: ; preds = %entry 25 store i32 111, i32* %b, align 4 26 store i32 222, i32* %c, align 4 27 br label %sw.epilog 28 29 sw.bb.2: ; preds = %entry 30 store i32 333, i32* %b, align 4 31 store i32 444, i32* %c, align 4 32 br label %sw.epilog 33 34 sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry 35 ret void 36 ; CHECK-LABEL: test1: 37 ; CHECK: leaq (%rdi,%rdi,2), [[REG1:%[a-z]+]] 38 ; CHECK: movl arr1(,[[REG1]],4), {{.*}} 39 ; CHECK: leaq arr1+4(,[[REG1]],4), [[REG2:%[a-z]+]] 40 ; CHECK: subl arr1+4(,[[REG1]],4), {{.*}} 41 ; CHECK: leaq arr1+8(,[[REG1]],4), [[REG3:%[a-z]+]] 42 ; CHECK: addl arr1+8(,[[REG1]],4), {{.*}} 43 ; CHECK: movl ${{[1-4]+}}, ([[REG2]]) 44 ; CHECK: movl ${{[1-4]+}}, ([[REG3]]) 45 ; CHECK: movl ${{[1-4]+}}, ([[REG2]]) 46 ; CHECK: movl ${{[1-4]+}}, ([[REG3]]) 47 } 48 49 define void @test2(i64 %x) nounwind optsize { 50 entry: 51 %a = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 0 52 %tmp = load i32, i32* %a, align 4 53 %b = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 1 54 %tmp1 = load i32, i32* %b, align 4 55 %sub = sub i32 %tmp, %tmp1 56 %c = getelementptr inbounds [65 x %struct.anon1], [65 x %struct.anon1]* @arr1, i64 0, i64 %x, i32 2 57 %tmp2 = load i32, i32* %c, align 4 58 %add = add nsw i32 %sub, %tmp2 59 switch i32 %add, label %sw.epilog [ 60 i32 1, label %sw.bb.1 61 i32 2, label %sw.bb.2 62 ] 63 64 sw.bb.1: ; preds = %entry 65 store i32 111, i32* %b, align 4 66 store i32 222, i32* %c, align 4 67 br label %sw.epilog 68 69 sw.bb.2: ; preds = %entry 70 store i32 333, i32* %b, align 4 71 store i32 444, i32* %c, align 4 72 br label %sw.epilog 73 74 sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry 75 ret void 76 ; CHECK-LABEL: test2: 77 ; CHECK: leaq (%rdi,%rdi,2), [[REG1:%[a-z]+]] 78 ; CHECK: leaq arr1+4(,[[REG1]],4), [[REG2:%[a-z]+]] 79 ; CHECK: movl -4([[REG2]]), {{.*}} 80 ; CHECK: subl ([[REG2]]), {{.*}} 81 ; CHECK: leaq arr1+8(,[[REG1]],4), [[REG3:%[a-z]+]] 82 ; CHECK: addl ([[REG3]]), {{.*}} 83 ; CHECK: movl ${{[1-4]+}}, ([[REG2]]) 84 ; CHECK: movl ${{[1-4]+}}, ([[REG3]]) 85 ; CHECK: movl ${{[1-4]+}}, ([[REG2]]) 86 ; CHECK: movl ${{[1-4]+}}, ([[REG3]]) 87 } 88 89 ; Check that LEA optimization pass takes into account a resultant address 90 ; displacement when choosing a LEA instruction for replacing a redundant 91 ; address recalculation. 92 93 define void @test3(i64 %x) nounwind optsize { 94 entry: 95 %a = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 2 96 %tmp = load i32, i32* %a, align 4 97 %b = getelementptr inbounds [65 x %struct.anon2], [65 x %struct.anon2]* @arr2, i64 0, i64 %x, i32 0 98 %tmp1 = load i32, i32* %b, align 4 99 %add = add nsw i32 %tmp, %tmp1 100 switch i32 %add, label %sw.epilog [ 101 i32 1, label %sw.bb.1 102 i32 2, label %sw.bb.2 103 ] 104 105 sw.bb.1: ; preds = %entry 106 store i32 111, i32* %a, align 4 107 store i32 222, i32* %b, align 4 108 br label %sw.epilog 109 110 sw.bb.2: ; preds = %entry 111 store i32 333, i32* %a, align 4 112 store i32 444, i32* %b, align 4 113 br label %sw.epilog 114 115 sw.epilog: ; preds = %sw.bb.2, %sw.bb.1, %entry 116 ret void 117 ; CHECK-LABEL: test3: 118 ; CHECK: imulq {{.*}}, [[REG1:%[a-z]+]] 119 ; CHECK: leaq arr2+132([[REG1]]), [[REG2:%[a-z]+]] 120 ; CHECK: leaq arr2([[REG1]]), [[REG3:%[a-z]+]] 121 122 ; REG3's definition is closer to movl than REG2's, but the pass still chooses 123 ; REG2 because it provides the resultant address displacement fitting 1 byte. 124 125 ; CHECK: movl ([[REG2]]), {{.*}} 126 ; CHECK: addl ([[REG3]]), {{.*}} 127 ; CHECK: movl ${{[1-4]+}}, ([[REG2]]) 128 ; CHECK: movl ${{[1-4]+}}, ([[REG3]]) 129 ; CHECK: movl ${{[1-4]+}}, ([[REG2]]) 130 ; CHECK: movl ${{[1-4]+}}, ([[REG3]]) 131 } 132