Index: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp @@ -8535,6 +8535,14 @@ MI.getOperand(2).getTargetFlags() == X86II::MO_GOT_ABSOLUTE_ADDRESS) return nullptr; + // GOTTPOFF relocation loads can only be folded into add instructions. + // FIXME: Need to exclude other relocations that only support specific + // instructions. + if (MOs.size() == X86::AddrNumOperands && + MOs[X86::AddrDisp].getTargetFlags() == X86II::MO_GOTTPOFF && + MI.getOpcode() != X86::ADD64rr) + return nullptr; + MachineInstr *NewMI = nullptr; // Attempt to fold any custom cases we have. Index: llvm/trunk/test/CodeGen/X86/bad-tls-fold.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/bad-tls-fold.mir +++ llvm/trunk/test/CodeGen/X86/bad-tls-fold.mir @@ -0,0 +1,77 @@ +# RUN: llc -x mir < %s | FileCheck %s +--- | + target triple = "x86_64-unknown-linux-gnu" + + @x = external global i64 + @i = external thread_local global i32 + + define i32 @or() { + entry: + ret i32 undef + } + + define i32 @and() { + entry: + ret i32 undef + } +... +--- +# CHECK-LABEL: or: +name: or +alignment: 4 +tracksRegLiveness: true +registers: + - { id: 0, class: gr64 } + - { id: 1, class: gr64 } + - { id: 2, class: gr64 } + - { id: 3, class: gr64 } + - { id: 4, class: gr32 } +body: | + bb.0.entry: + %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load 8) + %1:gr64 = OR64ri8 %0, 7, implicit-def dead $eflags + %2:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg :: (load 8) + %3:gr64 = OR64rr %2, %1, implicit-def dead $eflags + %4:gr32 = MOV32rm killed %3, 1, $noreg, 0, $fs :: (load 4) + ; CHECK-NOT: orq {{.*}}GOTTPOFF{{.*}} + ; + ; What we actually expect: + ; CHECK: movq {{.*}}GOTTPOFF{{.*}}, %[[R:.*]] + ; CHECK-NEXT: orq %{{.*}}, %[[R]] + ; CHECK-NEXT: movl %fs:(%[[R]]), + ; + ; CHECK-NOT: orq {{.*}}GOTTPOFF{{.*}} + $eax = COPY %4 + RET 0, $eax + +... +--- +# CHECK-LABEL: and: +name: and +alignment: 4 +tracksRegLiveness: true +registers: + - { id: 0, class: gr64 } + - { id: 1, class: gr64 } + - { id: 2, class: gr64 } + - { id: 3, class: gr64 } + - { id: 4, class: gr32 } +body: | + bb.0.entry: + %0:gr64 = MOV64rm $rip, 1, $noreg, @x, $noreg :: (load 8) + %1:gr64 = OR64ri8 %0, 7, implicit-def dead $eflags + %2:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gottpoff) @i, $noreg :: (load 8) + %3:gr64 = AND64rr %2, %1, implicit-def dead $eflags + %4:gr32 = MOV32rm killed %3, 1, $noreg, 0, $fs :: (load 4) + ; CHECK-NOT: andq {{.*}}GOTTPOFF{{.*}} + ; + ; What we actually expect: + ; CHECK: movq {{.*}}GOTTPOFF{{.*}}, %[[R:.*]] + ; CHECK-NEXT: andq %{{.*}}, %[[R]] + ; CHECK-NEXT: movl %fs:(%[[R]]), + ; + ; CHECK-NOT: andq {{.*}}GOTTPOFF{{.*}} + $eax = COPY %4 + RET 0, $eax + +...