1 ; RUN: %p2i -i %s --target=x8632 --filetype=obj --assemble --disassemble \ 2 ; RUN: --args -O2 -nonsfi=1 --ffunction-sections \ 3 ; RUN: | FileCheck --check-prefix=NONSFI %s 4 ; RUN: %p2i -i %s --target=x8632 --filetype=obj --assemble --disassemble \ 5 ; RUN: --args -O2 -nonsfi=0 --ffunction-sections \ 6 ; RUN: | FileCheck --check-prefix=DEFAULT %s 7 8 ; RUN: %p2i -i %s --target=arm32 --filetype=obj --assemble --disassemble \ 9 ; RUN: --args -O2 -nonsfi=1 --ffunction-sections \ 10 ; RUN: | FileCheck --check-prefix=ARM32-NONSFI %s 11 12 @G1 = internal global [4 x i8] zeroinitializer, align 4 13 @G2 = internal global [4 x i8] zeroinitializer, align 4 14 15 define internal void @testCallRegular() { 16 entry: 17 ; Make a call to a *different* function, plus use -ffunction-sections, to 18 ; force an appropriately-named relocation. 19 call i32 @testLoadBasic() 20 ret void 21 } 22 ; Expect a simple direct call to testCallRegular. 23 ; NONSFI-LABEL: testCallRegular 24 ; NONSFI: call {{.*}} R_386_PC32 {{.*}}testLoadBasic 25 ; DEFAULT-LABEL: testCallRegular 26 27 ; ARM32-NONSFI-LABEL: testCallRegular 28 ; ARM32-NONSFI: bl {{.*}} R_ARM_CALL {{.*}}testLoadBasic 29 30 define internal double @testCallBuiltin(double %val) { 31 entry: 32 %result = frem double %val, %val 33 ret double %result 34 } 35 ; Expect a simple direct call to fmod. 36 ; NONSFI-LABEL: testCallBuiltin 37 ; NONSFI: call {{.*}} R_386_PC32 fmod 38 ; DEFAULT-LABEL: testCallBuiltin 39 40 ; ARM32-NONSFI-LABEL: testCallBuiltin 41 ; ARM32-NONSFI: bl {{.*}} R_ARM_CALL {{.*}}fmod 42 43 define internal i32 @testLoadBasic() { 44 entry: 45 %a = bitcast [4 x i8]* @G1 to i32* 46 %b = load i32, i32* %a, align 1 47 ret i32 %b 48 } 49 ; Expect a load with a R_386_GOTOFF relocation. 50 ; NONSFI-LABEL: testLoadBasic 51 ; NONSFI: mov {{.*}} R_386_GOTOFF {{G1|.bss}} 52 ; DEFAULT-LABEL: testLoadBasic 53 54 ; ARM32 PIC load. 55 ; ARM32-NONSFI-LABEL: testLoadBasic 56 ; ARM32-NONSFI: movw {{.*}} R_ARM_MOVW_PREL_NC _GLOBAL_OFFSET_TABLE_ 57 ; ARM32-NONSFI-NEXT: movt {{.*}} R_ARM_MOVT_PREL _GLOBAL_OFFSET_TABLE_ 58 ; ARM32-NONSFI: movw [[REG:r[0-9]+]], {{.*}} R_ARM_MOVW_PREL_NC {{.*}}G1 59 ; ARM32-NONSFI-NEXT: movt [[REG]], {{.*}} R_ARM_MOVT_PREL {{.*}}G1 60 ; ARM32-NONSFI-NEXT: ldr r{{[0-9]+}}, [pc, [[REG]]] 61 62 define internal i32 @testLoadFixedOffset() { 63 entry: 64 %a = ptrtoint [4 x i8]* @G1 to i32 65 %a1 = add i32 %a, 4 66 %a2 = inttoptr i32 %a1 to i32* 67 %b = load i32, i32* %a2, align 1 68 ret i32 %b 69 } 70 ; Expect a load with a R_386_GOTOFF relocation plus an immediate offset. 71 ; NONSFI-LABEL: testLoadFixedOffset 72 ; NONSFI: mov {{.*}}+0x4] {{.*}} R_386_GOTOFF {{G1|.bss}} 73 ; DEFAULT-LABEL: testLoadFixedOffset 74 75 ; ARM32-NONSFI-LABEL: testLoadFixedOffset 76 ; ARM32-NONSFI: movw [[GOT:r[0-9]+]], {{.*}} R_ARM_MOVW_PREL_NC _GLOBAL_OFFSET_TABLE_ 77 ; ARM32-NONSFI-NEXT: movt [[GOT]], {{.*}} R_ARM_MOVT_PREL _GLOBAL_OFFSET_TABLE_ 78 ; ARM32-NONSFI: movw [[REG:r[0-9]+]], {{.*}} R_ARM_MOVW_PREL_NC {{.*}}G1 79 ; ARM32-NONSFI-NEXT: movt [[REG]], {{.*}} R_ARM_MOVT_PREL {{.*}}G1 80 ; ARM32-NONSFI-NEXT: ldr [[ADDR:r[0-9]+]], [pc, [[REG]]] 81 ; ARM32-NONSFI-NEXT: add [[G1BASE:r[0-9]+]], [[GOT]], [[ADDR]] 82 ; ARM32-NONSFI-NEXT: add {{.*}}, [[G1BASE]], #4 83 84 define internal i32 @testLoadIndexed(i32 %idx) { 85 entry: 86 %a = ptrtoint [4 x i8]* @G1 to i32 87 %a0 = mul i32 %idx, 4 88 %a1 = add i32 %a0, 12 89 %a2 = add i32 %a1, %a 90 %a3 = inttoptr i32 %a2 to i32* 91 %b = load i32, i32* %a3, align 1 92 ret i32 %b 93 } 94 ; Expect a load with a R_386_GOTOFF relocation plus an immediate offset, plus a 95 ; scaled index register. 96 ; NONSFI-LABEL: testLoadIndexed 97 ; NONSFI: mov {{.*}}*4+0xc] {{.*}} R_386_GOTOFF {{G1|.bss}} 98 ; DEFAULT-LABEL: testLoadIndexed 99 100 ; ARM32-NONSFI-LABEL: testLoadIndexed 101 ; ARM32-NONSFI: movw [[GOT:r[0-9]+]], {{.*}} R_ARM_MOVW_PREL_NC _GLOBAL_OFFSET_TABLE_ 102 ; ARM32-NONSFI-NEXT: movt [[GOT]], {{.*}} R_ARM_MOVT_PREL _GLOBAL_OFFSET_TABLE_ 103 ; ARM32-NONSFI: movw [[REG:r[0-9]+]], {{.*}} R_ARM_MOVW_PREL_NC {{.*}}G1 104 ; ARM32-NONSFI-NEXT: movt [[REG]], {{.*}} R_ARM_MOVT_PREL {{.*}}G1 105 ; ARM32-NONSFI-NEXT: ldr [[ADDR:r[0-9]+]], [pc, [[REG]]] 106 ; ARM32-NONSFI-NEXT: add [[G1BASE:r[0-9]+]], [[GOT]], [[ADDR]] 107 ; ARaM32-NONSFI-NEXT: add {{.*}}, [[G1BASE]] 108 109 define internal i32 @testLoadIndexedBase(i32 %base, i32 %idx) { 110 entry: 111 %a = ptrtoint [4 x i8]* @G1 to i32 112 %a0 = mul i32 %idx, 4 113 %a1 = add i32 %a0, %base 114 %a2 = add i32 %a1, %a 115 %a3 = add i32 %a2, 12 116 %a4 = inttoptr i32 %a3 to i32* 117 %b = load i32, i32* %a4, align 1 118 ret i32 %b 119 } 120 ; Expect a load with a R_386_GOTOFF relocation plus an immediate offset, but 121 ; without the scaled index. 122 ; NONSFI-LABEL: testLoadIndexedBase 123 ; NONSFI: mov {{.*}}*1+0xc] {{.*}} R_386_GOTOFF {{G1|.bss}} 124 ; By contrast, without -nonsfi, expect a load with a *R_386_32* relocation plus 125 ; an immediate offset, and *with* the scaled index. 126 ; DEFAULT-LABEL: testLoadIndexedBase 127 ; DEFAULT: mov {{.*}},DWORD PTR [{{.*}}+{{.*}}*4+0xc] {{.*}} R_386_32 {{G1|.bss}} 128 129 define internal i32 @testLoadOpt() { 130 entry: 131 %a = bitcast [4 x i8]* @G1 to i32* 132 %b = load i32, i32* %a, align 1 133 %c = bitcast [4 x i8]* @G2 to i32* 134 %d = load i32, i32* %c, align 1 135 %e = add i32 %b, %d 136 ret i32 %e 137 } 138 ; Expect a load-folding optimization with a R_386_GOTOFF relocation. 139 ; NONSFI-LABEL: testLoadOpt 140 ; NONSFI: mov [[REG:e..]],{{.*}}+0x0] {{.*}} R_386_GOTOFF {{G1|.bss}} 141 ; NONSFI-NEXT: add [[REG]],{{.*}}+0x{{0|4}}] {{.*}} R_386_GOTOFF {{G2|.bss}} 142 ; DEFAULT-LABEL: testLoadOpt 143 144 define internal void @testRMW() { 145 entry: 146 %a = bitcast [4 x i8]* @G1 to i32* 147 %b = load i32, i32* %a, align 1 148 %c = add i32 %b, 1234 149 store i32 %c, i32* %a, align 1 150 ret void 151 } 152 ; Expect an RMW optimization with a R_386_GOTOFF relocation. 153 ; NONSFI-LABEL: testRMW 154 ; NONSFI: add DWORD PTR {{.*}}+0x0],0x4d2 {{.*}} R_386_GOTOFF {{G1|.bss}} 155 ; DEFAULT-LABEL: testRMW 156