From 6778a62eb0d222dc625b8785516f027df12aaf16 Mon Sep 17 00:00:00 2001 From: Dmitry Preobrazhensky Date: Wed, 20 Nov 2019 17:04:36 +0300 Subject: [PATCH 01/14] [AMDGPU][GFX10] Disabled v_movrel*[sdwa|dpp] opcodes in codegen These opcodes use indirect register addressing so they need special handling by codegen (currently missing). Reviewers: vpykhtin, arsenm, rampitec Differential Revision: https://reviews.llvm.org/D70400 --- llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 23 +++++++++++++++++++++++ llvm/lib/Target/AMDGPU/SIInstrInfo.h | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp index 3737d0a7b41fae..ed915f03be217a 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -6329,6 +6329,26 @@ static SIEncodingFamily subtargetEncodingFamily(const GCNSubtarget &ST) { llvm_unreachable("Unknown subtarget generation!"); } +bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const { + switch(MCOp) { + // These opcodes use indirect register addressing so + // they need special handling by codegen (currently missing). + // Therefore it is too risky to allow these opcodes + // to be selected by dpp combiner or sdwa peepholer. + case AMDGPU::V_MOVRELS_B32_dpp_gfx10: + case AMDGPU::V_MOVRELS_B32_sdwa_gfx10: + case AMDGPU::V_MOVRELD_B32_dpp_gfx10: + case AMDGPU::V_MOVRELD_B32_sdwa_gfx10: + case AMDGPU::V_MOVRELSD_B32_dpp_gfx10: + case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10: + case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10: + case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10: + return true; + default: + return false; + } +} + int SIInstrInfo::pseudoToMCOpcode(int Opcode) const { SIEncodingFamily Gen = subtargetEncodingFamily(ST); @@ -6367,6 +6387,9 @@ int SIInstrInfo::pseudoToMCOpcode(int Opcode) const { if (MCOp == (uint16_t)-1) return -1; + if (isAsmOnlyOpcode(MCOp)) + return -1; + return MCOp; } diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h index 821215d08f4142..492bf4e4e929f2 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h @@ -1017,6 +1017,10 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo { /// not exist. If Opcode is not a pseudo instruction, this is identity. int pseudoToMCOpcode(int Opcode) const; + /// \brief Check if this instruction should only be used by assembler. + /// Return true if this opcode should not be used by codegen. + bool isAsmOnlyOpcode(int MCOp) const; + const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum, const TargetRegisterInfo *TRI, const MachineFunction &MF) From 51ad025ff313804674b4fb01f56f7b83e3ecc5e3 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Wed, 20 Nov 2019 15:58:07 +0100 Subject: [PATCH 02/14] [lldb][NFC] Move searching for $__lldb_objc_class into its own function Same as in commit e7cc833ddafdca10be4ef1322ab96ffee774045b but with $__lldb_objc_class. --- .../Clang/ClangExpressionDeclMap.cpp | 246 +++++++++--------- .../Clang/ClangExpressionDeclMap.h | 10 + 2 files changed, 134 insertions(+), 122 deletions(-) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index b95713b44672a3..7b8456257c627c 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -938,178 +938,180 @@ void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context, } } -void ClangExpressionDeclMap::FindExternalVisibleDecls( - NameSearchContext &context, lldb::ModuleSP module_sp, - CompilerDeclContext &namespace_decl, unsigned int current_id) { - assert(m_ast_context); - +void ClangExpressionDeclMap::LookUpLldbObjCClass(NameSearchContext &context, + unsigned int current_id) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - SymbolContextList sc_list; + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); - const ConstString name(context.m_decl_name.getAsString().c_str()); - if (IgnoreName(name, false)) - return; + if (m_ctx_obj) { + Status status; + lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status); + if (!ctx_obj_ptr || status.Fail()) + return; - // Only look for functions by name out in our symbols if the function doesn't - // start with our phony prefix of '$' - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); - SymbolContext sym_ctx; - if (frame != nullptr) - sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | - lldb::eSymbolContextBlock); + AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), current_id); - // Try the persistent decls, which take precedence over all else. - if (!namespace_decl) - SearchPersistenDecls(context, name, current_id); + m_struct_vars->m_object_pointer_type = + TypeFromUser(ctx_obj_ptr->GetCompilerType()); - if (name.GetCString()[0] == '$' && !namespace_decl) { - static ConstString g_lldb_class_name("$__lldb_class"); + return; + } - if (name == g_lldb_class_name) { - LookUpLldbClass(context, current_id); - return; - } + // Clang is looking for the type of "*self" - static ConstString g_lldb_objc_class_name("$__lldb_objc_class"); - if (name == g_lldb_objc_class_name) { - if (m_ctx_obj) { - Status status; - lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status); - if (!ctx_obj_ptr || status.Fail()) - return; + if (!frame) + return; + + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | + lldb::eSymbolContextBlock); - AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), - current_id); + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); - m_struct_vars->m_object_pointer_type = - TypeFromUser(ctx_obj_ptr->GetCompilerType()); + if (!function_block) + return; - return; - } + CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); - // Clang is looking for the type of "*self" + if (!function_decl_ctx) + return; - if (!frame) - return; + clang::ObjCMethodDecl *method_decl = + ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); - SymbolContext sym_ctx = frame->GetSymbolContext( - lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); + if (method_decl) { + ObjCInterfaceDecl *self_interface = method_decl->getClassInterface(); - // Find the block that defines the function represented by "sym_ctx" - Block *function_block = sym_ctx.GetFunctionBlock(); + if (!self_interface) + return; - if (!function_block) - return; + const clang::Type *interface_type = self_interface->getTypeForDecl(); - CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + if (!interface_type) + return; // This is unlikely, but we have seen crashes where this + // occurred - if (!function_decl_ctx) - return; + TypeFromUser class_user_type( + QualType(interface_type, 0).getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + if (log) { + ASTDumper ast_dumper(interface_type); + LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_objc_class: %s", + current_id, ast_dumper.GetCString()); + } - clang::ObjCMethodDecl *method_decl = - ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + AddOneType(context, class_user_type, current_id); - if (method_decl) { - ObjCInterfaceDecl *self_interface = method_decl->getClassInterface(); + if (method_decl->isInstanceMethod()) { + // self is a pointer to the object - if (!self_interface) - return; + QualType class_pointer_type = + method_decl->getASTContext().getObjCObjectPointerType( + QualType(interface_type, 0)); - const clang::Type *interface_type = self_interface->getTypeForDecl(); + TypeFromUser self_user_type( + class_pointer_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); - if (!interface_type) - return; // This is unlikely, but we have seen crashes where this - // occurred + m_struct_vars->m_object_pointer_type = self_user_type; + } else { + // self is a Class pointer + QualType class_type = method_decl->getASTContext().getObjCClassType(); - TypeFromUser class_user_type( - QualType(interface_type, 0).getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + TypeFromUser self_user_type( + class_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); - if (log) { - ASTDumper ast_dumper(interface_type); - LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_objc_class: %s", - current_id, ast_dumper.GetCString()); - } + m_struct_vars->m_object_pointer_type = self_user_type; + } - AddOneType(context, class_user_type, current_id); + return; + } + // This branch will get hit if we are executing code in the context of + // a function that claims to have an object pointer (through + // DW_AT_object_pointer?) but is not formally a method of the class. + // In that case, just look up the "self" variable in the current scope + // and use its type. - if (method_decl->isInstanceMethod()) { - // self is a pointer to the object + VariableList *vars = frame->GetVariableList(false); - QualType class_pointer_type = - method_decl->getASTContext().getObjCObjectPointerType( - QualType(interface_type, 0)); + lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); - TypeFromUser self_user_type( - class_pointer_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + if (self_var && self_var->IsInScope(frame) && + self_var->LocationIsValidForFrame(frame)) { + Type *self_type = self_var->GetType(); - m_struct_vars->m_object_pointer_type = self_user_type; - } else { - // self is a Class pointer - QualType class_type = method_decl->getASTContext().getObjCClassType(); + if (!self_type) + return; - TypeFromUser self_user_type( - class_type.getAsOpaquePtr(), - ClangASTContext::GetASTContext(&method_decl->getASTContext())); + CompilerType self_clang_type = self_type->GetFullCompilerType(); - m_struct_vars->m_object_pointer_type = self_user_type; - } + if (ClangASTContext::IsObjCClassType(self_clang_type)) { + return; + } else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) { + self_clang_type = self_clang_type.GetPointeeType(); + if (!self_clang_type) return; - } else { - // This branch will get hit if we are executing code in the context of - // a function that claims to have an object pointer (through - // DW_AT_object_pointer?) but is not formally a method of the class. - // In that case, just look up the "self" variable in the current scope - // and use its type. - VariableList *vars = frame->GetVariableList(false); + if (log) { + ASTDumper ast_dumper(self_type->GetFullCompilerType()); + LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_objc_class: %s", + current_id, ast_dumper.GetCString()); + } - lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); + TypeFromUser class_user_type(self_clang_type); - if (self_var && self_var->IsInScope(frame) && - self_var->LocationIsValidForFrame(frame)) { - Type *self_type = self_var->GetType(); + AddOneType(context, class_user_type, current_id); - if (!self_type) - return; + TypeFromUser self_user_type(self_type->GetFullCompilerType()); - CompilerType self_clang_type = self_type->GetFullCompilerType(); + m_struct_vars->m_object_pointer_type = self_user_type; + } + } +} - if (ClangASTContext::IsObjCClassType(self_clang_type)) { - return; - } else if (ClangASTContext::IsObjCObjectPointerType( - self_clang_type)) { - self_clang_type = self_clang_type.GetPointeeType(); +void ClangExpressionDeclMap::FindExternalVisibleDecls( + NameSearchContext &context, lldb::ModuleSP module_sp, + CompilerDeclContext &namespace_decl, unsigned int current_id) { + assert(m_ast_context); - if (!self_clang_type) - return; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) { - ASTDumper ast_dumper(self_type->GetFullCompilerType()); - LLDB_LOGF(log, - " FEVD[%u] Adding type for $__lldb_objc_class: %s", - current_id, ast_dumper.GetCString()); - } + SymbolContextList sc_list; - TypeFromUser class_user_type(self_clang_type); + const ConstString name(context.m_decl_name.getAsString().c_str()); + if (IgnoreName(name, false)) + return; - AddOneType(context, class_user_type, current_id); + // Only look for functions by name out in our symbols if the function doesn't + // start with our phony prefix of '$' + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + SymbolContext sym_ctx; + if (frame != nullptr) + sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | + lldb::eSymbolContextBlock); - TypeFromUser self_user_type(self_type->GetFullCompilerType()); + // Try the persistent decls, which take precedence over all else. + if (!namespace_decl) + SearchPersistenDecls(context, name, current_id); - m_struct_vars->m_object_pointer_type = self_user_type; - return; - } - } - } + if (name.GetCString()[0] == '$' && !namespace_decl) { + static ConstString g_lldb_class_name("$__lldb_class"); + if (name == g_lldb_class_name) { + LookUpLldbClass(context, current_id); return; } + static ConstString g_lldb_objc_class_name("$__lldb_objc_class"); + if (name == g_lldb_objc_class_name) { + LookUpLldbObjCClass(context, current_id); + return; + } if (name == ConstString(g_lldb_local_vars_namespace_cstr)) { CompilerDeclContext frame_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index 2d7b3712ad5355..93342dace77e6a 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -400,6 +400,16 @@ class ClangExpressionDeclMap : public ClangASTSource { /// for logging purposes. void LookUpLldbClass(NameSearchContext &context, unsigned int current_id); + /// Handles looking up $__lldb_objc_class which requires special treatment. + /// + /// \param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// \param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + void LookUpLldbObjCClass(NameSearchContext &context, unsigned int current_id); + /// Given a target, find a variable that matches the given name and type. /// /// \param[in] target From b80033ef6528ed868294ba0c1e18bfcf74597a1b Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 20 Nov 2019 09:31:17 -0500 Subject: [PATCH 03/14] [SLP] reduce duplicate CHECK lines in tests; NFC --- .../X86/insert-element-build-vector.ll | 600 ++++++------------ 1 file changed, 208 insertions(+), 392 deletions(-) diff --git a/llvm/test/Transforms/SLPVectorizer/X86/insert-element-build-vector.ll b/llvm/test/Transforms/SLPVectorizer/X86/insert-element-build-vector.ll index f16d7e2160fe67..89cb14b171e335 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/insert-element-build-vector.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/insert-element-build-vector.ll @@ -1,36 +1,23 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -slp-vectorizer -slp-threshold=-10000 < %s | FileCheck %s -; RUN: opt -S -slp-vectorizer -slp-threshold=0 < %s | FileCheck %s --check-prefix=ZEROTHRESH -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-n8:16:32:64-S128" +; RUN: opt -S -slp-vectorizer -slp-threshold=-10000 < %s | FileCheck %s --check-prefixes=ANY,BIGTHRESH +; RUN: opt -S -slp-vectorizer -slp-threshold=0 < %s | FileCheck %s --check-prefixes=ANY,ZEROTHRESH +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.8.0" define <4 x float> @simple_select(<4 x float> %a, <4 x float> %b, <4 x i32> %c) #0 { -; CHECK-LABEL: @simple_select( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[C:%.*]], zeroinitializer -; CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[A:%.*]], <4 x float> [[B:%.*]] -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP2]], i32 0 -; CHECK-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP3]], i32 0 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP2]], i32 1 -; CHECK-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP4]], i32 1 -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP2]], i32 2 -; CHECK-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[TMP5]], i32 2 -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[TMP2]], i32 3 -; CHECK-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP6]], i32 3 -; CHECK-NEXT: ret <4 x float> [[RD]] -; -; ZEROTHRESH-LABEL: @simple_select( -; ZEROTHRESH-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[C:%.*]], zeroinitializer -; ZEROTHRESH-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[A:%.*]], <4 x float> [[B:%.*]] -; ZEROTHRESH-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP2]], i32 0 -; ZEROTHRESH-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP3]], i32 0 -; ZEROTHRESH-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP2]], i32 1 -; ZEROTHRESH-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP4]], i32 1 -; ZEROTHRESH-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP2]], i32 2 -; ZEROTHRESH-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[TMP5]], i32 2 -; ZEROTHRESH-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[TMP2]], i32 3 -; ZEROTHRESH-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP6]], i32 3 -; ZEROTHRESH-NEXT: ret <4 x float> [[RD]] +; ANY-LABEL: @simple_select( +; ANY-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[C:%.*]], zeroinitializer +; ANY-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[A:%.*]], <4 x float> [[B:%.*]] +; ANY-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP2]], i32 0 +; ANY-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP3]], i32 0 +; ANY-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP2]], i32 1 +; ANY-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP4]], i32 1 +; ANY-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP2]], i32 2 +; ANY-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[TMP5]], i32 2 +; ANY-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[TMP2]], i32 3 +; ANY-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP6]], i32 3 +; ANY-NEXT: ret <4 x float> [[RD]] ; %c0 = extractelement <4 x i32> %c, i32 0 %c1 = extractelement <4 x i32> %c, i32 1 @@ -63,77 +50,41 @@ declare void @llvm.assume(i1) nounwind ; This entire tree is ephemeral, don't vectorize any of it. define <4 x float> @simple_select_eph(<4 x float> %a, <4 x float> %b, <4 x i32> %c) #0 { -; CHECK-LABEL: @simple_select_eph( -; CHECK-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 -; CHECK-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 -; CHECK-NEXT: [[C2:%.*]] = extractelement <4 x i32> [[C]], i32 2 -; CHECK-NEXT: [[C3:%.*]] = extractelement <4 x i32> [[C]], i32 3 -; CHECK-NEXT: [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0 -; CHECK-NEXT: [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1 -; CHECK-NEXT: [[A2:%.*]] = extractelement <4 x float> [[A]], i32 2 -; CHECK-NEXT: [[A3:%.*]] = extractelement <4 x float> [[A]], i32 3 -; CHECK-NEXT: [[B0:%.*]] = extractelement <4 x float> [[B:%.*]], i32 0 -; CHECK-NEXT: [[B1:%.*]] = extractelement <4 x float> [[B]], i32 1 -; CHECK-NEXT: [[B2:%.*]] = extractelement <4 x float> [[B]], i32 2 -; CHECK-NEXT: [[B3:%.*]] = extractelement <4 x float> [[B]], i32 3 -; CHECK-NEXT: [[CMP0:%.*]] = icmp ne i32 [[C0]], 0 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[C1]], 0 -; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[C2]], 0 -; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i32 [[C3]], 0 -; CHECK-NEXT: [[S0:%.*]] = select i1 [[CMP0]], float [[A0]], float [[B0]] -; CHECK-NEXT: [[S1:%.*]] = select i1 [[CMP1]], float [[A1]], float [[B1]] -; CHECK-NEXT: [[S2:%.*]] = select i1 [[CMP2]], float [[A2]], float [[B2]] -; CHECK-NEXT: [[S3:%.*]] = select i1 [[CMP3]], float [[A3]], float [[B3]] -; CHECK-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[S0]], i32 0 -; CHECK-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[S1]], i32 1 -; CHECK-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[S2]], i32 2 -; CHECK-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[S3]], i32 3 -; CHECK-NEXT: [[Q0:%.*]] = extractelement <4 x float> [[RD]], i32 0 -; CHECK-NEXT: [[Q1:%.*]] = extractelement <4 x float> [[RD]], i32 1 -; CHECK-NEXT: [[Q2:%.*]] = extractelement <4 x float> [[RD]], i32 2 -; CHECK-NEXT: [[Q3:%.*]] = extractelement <4 x float> [[RD]], i32 3 -; CHECK-NEXT: [[Q4:%.*]] = fadd float [[Q0]], [[Q1]] -; CHECK-NEXT: [[Q5:%.*]] = fadd float [[Q2]], [[Q3]] -; CHECK-NEXT: [[Q6:%.*]] = fadd float [[Q4]], [[Q5]] -; CHECK-NEXT: [[QI:%.*]] = fcmp olt float [[Q6]], [[Q5]] -; CHECK-NEXT: call void @llvm.assume(i1 [[QI]]) -; CHECK-NEXT: ret <4 x float> undef -; -; ZEROTHRESH-LABEL: @simple_select_eph( -; ZEROTHRESH-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 -; ZEROTHRESH-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 -; ZEROTHRESH-NEXT: [[C2:%.*]] = extractelement <4 x i32> [[C]], i32 2 -; ZEROTHRESH-NEXT: [[C3:%.*]] = extractelement <4 x i32> [[C]], i32 3 -; ZEROTHRESH-NEXT: [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0 -; ZEROTHRESH-NEXT: [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1 -; ZEROTHRESH-NEXT: [[A2:%.*]] = extractelement <4 x float> [[A]], i32 2 -; ZEROTHRESH-NEXT: [[A3:%.*]] = extractelement <4 x float> [[A]], i32 3 -; ZEROTHRESH-NEXT: [[B0:%.*]] = extractelement <4 x float> [[B:%.*]], i32 0 -; ZEROTHRESH-NEXT: [[B1:%.*]] = extractelement <4 x float> [[B]], i32 1 -; ZEROTHRESH-NEXT: [[B2:%.*]] = extractelement <4 x float> [[B]], i32 2 -; ZEROTHRESH-NEXT: [[B3:%.*]] = extractelement <4 x float> [[B]], i32 3 -; ZEROTHRESH-NEXT: [[CMP0:%.*]] = icmp ne i32 [[C0]], 0 -; ZEROTHRESH-NEXT: [[CMP1:%.*]] = icmp ne i32 [[C1]], 0 -; ZEROTHRESH-NEXT: [[CMP2:%.*]] = icmp ne i32 [[C2]], 0 -; ZEROTHRESH-NEXT: [[CMP3:%.*]] = icmp ne i32 [[C3]], 0 -; ZEROTHRESH-NEXT: [[S0:%.*]] = select i1 [[CMP0]], float [[A0]], float [[B0]] -; ZEROTHRESH-NEXT: [[S1:%.*]] = select i1 [[CMP1]], float [[A1]], float [[B1]] -; ZEROTHRESH-NEXT: [[S2:%.*]] = select i1 [[CMP2]], float [[A2]], float [[B2]] -; ZEROTHRESH-NEXT: [[S3:%.*]] = select i1 [[CMP3]], float [[A3]], float [[B3]] -; ZEROTHRESH-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[S0]], i32 0 -; ZEROTHRESH-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[S1]], i32 1 -; ZEROTHRESH-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[S2]], i32 2 -; ZEROTHRESH-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[S3]], i32 3 -; ZEROTHRESH-NEXT: [[Q0:%.*]] = extractelement <4 x float> [[RD]], i32 0 -; ZEROTHRESH-NEXT: [[Q1:%.*]] = extractelement <4 x float> [[RD]], i32 1 -; ZEROTHRESH-NEXT: [[Q2:%.*]] = extractelement <4 x float> [[RD]], i32 2 -; ZEROTHRESH-NEXT: [[Q3:%.*]] = extractelement <4 x float> [[RD]], i32 3 -; ZEROTHRESH-NEXT: [[Q4:%.*]] = fadd float [[Q0]], [[Q1]] -; ZEROTHRESH-NEXT: [[Q5:%.*]] = fadd float [[Q2]], [[Q3]] -; ZEROTHRESH-NEXT: [[Q6:%.*]] = fadd float [[Q4]], [[Q5]] -; ZEROTHRESH-NEXT: [[QI:%.*]] = fcmp olt float [[Q6]], [[Q5]] -; ZEROTHRESH-NEXT: call void @llvm.assume(i1 [[QI]]) -; ZEROTHRESH-NEXT: ret <4 x float> undef +; ANY-LABEL: @simple_select_eph( +; ANY-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 +; ANY-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 +; ANY-NEXT: [[C2:%.*]] = extractelement <4 x i32> [[C]], i32 2 +; ANY-NEXT: [[C3:%.*]] = extractelement <4 x i32> [[C]], i32 3 +; ANY-NEXT: [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0 +; ANY-NEXT: [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1 +; ANY-NEXT: [[A2:%.*]] = extractelement <4 x float> [[A]], i32 2 +; ANY-NEXT: [[A3:%.*]] = extractelement <4 x float> [[A]], i32 3 +; ANY-NEXT: [[B0:%.*]] = extractelement <4 x float> [[B:%.*]], i32 0 +; ANY-NEXT: [[B1:%.*]] = extractelement <4 x float> [[B]], i32 1 +; ANY-NEXT: [[B2:%.*]] = extractelement <4 x float> [[B]], i32 2 +; ANY-NEXT: [[B3:%.*]] = extractelement <4 x float> [[B]], i32 3 +; ANY-NEXT: [[CMP0:%.*]] = icmp ne i32 [[C0]], 0 +; ANY-NEXT: [[CMP1:%.*]] = icmp ne i32 [[C1]], 0 +; ANY-NEXT: [[CMP2:%.*]] = icmp ne i32 [[C2]], 0 +; ANY-NEXT: [[CMP3:%.*]] = icmp ne i32 [[C3]], 0 +; ANY-NEXT: [[S0:%.*]] = select i1 [[CMP0]], float [[A0]], float [[B0]] +; ANY-NEXT: [[S1:%.*]] = select i1 [[CMP1]], float [[A1]], float [[B1]] +; ANY-NEXT: [[S2:%.*]] = select i1 [[CMP2]], float [[A2]], float [[B2]] +; ANY-NEXT: [[S3:%.*]] = select i1 [[CMP3]], float [[A3]], float [[B3]] +; ANY-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[S0]], i32 0 +; ANY-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[S1]], i32 1 +; ANY-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[S2]], i32 2 +; ANY-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[S3]], i32 3 +; ANY-NEXT: [[Q0:%.*]] = extractelement <4 x float> [[RD]], i32 0 +; ANY-NEXT: [[Q1:%.*]] = extractelement <4 x float> [[RD]], i32 1 +; ANY-NEXT: [[Q2:%.*]] = extractelement <4 x float> [[RD]], i32 2 +; ANY-NEXT: [[Q3:%.*]] = extractelement <4 x float> [[RD]], i32 3 +; ANY-NEXT: [[Q4:%.*]] = fadd float [[Q0]], [[Q1]] +; ANY-NEXT: [[Q5:%.*]] = fadd float [[Q2]], [[Q3]] +; ANY-NEXT: [[Q6:%.*]] = fadd float [[Q4]], [[Q5]] +; ANY-NEXT: [[QI:%.*]] = fcmp olt float [[Q6]], [[Q5]] +; ANY-NEXT: call void @llvm.assume(i1 [[QI]]) +; ANY-NEXT: ret <4 x float> undef ; %c0 = extractelement <4 x i32> %c, i32 0 %c1 = extractelement <4 x i32> %c, i32 1 @@ -174,31 +125,18 @@ define <4 x float> @simple_select_eph(<4 x float> %a, <4 x float> %b, <4 x i32> ; Insert in an order different from the vector indices to make sure it ; doesn't matter define <4 x float> @simple_select_insert_out_of_order(<4 x float> %a, <4 x float> %b, <4 x i32> %c) #0 { -; CHECK-LABEL: @simple_select_insert_out_of_order( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[C:%.*]], zeroinitializer -; CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[A:%.*]], <4 x float> [[B:%.*]] -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP2]], i32 0 -; CHECK-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP3]], i32 2 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP2]], i32 1 -; CHECK-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP4]], i32 1 -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP2]], i32 2 -; CHECK-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[TMP5]], i32 0 -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[TMP2]], i32 3 -; CHECK-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP6]], i32 3 -; CHECK-NEXT: ret <4 x float> [[RD]] -; -; ZEROTHRESH-LABEL: @simple_select_insert_out_of_order( -; ZEROTHRESH-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[C:%.*]], zeroinitializer -; ZEROTHRESH-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[A:%.*]], <4 x float> [[B:%.*]] -; ZEROTHRESH-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP2]], i32 0 -; ZEROTHRESH-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP3]], i32 2 -; ZEROTHRESH-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP2]], i32 1 -; ZEROTHRESH-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP4]], i32 1 -; ZEROTHRESH-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP2]], i32 2 -; ZEROTHRESH-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[TMP5]], i32 0 -; ZEROTHRESH-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[TMP2]], i32 3 -; ZEROTHRESH-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP6]], i32 3 -; ZEROTHRESH-NEXT: ret <4 x float> [[RD]] +; ANY-LABEL: @simple_select_insert_out_of_order( +; ANY-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[C:%.*]], zeroinitializer +; ANY-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[A:%.*]], <4 x float> [[B:%.*]] +; ANY-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP2]], i32 0 +; ANY-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP3]], i32 2 +; ANY-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP2]], i32 1 +; ANY-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP4]], i32 1 +; ANY-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP2]], i32 2 +; ANY-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[TMP5]], i32 0 +; ANY-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[TMP2]], i32 3 +; ANY-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP6]], i32 3 +; ANY-NEXT: ret <4 x float> [[RD]] ; %c0 = extractelement <4 x i32> %c, i32 0 %c1 = extractelement <4 x i32> %c, i32 1 @@ -232,33 +170,19 @@ declare void @f32_user(float) #0 ; Multiple users of the final constructed vector define <4 x float> @simple_select_users(<4 x float> %a, <4 x float> %b, <4 x i32> %c) #0 { -; CHECK-LABEL: @simple_select_users( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[C:%.*]], zeroinitializer -; CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[A:%.*]], <4 x float> [[B:%.*]] -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP2]], i32 0 -; CHECK-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP3]], i32 0 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP2]], i32 1 -; CHECK-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP4]], i32 1 -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP2]], i32 2 -; CHECK-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[TMP5]], i32 2 -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[TMP2]], i32 3 -; CHECK-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP6]], i32 3 -; CHECK-NEXT: call void @v4f32_user(<4 x float> [[RD]]) #0 -; CHECK-NEXT: ret <4 x float> [[RD]] -; -; ZEROTHRESH-LABEL: @simple_select_users( -; ZEROTHRESH-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[C:%.*]], zeroinitializer -; ZEROTHRESH-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[A:%.*]], <4 x float> [[B:%.*]] -; ZEROTHRESH-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP2]], i32 0 -; ZEROTHRESH-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP3]], i32 0 -; ZEROTHRESH-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP2]], i32 1 -; ZEROTHRESH-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP4]], i32 1 -; ZEROTHRESH-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP2]], i32 2 -; ZEROTHRESH-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[TMP5]], i32 2 -; ZEROTHRESH-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[TMP2]], i32 3 -; ZEROTHRESH-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP6]], i32 3 -; ZEROTHRESH-NEXT: call void @v4f32_user(<4 x float> [[RD]]) #0 -; ZEROTHRESH-NEXT: ret <4 x float> [[RD]] +; ANY-LABEL: @simple_select_users( +; ANY-NEXT: [[TMP1:%.*]] = icmp ne <4 x i32> [[C:%.*]], zeroinitializer +; ANY-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[A:%.*]], <4 x float> [[B:%.*]] +; ANY-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP2]], i32 0 +; ANY-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP3]], i32 0 +; ANY-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP2]], i32 1 +; ANY-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP4]], i32 1 +; ANY-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP2]], i32 2 +; ANY-NEXT: [[RC:%.*]] = insertelement <4 x float> [[RB]], float [[TMP5]], i32 2 +; ANY-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[TMP2]], i32 3 +; ANY-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP6]], i32 3 +; ANY-NEXT: call void @v4f32_user(<4 x float> [[RD]]) #0 +; ANY-NEXT: ret <4 x float> [[RD]] ; %c0 = extractelement <4 x i32> %c, i32 0 %c1 = extractelement <4 x i32> %c, i32 1 @@ -290,44 +214,44 @@ define <4 x float> @simple_select_users(<4 x float> %a, <4 x float> %b, <4 x i32 ; Unused insertelement define <4 x float> @simple_select_no_users(<4 x float> %a, <4 x float> %b, <4 x i32> %c) #0 { -; CHECK-LABEL: @simple_select_no_users( -; CHECK-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 -; CHECK-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 -; CHECK-NEXT: [[C2:%.*]] = extractelement <4 x i32> [[C]], i32 2 -; CHECK-NEXT: [[C3:%.*]] = extractelement <4 x i32> [[C]], i32 3 -; CHECK-NEXT: [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0 -; CHECK-NEXT: [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1 -; CHECK-NEXT: [[A2:%.*]] = extractelement <4 x float> [[A]], i32 2 -; CHECK-NEXT: [[A3:%.*]] = extractelement <4 x float> [[A]], i32 3 -; CHECK-NEXT: [[B0:%.*]] = extractelement <4 x float> [[B:%.*]], i32 0 -; CHECK-NEXT: [[B1:%.*]] = extractelement <4 x float> [[B]], i32 1 -; CHECK-NEXT: [[B2:%.*]] = extractelement <4 x float> [[B]], i32 2 -; CHECK-NEXT: [[B3:%.*]] = extractelement <4 x float> [[B]], i32 3 -; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> undef, i32 [[C0]], i32 0 -; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[C1]], i32 1 -; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer -; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i32> undef, i32 [[C2]], i32 0 -; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x i32> [[TMP4]], i32 [[C3]], i32 1 -; CHECK-NEXT: [[TMP6:%.*]] = icmp ne <2 x i32> [[TMP5]], zeroinitializer -; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x float> undef, float [[A0]], i32 0 -; CHECK-NEXT: [[TMP8:%.*]] = insertelement <2 x float> [[TMP7]], float [[A1]], i32 1 -; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x float> undef, float [[B0]], i32 0 -; CHECK-NEXT: [[TMP10:%.*]] = insertelement <2 x float> [[TMP9]], float [[B1]], i32 1 -; CHECK-NEXT: [[TMP11:%.*]] = select <2 x i1> [[TMP3]], <2 x float> [[TMP8]], <2 x float> [[TMP10]] -; CHECK-NEXT: [[TMP12:%.*]] = insertelement <2 x float> undef, float [[A2]], i32 0 -; CHECK-NEXT: [[TMP13:%.*]] = insertelement <2 x float> [[TMP12]], float [[A3]], i32 1 -; CHECK-NEXT: [[TMP14:%.*]] = insertelement <2 x float> undef, float [[B2]], i32 0 -; CHECK-NEXT: [[TMP15:%.*]] = insertelement <2 x float> [[TMP14]], float [[B3]], i32 1 -; CHECK-NEXT: [[TMP16:%.*]] = select <2 x i1> [[TMP6]], <2 x float> [[TMP13]], <2 x float> [[TMP15]] -; CHECK-NEXT: [[TMP17:%.*]] = extractelement <2 x float> [[TMP11]], i32 0 -; CHECK-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP17]], i32 0 -; CHECK-NEXT: [[TMP18:%.*]] = extractelement <2 x float> [[TMP11]], i32 1 -; CHECK-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP18]], i32 1 -; CHECK-NEXT: [[TMP19:%.*]] = extractelement <2 x float> [[TMP16]], i32 0 -; CHECK-NEXT: [[RC:%.*]] = insertelement <4 x float> undef, float [[TMP19]], i32 2 -; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x float> [[TMP16]], i32 1 -; CHECK-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP20]], i32 3 -; CHECK-NEXT: ret <4 x float> [[RD]] +; BIGTHRESH-LABEL: @simple_select_no_users( +; BIGTHRESH-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 +; BIGTHRESH-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 +; BIGTHRESH-NEXT: [[C2:%.*]] = extractelement <4 x i32> [[C]], i32 2 +; BIGTHRESH-NEXT: [[C3:%.*]] = extractelement <4 x i32> [[C]], i32 3 +; BIGTHRESH-NEXT: [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0 +; BIGTHRESH-NEXT: [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1 +; BIGTHRESH-NEXT: [[A2:%.*]] = extractelement <4 x float> [[A]], i32 2 +; BIGTHRESH-NEXT: [[A3:%.*]] = extractelement <4 x float> [[A]], i32 3 +; BIGTHRESH-NEXT: [[B0:%.*]] = extractelement <4 x float> [[B:%.*]], i32 0 +; BIGTHRESH-NEXT: [[B1:%.*]] = extractelement <4 x float> [[B]], i32 1 +; BIGTHRESH-NEXT: [[B2:%.*]] = extractelement <4 x float> [[B]], i32 2 +; BIGTHRESH-NEXT: [[B3:%.*]] = extractelement <4 x float> [[B]], i32 3 +; BIGTHRESH-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> undef, i32 [[C0]], i32 0 +; BIGTHRESH-NEXT: [[TMP2:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[C1]], i32 1 +; BIGTHRESH-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer +; BIGTHRESH-NEXT: [[TMP4:%.*]] = insertelement <2 x i32> undef, i32 [[C2]], i32 0 +; BIGTHRESH-NEXT: [[TMP5:%.*]] = insertelement <2 x i32> [[TMP4]], i32 [[C3]], i32 1 +; BIGTHRESH-NEXT: [[TMP6:%.*]] = icmp ne <2 x i32> [[TMP5]], zeroinitializer +; BIGTHRESH-NEXT: [[TMP7:%.*]] = insertelement <2 x float> undef, float [[A0]], i32 0 +; BIGTHRESH-NEXT: [[TMP8:%.*]] = insertelement <2 x float> [[TMP7]], float [[A1]], i32 1 +; BIGTHRESH-NEXT: [[TMP9:%.*]] = insertelement <2 x float> undef, float [[B0]], i32 0 +; BIGTHRESH-NEXT: [[TMP10:%.*]] = insertelement <2 x float> [[TMP9]], float [[B1]], i32 1 +; BIGTHRESH-NEXT: [[TMP11:%.*]] = select <2 x i1> [[TMP3]], <2 x float> [[TMP8]], <2 x float> [[TMP10]] +; BIGTHRESH-NEXT: [[TMP12:%.*]] = insertelement <2 x float> undef, float [[A2]], i32 0 +; BIGTHRESH-NEXT: [[TMP13:%.*]] = insertelement <2 x float> [[TMP12]], float [[A3]], i32 1 +; BIGTHRESH-NEXT: [[TMP14:%.*]] = insertelement <2 x float> undef, float [[B2]], i32 0 +; BIGTHRESH-NEXT: [[TMP15:%.*]] = insertelement <2 x float> [[TMP14]], float [[B3]], i32 1 +; BIGTHRESH-NEXT: [[TMP16:%.*]] = select <2 x i1> [[TMP6]], <2 x float> [[TMP13]], <2 x float> [[TMP15]] +; BIGTHRESH-NEXT: [[TMP17:%.*]] = extractelement <2 x float> [[TMP11]], i32 0 +; BIGTHRESH-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP17]], i32 0 +; BIGTHRESH-NEXT: [[TMP18:%.*]] = extractelement <2 x float> [[TMP11]], i32 1 +; BIGTHRESH-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP18]], i32 1 +; BIGTHRESH-NEXT: [[TMP19:%.*]] = extractelement <2 x float> [[TMP16]], i32 0 +; BIGTHRESH-NEXT: [[RC:%.*]] = insertelement <4 x float> undef, float [[TMP19]], i32 2 +; BIGTHRESH-NEXT: [[TMP20:%.*]] = extractelement <2 x float> [[TMP16]], i32 1 +; BIGTHRESH-NEXT: [[RD:%.*]] = insertelement <4 x float> [[RC]], float [[TMP20]], i32 3 +; BIGTHRESH-NEXT: ret <4 x float> [[RD]] ; ; ZEROTHRESH-LABEL: @simple_select_no_users( ; ZEROTHRESH-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 @@ -392,27 +316,16 @@ define <4 x float> @simple_select_no_users(<4 x float> %a, <4 x float> %b, <4 x ; Make sure infinite loop doesn't happen which I ran into when trying ; to do this backwards this backwards define <4 x i32> @reconstruct(<4 x i32> %c) #0 { -; CHECK-LABEL: @reconstruct( -; CHECK-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 -; CHECK-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 -; CHECK-NEXT: [[C2:%.*]] = extractelement <4 x i32> [[C]], i32 2 -; CHECK-NEXT: [[C3:%.*]] = extractelement <4 x i32> [[C]], i32 3 -; CHECK-NEXT: [[RA:%.*]] = insertelement <4 x i32> undef, i32 [[C0]], i32 0 -; CHECK-NEXT: [[RB:%.*]] = insertelement <4 x i32> [[RA]], i32 [[C1]], i32 1 -; CHECK-NEXT: [[RC:%.*]] = insertelement <4 x i32> [[RB]], i32 [[C2]], i32 2 -; CHECK-NEXT: [[RD:%.*]] = insertelement <4 x i32> [[RC]], i32 [[C3]], i32 3 -; CHECK-NEXT: ret <4 x i32> [[RD]] -; -; ZEROTHRESH-LABEL: @reconstruct( -; ZEROTHRESH-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 -; ZEROTHRESH-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 -; ZEROTHRESH-NEXT: [[C2:%.*]] = extractelement <4 x i32> [[C]], i32 2 -; ZEROTHRESH-NEXT: [[C3:%.*]] = extractelement <4 x i32> [[C]], i32 3 -; ZEROTHRESH-NEXT: [[RA:%.*]] = insertelement <4 x i32> undef, i32 [[C0]], i32 0 -; ZEROTHRESH-NEXT: [[RB:%.*]] = insertelement <4 x i32> [[RA]], i32 [[C1]], i32 1 -; ZEROTHRESH-NEXT: [[RC:%.*]] = insertelement <4 x i32> [[RB]], i32 [[C2]], i32 2 -; ZEROTHRESH-NEXT: [[RD:%.*]] = insertelement <4 x i32> [[RC]], i32 [[C3]], i32 3 -; ZEROTHRESH-NEXT: ret <4 x i32> [[RD]] +; ANY-LABEL: @reconstruct( +; ANY-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 +; ANY-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 +; ANY-NEXT: [[C2:%.*]] = extractelement <4 x i32> [[C]], i32 2 +; ANY-NEXT: [[C3:%.*]] = extractelement <4 x i32> [[C]], i32 3 +; ANY-NEXT: [[RA:%.*]] = insertelement <4 x i32> undef, i32 [[C0]], i32 0 +; ANY-NEXT: [[RB:%.*]] = insertelement <4 x i32> [[RA]], i32 [[C1]], i32 1 +; ANY-NEXT: [[RC:%.*]] = insertelement <4 x i32> [[RB]], i32 [[C2]], i32 2 +; ANY-NEXT: [[RD:%.*]] = insertelement <4 x i32> [[RC]], i32 [[C3]], i32 3 +; ANY-NEXT: ret <4 x i32> [[RD]] ; %c0 = extractelement <4 x i32> %c, i32 0 %c1 = extractelement <4 x i32> %c, i32 1 @@ -426,23 +339,14 @@ define <4 x i32> @reconstruct(<4 x i32> %c) #0 { } define <2 x float> @simple_select_v2(<2 x float> %a, <2 x float> %b, <2 x i32> %c) #0 { -; CHECK-LABEL: @simple_select_v2( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[C:%.*]], zeroinitializer -; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x float> [[A:%.*]], <2 x float> [[B:%.*]] -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x float> [[TMP2]], i32 0 -; CHECK-NEXT: [[RA:%.*]] = insertelement <2 x float> undef, float [[TMP3]], i32 0 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x float> [[TMP2]], i32 1 -; CHECK-NEXT: [[RB:%.*]] = insertelement <2 x float> [[RA]], float [[TMP4]], i32 1 -; CHECK-NEXT: ret <2 x float> [[RB]] -; -; ZEROTHRESH-LABEL: @simple_select_v2( -; ZEROTHRESH-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[C:%.*]], zeroinitializer -; ZEROTHRESH-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x float> [[A:%.*]], <2 x float> [[B:%.*]] -; ZEROTHRESH-NEXT: [[TMP3:%.*]] = extractelement <2 x float> [[TMP2]], i32 0 -; ZEROTHRESH-NEXT: [[RA:%.*]] = insertelement <2 x float> undef, float [[TMP3]], i32 0 -; ZEROTHRESH-NEXT: [[TMP4:%.*]] = extractelement <2 x float> [[TMP2]], i32 1 -; ZEROTHRESH-NEXT: [[RB:%.*]] = insertelement <2 x float> [[RA]], float [[TMP4]], i32 1 -; ZEROTHRESH-NEXT: ret <2 x float> [[RB]] +; ANY-LABEL: @simple_select_v2( +; ANY-NEXT: [[TMP1:%.*]] = icmp ne <2 x i32> [[C:%.*]], zeroinitializer +; ANY-NEXT: [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x float> [[A:%.*]], <2 x float> [[B:%.*]] +; ANY-NEXT: [[TMP3:%.*]] = extractelement <2 x float> [[TMP2]], i32 0 +; ANY-NEXT: [[RA:%.*]] = insertelement <2 x float> undef, float [[TMP3]], i32 0 +; ANY-NEXT: [[TMP4:%.*]] = extractelement <2 x float> [[TMP2]], i32 1 +; ANY-NEXT: [[RB:%.*]] = insertelement <2 x float> [[RA]], float [[TMP4]], i32 1 +; ANY-NEXT: ret <2 x float> [[RB]] ; %c0 = extractelement <2 x i32> %c, i32 0 %c1 = extractelement <2 x i32> %c, i32 1 @@ -463,47 +367,26 @@ define <2 x float> @simple_select_v2(<2 x float> %a, <2 x float> %b, <2 x i32> % ; re-visiting the insertelement chains starting with undef ; (low cost threshold needed to force this to happen) define <4 x float> @simple_select_partial_vector(<4 x float> %a, <4 x float> %b, <4 x i32> %c) #0 { -; CHECK-LABEL: @simple_select_partial_vector( -; CHECK-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 -; CHECK-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 -; CHECK-NEXT: [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0 -; CHECK-NEXT: [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1 -; CHECK-NEXT: [[B0:%.*]] = extractelement <4 x float> [[B:%.*]], i32 0 -; CHECK-NEXT: [[B1:%.*]] = extractelement <4 x float> [[B]], i32 1 -; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> undef, i32 [[C0]], i32 0 -; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[C1]], i32 1 -; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer -; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x float> undef, float [[A0]], i32 0 -; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x float> [[TMP4]], float [[A1]], i32 1 -; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x float> undef, float [[B0]], i32 0 -; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[B1]], i32 1 -; CHECK-NEXT: [[TMP8:%.*]] = select <2 x i1> [[TMP3]], <2 x float> [[TMP5]], <2 x float> [[TMP7]] -; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[TMP8]], i32 0 -; CHECK-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP9]], i32 0 -; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x float> [[TMP8]], i32 1 -; CHECK-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP10]], i32 1 -; CHECK-NEXT: ret <4 x float> [[RB]] -; -; ZEROTHRESH-LABEL: @simple_select_partial_vector( -; ZEROTHRESH-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 -; ZEROTHRESH-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 -; ZEROTHRESH-NEXT: [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0 -; ZEROTHRESH-NEXT: [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1 -; ZEROTHRESH-NEXT: [[B0:%.*]] = extractelement <4 x float> [[B:%.*]], i32 0 -; ZEROTHRESH-NEXT: [[B1:%.*]] = extractelement <4 x float> [[B]], i32 1 -; ZEROTHRESH-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> undef, i32 [[C0]], i32 0 -; ZEROTHRESH-NEXT: [[TMP2:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[C1]], i32 1 -; ZEROTHRESH-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer -; ZEROTHRESH-NEXT: [[TMP4:%.*]] = insertelement <2 x float> undef, float [[A0]], i32 0 -; ZEROTHRESH-NEXT: [[TMP5:%.*]] = insertelement <2 x float> [[TMP4]], float [[A1]], i32 1 -; ZEROTHRESH-NEXT: [[TMP6:%.*]] = insertelement <2 x float> undef, float [[B0]], i32 0 -; ZEROTHRESH-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[B1]], i32 1 -; ZEROTHRESH-NEXT: [[TMP8:%.*]] = select <2 x i1> [[TMP3]], <2 x float> [[TMP5]], <2 x float> [[TMP7]] -; ZEROTHRESH-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[TMP8]], i32 0 -; ZEROTHRESH-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP9]], i32 0 -; ZEROTHRESH-NEXT: [[TMP10:%.*]] = extractelement <2 x float> [[TMP8]], i32 1 -; ZEROTHRESH-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP10]], i32 1 -; ZEROTHRESH-NEXT: ret <4 x float> [[RB]] +; ANY-LABEL: @simple_select_partial_vector( +; ANY-NEXT: [[C0:%.*]] = extractelement <4 x i32> [[C:%.*]], i32 0 +; ANY-NEXT: [[C1:%.*]] = extractelement <4 x i32> [[C]], i32 1 +; ANY-NEXT: [[A0:%.*]] = extractelement <4 x float> [[A:%.*]], i32 0 +; ANY-NEXT: [[A1:%.*]] = extractelement <4 x float> [[A]], i32 1 +; ANY-NEXT: [[B0:%.*]] = extractelement <4 x float> [[B:%.*]], i32 0 +; ANY-NEXT: [[B1:%.*]] = extractelement <4 x float> [[B]], i32 1 +; ANY-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> undef, i32 [[C0]], i32 0 +; ANY-NEXT: [[TMP2:%.*]] = insertelement <2 x i32> [[TMP1]], i32 [[C1]], i32 1 +; ANY-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer +; ANY-NEXT: [[TMP4:%.*]] = insertelement <2 x float> undef, float [[A0]], i32 0 +; ANY-NEXT: [[TMP5:%.*]] = insertelement <2 x float> [[TMP4]], float [[A1]], i32 1 +; ANY-NEXT: [[TMP6:%.*]] = insertelement <2 x float> undef, float [[B0]], i32 0 +; ANY-NEXT: [[TMP7:%.*]] = insertelement <2 x float> [[TMP6]], float [[B1]], i32 1 +; ANY-NEXT: [[TMP8:%.*]] = select <2 x i1> [[TMP3]], <2 x float> [[TMP5]], <2 x float> [[TMP7]] +; ANY-NEXT: [[TMP9:%.*]] = extractelement <2 x float> [[TMP8]], i32 0 +; ANY-NEXT: [[RA:%.*]] = insertelement <4 x float> undef, float [[TMP9]], i32 0 +; ANY-NEXT: [[TMP10:%.*]] = extractelement <2 x float> [[TMP8]], i32 1 +; ANY-NEXT: [[RB:%.*]] = insertelement <4 x float> [[RA]], float [[TMP10]], i32 1 +; ANY-NEXT: ret <4 x float> [[RB]] ; %c0 = extractelement <4 x i32> %c, i32 0 %c1 = extractelement <4 x i32> %c, i32 1 @@ -529,29 +412,17 @@ define <4 x float> @simple_select_partial_vector(<4 x float> %a, <4 x float> %b, ; Make sure that vectorization happens even if insertelements operations ; must be rescheduled. The case here is from compiling Julia. define <4 x float> @reschedule_extract(<4 x float> %a, <4 x float> %b) { -; CHECK-LABEL: @reschedule_extract( -; CHECK-NEXT: [[TMP1:%.*]] = fadd <4 x float> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0 -; CHECK-NEXT: [[V0:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0 -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1 -; CHECK-NEXT: [[V1:%.*]] = insertelement <4 x float> [[V0]], float [[TMP3]], i32 1 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2 -; CHECK-NEXT: [[V2:%.*]] = insertelement <4 x float> [[V1]], float [[TMP4]], i32 2 -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3 -; CHECK-NEXT: [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[TMP5]], i32 3 -; CHECK-NEXT: ret <4 x float> [[V3]] -; -; ZEROTHRESH-LABEL: @reschedule_extract( -; ZEROTHRESH-NEXT: [[TMP1:%.*]] = fadd <4 x float> [[A:%.*]], [[B:%.*]] -; ZEROTHRESH-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0 -; ZEROTHRESH-NEXT: [[V0:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0 -; ZEROTHRESH-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1 -; ZEROTHRESH-NEXT: [[V1:%.*]] = insertelement <4 x float> [[V0]], float [[TMP3]], i32 1 -; ZEROTHRESH-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2 -; ZEROTHRESH-NEXT: [[V2:%.*]] = insertelement <4 x float> [[V1]], float [[TMP4]], i32 2 -; ZEROTHRESH-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3 -; ZEROTHRESH-NEXT: [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[TMP5]], i32 3 -; ZEROTHRESH-NEXT: ret <4 x float> [[V3]] +; ANY-LABEL: @reschedule_extract( +; ANY-NEXT: [[TMP1:%.*]] = fadd <4 x float> [[A:%.*]], [[B:%.*]] +; ANY-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0 +; ANY-NEXT: [[V0:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0 +; ANY-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1 +; ANY-NEXT: [[V1:%.*]] = insertelement <4 x float> [[V0]], float [[TMP3]], i32 1 +; ANY-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2 +; ANY-NEXT: [[V2:%.*]] = insertelement <4 x float> [[V1]], float [[TMP4]], i32 2 +; ANY-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3 +; ANY-NEXT: [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[TMP5]], i32 3 +; ANY-NEXT: ret <4 x float> [[V3]] ; %a0 = extractelement <4 x float> %a, i32 0 %b0 = extractelement <4 x float> %b, i32 0 @@ -575,29 +446,17 @@ define <4 x float> @reschedule_extract(<4 x float> %a, <4 x float> %b) { ; Check that cost model for vectorization takes credit for ; instructions that are erased. define <4 x float> @take_credit(<4 x float> %a, <4 x float> %b) { -; CHECK-LABEL: @take_credit( -; CHECK-NEXT: [[TMP1:%.*]] = fadd <4 x float> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0 -; CHECK-NEXT: [[V0:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0 -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1 -; CHECK-NEXT: [[V1:%.*]] = insertelement <4 x float> [[V0]], float [[TMP3]], i32 1 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2 -; CHECK-NEXT: [[V2:%.*]] = insertelement <4 x float> [[V1]], float [[TMP4]], i32 2 -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3 -; CHECK-NEXT: [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[TMP5]], i32 3 -; CHECK-NEXT: ret <4 x float> [[V3]] -; -; ZEROTHRESH-LABEL: @take_credit( -; ZEROTHRESH-NEXT: [[TMP1:%.*]] = fadd <4 x float> [[A:%.*]], [[B:%.*]] -; ZEROTHRESH-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0 -; ZEROTHRESH-NEXT: [[V0:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0 -; ZEROTHRESH-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1 -; ZEROTHRESH-NEXT: [[V1:%.*]] = insertelement <4 x float> [[V0]], float [[TMP3]], i32 1 -; ZEROTHRESH-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2 -; ZEROTHRESH-NEXT: [[V2:%.*]] = insertelement <4 x float> [[V1]], float [[TMP4]], i32 2 -; ZEROTHRESH-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3 -; ZEROTHRESH-NEXT: [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[TMP5]], i32 3 -; ZEROTHRESH-NEXT: ret <4 x float> [[V3]] +; ANY-LABEL: @take_credit( +; ANY-NEXT: [[TMP1:%.*]] = fadd <4 x float> [[A:%.*]], [[B:%.*]] +; ANY-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0 +; ANY-NEXT: [[V0:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0 +; ANY-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1 +; ANY-NEXT: [[V1:%.*]] = insertelement <4 x float> [[V0]], float [[TMP3]], i32 1 +; ANY-NEXT: [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2 +; ANY-NEXT: [[V2:%.*]] = insertelement <4 x float> [[V1]], float [[TMP4]], i32 2 +; ANY-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3 +; ANY-NEXT: [[V3:%.*]] = insertelement <4 x float> [[V2]], float [[TMP5]], i32 3 +; ANY-NEXT: ret <4 x float> [[V3]] ; %a0 = extractelement <4 x float> %a, i32 0 %b0 = extractelement <4 x float> %b, i32 0 @@ -620,43 +479,23 @@ define <4 x float> @take_credit(<4 x float> %a, <4 x float> %b) { ; Make sure we handle multiple trees that feed one build vector correctly. define <4 x double> @multi_tree(double %w, double %x, double %y, double %z) { -; CHECK-LABEL: @multi_tree( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x double> undef, double [[W:%.*]], i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x double> [[TMP0]], double [[X:%.*]], i32 1 -; CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x double> [[TMP1]], double [[Y:%.*]], i32 2 -; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x double> [[TMP2]], double [[Z:%.*]], i32 3 -; CHECK-NEXT: [[TMP4:%.*]] = fadd <4 x double> [[TMP3]], -; CHECK-NEXT: [[TMP5:%.*]] = fmul <4 x double> [[TMP4]], -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x double> [[TMP5]], i32 0 -; CHECK-NEXT: [[I1:%.*]] = insertelement <4 x double> undef, double [[TMP6]], i32 3 -; CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x double> [[TMP5]], i32 1 -; CHECK-NEXT: [[I2:%.*]] = insertelement <4 x double> [[I1]], double [[TMP7]], i32 2 -; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x double> [[TMP5]], i32 2 -; CHECK-NEXT: [[I3:%.*]] = insertelement <4 x double> [[I2]], double [[TMP8]], i32 1 -; CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x double> [[TMP5]], i32 3 -; CHECK-NEXT: [[I4:%.*]] = insertelement <4 x double> [[I3]], double [[TMP9]], i32 0 -; CHECK-NEXT: ret <4 x double> [[I4]] -; -; ZEROTHRESH-LABEL: @multi_tree( -; ZEROTHRESH-NEXT: entry: -; ZEROTHRESH-NEXT: [[TMP0:%.*]] = insertelement <4 x double> undef, double [[W:%.*]], i32 0 -; ZEROTHRESH-NEXT: [[TMP1:%.*]] = insertelement <4 x double> [[TMP0]], double [[X:%.*]], i32 1 -; ZEROTHRESH-NEXT: [[TMP2:%.*]] = insertelement <4 x double> [[TMP1]], double [[Y:%.*]], i32 2 -; ZEROTHRESH-NEXT: [[TMP3:%.*]] = insertelement <4 x double> [[TMP2]], double [[Z:%.*]], i32 3 -; ZEROTHRESH-NEXT: [[TMP4:%.*]] = fadd <4 x double> [[TMP3]], -; ZEROTHRESH-NEXT: [[TMP5:%.*]] = fmul <4 x double> [[TMP4]], -; ZEROTHRESH-NEXT: [[TMP6:%.*]] = extractelement <4 x double> [[TMP5]], i32 0 -; ZEROTHRESH-NEXT: [[I1:%.*]] = insertelement <4 x double> undef, double [[TMP6]], i32 3 -; ZEROTHRESH-NEXT: [[TMP7:%.*]] = extractelement <4 x double> [[TMP5]], i32 1 -; ZEROTHRESH-NEXT: [[I2:%.*]] = insertelement <4 x double> [[I1]], double [[TMP7]], i32 2 -; ZEROTHRESH-NEXT: [[TMP8:%.*]] = extractelement <4 x double> [[TMP5]], i32 2 -; ZEROTHRESH-NEXT: [[I3:%.*]] = insertelement <4 x double> [[I2]], double [[TMP8]], i32 1 -; ZEROTHRESH-NEXT: [[TMP9:%.*]] = extractelement <4 x double> [[TMP5]], i32 3 -; ZEROTHRESH-NEXT: [[I4:%.*]] = insertelement <4 x double> [[I3]], double [[TMP9]], i32 0 -; ZEROTHRESH-NEXT: ret <4 x double> [[I4]] +; ANY-LABEL: @multi_tree( +; ANY-NEXT: [[TMP1:%.*]] = insertelement <4 x double> undef, double [[W:%.*]], i32 0 +; ANY-NEXT: [[TMP2:%.*]] = insertelement <4 x double> [[TMP1]], double [[X:%.*]], i32 1 +; ANY-NEXT: [[TMP3:%.*]] = insertelement <4 x double> [[TMP2]], double [[Y:%.*]], i32 2 +; ANY-NEXT: [[TMP4:%.*]] = insertelement <4 x double> [[TMP3]], double [[Z:%.*]], i32 3 +; ANY-NEXT: [[TMP5:%.*]] = fadd <4 x double> [[TMP4]], +; ANY-NEXT: [[TMP6:%.*]] = fmul <4 x double> [[TMP5]], +; ANY-NEXT: [[TMP7:%.*]] = extractelement <4 x double> [[TMP6]], i32 0 +; ANY-NEXT: [[I1:%.*]] = insertelement <4 x double> undef, double [[TMP7]], i32 3 +; ANY-NEXT: [[TMP8:%.*]] = extractelement <4 x double> [[TMP6]], i32 1 +; ANY-NEXT: [[I2:%.*]] = insertelement <4 x double> [[I1]], double [[TMP8]], i32 2 +; ANY-NEXT: [[TMP9:%.*]] = extractelement <4 x double> [[TMP6]], i32 2 +; ANY-NEXT: [[I3:%.*]] = insertelement <4 x double> [[I2]], double [[TMP9]], i32 1 +; ANY-NEXT: [[TMP10:%.*]] = extractelement <4 x double> [[TMP6]], i32 3 +; ANY-NEXT: [[I4:%.*]] = insertelement <4 x double> [[I3]], double [[TMP10]], i32 0 +; ANY-NEXT: ret <4 x double> [[I4]] ; -entry: %t0 = fadd double %w , 0.000000e+00 %t1 = fadd double %x , 1.000000e+00 %t2 = fadd double %y , 2.000000e+00 @@ -673,49 +512,26 @@ entry: } define <8 x float> @_vadd256(<8 x float> %a, <8 x float> %b) local_unnamed_addr #0 { -; CHECK-LABEL: @_vadd256( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = fadd <8 x float> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = extractelement <8 x float> [[TMP0]], i32 0 -; CHECK-NEXT: [[VECINIT_I:%.*]] = insertelement <8 x float> undef, float [[TMP1]], i32 0 -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <8 x float> [[TMP0]], i32 1 -; CHECK-NEXT: [[VECINIT1_I:%.*]] = insertelement <8 x float> [[VECINIT_I]], float [[TMP2]], i32 1 -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <8 x float> [[TMP0]], i32 2 -; CHECK-NEXT: [[VECINIT2_I:%.*]] = insertelement <8 x float> [[VECINIT1_I]], float [[TMP3]], i32 2 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <8 x float> [[TMP0]], i32 3 -; CHECK-NEXT: [[VECINIT3_I:%.*]] = insertelement <8 x float> [[VECINIT2_I]], float [[TMP4]], i32 3 -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <8 x float> [[TMP0]], i32 4 -; CHECK-NEXT: [[VECINIT4_I:%.*]] = insertelement <8 x float> [[VECINIT3_I]], float [[TMP5]], i32 4 -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <8 x float> [[TMP0]], i32 5 -; CHECK-NEXT: [[VECINIT5_I:%.*]] = insertelement <8 x float> [[VECINIT4_I]], float [[TMP6]], i32 5 -; CHECK-NEXT: [[TMP7:%.*]] = extractelement <8 x float> [[TMP0]], i32 6 -; CHECK-NEXT: [[VECINIT6_I:%.*]] = insertelement <8 x float> [[VECINIT5_I]], float [[TMP7]], i32 6 -; CHECK-NEXT: [[TMP8:%.*]] = extractelement <8 x float> [[TMP0]], i32 7 -; CHECK-NEXT: [[VECINIT7_I:%.*]] = insertelement <8 x float> [[VECINIT6_I]], float [[TMP8]], i32 7 -; CHECK-NEXT: ret <8 x float> [[VECINIT7_I]] -; -; ZEROTHRESH-LABEL: @_vadd256( -; ZEROTHRESH-NEXT: entry: -; ZEROTHRESH-NEXT: [[TMP0:%.*]] = fadd <8 x float> [[A:%.*]], [[B:%.*]] -; ZEROTHRESH-NEXT: [[TMP1:%.*]] = extractelement <8 x float> [[TMP0]], i32 0 -; ZEROTHRESH-NEXT: [[VECINIT_I:%.*]] = insertelement <8 x float> undef, float [[TMP1]], i32 0 -; ZEROTHRESH-NEXT: [[TMP2:%.*]] = extractelement <8 x float> [[TMP0]], i32 1 -; ZEROTHRESH-NEXT: [[VECINIT1_I:%.*]] = insertelement <8 x float> [[VECINIT_I]], float [[TMP2]], i32 1 -; ZEROTHRESH-NEXT: [[TMP3:%.*]] = extractelement <8 x float> [[TMP0]], i32 2 -; ZEROTHRESH-NEXT: [[VECINIT2_I:%.*]] = insertelement <8 x float> [[VECINIT1_I]], float [[TMP3]], i32 2 -; ZEROTHRESH-NEXT: [[TMP4:%.*]] = extractelement <8 x float> [[TMP0]], i32 3 -; ZEROTHRESH-NEXT: [[VECINIT3_I:%.*]] = insertelement <8 x float> [[VECINIT2_I]], float [[TMP4]], i32 3 -; ZEROTHRESH-NEXT: [[TMP5:%.*]] = extractelement <8 x float> [[TMP0]], i32 4 -; ZEROTHRESH-NEXT: [[VECINIT4_I:%.*]] = insertelement <8 x float> [[VECINIT3_I]], float [[TMP5]], i32 4 -; ZEROTHRESH-NEXT: [[TMP6:%.*]] = extractelement <8 x float> [[TMP0]], i32 5 -; ZEROTHRESH-NEXT: [[VECINIT5_I:%.*]] = insertelement <8 x float> [[VECINIT4_I]], float [[TMP6]], i32 5 -; ZEROTHRESH-NEXT: [[TMP7:%.*]] = extractelement <8 x float> [[TMP0]], i32 6 -; ZEROTHRESH-NEXT: [[VECINIT6_I:%.*]] = insertelement <8 x float> [[VECINIT5_I]], float [[TMP7]], i32 6 -; ZEROTHRESH-NEXT: [[TMP8:%.*]] = extractelement <8 x float> [[TMP0]], i32 7 -; ZEROTHRESH-NEXT: [[VECINIT7_I:%.*]] = insertelement <8 x float> [[VECINIT6_I]], float [[TMP8]], i32 7 -; ZEROTHRESH-NEXT: ret <8 x float> [[VECINIT7_I]] +; ANY-LABEL: @_vadd256( +; ANY-NEXT: [[TMP1:%.*]] = fadd <8 x float> [[A:%.*]], [[B:%.*]] +; ANY-NEXT: [[TMP2:%.*]] = extractelement <8 x float> [[TMP1]], i32 0 +; ANY-NEXT: [[VECINIT_I:%.*]] = insertelement <8 x float> undef, float [[TMP2]], i32 0 +; ANY-NEXT: [[TMP3:%.*]] = extractelement <8 x float> [[TMP1]], i32 1 +; ANY-NEXT: [[VECINIT1_I:%.*]] = insertelement <8 x float> [[VECINIT_I]], float [[TMP3]], i32 1 +; ANY-NEXT: [[TMP4:%.*]] = extractelement <8 x float> [[TMP1]], i32 2 +; ANY-NEXT: [[VECINIT2_I:%.*]] = insertelement <8 x float> [[VECINIT1_I]], float [[TMP4]], i32 2 +; ANY-NEXT: [[TMP5:%.*]] = extractelement <8 x float> [[TMP1]], i32 3 +; ANY-NEXT: [[VECINIT3_I:%.*]] = insertelement <8 x float> [[VECINIT2_I]], float [[TMP5]], i32 3 +; ANY-NEXT: [[TMP6:%.*]] = extractelement <8 x float> [[TMP1]], i32 4 +; ANY-NEXT: [[VECINIT4_I:%.*]] = insertelement <8 x float> [[VECINIT3_I]], float [[TMP6]], i32 4 +; ANY-NEXT: [[TMP7:%.*]] = extractelement <8 x float> [[TMP1]], i32 5 +; ANY-NEXT: [[VECINIT5_I:%.*]] = insertelement <8 x float> [[VECINIT4_I]], float [[TMP7]], i32 5 +; ANY-NEXT: [[TMP8:%.*]] = extractelement <8 x float> [[TMP1]], i32 6 +; ANY-NEXT: [[VECINIT6_I:%.*]] = insertelement <8 x float> [[VECINIT5_I]], float [[TMP8]], i32 6 +; ANY-NEXT: [[TMP9:%.*]] = extractelement <8 x float> [[TMP1]], i32 7 +; ANY-NEXT: [[VECINIT7_I:%.*]] = insertelement <8 x float> [[VECINIT6_I]], float [[TMP9]], i32 7 +; ANY-NEXT: ret <8 x float> [[VECINIT7_I]] ; - entry: %vecext = extractelement <8 x float> %a, i32 0 %vecext1 = extractelement <8 x float> %b, i32 0 %add = fadd float %vecext, %vecext1 From a03435ec8e219e236331780626351c74a95f1b6e Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Fri, 8 Nov 2019 15:24:11 +0100 Subject: [PATCH 04/14] Recommit "[DWARF] Add an api to get "interpreted" location lists" This recommits 089c0f581492cd6e2a3d2927be3fbf60ea2d7e62, which was reverted due to failing tests on big endian machines. It includes a fix which I believe (I don't have BE machine) should fix this issue. The fix consists of correcting the invocation DWARFYAML::EmitDebugSections, which was missing one (default) function arguments, and so didn't actually force the little-endian mode. The original commit message follows. Summary: This patch adds DWARFDie::getLocations, which returns the location expressions for a given attribute (typically DW_AT_location). It handles both "inline" locations and references to the external location list sections (currently only of the DW_FORM_sec_offset type). It is implemented on top of DWARFUnit::findLoclistFromOffset, which is also added in this patch. I tried to make their signatures similar to the equivalent range list functionality. The actual location list interpretation logic is in DWARFLocationTable::visitAbsoluteLocationList. This part is not equivalent to the range list code, but this deviation is motivated by a desire to reuse the same location list parsing code within lldb. The functionality is tested via a c++ unit test of the DWARFDie API. Reviewers: dblaikie, JDevlieghere, SouraVX Subscribers: mgorny, hiraditya, cmtice, probinson, llvm-commits, aprantl Tags: #llvm Differential Revision: https://reviews.llvm.org/D70394 --- .../llvm/DebugInfo/DWARF/DWARFDebugLoc.h | 5 + llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h | 4 + .../DebugInfo/DWARF/DWARFLocationExpression.h | 3 + llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 3 + llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp | 15 +++ llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 21 ++++ llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 24 ++++ llvm/lib/ObjectYAML/DWARFEmitter.cpp | 5 +- llvm/unittests/DebugInfo/DWARF/CMakeLists.txt | 1 + .../DebugInfo/DWARF/DWARFDieTest.cpp | 118 ++++++++++++++++++ 10 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h index 2ca98cfcfff71a..8ac3e2add8828c 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -63,6 +63,11 @@ class DWARFLocationTable { const MCRegisterInfo *MRI, DWARFUnit *U, DIDumpOptions DumpOpts, unsigned Indent) const; + Error visitAbsoluteLocationList( + uint64_t Offset, Optional BaseAddr, + std::function(uint32_t)> LookupAddr, + function_ref)> Callback) const; + protected: DWARFDataExtractor Data; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h index 52a0247b3e428c..158bd82edee0ba 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -18,6 +18,7 @@ #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFAttribute.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include #include #include @@ -231,6 +232,9 @@ class DWARFDie { bool addressRangeContainsAddress(const uint64_t Address) const; + Expected + getLocations(dwarf::Attribute Attr) const; + /// If a DIE represents a subprogram (or inlined subroutine), returns its /// mangled name (or short name, if mangled is missing). This name may be /// fetched from specification or abstract origin for this subprogram. diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFLocationExpression.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFLocationExpression.h index 1522658ead75c8..35aa1a78e129f6 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFLocationExpression.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFLocationExpression.h @@ -41,6 +41,9 @@ inline bool operator!=(const DWARFLocationExpression &L, raw_ostream &operator<<(raw_ostream &OS, const DWARFLocationExpression &Loc); +/// Represents a set of absolute location expressions. +using DWARFLocationExpressionsVector = std::vector; + } // end namespace llvm #endif // LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index d0a8533d1e3448..98d7a7ee3cae10 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -439,6 +439,9 @@ class DWARFUnit { } Expected collectAddressRanges(); + Expected + findLoclistFromOffset(uint64_t Offset); + /// Returns subprogram DIE with address range encompassing the provided /// address. The pointer is alive as long as parsed compile unit DIEs are not /// cleared. diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index 1af51a85d18d28..8b84822914d32a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -151,6 +151,21 @@ bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS, return true; } +Error DWARFLocationTable::visitAbsoluteLocationList( + uint64_t Offset, Optional BaseAddr, + std::function(uint32_t)> LookupAddr, + function_ref)> Callback) const { + DWARFLocationInterpreter Interp(BaseAddr, std::move(LookupAddr)); + return visitLocationList(&Offset, [&](const DWARFLocationEntry &E) { + Expected> Loc = Interp.Interpret(E); + if (!Loc) + return Callback(Loc.takeError()); + if (*Loc) + return Callback(**Loc); + return true; + }); +} + DWARFDebugLoc::LocationList const * DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { auto It = partition_point( diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index a11865e048c526..6cf30270539b28 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -486,6 +486,27 @@ bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { return false; } +Expected +DWARFDie::getLocations(dwarf::Attribute Attr) const { + Optional Location = find(Attr); + if (!Location) + return createStringError(inconvertibleErrorCode(), "No %s", + dwarf::AttributeString(Attr).data()); + + if (Optional Off = Location->getAsSectionOffset()) + return U->findLoclistFromOffset(*Off); + + if (Optional> Expr = Location->getAsBlock()) { + return DWARFLocationExpressionsVector{ + DWARFLocationExpression{None, to_vector<4>(*Expr)}}; + } + + return createStringError( + inconvertibleErrorCode(), "Unsupported %s encoding: %s", + dwarf::AttributeString(Attr).data(), + dwarf::FormEncodingString(Location->getForm()).data()); +} + const char *DWARFDie::getSubroutineName(DINameKind Kind) const { if (!isSubroutineDIE()) return nullptr; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 2eb7d2f945a328..e5d33e136445f8 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -637,6 +637,30 @@ Expected DWARFUnit::collectAddressRanges() { return *CUDIERangesOrError; } +Expected +DWARFUnit::findLoclistFromOffset(uint64_t Offset) { + DWARFLocationExpressionsVector Result; + + Error InterpretationError = Error::success(); + + Error ParseError = getLocationTable().visitAbsoluteLocationList( + Offset, getBaseAddress(), + [this](uint32_t Index) { return getAddrOffsetSectionItem(Index); }, + [&](Expected L) { + if (L) + Result.push_back(std::move(*L)); + else + InterpretationError = + joinErrors(L.takeError(), std::move(InterpretationError)); + return !InterpretationError; + }); + + if (ParseError || InterpretationError) + return joinErrors(std::move(ParseError), std::move(InterpretationError)); + + return Result; +} + void DWARFUnit::updateAddressDieMap(DWARFDie Die) { if (Die.isSubroutineDIE()) { auto DIERangesOrError = Die.getAddressRanges(); diff --git a/llvm/lib/ObjectYAML/DWARFEmitter.cpp b/llvm/lib/ObjectYAML/DWARFEmitter.cpp index 2ae66997cf597d..b410fed16f09cc 100644 --- a/llvm/lib/ObjectYAML/DWARFEmitter.cpp +++ b/llvm/lib/ObjectYAML/DWARFEmitter.cpp @@ -314,7 +314,10 @@ class DIEFixupVisitor : public DWARFYAML::Visitor { DIEFixupVisitor(DWARFYAML::Data &DI) : DWARFYAML::Visitor(DI){}; private: - virtual void onStartCompileUnit(DWARFYAML::Unit &CU) { Length = 7; } + virtual void onStartCompileUnit(DWARFYAML::Unit &CU) { + // Size of the unit header, excluding the length field itself. + Length = CU.Version >= 5 ? 8 : 7; + } virtual void onEndCompileUnit(DWARFYAML::Unit &CU) { CU.Length.setLength(Length); diff --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt index 2181e0543d049d..4fb79b2a96e919 100644 --- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_unittest(DebugInfoDWARFTests DwarfUtils.cpp DWARFDebugInfoTest.cpp DWARFDebugLineTest.cpp + DWARFDieTest.cpp DWARFFormValueTest.cpp DWARFLocationExpressionTest.cpp ) diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp new file mode 100644 index 00000000000000..53124925a8954b --- /dev/null +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp @@ -0,0 +1,118 @@ +//===- llvm/unittest/DebugInfo/DWARFDieTest.cpp ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/ObjectYAML/DWARFEmitter.h" +#include "llvm/Testing/Support/Error.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::dwarf; +using object::SectionedAddress; + +namespace { + +TEST(DWARFDie, getLocations) { + const char *yamldata = R"( + debug_abbrev: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_location + Form: DW_FORM_sec_offset + - Attribute: DW_AT_data_member_location + Form: DW_FORM_exprloc + - Attribute: DW_AT_vtable_elem_location + Form: DW_FORM_sec_offset + - Attribute: DW_AT_call_data_location + Form: DW_FORM_sec_offset + debug_info: + - Length: + TotalLength: 0 + Version: 5 + UnitType: DW_UT_compile + AbbrOffset: 0 + AddrSize: 4 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 12 + - Value: 0x0000000000000001 + BlockData: [ 0x47 ] + - Value: 20 + - Value: 25 + )"; + Expected>> Sections = + DWARFYAML::EmitDebugSections(StringRef(yamldata), /*ApplyFixups=*/true, + /*IsLittleEndian=*/true); + ASSERT_THAT_EXPECTED(Sections, Succeeded()); + std::vector Loclists{ + // Header + 0, 0, 0, 0, // Length + 5, 0, // Version + 4, // Address size + 0, // Segment selector size + 0, 0, 0, 0, // Offset entry count + // First location list. + DW_LLE_start_length, // First entry + 1, 0, 0, 0, // Start offset + 2, // Length + 0, // Expression length + DW_LLE_end_of_list, + // Second location list. + DW_LLE_startx_length, // First entry + 1, // Start index + 2, // Length + 0, // Expression length + DW_LLE_end_of_list, + // Third location list. + DW_LLE_start_length, // First entry + 1, 0, 0, 0, // Start offset + 2, // Length + 0, // Expression length + // end_of_list intentionally missing + }; + Loclists[0] = Loclists.size() - 4; + Sections->try_emplace( + "debug_loclists", + MemoryBuffer::getMemBuffer(toStringRef(Loclists), "debug_loclists", + /*RequiresNullTerminator=*/false)); + std::unique_ptr Ctx = + DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true); + DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); + ASSERT_NE(nullptr, CU); + DWARFDie Die = CU->getUnitDIE(); + ASSERT_TRUE(Die.isValid()); + + EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_location), + HasValue(testing::ElementsAre(DWARFLocationExpression{ + DWARFAddressRange{1, 3}, {}}))); + + EXPECT_THAT_EXPECTED( + Die.getLocations(DW_AT_data_member_location), + HasValue(testing::ElementsAre(DWARFLocationExpression{None, {0x47}}))); + + EXPECT_THAT_EXPECTED( + Die.getLocations(DW_AT_vtable_elem_location), + Failed(testing::Property( + &ErrorInfoBase::message, + "Unable to resolve indirect address 1 for: DW_LLE_startx_length"))); + + EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_call_data_location), + Failed(testing::Property( + &ErrorInfoBase::message, "unexpected end of data"))); + + EXPECT_THAT_EXPECTED( + Die.getLocations(DW_AT_call_data_value), + Failed(testing::Property(&ErrorInfoBase::message, + "No DW_AT_call_data_value"))); +} + +} // end anonymous namespace From ca33727abe4cd7202fe550972525bb23890da053 Mon Sep 17 00:00:00 2001 From: Xiangling Liao Date: Thu, 14 Nov 2019 09:52:32 -0500 Subject: [PATCH 05/14] [AIX] Lowering jump table, constant pool and block address in asm This patch lowering jump table, constant pool and block address in assembly. 1. On AIX, jump table index is always relative; 2. Put CPI and JTI into ReadOnlySection until we support unique data sections; 3. Create the temp symbol for block address symbol; 4. Update MIR testcases and add related assembly part; Differential Revision: https://reviews.llvm.org/D70243 --- .../CodeGen/TargetLoweringObjectFileImpl.h | 9 ++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 15 +- llvm/lib/CodeGen/MachineModuleInfo.cpp | 13 +- .../CodeGen/TargetLoweringObjectFileImpl.cpp | 21 ++- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 6 +- .../PowerPC/aix-lower-block-address.ll | 37 +++++ .../PowerPC/aix-lower-constant-pool-index.ll | 53 +++++++ .../CodeGen/PowerPC/aix-lower-jump-table.ll | 131 +++++++++++++++++- 8 files changed, 275 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 59f5ddbd9dac33..4f58df93b93e49 100644 --- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -233,6 +233,15 @@ class TargetLoweringObjectFileXCOFF : public TargetLoweringObjectFile { MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override; + MCSection *getSectionForJumpTable(const Function &F, + const TargetMachine &TM) const override; + + /// Given a constant with the SectionKind, return a section that it should be + /// placed in. + MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, + const Constant *C, + unsigned &Align) const override; + static XCOFF::StorageClass getStorageClassForGlobal(const GlobalObject *GO); }; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 8a4b4599f92e44..e2ef415e4d1e76 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1754,6 +1754,11 @@ void AsmPrinter::EmitConstantPool() { if (!Sym->isUndefined()) continue; + if (TM.getTargetTriple().isOSBinFormatXCOFF()) { + cast(Sym)->setContainingCsect( + cast(CPSections[i].S)); + } + if (CurSection != CPSections[i].S) { OutStreamer->SwitchSection(CPSections[i].S); EmitAlignment(Align(CPSections[i].Alignment)); @@ -1843,10 +1848,16 @@ void AsmPrinter::EmitJumpTableInfo() { // second label is actually referenced by the code. if (JTInDiffSection && DL.hasLinkerPrivateGlobalPrefix()) // FIXME: This doesn't have to have any specific name, just any randomly - // named and numbered 'l' label would work. Simplify GetJTISymbol. + // named and numbered local label started with 'l' would work. Simplify + // GetJTISymbol. OutStreamer->EmitLabel(GetJTISymbol(JTI, true)); - OutStreamer->EmitLabel(GetJTISymbol(JTI)); + MCSymbol* JTISymbol = GetJTISymbol(JTI); + if (TM.getTargetTriple().isOSBinFormatXCOFF()) { + cast(JTISymbol)->setContainingCsect( + cast(TLOF.getSectionForJumpTable(F, TM))); + } + OutStreamer->EmitLabel(JTISymbol); for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) EmitJumpTableEntry(MJTI, JTBBs[ii], JTI); diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp index 48a72c8357ed02..0094a923e03909 100644 --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -23,6 +23,7 @@ #include "llvm/InitializePasses.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolXCOFF.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -117,7 +118,17 @@ ArrayRef MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) { BBCallbacks.back().setMap(this); Entry.Index = BBCallbacks.size() - 1; Entry.Fn = BB->getParent(); - Entry.Symbols.push_back(Context.createTempSymbol(!BB->hasAddressTaken())); + MCSymbol *Sym = Context.createTempSymbol(!BB->hasAddressTaken()); + if (Context.getObjectFileInfo()->getTargetTriple().isOSBinFormatXCOFF()) { + MCSymbol *FnEntryPointSym = + Context.lookupSymbol("." + Entry.Fn->getName()); + assert(FnEntryPointSym && "The function entry pointer symbol should have" + " already been initialized."); + MCSectionXCOFF *Csect = + cast(FnEntryPointSym)->getContainingCsect(); + cast(Sym)->setContainingCsect(Csect); + } + Entry.Symbols.push_back(Sym); return Entry.Symbols; } diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 2dc13e9a250e02..5d5f77b83ef35a 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1868,9 +1868,28 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal( report_fatal_error("XCOFF other section types not yet implemented."); } +MCSection *TargetLoweringObjectFileXCOFF::getSectionForJumpTable( + const Function &F, const TargetMachine &TM) const { + assert (!TM.getFunctionSections() && "Unique sections not supported on XCOFF" + " yet."); + assert (!F.getComdat() && "Comdat not supported on XCOFF."); + //TODO: Enable emiting jump table to unique sections when we support it. + return ReadOnlySection; +} + bool TargetLoweringObjectFileXCOFF::shouldPutJumpTableInFunctionSection( bool UsesLabelDifference, const Function &F) const { - report_fatal_error("TLOF XCOFF not yet implemented."); + return false; +} + +/// Given a mergeable constant with the specified size and relocation +/// information, return a section that it should be placed in. +MCSection *TargetLoweringObjectFileXCOFF::getSectionForConstant( + const DataLayout &DL, SectionKind Kind, const Constant *C, + unsigned &Align) const { + //TODO: Enable emiting constant pool to unique sections when we support it. + if (Kind.isReadOnly() && ReadOnlySection != nullptr) + return ReadOnlySection; } void TargetLoweringObjectFileXCOFF::Initialize(MCContext &Ctx, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 313d6b835dbc70..0159e8c63c8547 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -2749,14 +2749,14 @@ unsigned PPCTargetLowering::getJumpTableEncoding() const { bool PPCTargetLowering::isJumpTableRelative() const { if (UseAbsoluteJumpTables) return false; - if (Subtarget.isPPC64()) + if (Subtarget.isPPC64() || Subtarget.isAIXABI()) return true; return TargetLowering::isJumpTableRelative(); } SDValue PPCTargetLowering::getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const { - if (!Subtarget.isPPC64()) + if (!Subtarget.isPPC64() || Subtarget.isAIXABI()) return TargetLowering::getPICJumpTableRelocBase(Table, DAG); switch (getTargetMachine().getCodeModel()) { @@ -2773,7 +2773,7 @@ const MCExpr * PPCTargetLowering::getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const { - if (!Subtarget.isPPC64()) + if (!Subtarget.isPPC64() || Subtarget.isAIXABI()) return TargetLowering::getPICJumpTableRelocBaseExpr(MF, JTI, Ctx); switch (getTargetMachine().getCodeModel()) { diff --git a/llvm/test/CodeGen/PowerPC/aix-lower-block-address.ll b/llvm/test/CodeGen/PowerPC/aix-lower-block-address.ll index 24ea946bacb681..2d6353876a3310 100644 --- a/llvm/test/CodeGen/PowerPC/aix-lower-block-address.ll +++ b/llvm/test/CodeGen/PowerPC/aix-lower-block-address.ll @@ -14,6 +14,18 @@ ; RUN: -code-model=large -stop-after=machine-cp < %s | FileCheck \ ; RUN: --check-prefix=64LARGE-MIR %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc-ibm-aix-xcoff \ +; RUN: -code-model=small < %s | FileCheck --check-prefixes=32SMALL-ASM,CHECK %s + +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc-ibm-aix-xcoff \ +; RUN: -code-model=large < %s | FileCheck --check-prefixes=32LARGE-ASM,CHECK %s + +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc64-ibm-aix-xcoff \ +; RUN: -code-model=small < %s | FileCheck --check-prefixes=64SMALL-ASM,CHECK %s + +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc64-ibm-aix-xcoff \ +; RUN: -code-model=large < %s | FileCheck --check-prefixes=64LARGE-ASM,CHECK %s + define void @foo() { entry: %tmp = alloca i64 @@ -33,3 +45,28 @@ __here: ; 64LARGE-MIR: renamable $x[[REG1:[0-9]+]] = ADDIStocHA8 $x2, blockaddress(@foo, %ir-block.__here) ; 64LARGE-MIR: renamable $x[[REG2:[0-9]+]] = LDtocL blockaddress(@foo, %ir-block.__here), killed renamable $x[[REG1]], implicit $x2 :: (load 8 from got) + +; 32SMALL-ASM-LABEL: foo +; 32SMALL-ASM: .foo: +; 32SMALL-ASM: Ltmp0: +; 32SMALL-ASM: lwz [[REG1:[0-9]+]], LC0(2) + +; 32LARGE-ASM-LABEL: foo +; 32LARGE-ASM: .foo: +; 32LARGE-ASM: Ltmp0: +; 32LARGE-ASM: addis [[REG1:[0-9]+]], LC0@u(2) +; 32LARGE-ASM: lwz [[REG2:[0-9]+]], LC0@l([[REG1]]) + +; 64SMALL-ASM-LABEL: foo +; 64SMALL-ASM: .foo: +; 64SMALL-ASM: Ltmp0: +; 64SMALL-ASM: ld [[REG1:[0-9]+]], LC0(2) + +; 64LARGE-ASM-LABEL: foo +; 64LARGE-ASM: .foo: +; 64LARGE-ASM: Ltmp0: +; 64LARGE-ASM: addis [[REG1:[0-9]+]], LC0@u(2) +; 64LARGE-ASM: ld [[REG2:[0-9]+]], LC0@l([[REG1]]) + +; CHECK: .toc +; CHECK-NOT: .tc diff --git a/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll b/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll index 7268773c9ea800..8803a1e4569fb8 100644 --- a/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll +++ b/llvm/test/CodeGen/PowerPC/aix-lower-constant-pool-index.ll @@ -14,6 +14,18 @@ ; RUN: -code-model=large -stop-after=machine-cp < %s | FileCheck \ ; RUN: --check-prefix=64LARGE-MIR %s +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc-ibm-aix-xcoff \ +; RUN: -code-model=small < %s | FileCheck --check-prefixes=32SMALL-ASM,CHECK %s + +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc-ibm-aix-xcoff \ +; RUN: -code-model=large < %s | FileCheck --check-prefixes=32LARGE-ASM,CHECK %s + +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc64-ibm-aix-xcoff \ +; RUN: -code-model=small < %s | FileCheck --check-prefixes=64SMALL-ASM,CHECK %s + +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -mtriple powerpc64-ibm-aix-xcoff \ +; RUN: -code-model=large < %s | FileCheck --check-prefixes=64LARGE-ASM,CHECK %s + define float @test_float() { entry: ret float 5.500000e+00 @@ -32,3 +44,44 @@ entry: ; 64LARGE-MIR: renamable $x[[REG1:[0-9]+]] = ADDIStocHA8 $x2, %const.0 ; 64LARGE-MIR: renamable $x[[REG2:[0-9]+]] = LDtocL %const.0, killed renamable $x[[REG1]], implicit $x2 :: (load 8 from got) ; 64LARGE-MIR: renamable $f[[REG3:[0-9]+]] = LFS 0, killed renamable $x[[REG2]] :: (load 4 from constant-pool) + +; 32SMALL-ASM: .csect .rodata[RO] +; 32SMALL-ASM: .align 2 +; 32SMALL-ASM: .LCPI0_0: +; 32SMALL-ASM: .long 1085276160 +; 32SMALL-ASM: .test_float: +; 32SMALL-ASM: lwz [[REG1:[0-9]+]], LC0(2) +; 32SMALL-ASM: lfs 1, 0([[REG1]]) +; 32SMALL-ASM: blr + +; 32LARGE-ASM: .csect .rodata[RO] +; 32LARGE-ASM: .align 2 +; 32LARGE-ASM: .LCPI0_0: +; 32LARGE-ASM: .long 1085276160 +; 32LARGE-ASM: .test_float: +; 32LARGE-ASM: addis [[REG1:[0-9]+]], LC0@u(2) +; 32LARGE-ASM: lwz [[REG2:[0-9]+]], LC0@l([[REG1]]) +; 32LARGE-ASM: lfs 1, 0([[REG2]]) +; 32LARGE-ASM: blr + +; 64SMALL-ASM: .csect .rodata[RO] +; 64SMALL-ASM: .align 2 +; 64SMALL-ASM: .LCPI0_0: +; 64SMALL-ASM: .long 1085276160 +; 64SMALL-ASM: .test_float: +; 64SMALL-ASM: ld [[REG1:[0-9]+]], LC0(2) +; 64SMALL-ASM: lfs 1, 0([[REG1]]) +; 64SMALL-ASM: blr + +; 64LARGE-ASM: .csect .rodata[RO] +; 64LARGE-ASM: .align 2 +; 64LARGE-ASM: .LCPI0_0: +; 64LARGE-ASM: .long 1085276160 +; 64LARGE-ASM: .test_float: +; 64LARGE-ASM: addis [[REG1:[0-9]+]], LC0@u(2) +; 64LARGE-ASM: ld [[REG2:[0-9]+]], LC0@l([[REG1]]) +; 64LARGE-ASM: lfs 1, 0([[REG2]]) +; 64LARGE-ASM: blr + +; CHECK: .toc +; CHECK-NOT: .tc diff --git a/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll b/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll index c6ffc0201a9ce1..5efb956b1529dd 100644 --- a/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll +++ b/llvm/test/CodeGen/PowerPC/aix-lower-jump-table.ll @@ -14,6 +14,18 @@ ; RUN: -code-model=large -stop-after=machine-cp < %s | FileCheck \ ; RUN: --check-prefix=64LARGE-MIR %s +; RUN: llc -mtriple powerpc-ibm-aix-xcoff -code-model=small < %s | FileCheck \ +; RUN: --check-prefixes=32SMALL-ASM,CHECK %s + +; RUN: llc -mtriple powerpc-ibm-aix-xcoff -code-model=large < %s | FileCheck \ +; RUN: --check-prefixes=32LARGE-ASM,CHECK %s + +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=small < %s | FileCheck \ +; RUN: --check-prefixes=64SMALL-ASM,CHECK %s + +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=large < %s | FileCheck \ +; RUN: --check-prefixes=64LARGE-ASM,CHECK %s + define i32 @jump_table(i32 %a) { entry: switch i32 %a, label %sw.epilog [ @@ -46,18 +58,131 @@ ; 32SMALL-MIR: renamable $r[[REG1:[0-9]+]] = LWZtoc %jump-table.0, $r2 :: (load 4 from got) ; 32SMALL-MIR: renamable $r[[REG3:[0-9]+]] = RLWINM killed renamable $r[[REG2:[0-9]+]], 2, 0, 29 -; 32SMALL-MIR: renamable $r[[REG4:[0-9]+]] = LWZX killed renamable $r[[REG3]], killed renamable $r[[REG1]] :: (load 4 from jump-table) +; 32SMALL-MIR: renamable $r[[REG4:[0-9]+]] = LWZX killed renamable $r[[REG3]], renamable $r[[REG1]] :: (load 4 from jump-table) +; 32SMALL-MIR: renamable $r[[REG5:[0-9]+]] = ADD4 killed renamable $r[[REG4]], killed renamable $r[[REG1]] ; 32LARGE-MIR: renamable $r[[REG1:[0-9]+]] = ADDIStocHA $r2, %jump-table.0 ; 32LARGE-MIR: renamable $r[[REG2:[0-9]+]] = LWZtocL %jump-table.0, killed renamable $r[[REG1]], implicit $r2 :: (load 4 from got) ; 32LARGE-MIR: renamable $r[[REG4:[0-9]+]] = RLWINM killed renamable $r[[REG3:[0-9]+]], 2, 0, 29 -; 32LARGE-MIR: renamable $r[[REG5:[0-9]+]] = LWZX killed renamable $r[[REG4]], killed renamable $r[[REG2]] :: (load 4 from jump-table) +; 32LARGE-MIR: renamable $r[[REG5:[0-9]+]] = LWZX killed renamable $r[[REG4]], renamable $r[[REG2]] :: (load 4 from jump-table) +; 32LARGE-MIR: renamable $r[[REG6:[0-9]+]] = ADD4 killed renamable $r[[REG5]], killed renamable $r[[REG2]] ; 64SMALL-MIR: renamable $x[[REG1:[0-9]+]] = LDtocJTI %jump-table.0, $x2 :: (load 8 from got) ; 64SMALL-MIR: renamable $x[[REG3:[0-9]+]] = RLDIC killed renamable $x[[REG2:[0-9]+]], 2, 30 ; 64SMALL-MIR: renamable $x[[REG4:[0-9]+]] = LWAX killed renamable $x[[REG3]], renamable $x[[REG1]] :: (load 4 from jump-table) +; 64SMALL-MIR: renamable $x[[REG6:[0-9]+]] = ADD8 killed renamable $x[[REG4]], killed renamable $x[[REG1]] ; 64LARGE-MIR: renamable $x[[REG1:[0-9]+]] = ADDIStocHA8 $x2, %jump-table.0 ; 64LARGE-MIR: renamable $x[[REG2:[0-9]+]] = LDtocL %jump-table.0, killed renamable $x[[REG1]], implicit $x2 :: (load 8 from got) ; 64LARGE-MIR: renamable $x[[REG4:[0-9]+]] = RLDIC killed renamable $x[[REG3:[0-9]+]], 2, 30 -; 64LARGE-MIR: renamable $x[[REG5:[0-9]+]] = LWAX killed renamable $x[[REG4]], killed renamable $x[[REG2]] :: (load 4 from jump-table) +; 64LARGE-MIR: renamable $x[[REG5:[0-9]+]] = LWAX killed renamable $x[[REG4]], renamable $x[[REG2]] :: (load 4 from jump-table) +; 64LARGE-MIR: renamable $x[[REG6:[0-9]+]] = ADD8 killed renamable $x[[REG5]], killed renamable $x[[REG2]] + +; 32SMALL-ASM-LABEL: jump_table +; 32SMALL-ASM: .jump_table: +; 32SMALL-ASM: addi 3, 3, -1 +; 32SMALL-ASM: cmplwi 3, 3 +; 32SMALL-ASM: bgt 0, LBB0_6 +; 32SMALL-ASM: lwz 4, LC0(2) +; 32SMALL-ASM: slwi 3, 3, 2 +; 32SMALL-ASM: lwzx 3, 3, 4 +; 32SMALL-ASM: add 3, 3, 4 +; 32SMALL-ASM: mtctr 3 +; 32SMALL-ASM: bctr +; 32SMALL-ASM: LBB0_2: +; 32SMALL-ASM: LBB0_3: +; 32SMALL-ASM: LBB0_4: +; 32SMALL-ASM: LBB0_5: +; 32SMALL-ASM: LBB0_6: +; 32SMALL-ASM: li 3, 0 +; 32SMALL-ASM: blr +; 32SMALL-ASM: .csect .rodata[RO] +; 32SMALL-ASM: .align 2 +; 32SMALL-ASM: .LJTI0_0: +; 32SMALL-ASM: .long LBB0_2-.LJTI0_0 +; 32SMALL-ASM: .long LBB0_3-.LJTI0_0 +; 32SMALL-ASM: .long LBB0_4-.LJTI0_0 +; 32SMALL-ASM: .long LBB0_5-.LJTI0_0 + +; 32LARGE-ASM-LABEL: jump_table +; 32LARGE-ASM: .jump_table: +; 32LARGE-ASM: addi 3, 3, -1 +; 32LARGE-ASM: cmplwi 3, 3 +; 32LARGE-ASM: bgt 0, LBB0_6 +; 32LARGE-ASM: addis 4, LC0@u(2) +; 32LARGE-ASM: slwi 3, 3, 2 +; 32LARGE-ASM: lwz 4, LC0@l(4) +; 32LARGE-ASM: lwzx 3, 3, 4 +; 32LARGE-ASM: add 3, 3, 4 +; 32LARGE-ASM: mtctr 3 +; 32LARGE-ASM: bctr +; 32LARGE-ASM: LBB0_2: +; 32LARGE-ASM: LBB0_3: +; 32LARGE-ASM: LBB0_4: +; 32LARGE-ASM: LBB0_5: +; 32LARGE-ASM: LBB0_6: +; 32LARGE-ASM: li 3, 0 +; 32LARGE-ASM: blr +; 32LARGE-ASM: .csect .rodata[RO] +; 32LARGE-ASM: .align 2 +; 32LARGE-ASM: .LJTI0_0: +; 32LARGE-ASM: .long LBB0_2-.LJTI0_0 +; 32LARGE-ASM: .long LBB0_3-.LJTI0_0 +; 32LARGE-ASM: .long LBB0_4-.LJTI0_0 +; 32LARGE-ASM: .long LBB0_5-.LJTI0_0 + +; 64SMALL-ASM-LABEL: jump_table +; 64SMALL-ASM: .jump_table: +; 64SMALL-ASM: addi 3, 3, -1 +; 64SMALL-ASM: cmplwi 3, 3 +; 64SMALL-ASM: bgt 0, LBB0_6 +; 64SMALL-ASM: ld 4, LC0(2) +; 64SMALL-ASM: rldic 3, 3, 2, 30 +; 64SMALL-ASM: lwax 3, 3, 4 +; 64SMALL-ASM: add 3, 3, 4 +; 64SMALL-ASM: mtctr 3 +; 64SMALL-ASM: bctr +; 64SMALL-ASM: LBB0_2: +; 64SMALL-ASM: LBB0_3: +; 64SMALL-ASM: LBB0_4: +; 64SMALL-ASM: LBB0_5: +; 64SMALL-ASM: LBB0_6: +; 64SMALL-ASM: li 3, 0 +; 64SMALL-ASM: blr +; 64SMALL-ASM: .csect .rodata[RO] +; 64SMALL-ASM: .align 2 +; 64SMALL-ASM: .LJTI0_0: +; 64SMALL-ASM: .long LBB0_2-.LJTI0_0 +; 64SMALL-ASM: .long LBB0_3-.LJTI0_0 +; 64SMALL-ASM: .long LBB0_4-.LJTI0_0 +; 64SMALL-ASM: .long LBB0_5-.LJTI0_0 + +; 64LARGE-ASM-LABEL: jump_table +; 64LARGE-ASM: .jump_table: +; 64LARGE-ASM: addi 3, 3, -1 +; 64LARGE-ASM: cmplwi 3, 3 +; 64LARGE-ASM: bgt 0, LBB0_6 +; 64LARGE-ASM: addis 4, LC0@u(2) +; 64LARGE-ASM: rldic 3, 3, 2, 30 +; 64LARGE-ASM: ld 4, LC0@l(4) +; 64LARGE-ASM: lwax 3, 3, 4 +; 64LARGE-ASM: add 3, 3, 4 +; 64LARGE-ASM: mtctr 3 +; 64LARGE-ASM: bctr +; 64LARGE-ASM: LBB0_2: +; 64LARGE-ASM: LBB0_3: +; 64LARGE-ASM: LBB0_4: +; 64LARGE-ASM: LBB0_5: +; 64LARGE-ASM: LBB0_6: +; 64LARGE-ASM: li 3, 0 +; 64LARGE-ASM: blr +; 64LARGE-ASM: .csect .rodata[RO] +; 64LARGE-ASM: .align 2 +; 64LARGE-ASM: .LJTI0_0: +; 64LARGE-ASM: .long LBB0_2-.LJTI0_0 +; 64LARGE-ASM: .long LBB0_3-.LJTI0_0 +; 64LARGE-ASM: .long LBB0_4-.LJTI0_0 +; 64LARGE-ASM: .long LBB0_5-.LJTI0_0 + +; CHECK: .toc +; CHECK-NOT: .tc From c1ed22954a138570a721da5b3fec390d4884237e Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Wed, 20 Nov 2019 15:28:09 +0000 Subject: [PATCH 06/14] gn build: Merge a03435ec8e2 --- llvm/utils/gn/secondary/llvm/unittests/DebugInfo/DWARF/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/llvm/unittests/DebugInfo/DWARF/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/DebugInfo/DWARF/BUILD.gn index 294605578e51c2..12c5b3b90a8ab6 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/DebugInfo/DWARF/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/DebugInfo/DWARF/BUILD.gn @@ -14,6 +14,7 @@ unittest("DebugInfoDWARFTests") { sources = [ "DWARFDebugInfoTest.cpp", "DWARFDebugLineTest.cpp", + "DWARFDieTest.cpp", "DWARFFormValueTest.cpp", "DWARFLocationExpressionTest.cpp", "DwarfGenerator.cpp", From b5135a86e04761577494c70e7c0057136cc90b5b Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Wed, 20 Nov 2019 15:51:18 +0100 Subject: [PATCH 07/14] [clangd] Fix a crash in expected types Reviewers: kadircet Reviewed By: kadircet Subscribers: merge_guards_bot, MaskRay, jkorous, arphaman, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D70481 --- clang-tools-extra/clangd/ExpectedTypes.cpp | 6 ++---- .../clangd/unittests/CodeCompleteTests.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clangd/ExpectedTypes.cpp b/clang-tools-extra/clangd/ExpectedTypes.cpp index 3b0779ea66bc6d..a82a64cf14e2bb 100644 --- a/clang-tools-extra/clangd/ExpectedTypes.cpp +++ b/clang-tools-extra/clangd/ExpectedTypes.cpp @@ -44,12 +44,10 @@ static const Type *toEquivClass(ASTContext &Ctx, QualType T) { static llvm::Optional typeOfCompletion(const CodeCompletionResult &R) { const NamedDecl *D = R.Declaration; - if (!D) - return llvm::None; // Templates do not have a type on their own, look at the templated decl. - if (auto *Template = dyn_cast(D)) + if (auto *Template = dyn_cast_or_null(D)) D = Template->getTemplatedDecl(); - auto *VD = dyn_cast(D); + auto *VD = dyn_cast_or_null(D); if (!VD) return llvm::None; // We handle only variables and functions below. auto T = VD->getType(); diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 5b50b9fe9f8ba5..e69b2a6205f6a8 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1030,6 +1030,16 @@ TEST(CompletionTest, DefaultArgs) { SnippetSuffix("(${1:int A})")))); } +TEST(CompletionTest, NoCrashWithTemplateParamsAndPreferredTypes) { + auto Completions = completions(R"cpp( +template