Index: llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -676,7 +676,8 @@ #ifndef NDEBUG auto isExpectedBDVType = [](Value *BDV) { return isa(BDV) || isa(BDV) || - isa(BDV) || isa(BDV); + isa(BDV) || isa(BDV) || + isa(BDV); }; #endif @@ -719,9 +720,11 @@ } else if (auto *IE = dyn_cast(Current)) { visitIncomingValue(IE->getOperand(0)); // vector operand visitIncomingValue(IE->getOperand(1)); // scalar operand - } else { - // There is one known class of instructions we know we don't handle. - assert(isa(Current)); + } else if (auto *SV = dyn_cast(Current)) { + visitIncomingValue(SV->getOperand(0)); + visitIncomingValue(SV->getOperand(1)); + } + else { llvm_unreachable("Unimplemented instruction case"); } } @@ -778,12 +781,17 @@ // useful in that it drives us to conflict if our input is. NewState = meetBDVState(NewState, getStateForInput(EE->getVectorOperand())); - } else { + } else if (auto *IE = dyn_cast(BDV)){ // Given there's a inherent type mismatch between the operands, will // *always* produce Conflict. - auto *IE = cast(BDV); NewState = meetBDVState(NewState, getStateForInput(IE->getOperand(0))); NewState = meetBDVState(NewState, getStateForInput(IE->getOperand(1))); + } else { + // The only instance this does not return a Conflict is when both the + // vector operands are the same vector. + auto *SV = cast(BDV); + NewState = meetBDVState(NewState, getStateForInput(SV->getOperand(0))); + NewState = meetBDVState(NewState, getStateForInput(SV->getOperand(1))); } BDVState OldState = States[BDV]; @@ -855,13 +863,18 @@ std::string Name = suffixed_name_or(I, ".base", "base_ee"); return ExtractElementInst::Create(Undef, EE->getIndexOperand(), Name, EE); - } else { - auto *IE = cast(I); + } else if (auto *IE = dyn_cast(I)) { UndefValue *VecUndef = UndefValue::get(IE->getOperand(0)->getType()); UndefValue *ScalarUndef = UndefValue::get(IE->getOperand(1)->getType()); std::string Name = suffixed_name_or(I, ".base", "base_ie"); return InsertElementInst::Create(VecUndef, ScalarUndef, IE->getOperand(2), Name, IE); + } else { + auto *SV = cast(I); + UndefValue *VecUndef = UndefValue::get(SV->getOperand(0)->getType()); + std::string Name = suffixed_name_or(I, ".base", "base_sv"); + return new ShuffleVectorInst(VecUndef, VecUndef, SV->getOperand(2), + Name, SV); } }; Instruction *BaseInst = MakeBaseInstPlaceholder(I); @@ -963,8 +976,7 @@ // Find the instruction which produces the base for each input. We may // need to insert a bitcast. BaseEE->setOperand(0, getBaseForInput(InVal, BaseEE)); - } else { - auto *BaseIE = cast(State.getBaseValue()); + } else if (auto *BaseIE = dyn_cast(State.getBaseValue())){ auto *BdvIE = cast(BDV); auto UpdateOperand = [&](int OperandIdx) { Value *InVal = BdvIE->getOperand(OperandIdx); @@ -973,6 +985,16 @@ }; UpdateOperand(0); // vector operand UpdateOperand(1); // scalar operand + } else { + auto *BaseSV = cast(State.getBaseValue()); + auto *BdvSV = cast(BDV); + auto UpdateOperand = [&](int OperandIdx) { + Value *InVal = BdvSV->getOperand(OperandIdx); + Value *Base = getBaseForInput(InVal, BaseSV); + BaseSV->setOperand(OperandIdx, Base); + }; + UpdateOperand(0); // vector operand + UpdateOperand(1); // vector operand } } Index: llvm/trunk/test/Transforms/RewriteStatepointsForGC/base-vector.ll =================================================================== --- llvm/trunk/test/Transforms/RewriteStatepointsForGC/base-vector.ll +++ llvm/trunk/test/Transforms/RewriteStatepointsForGC/base-vector.ll @@ -165,4 +165,83 @@ ret i64 addrspace(1)* %objb } +; identify base for shufflevector +define void @test8(i64 addrspace(1)* %obj, i64 %idx) gc "statepoint-example" { +; CHECK-LABEL: @test8 +; CHECK: %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1 +; CHECK: %gep2 = getelementptr i64, i64 addrspace(1)* %obj, i64 2 +; CHECK: %vec1.base = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* %obj, i32 0, !is_base_value !0 +; CHECK: %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0 +; CHECK: %vec2.base = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* %obj, i32 2, !is_base_value !0 +; CHECK: %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep2, i32 2 +; CHECK: %vec.base = shufflevector <4 x i64 addrspace(1)*> %vec1.base, <4 x i64 addrspace(1)*> %vec2.base, <2 x i32> , !is_base_value !0 +; CHECK: %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec2, <2 x i32> +; CHECK: %bdv.base = extractelement <2 x i64 addrspace(1)*> %vec.base, i64 %idx, !is_base_value !0 +; CHECK: %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx +; CHECK: gc.statepoint +; CHECK: gc.relocate +; CHECK-DAG: (%bdv.base, %bdv) +entry: + %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1 + %gep2 = getelementptr i64, i64 addrspace(1)* %obj, i64 2 + %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0 + %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep2, i32 2 + %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec2, <2 x i32> + %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx + call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] + call void @use(i64 addrspace(1)* %bdv) + ret void +} + +; Since the same 'base' vector is used in the shuffle operands, we do not need +; create a shufflevector base. +define void @test9(<4 x i64 addrspace(1)*> %vec1, i64 %idx) gc "statepoint-example" { +; CHECK-LABEL: @test9 +; CHECK: %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec1, <2 x i32> +; CHECK: %base_ee = extractelement <4 x i64 addrspace(1)*> %vec1, i64 %idx, !is_base_value !0 +; CHECK: %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx +; CHECK: gc.statepoint +; CHECK: gc.relocate +; CHECK-DAG: (%base_ee, %bdv) +entry: + ; shrinking vec1 into vec + %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec1, <2 x i32> + %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx + call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] + call void @use(i64 addrspace(1)* %bdv) + ret void +} + +; vector operand of shufflevector is a phi +define i64 addrspace(1)* @test10(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" { +; CHECK-LABEL: @test10 +entry: + %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj, i32 0 + br i1 %cnd, label %here, label %merge + +here: + %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj2, i32 2 + br label %merge + +merge: ; preds = %merge, %entry, %here +; CHECK-LABEL: merge: +; CHECK: %vec.base = phi <4 x i64 addrspace(1)*> [ %vec1.base, %entry ], [ %vec2.base, %here ], [ %vec3.base, %merge ], !is_base_value !0 +; CHECK: vec +; CHECK: vec3.base = shufflevector <4 x i64 addrspace(1)*> %vec.base, <4 x i64 addrspace(1)*> %vec.base +; CHECK: vec3 +; CHECK: bdv.base +; CHECK: bdv + %vec = phi <4 x i64 addrspace(1)*> [ %vec1, %entry ], [ %vec2, %here], [ %vec3, %merge] + %vec3 = shufflevector <4 x i64 addrspace(1)*> %vec, <4 x i64 addrspace(1)*> %vec, <4 x i32> + %bdv = extractelement <4 x i64 addrspace(1)*> %vec3, i32 0 + br i1 %cnd, label %merge, label %next + +next: +; CHECK-LABEL: next: +; CHECK: gc.statepoint +; CHECK: gc.relocate +; CHECK-DAG: (%bdv.base, %bdv) + call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] + ret i64 addrspace(1)* %bdv +} declare void @do_safepoint()