From: Michael Gottesman Date: Tue, 24 Sep 2013 01:50:26 +0000 (+0000) Subject: [stackprotector] Allow for copies from vreg -> vreg to be in a terminator sequence. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=eed779ff68c9a4612ea229f4fbd23a5258458889 [stackprotector] Allow for copies from vreg -> vreg to be in a terminator sequence. Sometimes a copy from a vreg -> vreg sneaks into the middle of a terminator sequence. It is safe to slice this into the stack protector success bb. This fixes PR16979. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191260 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 9b15c88156f..fed9f661c2d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1165,13 +1165,33 @@ static bool MIIsInTerminatorSequence(const MachineInstr *MI) { // sequence, so we return true in that case. return MI->isDebugValue(); - // If we are not defining a register that is a physical register via a copy or - // are defining a register via an implicit def, we have left the terminator - // sequence. - MachineInstr::const_mop_iterator OPI = MI->operands_begin(); - if (!OPI->isReg() || !OPI->isDef() || + // We have left the terminator sequence if we are not doing one of the + // following: + // + // 1. Copying a vreg into a physical register. + // 2. Copying a vreg into a vreg. + // 3. Defining a register via an implicit def. + + // OPI should always be a register definition... + MachineInstr::const_mop_iterator OPI = MI->operands_begin(); + if (!OPI->isReg() || !OPI->isDef()) + return false; + + // Defining any register via an implicit def is always ok. + if (MI->isImplicitDef()) + return true; + + // Grab the copy source... + MachineInstr::const_mop_iterator OPI2 = OPI; + ++OPI2; + assert(OPI2 != MI->operands_end() + && "Should have a copy implying we should have 2 arguments."); + + // Make sure that the copy dest is not a vreg when the copy source is a + // physical register. + if (!OPI2->isReg() || (!TargetRegisterInfo::isPhysicalRegister(OPI->getReg()) && - !MI->isImplicitDef())) + TargetRegisterInfo::isPhysicalRegister(OPI2->getReg()))) return false; return true; diff --git a/test/CodeGen/X86/stack-protector-vreg-to-vreg-copy.ll b/test/CodeGen/X86/stack-protector-vreg-to-vreg-copy.ll new file mode 100644 index 00000000000..8ea109dd4a6 --- /dev/null +++ b/test/CodeGen/X86/stack-protector-vreg-to-vreg-copy.ll @@ -0,0 +1,63 @@ +; RUN: llc -mtriple i386-unknown-freebsd10.0 -march=x86 --relocation-model=pic %s -o - + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-unknown-freebsd10.0" + +@state = internal unnamed_addr global i32 0, align 4 + +; Function Attrs: nounwind sspreq +define void @set_state(i32 %s) #0 { +entry: + store i32 %s, i32* @state, align 4, !tbaa !0 + ret void +} + +; Function Attrs: nounwind sspreq +define void @zero_char(i8* nocapture %p) #0 { +entry: + store i8 0, i8* %p, align 1, !tbaa !1 + tail call void @g(i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0) #2 + ret void +} + +declare void @g(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) #1 + +; Function Attrs: nounwind sspreq +define void @do_something(i32 %i) #0 { +entry: + %data = alloca [8 x i8], align 1 + %0 = load i32* @state, align 4, !tbaa !0 + %cmp = icmp eq i32 %0, 0 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + tail call fastcc void @send_int(i32 0) + br label %if.end + +if.else: ; preds = %entry + tail call fastcc void @send_int(i32 %i) + %arrayidx = getelementptr inbounds [8 x i8]* %data, i32 0, i32 0 + call void @zero_char(i8* %arrayidx) + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +; Function Attrs: nounwind sspreq +define internal fastcc void @send_int(i32 %p) #0 { +entry: + tail call void @f(i32 %p) #2 + tail call void @g(i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0) #2 + ret void +} + +declare void @f(i32) #1 + +attributes #0 = { nounwind sspreq "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind } + +!0 = metadata !{metadata !"int", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA"}