diff --git a/configure b/configure index f7a7da118cc..3b0abeb8b2e 100755 --- a/configure +++ b/configure @@ -3518,8 +3518,6 @@ esac # Disable libffi for some systems. case "${target}" in - aarch64*-*-darwin2*) - ;; powerpc-*-darwin*) ;; i[3456789]86-*-darwin*) diff --git a/configure.ac b/configure.ac index 21218446587..042681c27be 100644 --- a/configure.ac +++ b/configure.ac @@ -747,8 +747,6 @@ esac # Disable libffi for some systems. case "${target}" in - aarch64*-*-darwin2*) - ;; powerpc-*-darwin*) ;; i[[3456789]]86-*-darwin*) diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 2a2d38cd4d8..0ae21164924 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,7 @@ +2024-06-05 Robin Dapp + + * check_GNU_style_lib.py: Use raw strings for regexps. + 2024-05-21 Tobias Burnus * gcc-changelog/git_update_version.py: Add '-i'/'--ignore' argument diff --git a/contrib/check_GNU_style_lib.py b/contrib/check_GNU_style_lib.py index f1a120fa8d3..6dbe4b53559 100755 --- a/contrib/check_GNU_style_lib.py +++ b/contrib/check_GNU_style_lib.py @@ -103,7 +103,7 @@ class SpacesCheck: class SpacesAndTabsMixedCheck: def __init__(self): - self.re = re.compile('\ \t') + self.re = re.compile(r'\ \t') def check(self, filename, lineno, line): stripped = line.lstrip() @@ -115,7 +115,7 @@ class SpacesAndTabsMixedCheck: class TrailingWhitespaceCheck: def __init__(self): - self.re = re.compile('(\s+)$') + self.re = re.compile(r'(\s+)$') def check(self, filename, lineno, line): assert(len(line) == 0 or line[-1] != '\n') @@ -128,7 +128,7 @@ class TrailingWhitespaceCheck: class SentenceSeparatorCheck: def __init__(self): - self.re = re.compile('\w\.(\s|\s{3,})\w') + self.re = re.compile(r'\w\.(\s|\s{3,})\w') def check(self, filename, lineno, line): m = self.re.search(line) @@ -140,7 +140,7 @@ class SentenceSeparatorCheck: class SentenceEndOfCommentCheck: def __init__(self): - self.re = re.compile('\w\.(\s{0,1}|\s{3,})\*/') + self.re = re.compile(r'\w\.(\s{0,1}|\s{3,})\*/') def check(self, filename, lineno, line): m = self.re.search(line) @@ -152,7 +152,7 @@ class SentenceEndOfCommentCheck: class SentenceDotEndCheck: def __init__(self): - self.re = re.compile('\w(\s*\*/)') + self.re = re.compile(r'\w(\s*\*/)') def check(self, filename, lineno, line): m = self.re.search(line) @@ -164,7 +164,7 @@ class SentenceDotEndCheck: class FunctionParenthesisCheck: # TODO: filter out GTY stuff def __init__(self): - self.re = re.compile('\w(\s{2,})?(\()') + self.re = re.compile(r'\w(\s{2,})?(\()') def check(self, filename, lineno, line): if '#define' in line: @@ -179,7 +179,7 @@ class FunctionParenthesisCheck: class SquareBracketCheck: def __init__(self): - self.re = re.compile('\w\s+(\[)') + self.re = re.compile(r'\w\s+(\[)') def check(self, filename, lineno, line): if filename.endswith('.md'): @@ -194,7 +194,7 @@ class SquareBracketCheck: class ClosingParenthesisCheck: def __init__(self): - self.re = re.compile('\S\s+(\))') + self.re = re.compile(r'\S\s+(\))') def check(self, filename, lineno, line): m = self.re.search(line) @@ -208,7 +208,7 @@ class BracesOnSeparateLineCheck: # This will give false positives for C99 compound literals. def __init__(self): - self.re = re.compile('(\)|else)\s*({)') + self.re = re.compile(r'(\)|else)\s*({)') def check(self, filename, lineno, line): m = self.re.search(line) @@ -219,7 +219,7 @@ class BracesOnSeparateLineCheck: class TrailinigOperatorCheck: def __init__(self): - regex = '^\s.*(([^a-zA-Z_]\*)|([-%<=&|^?])|([^*]/)|([^:][+]))$' + regex = r'^\s.*(([^a-zA-Z_]\*)|([-%<=&|^?])|([^*]/)|([^:][+]))$' self.re = re.compile(regex) def check(self, filename, lineno, line): diff --git a/contrib/header-tools/ChangeLog b/contrib/header-tools/ChangeLog index c8735e1d73e..3875953ab9f 100644 --- a/contrib/header-tools/ChangeLog +++ b/contrib/header-tools/ChangeLog @@ -1,3 +1,20 @@ +2024-06-05 Jonathan Wakely + + * README: Fix spelling and capitalization typos. + * gcc-order-headers: Fix spelling typo. + +2024-06-05 Sundeep KOKKONDA + + * count-headers: Adapt to Python 3. + * gcc-order-headers: Likewise. + * graph-header-logs: Likewise. + * graph-include-web: Likewise. + * headerutils.py: Likewise. + * included-by: Likewise. + * reduce-headers: Likewise. + * replace-header: Likewise. + * show-headers: Likewise. + 2022-08-31 Martin Liska * README: Remove deprecated ports. diff --git a/contrib/header-tools/README b/contrib/header-tools/README index 48381fe0ba4..906572e5059 100644 --- a/contrib/header-tools/README +++ b/contrib/header-tools/README @@ -1,8 +1,8 @@ Quick start documentation for the header file utilities. -This isn't a full breakdown of the tools, just they typical use scenarios. +This isn't a full breakdown of the tools, just the typical use scenarios. -- Each tool accepts -h to show it's usage. Usually no parameters will also +- Each tool accepts -h to show its usage. Usually no parameters will also trigger the help message. Help may specify additional functionality to what is listed here. @@ -37,7 +37,7 @@ gcc-order-headers command line. Any files which are changed are output, and the original is saved with a - .bak extention. + .bak extension. ex.: gcc-order-headers tree-ssa.cc c/c-decl.cc @@ -45,7 +45,7 @@ gcc-order-headers show which of those headers include other headers, just the final canonical ordering. - if any header files are included within a conditional code block, the tool + If any header files are included within a conditional code block, the tool will issue a message and not change the file. When this happens, you can manually inspect the file to determine if reordering it is actually OK. Then rerun the command with the -i option. This will ignore the conditional error @@ -162,11 +162,11 @@ reduce-headers a native build and sometimes target builds, depending on what you are trying to reduce. - it is good practice to run 'gcc-order-headers' on a source file before trying + It is good practice to run 'gcc-order-headers' on a source file before trying to reduce it. This removes duplicates and performs some simplifications which reduce the chances of the reduction tool missing things. - start with a completely bootstrapped native compiler. + Start with a completely bootstrapped native compiler. Any desired target builds should be built in one directory using a modified config-list.mk file which does not delete the build directory when it is done. @@ -198,7 +198,7 @@ reduce-headers A small subset of targets has been determined to provide excellent coverage, at least as of Aug 31/15 . They were found by reducing all the files - contained in libbackend.a oer a full set of targets(207). All conditions + contained in libbackend.a over a full set of targets(207). All conditions which disallowed removal of a header file were triggered by one or more of these targets. They are also known to the tool. When building targets it will check those targets before the rest. @@ -223,7 +223,7 @@ reduce-headers # This will attempt to remove all header files from tree-ssa-live.cc - the tool will generate a number of log files: + The tool will generate a number of log files: reduce-headers.log : All compilation failures from attempted reductions. reduce-headers.sum : One line summary of what happened to each source file. @@ -234,13 +234,13 @@ reduce-headers reduce-headers-kept.log: List of all the successful compiles that were ignored because of conditional macro dependencies - and why it thinks that is the case - $src.c.log : for each failed header removal, the compilation + and why it thinks that is the case. + $src.c.log : For each failed header removal, the compilation messages as to why it failed. $header.h.log: The same log is put into the relevant header log as well. -a sample output from ira.cc.log: +A sample output from ira.cc.log: Compilation failed: for shrink-wrap.h: @@ -253,7 +253,7 @@ Compilation failed: make: *** [ira.o] Error 1 -the same message would be put into shrink-wrap.h.log. +The same message would be put into shrink-wrap.h.log. diff --git a/contrib/header-tools/count-headers b/contrib/header-tools/count-headers index 7a92596a602..f1eb08da317 100755 --- a/contrib/header-tools/count-headers +++ b/contrib/header-tools/count-headers @@ -1,4 +1,4 @@ -#! /usr/bin/python2 +#! /usr/bin/python3 import os.path import sys import shlex @@ -45,11 +45,11 @@ if not usage and len (src) > 0: l.sort (key=lambda tup:tup[0], reverse=True) for f in l: - print str (f[0]) + " : " + f[1] + print (str (f[0]) + " : " + f[1]) else: - print "count-headers file1 [filen]" - print "Count the number of occurrences of all includes across all listed files" + print ("count-headers file1 [filen]") + print ("Count the number of occurrences of all includes across all listed files") diff --git a/contrib/header-tools/gcc-order-headers b/contrib/header-tools/gcc-order-headers index ee76cba4b18..87fdddf60ee 100755 --- a/contrib/header-tools/gcc-order-headers +++ b/contrib/header-tools/gcc-order-headers @@ -1,11 +1,11 @@ -#! /usr/bin/python2 +#! /usr/bin/python3 import os import sys import shlex import re from headerutils import * -import Queue +import queue file_list = list () usage = False @@ -77,19 +77,19 @@ def create_master_list (fn, verbose): if fn != "diagnostic.h" and fn != "diagnostic-core.h": master_list.append (fn) if (verbose): - print fn + " included by: " + includes[fn][0] + print (fn + " included by: " + includes[fn][0]) def print_dups (): if dups: - print "\nduplicated includes" + print ("\nduplicated includes") for i in dups: string = "dup : " + i + " : " string += includes[i][0] for i2 in dups[i]: string += ", "+i2 - print string + print (string) def process_known_dups (): @@ -230,11 +230,11 @@ for arg in sys.argv[1:]: elif arg[0:2] == "-v": show_master = True else: - print "Error: unrecognized option " + arg + print ("Error: unrecognized option " + arg) elif os.path.exists(arg): file_list.append (arg) else: - print "Error: file " + arg + " Does not exist." + print ("Error: file " + arg + " Does not exist.") usage = True if not file_list and not show_master: @@ -242,7 +242,7 @@ if not file_list and not show_master: if not usage and not os.path.exists ("coretypes.h"): usage = True - print "Error: Must run command in main gcc source directory containing coretypes.h\n" + print ("Error: Must run command in main gcc source directory containing coretypes.h\n") # process diagnostic.h first.. it's special since GCC_DIAG_STYLE can be # overridden by languages, but must be done so by a file included BEFORE it. @@ -268,20 +268,20 @@ process_known_dups () desired_order = master_list if show_master: - print " Canonical order of gcc include files: " + print (" Canonical order of gcc include files: ") for x in master_list: - print x - print " " + print (x) + print (" ") if usage: - print "gcc-order-headers [-i] [-v] file1 [filen]" - print " Ensures gcc's headers files are included in a normalized form with" - print " redundant headers removed. The original files are saved in filename.bak" - print " Outputs a list of files which changed." - print " -i ignore conditional compilation." - print " Use after examining the file to be sure includes within #ifs are safe" - print " Any headers within conditional sections will be ignored." - print " -v Show the canonical order of known headers" + print ("gcc-order-headers [-i] [-v] file1 [filen]") + print (" Ensures gcc's headers files are included in a normalized form with") + print (" redundant headers removed. The original files are saved in filename.bak") + print (" Outputs a list of files which changed.") + print (" -i ignore conditional compilation.") + print (" Use after examining the file to be sure includes within #ifs are safe") + print (" Any headers within conditional sections will be ignored.") + print (" -v Show the canonical order of known headers") sys.exit(0) @@ -303,7 +303,7 @@ for fn in file_list: if ii_include_list_cond (iinfo): if not ignore_conditional: - print fn + ": Cannot process due to conditional compilation of includes" + print (fn + ": Cannot process due to conditional compilation of includes") didnt_do.append (fn) src = list () @@ -329,8 +329,8 @@ for fn in file_list: src_line[nm] = ii_src_line(iinfo)[d] if src_line[nm].find("/*") != -1 and src_line[nm].find("*/") == -1: # this means we have a multi line comment, abort!' - print fn + ": Cannot process due to a multi-line comment :" - print " " + src_line[nm] + print (fn + ": Cannot process due to a multi-line comment :") + print (" " + src_line[nm]) if fn not in didnt_do: didnt_do.append (fn) src = list () @@ -375,22 +375,22 @@ for fn in file_list: for line in new_src: fl.write (line) fl.close () - print fn + print (fn) if didnt_do: - print "\n\n Did not process the following files due to conditional dependencies:" + print ("\n\n Did not process the following files due to conditional dependencies:") str = "" for x in didnt_do: str += x + " " - print str - print "\n" - print "Please examine to see if they are safe to process, and re-try with -i. " - print "Safeness is determined by checking whether any of the reordered headers are" - print "within a conditional and could be hauled out of the conditional, thus changing" - print "what the compiler will see." - print "Multi-line comments after a #include can also cause failuer, they must be turned" - print "into single line comments or removed." + print (str) + print ("\n") + print ("Please examine to see if they are safe to process, and re-try with -i. ") + print ("Safeness is determined by checking whether any of the reordered headers are") + print ("within a conditional and could be hauled out of the conditional, thus changing") + print ("what the compiler will see.") + print ("Multi-line comments after a #include can also cause failure, they must be turned") + print ("into single line comments or removed.") diff --git a/contrib/header-tools/graph-header-logs b/contrib/header-tools/graph-header-logs index e537aaeac0c..b9a68fe64ac 100755 --- a/contrib/header-tools/graph-header-logs +++ b/contrib/header-tools/graph-header-logs @@ -1,4 +1,4 @@ -#! /usr/bin/python2 +#! /usr/bin/python3 import os.path import sys import shlex @@ -53,7 +53,7 @@ ignore = [ "coretypes_h", def process_log_file (header, logfile): if header_roots.get (header) != None: - print "Error: already processed log file: " + header + ".log" + print ("Error: already processed log file: " + header + ".log") return hname = pretty_name (header) header_roots[hname] = { } @@ -66,7 +66,7 @@ def process_log_file (header, logfile): if newinc: incfrom = list() newinc = False - fn = re.findall(ur".*/(.*?):", line) + fn = re.findall(r".*/(.*?):", line) if len(fn) != 1: continue if fn[0][-2:] != ".h": @@ -76,16 +76,16 @@ def process_log_file (header, logfile): incfrom.append (n) continue newinc = True - note = re.findall (ur"^.*note: (.*)", line) + note = re.findall (r"^.*note: (.*)", line) if len(note) > 0: sline.append (("note", note[0])) else: - err_msg = re.findall (ur"^.*: error: (.*)", line) + err_msg = re.findall (r"^.*: error: (.*)", line) if len(err_msg) == 1: msg = err_msg[0] if (len (re.findall("error: forward declaration", line))) != 0: continue - path = re.findall (ur"^(.*?):.*error: ", line) + path = re.findall (r"^(.*?):.*error: ", line) if len(path) != 1: continue if path[0][-2:] != ".h": @@ -95,7 +95,7 @@ def process_log_file (header, logfile): continue sline.append (("error", msg, fname, incfrom)) - print str(len(sline)) + " lines to process" + print (str(len(sline)) + " lines to process") lastline = "note" for line in sline: if line[0] != "note" and lastline[0] == "error": @@ -111,7 +111,7 @@ def process_log_file (header, logfile): if ee not in extra_edges: extra_edges.append (ee) fname = t - print string + print (string) if hname not in nodes: nodes.append(hname) @@ -125,7 +125,7 @@ def process_log_file (header, logfile): if header_roots[hname].get(fname) == None: header_roots[hname][fname] = list() if msg not in header_roots[hname][fname]: - print string + ofname + " : " +msg + print (string + ofname + " : " +msg) header_roots[hname][fname].append (msg) lastline = line; @@ -181,10 +181,10 @@ def build_dot_file (file_list): if verbose: depcount.sort(key=lambda tup:tup[2]) for x in depcount: - print " ("+str(x[2])+ ") : " + x[0] + " -> " + x[1] + print (" ("+str(x[2])+ ") : " + x[0] + " -> " + x[1]) if (x[2] <= verbosity): for l in header_roots[x[0]][x[1]]: - print " " + l + print (" " + l) output.write ("}\n"); @@ -205,7 +205,7 @@ for arg in sys.argv[1:]: if (verbosity == 9): verbosity = 9999 elif arg[0:1] == "-": - print "Unrecognized option " + arg + print ("Unrecognized option " + arg) dohelp = True else: files.append (arg) @@ -214,16 +214,16 @@ if len(sys.argv) == 1: dohelp = True if dohelp: - print "Parses the log files from the reduce-headers tool to generate" - print "dependency graphs for the include web for specified files." - print "Usage: [-nnum] [-h] [-v[n]] [-ooutput] file1 [[file2] ... [filen]]" - print " -ooutput : Specifies output to output.dot and output.png" - print " Defaults to 'graph.dot and graph.png" - print " -vn : verbose mode, shows the number of connections, and if n" - print " is specified, show the messages if # < n. 9 is infinity" - print " -h : help" + print ("Parses the log files from the reduce-headers tool to generate") + print ("dependency graphs for the include web for specified files.") + print ("Usage: [-nnum] [-h] [-v[n]] [-ooutput] file1 [[file2] ... [filen]]") + print (" -ooutput : Specifies output to output.dot and output.png") + print (" Defaults to 'graph.dot and graph.png") + print (" -vn : verbose mode, shows the number of connections, and if n") + print (" is specified, show the messages if # < n. 9 is infinity") + print (" -h : help") else: - print files + print (files) build_dot_file (files) os.system ("dot -Tpng " + dotname + " -o" + graphname) diff --git a/contrib/header-tools/graph-include-web b/contrib/header-tools/graph-include-web index 47576a177de..77e2450ca3f 100755 --- a/contrib/header-tools/graph-include-web +++ b/contrib/header-tools/graph-include-web @@ -1,4 +1,4 @@ -#! /usr/bin/python2 +#! /usr/bin/python3 import os.path import sys import shlex @@ -82,7 +82,7 @@ for arg in sys.argv[1:]: noterm = True elif arg[0:2] == "-f": if not os.path.exists (arg[2:]): - print "Option " + arg +" doesn't specify a proper file" + print ("Option " + arg +" doesn't specify a proper file") dohelp = True else: sfile = open (arg[2:], "r") @@ -93,7 +93,7 @@ for arg in sys.argv[1:]: elif arg[0:2] == "-n": edge_thresh = int (arg[2:]) elif arg[0:1] == "-": - print "Unrecognized option " + arg + print ("Unrecognized option " + arg) dohelp = True else: files.append (arg) @@ -102,17 +102,17 @@ if len(sys.argv) == 1: dohelp = True if dohelp: - print "Generates a graph of the include web for specified files." - print "Usage: [-finput_file] [-h] [-ooutput] [file1 ... [filen]]" - print " -finput_file : Input file containing a list of files to process." - print " -ooutput : Specifies output to output.dot and output.png." - print " defaults to graph.dot and graph.png." - print " -nnum : Specifies the # of edges beyond which sfdp is invoked. def=0." - print " -a : Aggregate all .c files to 1 file. Shows only include web." - print " -at : Aggregate, but don't include terminal.h to .c links." - print " -h : Print this help." + print ("Generates a graph of the include web for specified files.") + print ("Usage: [-finput_file] [-h] [-ooutput] [file1 ... [filen]]") + print (" -finput_file : Input file containing a list of files to process.") + print (" -ooutput : Specifies output to output.dot and output.png.") + print (" defaults to graph.dot and graph.png.") + print (" -nnum : Specifies the # of edges beyond which sfdp is invoked. def=0.") + print (" -a : Aggregate all .c files to 1 file. Shows only include web.") + print (" -at : Aggregate, but don't include terminal.h to .c links.") + print (" -h : Print this help.") else: - print files + print (files) build_dot_file (files) if edges > edge_thresh: os.system ("sfdp -Tpng " + dotname + " -o" + graphname) diff --git a/contrib/header-tools/headerutils.py b/contrib/header-tools/headerutils.py index 95c47fb4b69..1fb02214414 100755 --- a/contrib/header-tools/headerutils.py +++ b/contrib/header-tools/headerutils.py @@ -1,4 +1,4 @@ -#! /usr/bin/python2 +#! /usr/bin/python3 import os.path import sys import shlex @@ -10,7 +10,7 @@ import pickle import multiprocessing def find_pound_include (line, use_outside, use_slash): - inc = re.findall (ur"^\s*#\s*include\s*\"(.+?)\"", line) + inc = re.findall (r"^\s*#\s*include\s*\"(.+?)\"", line) if len(inc) == 1: nm = inc[0] if use_outside or os.path.exists (nm): @@ -19,17 +19,17 @@ def find_pound_include (line, use_outside, use_slash): return "" def find_system_include (line): - inc = re.findall (ur"^\s*#\s*include\s*<(.+?)>", line) + inc = re.findall (r"^\s*#\s*include\s*<(.+?)>", line) if len(inc) == 1: return inc[0] return "" def find_pound_define (line): - inc = re.findall (ur"^\s*#\s*define ([A-Za-z0-9_]+)", line) + inc = re.findall (r"^\s*#\s*define ([A-Za-z0-9_]+)", line) if len(inc) != 0: if len(inc) > 1: - print "What? more than 1 match in #define??" - print inc + print ("What? more than 1 match in #define??") + print (inc) sys.exit(5) return inc[0]; return "" @@ -49,26 +49,26 @@ def is_pound_endif (line): return False def find_pound_if (line): - inc = re.findall (ur"^\s*#\s*if\s+(.*)", line) + inc = re.findall (r"^\s*#\s*if\s+(.*)", line) if len(inc) == 0: - inc = re.findall (ur"^\s*#\s*elif\s+(.*)", line) + inc = re.findall (r"^\s*#\s*elif\s+(.*)", line) if len(inc) > 0: - inc2 = re.findall (ur"defined\s*\((.+?)\)", inc[0]) - inc3 = re.findall (ur"defined\s+([a-zA-Z0-9_]+)", inc[0]) + inc2 = re.findall (r"defined\s*\((.+?)\)", inc[0]) + inc3 = re.findall (r"defined\s+([a-zA-Z0-9_]+)", inc[0]) for yy in inc3: inc2.append (yy) return inc2 else: - inc = re.findall (ur"^\s*#\s*ifdef\s(.*)", line) + inc = re.findall (r"^\s*#\s*ifdef\s(.*)", line) if len(inc) == 0: - inc = re.findall (ur"^\s*#\s*ifndef\s(.*)", line) + inc = re.findall (r"^\s*#\s*ifndef\s(.*)", line) if len(inc) > 0: inc2 = re.findall ("[A-Za-z_][A-Za-z_0-9]*", inc[0]) return inc2 if len(inc) == 0: return list () - print "WTF. more than one line returned for find_pound_if" - print inc + print ("WTF. more than one line returned for find_pound_if") + print (inc) sys.exit(5) @@ -248,8 +248,8 @@ def find_gcc_bld_dir (path): for y in files: p = os.path.dirname (y) if os.path.basename (p) == "gcc": - blddir = p - break + blddir = p + break return blddir @@ -424,7 +424,7 @@ def find_replace_include (find, replace, src): # pass in a require and provide dictionary to be read in. def read_require_provides (require, provide): if not os.path.exists ("require-provide.master"): - print "require-provide.master file is not available. please run data collection." + print ("require-provide.master file is not available. please run data collection.") sys.exit(1) incl_list = open("require-provide.master").read().splitlines() for f in incl_list: @@ -501,7 +501,7 @@ def spawn_makes (command_list): c = subprocess.Popen(command, bufsize=-1, stdout=devnull, stderr=subprocess.PIPE, shell=True) proc_res.append ((c, tname)) - print text[:-2] + print (text[:-2]) for p in proc_res: output = p[0].communicate() diff --git a/contrib/header-tools/included-by b/contrib/header-tools/included-by index 9947fee6b2b..b953825f0b1 100755 --- a/contrib/header-tools/included-by +++ b/contrib/header-tools/included-by @@ -1,4 +1,4 @@ -#! /usr/bin/python2 +#! /usr/bin/python3 import os.path import sys import shlex @@ -43,7 +43,7 @@ for x in sys.argv[1:]: file_list = open (x[2:]).read().splitlines() scanfiles = False elif x[0] == "-": - print "Error: Unknown option " + x + print ("Error: Unknown option " + x) usage = True else: src.append (x) @@ -89,21 +89,21 @@ if not usage: if len (careabout) < num_match: output = "" if output != "": - print output + print (output) else: - print "included-by [-h] [-i] [-c] [-v] [-a] [-nx] file1 [file2] ... [filen]" - print "find the list of all files in subdirectories that include any of " - print "the listed files. processed to a depth of 3 subdirs" - print " -h : Show this message" - print " -i : process only header files (*.h) for #include" - print " -c : process only source files (*.c *.cc) for #include" - print " If nothing is specified, defaults to -i -c" - print " -s : Same as -c." - print " -v : Show which include(s) were found" - print " -nx : Only list files which have at least x different matches. Default = 1" - print " -a : Show only files which all listed files are included" - print " This is equivilent to -nT where T == # of items in list" - print " -flistfile : Show only files contained in the list of files" + print ("included-by [-h] [-i] [-c] [-v] [-a] [-nx] file1 [file2] ... [filen]") + print ("find the list of all files in subdirectories that include any of ") + print ("the listed files. processed to a depth of 3 subdirs") + print (" -h : Show this message") + print (" -i : process only header files (*.h) for #include") + print (" -c : process only source files (*.c *.cc) for #include") + print (" If nothing is specified, defaults to -i -c") + print (" -s : Same as -c.") + print (" -v : Show which include(s) were found") + print (" -nx : Only list files which have at least x different matches. Default = 1") + print (" -a : Show only files which all listed files are included") + print (" This is equivilent to -nT where T == # of items in list") + print (" -flistfile : Show only files contained in the list of files") diff --git a/contrib/header-tools/reduce-headers b/contrib/header-tools/reduce-headers index 7d236e30688..5826e67a3c8 100755 --- a/contrib/header-tools/reduce-headers +++ b/contrib/header-tools/reduce-headers @@ -1,4 +1,4 @@ -#! /usr/bin/python2 +#! /usr/bin/python3 import os.path import sys import shlex @@ -177,7 +177,7 @@ def build_target_dict (bld_dir, just_these): target = t.strip() tpath = bld_dir + "/" + target if not os.path.exists (tpath + "/gcc"): - print "Error: gcc build directory for target " + t + " Does not exist: " + tpath + "/gcc" + print ("Error: gcc build directory for target " + t + " Does not exist: " + tpath + "/gcc") error = True else: target_dict[target] = tpath @@ -209,7 +209,7 @@ def find_targets (src_file): targ_list = list() obj_name = get_obj_name (src_file) if not obj_name: - print "Error: " + src_file + " - Cannot determine object name." + print ("Error: " + src_file + " - Cannot determine object name.") return list() # Put the high priority targets which tend to trigger failures first @@ -263,22 +263,22 @@ def try_to_remove (src_file, h_list, verbose): hostbuild = True if not target_dict: summary = src_file + ": Target builds are required for config files. None found." - print summary + print (summary) return summary if not targ_list: summary =src_file + ": Cannot find any targets which build this file." - print summary + print (summary) return summary if hostbuild: # confirm it actually builds before we do anything - print "Confirming source file builds" + print ("Confirming source file builds") res = get_make_output (build_dir + "/gcc", "all") if res[0] != 0: message = "Error: " + src_file + " does not build currently." summary = src_file + " does not build on host." - print message - print res[1] + print (message) + print (res[1]) if verbose: verbose.write (message + "\n") verbose.write (res[1]+ "\n") @@ -314,7 +314,7 @@ def try_to_remove (src_file, h_list, verbose): lookfor = ii_src_line(src_info)[inc_file] src_tmp.remove (lookfor) message = "Trying " + src_file + " without " + inc_file - print message + print (message) if verbose: verbose.write (message + "\n") out = open(src_file, "w") @@ -350,7 +350,7 @@ def try_to_remove (src_file, h_list, verbose): message = "Passed host and target builds" if keep: - print message + "\n" + print (message + "\n") if (rc != 0): if verbose: @@ -392,7 +392,7 @@ def try_to_remove (src_file, h_list, verbose): if ii_path(iinfo) == "build" and not target_dict: keep = True text = message + " : Will not remove a build file without some targets." - print text + print (text) ilog = open(src_file+".log","a") ilog.write (text +"\n") ilog.write ("============================================\n"); @@ -414,7 +414,7 @@ def try_to_remove (src_file, h_list, verbose): text = message + ", but must keep " + inc_file + " because it provides " + dep if because.get(dep) != None: text = text + " Possibly required by " + because[dep] - print text + print (text) ilog = open(inc_file+".log","a") ilog.write (because[dep]+": Requires [dep] in "+src_file+"\n") ilog.write ("============================================\n"); @@ -444,7 +444,7 @@ def try_to_remove (src_file, h_list, verbose): src_tmp = copy.deepcopy (src_data) else: - print message + " --> removing " + inc_file + "\n" + print (message + " --> removing " + inc_file + "\n") rmcount += 1 if verbose: verbose.write (message + " --> removing " + inc_file + "\n") @@ -454,7 +454,7 @@ def try_to_remove (src_file, h_list, verbose): remove_count[inc_file] += 1 src_data = copy.deepcopy (src_tmp) except: - print "Interuption: restoring original file" + print ("Interuption: restoring original file") out = open(src_file, "w") for line in src_orig: out.write (line) @@ -473,8 +473,8 @@ def try_to_remove (src_file, h_list, verbose): rc = res[0] if (rc != 0): # host build failed! return to original version - print "Error: " + src_file + " Failed to bootstrap at end!!! restoring." - print " Bad version at " + src_file + ".bad" + print ("Error: " + src_file + " Failed to bootstrap at end!!! restoring.") + print (" Bad version at " + src_file + ".bad") os.rename (src_file, src_file + ".bad") out = open(src_file, "w") for line in src_orig: @@ -486,7 +486,7 @@ def try_to_remove (src_file, h_list, verbose): summary = src_file + ": No change." else: summary = src_file + ": Reduction performed, "+str(rmcount)+" includes removed." - print summary + print (summary) return summary only_h = list () @@ -513,11 +513,11 @@ for x in sys.argv[1:]: elif x[0:2] == "-t": target_dir = x[2:] elif x[0] == "-": - print "Error: Unrecognized option " + x + print ("Error: Unrecognized option " + x) usgae = True else: if not os.path.exists (x): - print "Error: specified file " + x + " does not exist." + print ("Error: specified file " + x + " does not exist.") usage = True else: src.append (x) @@ -526,50 +526,50 @@ if target_dir: build_target_dict (target_dir, only_targs) if build_dir == "" and target_dir == "": - print "Error: Must specify a build directory, and/or a target directory." + print ("Error: Must specify a build directory, and/or a target directory.") usage = True if build_dir and not os.path.exists (build_dir): - print "Error: specified build directory does not exist : " + build_dir + print ("Error: specified build directory does not exist : " + build_dir) usage = True if target_dir and not os.path.exists (target_dir): - print "Error: specified target directory does not exist : " + target_dir + print ("Error: specified target directory does not exist : " + target_dir) usage = True if usage: - print "Attempts to remove extraneous include files from source files." - print " " - print "Should be run from the main gcc source directory, and works on a target" - print "directory, as we attempt to make the 'all' target." - print " " - print "By default, gcc-reorder-includes is run on each file before attempting" - print "to remove includes. this removes duplicates and puts some headers in a" - print "canonical ordering" - print " " - print "The build directory should be ready to compile via make. Time is saved" - print "if the build is already complete, so that only changes need to be built." - print " " - print "Usage: [options] file1.c [file2.c] ... [filen.c]" - print " -bdir : the root build directory to attempt buiding .o files." - print " -tdir : the target build directory" - print " -d : Ignore conditional macro dependencies." - print " " - print " -Dmacro : Ignore a specific macro for dependencies" - print " -Ttarget : Only consider target in target directory." - print " -fheader : Specifies a specific .h file to be considered." - print " " - print " -D, -T, and -f can be specified mulitple times and are aggregated." - print " " - print " The original file will be in filen.bak" - print " " + print ("Attempts to remove extraneous include files from source files.") + print (" ") + print ("Should be run from the main gcc source directory, and works on a target") + print ("directory, as we attempt to make the 'all' target.") + print (" ") + print ("By default, gcc-reorder-includes is run on each file before attempting") + print ("to remove includes. this removes duplicates and puts some headers in a") + print ("canonical ordering") + print (" ") + print ("The build directory should be ready to compile via make. Time is saved") + print ("if the build is already complete, so that only changes need to be built.") + print (" ") + print ("Usage: [options] file1.c [file2.c] ... [filen.c]") + print (" -bdir : the root build directory to attempt buiding .o files.") + print (" -tdir : the target build directory") + print (" -d : Ignore conditional macro dependencies.") + print (" ") + print (" -Dmacro : Ignore a specific macro for dependencies") + print (" -Ttarget : Only consider target in target directory.") + print (" -fheader : Specifies a specific .h file to be considered.") + print (" ") + print (" -D, -T, and -f can be specified mulitple times and are aggregated.") + print (" ") + print (" The original file will be in filen.bak") + print (" ") sys.exit (0) if only_h: - print "Attempting to remove only these files:" + print ("Attempting to remove only these files:") for x in only_h: - print x - print " " + print (x) + print (" ") logfile = open("reduce-headers.log","w") @@ -583,7 +583,7 @@ ilog = open("reduce-headers.sum","a") ilog.write ("===============================================================\n") for x in remove_count: msg = x + ": Removed " + str(remove_count[x]) + " times." - print msg + print (msg) logfile.write (msg + "\n") ilog.write (msg + "\n") diff --git a/contrib/header-tools/replace-header b/contrib/header-tools/replace-header index ce20096a453..854640d9302 100755 --- a/contrib/header-tools/replace-header +++ b/contrib/header-tools/replace-header @@ -1,4 +1,4 @@ -#! /usr/bin/python2 +#! /usr/bin/python3 import os.path import sys import shlex @@ -20,7 +20,7 @@ for x in sys.argv[1:]: elif x[0:2] == "-r": replace.append (x[2:]) elif x[0:1] == "-": - print "Error: unrecognized option " + x + print ("Error: unrecognized option " + x) usage = True else: files.append (x) @@ -29,25 +29,25 @@ if find == "": usage = True if usage: - print "replace-header -fheader -rheader [-rheader] file1 [filen.]" + print ("replace-header -fheader -rheader [-rheader] file1 [filen.]") sys.exit(0) string = "" for x in replace: string = string + " '"+x+"'" -print "Replacing '"+find+"' with"+string +print ("Replacing '"+find+"' with"+string) for x in files: src = readwholefile (x) src = find_replace_include (find, replace, src) if (len(src) > 0): - print x + ": Changed" + print (x + ": Changed") out = open(x, "w") for line in src: out.write (line); out.close () else: - print x + print (x) diff --git a/contrib/header-tools/show-headers b/contrib/header-tools/show-headers index cb949ec1f44..3c3ca42f32b 100755 --- a/contrib/header-tools/show-headers +++ b/contrib/header-tools/show-headers @@ -1,4 +1,4 @@ -#! /usr/bin/python2 +#! /usr/bin/python3 import os.path import sys import shlex @@ -93,17 +93,17 @@ for x in sys.argv[1:]: if len(src) != 1: usage = True elif not os.path.exists (src[0]): - print src[0] + ": Requested source file does not exist.\n" + print (src[0] + ": Requested source file does not exist.\n") usage = True if usage: - print "show-headers [-idir] [-sfilen] file1 " - print " " - print " Show a hierarchical visual format how many times each header file" - print " is included in a source file. Should be run from the source directory" - print " files from find-include-depends" - print " -s : search for a header, and point it out." - print " -i : Specifies additonal directories to search for includes." + print ("show-headers [-idir] [-sfilen] file1 ") + print (" ") + print (" Show a hierarchical visual format how many times each header file") + print (" is included in a source file. Should be run from the source directory") + print (" files from find-include-depends") + print (" -s : search for a header, and point it out.") + print (" -i : Specifies additonal directories to search for includes.") sys.exit(0) @@ -114,10 +114,10 @@ if extradir: blddir = find_gcc_bld_dir ("../..") if blddir: - print "Using build directory: " + blddir + print ("Using build directory: " + blddir) incl_dirs.insert (0, blddir) else: - print "Could not find a build directory, better results if you specify one with -i" + print ("Could not find a build directory, better results if you specify one with -i") # search path is now ".", blddir, extradirs_from_-i, built_in_incl_dirs incl_dirs.insert (0, ".") @@ -137,15 +137,15 @@ for line in data: if d and d[-2:] == ".h": process_include (d, 1) -print "\n" + x +print ("\n" + x) for line in output: - print line + print (line) if highlight: - print " " + print (" ") for h in summary: - print h + " is included by source file." + print (h + " is included by source file.") for h in highlight: if h not in summary: - print h + " is not included by source file." + print (h + " is not included by source file.") diff --git a/fixincludes/fixincl.x b/fixincludes/fixincl.x index 8adc6bda2a3..caaff2883e0 100644 --- a/fixincludes/fixincl.x +++ b/fixincludes/fixincl.x @@ -2,11 +2,11 @@ * * DO NOT EDIT THIS FILE (fixincl.x) * - * It has been AutoGen-ed May 13, 2024 at 05:50:22 PM by AutoGen 5.18.7 + * It has been AutoGen-ed June 4, 2024 at 02:35:55 PM by AutoGen 5.18.16 * From the definitions inclhack.def * and the template file fixincl */ -/* DO NOT SVN-MERGE THIS FILE, EITHER Mon May 13 17:50:22 BST 2024 +/* DO NOT SVN-MERGE THIS FILE, EITHER Tue Jun 4 14:35:55 CEST 2024 * * You must regenerate it. Use the ./genfixes script. * @@ -15,7 +15,7 @@ * certain ANSI-incompatible system header files which are fixed to work * correctly with ANSI C and placed in a directory that GNU C will search. * - * This file contains 272 fixup descriptions. + * This file contains 274 fixup descriptions. * * See README for more information. * @@ -267,6 +267,56 @@ static const char* apzAab_Darwin7_9_Long_Double_FuncsPatch[] = { #endif /* __MATH__ */", (char*)NULL }; +/* * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Description of Darwin_Api_Availability fix + */ +tSCC zDarwin_Api_AvailabilityName[] = + "darwin_api_availability"; + +/* + * File name selection pattern + */ +tSCC zDarwin_Api_AvailabilityList[] = + "os/availability.h\0"; +/* + * Machine/OS name selection pattern + */ +tSCC* apzDarwin_Api_AvailabilityMachs[] = { + "*-*-darwin*", + (const char*)NULL }; + +/* + * content selection pattern - do fix if pattern found + */ +tSCC zDarwin_Api_AvailabilitySelect0[] = + " *#define __API_AVAILABLE.*\n\ + *#define __API_DEPRECATED.*\n\ + *#define __API_DEPRECATED_WITH_REPLACEMENT.*\n\ + *#define __API_UNAVAILABLE.*\n"; + +/* + * content bypass pattern - skip fix if pattern found + */ +tSCC zDarwin_Api_AvailabilityBypass0[] = + "__IPHONE_OS_VERSION_MIN_REQUIRED"; + +#define DARWIN_API_AVAILABILITY_TEST_CT 2 +static tTestDesc aDarwin_Api_AvailabilityTests[] = { + { TT_NEGREP, zDarwin_Api_AvailabilityBypass0, (regex_t*)NULL }, + { TT_EGREP, zDarwin_Api_AvailabilitySelect0, (regex_t*)NULL }, }; + +/* + * Fix Command Arguments for Darwin_Api_Availability + */ +static const char* apzDarwin_Api_AvailabilityPatch[] = { + "format", + " #define API_AVAILABLE(...)\n\ + #define API_DEPRECATED(...)\n\ + #define API_DEPRECATED_WITH_REPLACEMENT(...)\n\ + #define API_UNAVAILABLE(...)\n", + (char*)NULL }; + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * Description of Aab_Fd_Zero_Asm_Posix_Types_H fix @@ -2713,6 +2763,51 @@ extern \"C\" {\n\ #endif\n", (char*)NULL }; +/* * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Description of Darwin_Availabilityinternal fix + */ +tSCC zDarwin_AvailabilityinternalName[] = + "darwin_availabilityinternal"; + +/* + * File name selection pattern + */ +tSCC zDarwin_AvailabilityinternalList[] = + "AvailabilityInternal.h\0"; +/* + * Machine/OS name selection pattern + */ +tSCC* apzDarwin_AvailabilityinternalMachs[] = { + "*-*-darwin*", + (const char*)NULL }; + +/* + * content selection pattern - do fix if pattern found + */ +tSCC zDarwin_AvailabilityinternalSelect0[] = + "#define[ \t]+(__API_[ADU]\\([^)]*\\)).*"; + +#define DARWIN_AVAILABILITYINTERNAL_TEST_CT 1 +static tTestDesc aDarwin_AvailabilityinternalTests[] = { + { TT_EGREP, zDarwin_AvailabilityinternalSelect0, (regex_t*)NULL }, }; + +/* + * Fix Command Arguments for Darwin_Availabilityinternal + */ +static const char* apzDarwin_AvailabilityinternalPatch[] = { + "format", + "#if defined(__has_attribute)\n\ + #if __has_attribute(availability)\n\ +%0\n\ + #else\n\ + #define %1\n\ + #endif\n\ +#else\n\ + #define %1\n\ +#endif", + (char*)NULL }; + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * Description of Darwin_9_Long_Double_Funcs_2 fix @@ -2975,8 +3070,15 @@ tSCC* apzDarwin_Os_Trace_2Machs[] = { tSCC zDarwin_Os_Trace_2Select0[] = "typedef.*\\^os_trace_payload_t.*"; -#define DARWIN_OS_TRACE_2_TEST_CT 1 +/* + * content bypass pattern - skip fix if pattern found + */ +tSCC zDarwin_Os_Trace_2Bypass0[] = + "#ifdef __BLOCKS__"; + +#define DARWIN_OS_TRACE_2_TEST_CT 2 static tTestDesc aDarwin_Os_Trace_2Tests[] = { + { TT_NEGREP, zDarwin_Os_Trace_2Bypass0, (regex_t*)NULL }, { TT_EGREP, zDarwin_Os_Trace_2Select0, (regex_t*)NULL }, }; /* @@ -3104,8 +3206,15 @@ tSCC zDarwin_Os_Base_1Select0[] = "#define __has_attribute.*\n\ #endif"; -#define DARWIN_OS_BASE_1_TEST_CT 1 +/* + * content bypass pattern - skip fix if pattern found + */ +tSCC zDarwin_Os_Base_1Bypass0[] = + "#define __has_extension"; + +#define DARWIN_OS_BASE_1_TEST_CT 2 static tTestDesc aDarwin_Os_Base_1Tests[] = { + { TT_NEGREP, zDarwin_Os_Base_1Bypass0, (regex_t*)NULL }, { TT_EGREP, zDarwin_Os_Base_1Select0, (regex_t*)NULL }, }; /* @@ -3144,8 +3253,15 @@ tSCC* apzDarwin_Dispatch_Object_1Machs[] = { tSCC zDarwin_Dispatch_Object_1Select0[] = "typedef void.*\\^dispatch_block_t.*"; -#define DARWIN_DISPATCH_OBJECT_1_TEST_CT 1 +/* + * content bypass pattern - skip fix if pattern found + */ +tSCC zDarwin_Dispatch_Object_1Bypass0[] = + "#ifdef __BLOCKS__"; + +#define DARWIN_DISPATCH_OBJECT_1_TEST_CT 2 static tTestDesc aDarwin_Dispatch_Object_1Tests[] = { + { TT_NEGREP, zDarwin_Dispatch_Object_1Bypass0, (regex_t*)NULL }, { TT_EGREP, zDarwin_Dispatch_Object_1Select0, (regex_t*)NULL }, }; /* @@ -3496,8 +3612,15 @@ tSCC zDarwin_Stdint_7Select0[] = "#define INTMAX_C\\(v\\)[ \t]+\\(v ## LL\\)\n\ #define UINTMAX_C\\(v\\)[ \t]+\\(v ## ULL\\)"; -#define DARWIN_STDINT_7_TEST_CT 1 +/* + * content bypass pattern - skip fix if pattern found + */ +tSCC zDarwin_Stdint_7Bypass0[] = + "#ifdef __LP64__"; + +#define DARWIN_STDINT_7_TEST_CT 2 static tTestDesc aDarwin_Stdint_7Tests[] = { + { TT_NEGREP, zDarwin_Stdint_7Bypass0, (regex_t*)NULL }, { TT_EGREP, zDarwin_Stdint_7Select0, (regex_t*)NULL }, }; /* @@ -11074,9 +11197,9 @@ static const char* apzX11_SprintfPatch[] = { * * List of all fixes */ -#define REGEX_COUNT 310 +#define REGEX_COUNT 317 #define MACH_LIST_SIZE_LIMIT 187 -#define FIX_COUNT 272 +#define FIX_COUNT 274 /* * Enumerate the fixes @@ -11085,6 +11208,7 @@ typedef enum { AAB_AIX_STDIO_FIXIDX, AAB_AIX_FCNTL_FIXIDX, AAB_DARWIN7_9_LONG_DOUBLE_FUNCS_FIXIDX, + DARWIN_API_AVAILABILITY_FIXIDX, AAB_FD_ZERO_ASM_POSIX_TYPES_H_FIXIDX, AAB_FD_ZERO_GNU_TYPES_H_FIXIDX, AAB_FD_ZERO_SELECTBITS_H_FIXIDX, @@ -11146,6 +11270,7 @@ typedef enum { CTRL_QUOTES_DEF_FIXIDX, CTRL_QUOTES_USE_FIXIDX, CXX_UNREADY_FIXIDX, + DARWIN_AVAILABILITYINTERNAL_FIXIDX, DARWIN_9_LONG_DOUBLE_FUNCS_2_FIXIDX, DARWIN_EXTERNC_FIXIDX, DARWIN_GCC4_BREAKAGE_FIXIDX, @@ -11372,6 +11497,11 @@ tFixDesc fixDescList[ FIX_COUNT ] = { AAB_DARWIN7_9_LONG_DOUBLE_FUNCS_TEST_CT, FD_MACH_ONLY | FD_REPLACEMENT, aAab_Darwin7_9_Long_Double_FuncsTests, apzAab_Darwin7_9_Long_Double_FuncsPatch, 0 }, + { zDarwin_Api_AvailabilityName, zDarwin_Api_AvailabilityList, + apzDarwin_Api_AvailabilityMachs, + DARWIN_API_AVAILABILITY_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, + aDarwin_Api_AvailabilityTests, apzDarwin_Api_AvailabilityPatch, 0 }, + { zAab_Fd_Zero_Asm_Posix_Types_HName, zAab_Fd_Zero_Asm_Posix_Types_HList, apzAab_Fd_Zero_Asm_Posix_Types_HMachs, AAB_FD_ZERO_ASM_POSIX_TYPES_H_TEST_CT, FD_MACH_ONLY | FD_REPLACEMENT, @@ -11677,6 +11807,11 @@ tFixDesc fixDescList[ FIX_COUNT ] = { CXX_UNREADY_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, aCxx_UnreadyTests, apzCxx_UnreadyPatch, 0 }, + { zDarwin_AvailabilityinternalName, zDarwin_AvailabilityinternalList, + apzDarwin_AvailabilityinternalMachs, + DARWIN_AVAILABILITYINTERNAL_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, + aDarwin_AvailabilityinternalTests, apzDarwin_AvailabilityinternalPatch, 0 }, + { zDarwin_9_Long_Double_Funcs_2Name, zDarwin_9_Long_Double_Funcs_2List, apzDarwin_9_Long_Double_Funcs_2Machs, DARWIN_9_LONG_DOUBLE_FUNCS_2_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, diff --git a/fixincludes/inclhack.def b/fixincludes/inclhack.def index 9df2abbff7b..35402d0621c 100644 --- a/fixincludes/inclhack.def +++ b/fixincludes/inclhack.def @@ -194,6 +194,33 @@ fix = { _EndOfHeader_; }; +/* + * SDKs for 10.13 and 10.14 omit the definitions for API_AVAILABLE where + * __attribute__((availability)) is not supported. + */ +fix = { + hackname = darwin_api_availability; + mach = "*-*-darwin*"; + files = os/availability.h; + bypass = "__IPHONE_OS_VERSION_MIN_REQUIRED"; + select = + " *#define __API_AVAILABLE.*\n" + " *#define __API_DEPRECATED.*\n" + " *#define __API_DEPRECATED_WITH_REPLACEMENT.*\n" + " *#define __API_UNAVAILABLE.*\n"; + c_fix = format; + c_fix_arg = + " #define API_AVAILABLE(...)\n" + " #define API_DEPRECATED(...)\n" + " #define API_DEPRECATED_WITH_REPLACEMENT(...)\n" + " #define API_UNAVAILABLE(...)\n"; + test_text = + "#define __API_AVAILABLE(...)\n" + "#define __API_DEPRECATED(...)\n" + "#define __API_DEPRECATED_WITH_REPLACEMENT(...)\n" + "#define __API_UNAVAILABLE(...)\n"; +}; + /* * This fixes __FD_ZERO bug for linux 2.x.y (x <= 2 && y <= some n) */ @@ -1323,6 +1350,32 @@ fix = { test_text = "extern void* malloc( size_t );"; }; +/* + * macOS 10.12 uses __attribute__((availability)) + * unconditionally. + */ +fix = { + hackname = darwin_availabilityinternal; + mach = "*-*-darwin*"; + files = AvailabilityInternal.h; + select = "#define[ \t]+(__API_[ADU]\\([^)]*\\)).*"; + c_fix = format; + c_fix_arg = <<- _EOFix_ + #if defined(__has_attribute) + #if __has_attribute(availability) + %0 + #else + #define %1 + #endif + #else + #define %1 + #endif + _EOFix_; + + test_text = "#define __API_A(x) __attribute__((availability(__API_AVAILABLE_PLATFORM_##x)))\n" + "#define __API_D(msg,x) __attribute__((availability(__API_DEPRECATED_PLATFORM_##x,message=msg)))"; +}; + /* * For the AAB_darwin7_9_long_double_funcs fix (and later fixes for long long) * to be useful, the main math.h must use <> and not "" includes. @@ -1433,6 +1486,7 @@ fix = { mach = "*-*-darwin*"; files = os/trace.h; select = "typedef.*\\^os_trace_payload_t.*"; + bypass = "#ifdef __BLOCKS__"; c_fix = format; c_fix_arg = "#if __BLOCKS__\n%0\n#endif"; test_text = "typedef void (^os_trace_payload_t)(xpc_object_t xdict);"; @@ -1513,6 +1567,7 @@ fix = { #define __has_attribute.* #endif OS_BASE_1_SEL; + bypass = "#define __has_extension"; c_fix = format; c_fix_arg = <<- OS_BASE_1_FIX %0 @@ -1536,6 +1591,7 @@ fix = { mach = "*-*-darwin*"; files = dispatch/object.h; select = "typedef void.*\\^dispatch_block_t.*"; + bypass = "#ifdef __BLOCKS__"; c_fix = format; c_fix_arg = "#if __BLOCKS__\n%0\n#endif"; test_text = <<- DISPATCH_OBJECT_1_TEST @@ -1738,6 +1794,7 @@ fix = { "#endif"; select = "#define INTMAX_C\\(v\\)[ \t]+\\(v ## LL\\)\n" "#define UINTMAX_C\\(v\\)[ \t]+\\(v ## ULL\\)"; + bypass = '#ifdef __LP64__'; test_text = "#define INTMAX_C(v) (v ## LL)\n" "#define UINTMAX_C(v) (v ## ULL)"; }; diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b59cb4d3558..33ddca9e303 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,742 @@ +2024-06-06 Pan Li + + * doc/match-and-simplify.texi: Add doc for the matching flag '^'. + * genmatch.cc (cmp_operand): Add match_phi comparation. + (dt_node::gen_kids_1): Add cond_expr bool flag for phi match. + (dt_operand::gen_phi_on_cond): Add new func to gen phi matching + on cond_expr. + (parser::parse_expr): Add handling for the expr flag '^'. + * match.pd: Add more form for unsigned .SAT_ADD. + * tree-ssa-math-opts.cc (build_saturation_binary_arith_call): Add + new func impl to build call for phi gimple. + (match_unsigned_saturation_add): Add new func impl to match the + .SAT_ADD for phi gimple. + (math_opts_dom_walker::after_dom_children): Add phi matching + try for all gimple phi stmt. + +2024-06-06 Pengxuan Zheng + + PR target/113880 + PR target/113869 + * config/aarch64/aarch64-builtins.cc (VAR1): Remap float_extend_lo_ + builtin codes to standard optab ones. + * config/aarch64/aarch64-simd.md (aarch64_float_extend_lo_): Rename + to... + (extend2): ... This. + +2024-06-06 Andrew Pinski + + PR plugins/115288 + * Makefile.in (CPPLIB_H): Add label-text.h. + +2024-06-06 Richard Ball + + * config/aarch64/aarch64-c.cc (aarch64_define_unconditional_macros): + Add missing __ARM_NEON_SVE_BRIDGE. + +2024-06-06 Richard Ball + + PR target/115353 + * config/arm/arm.h (enum arm_auto_incmodes): + Correct CASE_VECTOR_SHORTEN_MODE query. + +2024-06-06 Tamar Christina + + * config/aarch64/aarch64-sve.md (@aarch64_pred_cmp, + *cmp_cc, *cmp_ptest, + @aarch64_pred_cmp_wide, + *aarch64_pred_cmp_wide_cc, + *aarch64_pred_cmp_wide_ptest): Fix Upl tie alternative. + * config/aarch64/aarch64-sve2.md (@aarch64_pred_): Fix + Upl tie alternative. + +2024-06-06 Thomas Schwinge + + * config/nvptx/nvptx.md (nvptx_uniform_warp_check): Make fit for + non-full-warp execution, via 'vote.all.pred'. + +2024-06-06 Pan Li + + * match.pd: Add new form for vector mode recog. + * tree-vect-patterns.cc (gimple_unsigned_integer_sat_sub): Add + new match func decl; + (vect_recog_build_binary_gimple_call): Extract helper func to + build gcall with given internal_fn. + (vect_recog_sat_sub_pattern): Add new func impl to recog .SAT_SUB. + +2024-06-06 Michal Jires + + * lto-streamer.cc (lto_get_section_name): Remove suffixes after WPA. + +2024-06-06 Michal Jires + + * lto-opts.cc (lto_write_options): Skip OPT_fltrans_output_list_. + +2024-06-06 Robin Dapp + + * config/riscv/riscv.opt.urls: Regenerate. + +2024-06-06 Hongyu Wang + + * config/i386/i386-expand.cc (ix86_gen_ccmp_first): + Add fp compare and check the allowed fp compare type. + (ix86_gen_ccmp_next): Adjust compare_code input to ccmp for + fp compare. + +2024-06-06 Hongyu Wang + + * ccmp.cc (expand_ccmp_expr_1): Check ret and ret2 of + expand_ccmp_next, returns the valid one first instead of + comparing cost. + +2024-06-06 Hongyu Wang + + * config/i386/i386-expand.cc (ix86_gen_ccmp_first): New function + that test if the first compare can be generated. + (ix86_gen_ccmp_next): New function to emit a simgle compare and ccmp + sequence. + * config/i386/i386-opts.h (enum apx_features): Add apx_ccmp. + * config/i386/i386-protos.h (ix86_gen_ccmp_first): New proto + declare. + (ix86_gen_ccmp_next): Likewise. + (ix86_get_flags_cc): Likewise. + * config/i386/i386.cc (ix86_flags_cc): New enum. + (ix86_ccmp_dfv_mapping): New string array to map conditional + code to dfv. + (ix86_print_operand): Handle special dfv flag for CCMP. + (ix86_get_flags_cc): New function to return x86 CC enum. + (TARGET_GEN_CCMP_FIRST): Define. + (TARGET_GEN_CCMP_NEXT): Likewise. + * config/i386/i386.h (TARGET_APX_CCMP): Define. + * config/i386/i386.md (@ccmp): New define_insn to support + ccmp. + (UNSPEC_APX_DFV): New unspec for ccmp dfv. + (ALL_CC): New mode iterator. + (cstorecc4): Change to ... + (cstore4) ... this, use ALL_CC to loop through all + available CCmodes. + * config/i386/i386.opt (apx_ccmp): Add enum value for ccmp. + +2024-06-06 Richard Biener + + * tree-vect-loop.cc (vectorizable_reduction): Allow + single-lane SLP in-order reductions. + (vectorize_fold_left_reduction): Handle SLP reduction with + conditional reduction op. + +2024-06-06 Richard Biener + + * tree-vect-loop.cc (vect_analyze_scalar_cycles_1): Queue + double reductions in LOOP_VINFO_REDUCTIONS. + (vect_create_epilog_for_reduction): Remove asserts disabling + SLP for double reductions. + (vectorizable_reduction): Analyze SLP double reductions + only once and start off the correct places. + * tree-vect-slp.cc (vect_get_and_check_slp_defs): Allow + vect_double_reduction_def. + (vect_build_slp_tree_2): Fix condition for the ignored + reduction initial values. + * tree-vect-stmts.cc (vect_analyze_stmt): Allow + vect_double_reduction_def. + +2024-06-06 Richard Biener + + * tree-vect-loop.cc (vect_create_epilog_for_reduction): + Adjust for single-lane COND_REDUCTION SLP vectorization. + (vectorizable_reduction): Likewise. + (vect_transform_cycle_phi): Likewise. + +2024-06-06 Richard Biener + + * tree-vect-stmts.cc (vectorizable_condition): Allow + single-lane SLP, but not when we need to swap then and + else clause. + +2024-06-06 YunQiang Su + + * config/mips/mips.cc(mips_insn_cost): Add missing COSTS_N_INSNS + to count. + +2024-06-06 liuhongt + + PR target/114428 + * config/i386/i386.cc (ix86_rtx_costs): Adjust cost for + CONST_VECTOR_DUPLICATE_P in constant_pool. + * config/i386/i386-expand.cc (ix86_broadcast_from_constant): + Remove static. + * config/i386/i386-protos.h (ix86_broadcast_from_constant): + Declare. + +2024-06-06 liuhongt + + PR target/114428 + * simplify-rtx.cc + (simplify_context::simplify_binary_operation_1): + Simplify (AND (ASHIFTRT A imm) mask) to (LSHIFTRT A imm) for + specific mask. + +2024-06-05 Robin Dapp + + * config/riscv/riscv-opts.h (TARGET_VECTOR_MISALIGN_SUPPORTED): + Move from here... + * config/riscv/riscv.h (TARGET_VECTOR_MISALIGN_SUPPORTED): + ...to here and map to riscv_vector_unaligned_access_p. + * config/riscv/riscv.opt: Add -mvector-strict-align. + * config/riscv/riscv.cc (struct riscv_tune_param): Add + vector_unaligned_access. + (riscv_override_options_internal): Set + riscv_vector_unaligned_access_p. + * doc/invoke.texi: Document -mvector-strict-align. + +2024-06-05 Tamar Christina + + * config/aarch64/tuning_models/neoversen2.h (neoversen2_tunings): Add + AARCH64_EXTRA_TUNE_AVOID_PRED_RMW. + * config/aarch64/tuning_models/neoversev1.h (neoversev1_tunings): Add + AARCH64_EXTRA_TUNE_AVOID_PRED_RMW. + * config/aarch64/tuning_models/neoversev2.h (neoversev2_tunings): Add + AARCH64_EXTRA_TUNE_AVOID_PRED_RMW. + +2024-06-05 Tamar Christina + + * config/aarch64/aarch64-sve.md (and3, + @aarch64_pred__z, *3_cc, + *3_ptest, aarch64_pred__z, + *3_cc, *3_ptest, + aarch64_pred__z, *3_cc, + *3_ptest, @aarch64_pred_cmp, + *cmp_cc, *cmp_ptest, + @aarch64_pred_cmp_wide, + *aarch64_pred_cmp_wide_cc, + *aarch64_pred_cmp_wide_ptest, @aarch64_brk, + *aarch64_brk_cc, *aarch64_brk_ptest, + @aarch64_brk, *aarch64_brk_cc, + *aarch64_brk_ptest, aarch64_rdffr_z, *aarch64_rdffr_z_ptest, + *aarch64_rdffr_ptest, *aarch64_rdffr_z_cc, *aarch64_rdffr_cc): Add + new early clobber + alternative. + * config/aarch64/aarch64-sve2.md + (@aarch64_pred_): Likewise. + +2024-06-05 Tamar Christina + + * config/aarch64/aarch64-tuning-flags.def + (AVOID_PRED_RMW): New. + * config/aarch64/aarch64.h (TARGET_SVE_PRED_CLOBBER): New. + * config/aarch64/aarch64.md (pred_clobber): New. + (arch_enabled): Use it. + +2024-06-05 Tamar Christina + + * config/aarch64/aarch64-sve.md (and3, + @aarch64_pred__z, *3_cc, + *3_ptest, aarch64_pred__z, + *3_cc, *3_ptest, + aarch64_pred__z, *3_cc, + *3_ptest, *cmp_ptest, + @aarch64_pred_cmp_wide, + *aarch64_pred_cmp_wide_cc, + *aarch64_pred_cmp_wide_ptest, *aarch64_brk_cc, + *aarch64_brk_ptest, @aarch64_brk, + *aarch64_brk_cc, *aarch64_brk_ptest, aarch64_rdffr_z, + *aarch64_rdffr_z_ptest, *aarch64_rdffr_ptest, *aarch64_rdffr_z_cc, + *aarch64_rdffr_cc): Convert to compact syntax. + * config/aarch64/aarch64-sve2.md + (@aarch64_pred_): Likewise. + +2024-06-05 Jakub Jelinek + Frederik Harwath + Sandra Loosemore + + * tree.def (OMP_TILE, OMP_UNROLL): New tree codes. + * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_PARTIAL, + OMP_CLAUSE_FULL and OMP_CLAUSE_SIZES. + * tree.h (OMP_LOOPXFORM_CHECK): Define. + (OMP_LOOPXFORM_LOWERED): Define. + (OMP_CLAUSE_PARTIAL_EXPR): Define. + (OMP_CLAUSE_SIZES_LIST): Define. + * tree.cc (omp_clause_num_ops, omp_clause_code_name): Add entries + for OMP_CLAUSE_{PARTIAL,FULL,SIZES}. + * tree-pretty-print.cc (dump_omp_clause): Handle + OMP_CLAUSE_{PARTIAL,FULL,SIZES}. + (dump_generic_node): Handle OMP_TILE and OMP_UNROLL. Skip printing + loops with NULL OMP_FOR_INIT (node) vector element. + * gimplify.cc (is_gimple_stmt): Handle OMP_TILE and OMP_UNROLL. + (gimplify_omp_taskloop_expr): For SAVE_EXPR use gimplify_save_expr. + (gimplify_omp_loop_xform): New function. + (gimplify_omp_for): Call omp_maybe_apply_loop_xforms and if that + reshuffles what the passed pointer points to, retry or return GS_OK. + Handle OMP_TILE and OMP_UNROLL. + (gimplify_omp_loop): Call omp_maybe_apply_loop_xforms and if that + reshuffles what the passed pointer points to, return GS_OK. + (gimplify_expr): Handle OMP_TILE and OMP_UNROLL. + * omp-general.h (omp_loop_number_of_iterations, + omp_maybe_apply_loop_xforms): Declare. + * omp-general.cc (omp_adjust_for_condition): For LE_EXPR and GE_EXPR + with pointers, don't add/subtract one, but the size of what the + pointer points to. + (omp_loop_number_of_iterations, omp_apply_tile, + find_nested_loop_xform, omp_maybe_apply_loop_xforms): New functions. + +2024-06-05 Kewen Lin + + * config/darwin.cc (darwin_patch_builtins): Use TYPE_PRECISION of + long_double_type_node to replace LONG_DOUBLE_TYPE_SIZE. + +2024-06-05 Pan Li + + PR target/51492 + PR target/112600 + * internal-fn.def (SAT_SUB): Add new IFN define for SAT_SUB. + * match.pd: Add new match for SAT_SUB. + * optabs.def (OPTAB_NL): Remove fixed-point for ussub/ssub. + * tree-ssa-math-opts.cc (gimple_unsigned_integer_sat_sub): Add + new decl for generated in match.pd. + (build_saturation_binary_arith_call): Add new helper function + to build the gimple call to binary SAT alu. + (match_saturation_arith): Rename from. + (match_unsigned_saturation_add): Rename to. + (match_unsigned_saturation_sub): Add new func to match the + unsigned sat sub. + (math_opts_dom_walker::after_dom_children): Add SAT_SUB matching + try when COND_EXPR. + +2024-06-05 Gerald Pfeifer + + PR other/69374 + * doc/install.texi (Prerequisites): Drop reference to GNU awk + version 3.1.5. Remove fluff. + +2024-06-05 liuhongt + + PR rtl-optimization/100927 + PR rtl-optimization/115161 + PR rtl-optimization/115115 + * simplify-rtx.cc (simplify_const_unary_operation): Prevent + simplication of FIX/UNSIGNED_FIX for NAN/INF/out-of-range + constant when flag_trapping_math. + * fold-const.cc (fold_convert_const_int_from_real): Don't fold + for overflow value when_trapping_math. + +2024-06-05 Xiao Zeng + + * config/riscv/iterators.md: Add mode_iterator between + floating-point modes and BFmode. + * config/riscv/riscv.cc (riscv_output_move): Handle BFmode move + for zfbfmin. + * config/riscv/riscv.md (truncbf2): New pattern for BFmode. + (extendbfsf2): Dotto. + (*movhf_hardfloat): Add BFmode. + (*mov_hardfloat): Dotto. + +2024-06-04 Jakub Jelinek + + PR tree-optimization/115337 + * gimple-range-op.cc (cfn_clz::fold_range): For + m_gimple_call_internal_p handle as a special case also second argument + of -1 next to prec. + +2024-06-04 Jakub Jelinek + + PR tree-optimization/115337 + * fold-const.cc (tree_call_nonnegative_warnv_p): Handle + CASE_CFN_CTZ like CASE_CFN_CLZ. + +2024-06-04 Jakub Jelinek + + * fold-const.cc (tree_call_nonnegative_warnv_p): Formatting fixes. + (tree_invalid_nonnegative_warnv_p): Likewise. + * gimple-fold.cc (gimple_call_nonnegative_warnv_p): Likewise. + +2024-06-04 Jakub Jelinek + + PR tree-optimization/115337 + * fold-const.cc (tree_call_nonnegative_warnv_p) : + If arg1 is non-NULL, RECURSE on it, otherwise return true. + +2024-06-04 Jakub Jelinek + + PR middle-end/108789 + * builtins.cc (fold_builtin_arith_overflow): For ovf_only, + don't call save_expr and don't build REALPART_EXPR, otherwise + set TREE_SIDE_EFFECTS on call before calling save_expr. + (fold_builtin_addc_subc): Set TREE_SIDE_EFFECTS on call before + calling save_expr. + +2024-06-04 Jakub Jelinek + + * doc/invoke.texi (lujiazui): Clarify that while the CPUs do support + AVX and F16C, -march=lujiazui actually doesn't enable those. + +2024-06-04 Richard Biener + + * tree-vect-slp.cc (vect_build_slp_tree_2): Only multi-lane + discoveries are reduction chains and need special backedge + treatment. + (vect_analyze_slp): Fall back to single-lane SLP discovery + for reductions. Make sure to try single-lane SLP reduction + for all reductions as fallback. + (vectorizable_load): Avoid outer loop SLP vectorization with + multi-copy vector stmts in the inner loop. + (vectorizable_store): Likewise. + * tree-vect-loop.cc (vect_create_epilog_for_reduction): Allow + direct opcode and shift reduction also for SLP reductions + with a single lane. + * tree-vect-stmts.cc (get_group_load_store_type): For SLP also + check for the PR65518 single-element interleaving case as done in + vect_grouped_load_supported. + +2024-06-04 Richard Biener + + * tree-vect-slp.cc (vect_schedule_slp_node): For mask/len + loops make sure to not advance the insertion iterator + beyond a GIMPLE_COND. + +2024-06-03 Jakub Jelinek + + PR target/115324 + * config/rs6000/rs6000-gen-builtins.cc (write_decls): Remove + GTY markup from struct bifdata and struct ovlddata and remove their + fntype members. Change next member in struct ovlddata and + first_instance member of struct ovldrecord to have int type rather + than struct ovlddata *. Remove GTY markup from rs6000_builtin_info + and rs6000_instance_info arrays, declare new + rs6000_builtin_info_fntype and rs6000_instance_info_fntype arrays, + which have GTY markup. + (write_bif_static_init): Adjust for the above changes. + (write_ovld_static_init): Likewise. + (write_init_bif_table): Likewise. + (write_init_ovld_table): Likewise. + * config/rs6000/rs6000-builtin.cc (rs6000_init_builtins): Likewise. + * config/rs6000/rs6000-c.cc (find_instance): Likewise. Make static. + (altivec_resolve_overloaded_builtin): Adjust for the above changes. + +2024-06-03 David Malcolm + + * diagnostic-format-sarif.cc: Include "ordered-hash-map.h" and + "sbitmap.h". + (enum class diagnostic_artifact_role): New. + (class sarif_artifact): New. + (sarif_builder::maybe_make_artifact_content_object): Make public. + (sarif_builder::m_filenames): Replace with... + (sarif_builder::m_filename_to_artifact_map): ...this. + (sarif_artifact::add_role): New. + (sarif_artifact::populate_contents): New. + (get_artifact_role_string): New. + (sarif_artifact::populate_roles): New. + (sarif_result::on_nested_diagnostic): Pass role to + make_location_object. + (sarif_ice_notification::sarif_ice_notification): Likewise. + (sarif_builder::sarif_builder): Add "main_input_filename_" param. + Mark it as the artifact that the tool was instructed to scan. + (sarif_builder::make_result_object): Pass role to + make_locations_arr. + (sarif_builder::make_locations_arr): Add "role" param and pass it + to make_location_object. + (sarif_builder::make_location_object): Add "role" param and pass + it to maybe_make_physical_location_object. + (sarif_builder::maybe_make_physical_location_object): Add "role" + param and pass it to call to get_or_create_artifact, rather than + adding to now-removed "m_filenames". Flag the artifact for its + contents to be embedded. + (sarif_builder::make_thread_flow_location_object): Pass role to + make_location_object. + (sarif_builder::make_run_object): Update for change from + m_filename to m_filename_to_artifact_map. Call populate_contents + and populate_roles on each artifact_obj. + (sarif_builder::make_artifact_object): Convert to... + (sarif_builder::get_or_create_artifact): ...this, moving addition + of contents to make_run_object, and conditionalizing setting of + sourceLanguage on "role". + (sarif_output_format::sarif_output_format): Add + "main_input_filename_" param and pass to m_builder's ctor. + (sarif_stream_output_format::sarif_stream_output_format): + Likewise. + (sarif_file_output_format::sarif_file_output_format): Likewise. + (diagnostic_output_format_init_sarif_stderr): Add + "main_input_filename_" param and pass to ctor. + (diagnostic_output_format_init_sarif_file): Likewise. + (diagnostic_output_format_init_sarif_stream): Likewise. + * diagnostic.cc (diagnostic_output_format_init): Add + "main_input_filename_" param and pass to the + diagnostic_output_format_init_sarif_* calls. + * diagnostic.h (diagnostic_output_format_init): Add + main_input_filename_" param to decl. + (diagnostic_output_format_init_sarif_stderr): Likewise. + (diagnostic_output_format_init_sarif_file): Likewise. + (diagnostic_output_format_init_sarif_stream): Likewise. + * gcc.cc (driver_handle_option): Pass main input filename to + diagnostic_output_format_init. + * opts.cc (common_handle_option): Likewise. + +2024-06-03 Eric Botcazou + + * dwarf2out.cc (loc_list_from_tree_1) ; Add const. + : Use a signed comparison for small unsigned types. + Implement wrap-around arithmetics for small integer types. + +2024-06-03 Uros Bizjak + + PR target/115321 + * config/i386/i386.md (bswapsi2): Force operand 1 + to a register also for !TARGET_BSWAP. + +2024-06-03 Aldy Hernandez + + * builtins.cc (expand_builtin_strnlen): Replace value_range use + with int_range_max or irange when appropriate. + (determine_block_size): Same. + * fold-const.cc (minmax_from_comparison): Same. + * gimple-array-bounds.cc (check_out_of_bounds_and_warn): Same. + (array_bounds_checker::check_array_ref): Same. + * gimple-fold.cc (size_must_be_zero_p): Same. + * gimple-predicate-analysis.cc (find_var_cmp_const): Same. + * gimple-ssa-sprintf.cc (get_int_range): Same. + (format_integer): Same. + (try_substitute_return_value): Same. + (handle_printf_call): Same. + * gimple-ssa-warn-restrict.cc + (builtin_memref::extend_offset_range): Same. + * graphite-sese-to-poly.cc (add_param_constraints): Same. + * internal-fn.cc (get_min_precision): Same. + * match.pd: Same. + * pointer-query.cc (get_size_range): Same. + * range-op.cc (get_shift_range): Same. + (operator_trunc_mod::op1_range): Same. + (operator_trunc_mod::op2_range): Same. + * range.cc (range_negatives): Same. + * range.h (range_positives): Same. + (range_negatives): Same. + * tree-affine.cc (expr_to_aff_combination): Same. + * tree-data-ref.cc (compute_distributive_range): Same. + (nop_conversion_for_offset_p): Same. + (split_constant_offset): Same. + (split_constant_offset_1): Same. + (dr_step_indicator): Same. + * tree-dfa.cc (get_ref_base_and_extent): Same. + * tree-scalar-evolution.cc (iv_can_overflow_p): Same. + * tree-ssa-math-opts.cc (optimize_spaceship): Same. + * tree-ssa-pre.cc (insert_into_preds_of_block): Same. + * tree-ssa-reassoc.cc (optimize_range_tests_to_bit_test): Same. + * tree-ssa-strlen.cc (compare_nonzero_chars): Same. + (dump_strlen_info): Same. + (get_range_strlen_dynamic): Same. + (set_strlen_range): Same. + (maybe_diag_stxncpy_trunc): Same. + (strlen_pass::get_len_or_size): Same. + (strlen_pass::handle_builtin_string_cmp): Same. + (strlen_pass::count_nonzero_bytes_addr): Same. + (strlen_pass::handle_integral_assign): Same. + * tree-switch-conversion.cc (bit_test_cluster::emit): Same. + * tree-vect-loop-manip.cc (vect_gen_vector_loop_niters): Same. + (vect_do_peeling): Same. + * tree-vect-patterns.cc (vect_get_range_info): Same. + (vect_recog_divmod_pattern): Same. + * tree.cc (get_range_pos_neg): Same. + * value-range.cc (debug): Remove value_range variants. + * value-range.h (value_range): Remove typedef. + * vr-values.cc + (simplify_using_ranges::op_with_boolean_value_range_p): Replace + value_range use with int_range_max or irange when appropriate. + (check_for_binary_op_overflow): Same. + (simplify_using_ranges::legacy_fold_cond_overflow): Same. + (find_case_label_ranges): Same. + (simplify_using_ranges::simplify_abs_using_ranges): Same. + (test_for_singularity): Same. + (simplify_using_ranges::simplify_compare_using_ranges_1): Same. + (simplify_using_ranges::simplify_casted_compare): Same. + (simplify_using_ranges::simplify_switch_using_ranges): Same. + (simplify_conversion_using_ranges): Same. + (simplify_using_ranges::two_valued_val_range_p): Same. + +2024-06-03 Tobias Burnus + + * doc/install.texi (gcn): Fix date of recommended newlib version. + +2024-06-03 Marc Poulhiès + + * config/aarch64/aarch64-ldp-fusion.cc (struct aarch64_pair_fusion): + Use new type name. + +2024-06-03 Marc Poulhiès + + * pair-fusion.h (enum class writeback): Rename to... + (enum class writeback_type): ...this. + (struct pair_fusion): Adjust type name after renaming. + * pair-fusion.cc (pair_fusion_bb_info::track_access): Likewise. + (pair_fusion_bb_info::fuse_pair): Likewise. + (pair_fusion::process_block): Likewise. + +2024-06-03 Richard Biener + + * tree-vect-loop.cc (vect_analyze_loop_1): Avoid extra space + before 'failed'. + +2024-06-03 Richard Biener + + * tree-vect-loop.cc (get_initial_defs_for_reduction): + Always convert neutral_op. + +2024-06-03 liuhongt + + PR target/115299 + * config/i386/i386.cc (ix86_noce_conversion_profitable_p): Add + some preference for floating point ifcvt when SSE4.1 is not + available. + +2024-06-03 Haochen Jiang + + * common/config/i386/i386-common.cc: Change Granite Rapids + series CPU type to P_PROC_AVX10_1_512. + * common/config/i386/i386-cpuinfo.h (enum feature_priority): + Revise comment part. Add P_AVX10_1_256, P_AVX10_1_512, + P_PROC_AVX10_1_512. + * common/config/i386/i386-isas.h: Link to avx10.1-256, avx10.1-512. + +2024-06-03 Lingling Kong + + * config/i386/i386.md (clz2_lzcnt_nf): New define_insn. + (*clz2_lzcnt_falsedep_nf): Ditto. + (__nf): Ditto. + (*__falsedep_nf): Ditto. + (_hi): Ditto. + (popcount2_nf): Ditto. + (*popcount2_falsedep_nf): Ditto. + (popcounthi2): Ditto. + +2024-06-03 Lingling Kong + + * config/i386/i386.md (*mul3_1): New define_insn. + (*mulqi3_1): Ditto. + (*divmod4_noext_nf): Ditto. + (divmodhiqi3): Ditto. + +2024-06-03 Lingling Kong + + * config/i386/i386.md (x86_64_shld): New define_insn. + (x86_64_shld): Ditto. + (x86_64_shld_ndd): Ditto. + (x86_64_shld_1): Ditto. + (x86_64_shld_ndd_1): Ditto. + (*x86_64_shld_shrd_1_nozext_nf): Ditto. + (x86_shld): Ditto. + (x86_shld_ndd): Ditto. + (x86_shld_1): Ditto. + (x86_shld_ndd_1): Ditto. + (*x86_shld_shrd_1_nozext_nf): Ditto. + (3_doubleword_lowpart_nf): Ditto. + (x86_64_shrd): Ditto. + (x86_64_shrd_ndd): Ditto. + (x86_64_shrd_1): Ditto. + (x86_64_shrd_ndd_1): Ditto. + (*x86_64_shrd_shld_1_nozext_nf): Ditto. + (x86_shrd): Ditto. + (x86_shrd_ndd): Ditto. + (x86_shrd_1): Ditto. + (x86_shrd_ndd_1): Ditto. + (*x86_shrd_shld_1_nozext_nf): Ditto. + +2024-06-03 Lingling Kong + + * config/i386/i386.md (ashr3_cvt): New + define_insn. + (*3_1): Ditto. + +2024-06-03 Lingling Kong + + * config/i386/i386.md (*ashr3_1): New + define_insn. + (*lshr3_1): Ditto. + (*lshrqi3_1): Ditto. + (*lshrhi3_1): Ditto. + +2024-06-03 Lingling Kong + + * config/i386/i386.md (*ashl3_1): New + define_insn. + (*ashlhi3_1): Ditto. + (*ashlqi3_1): Ditto. + * config/i386/sse.md: New define_split. + +2024-06-03 Lingling Kong + + * config/i386/i386.md (nf_nonf_attr): New subst_attr. + (nf_nonf_x64_attr): Ditto. + (*sub_1): New define_insn. + (*anddi_1): Ditto. + (*and_1): Ditto. + (*andqi_1): Ditto. + (*_1): Ditto. + (*qi_1): Ditto. + (*neg_1): Ditto. + * config/i386/sse.md: New define_split. + +2024-06-03 Lingling Kong + Hongyu Wong + + * config/i386/i386-opts.h (enum apx_features): Add nf + enumeration. + * config/i386/i386.h (TARGET_APX_NF): New. + * config/i386/i386.md (nf_name): New subst_att. + (nf_prefix): Ditto. + (nf_condition): Ditto. + (nf_mem_constraint): Ditto. + (nf_applied): Ditto. + (nf_subst): Add new define_subst. + (*add_1): New define_insn. + (*addhi_1): Ditto. + (*addqi_1): Diito. + * config/i386/i386.opt: Add apx_nf enumeration. + +2024-06-03 Hu, Lin1 + + PR target/113609 + * config/i386/sse.md + (*kortest_cmp_setcc): New define_insn_and_split. + (*kortest_cmp_jcc): Ditto. + +2024-06-01 Georg-Johann Lay + + PR tree-optimization/115307 + * config/avr/avr.md (SFDF): New mode iterator. + (isinf2) [sf, df]: New expanders. + +2024-06-01 Jeff Law + + * config/riscv/riscv.cc (riscv_integer_op): Add new field. + (riscv_build_integer_1): Initialize the new field. + (riscv_built_integer): Recognize more cases where Zbkb's + pack instruction is profitable. + (riscv_move_integer): Loop over all the codes. If requested, + save the current constant into a temporary. Generate pack + for more cases using the saved constant. + +2024-06-01 Feng Xue + + * tree-vect-loop.cc (vect_is_emulated_mixed_dot_prod): Remove parameter + loop_vinfo. Get input vectype from stmt_info instead of reduction PHI. + (vect_model_reduction_cost): Remove loop_vinfo argument of call to + vect_is_emulated_mixed_dot_prod. + (vect_transform_reduction): Likewise. + (vectorizable_reduction): Likewise, and bind input vectype to + lane-reducing operation. + +2024-06-01 Feng Xue + + * tree-vect-loop.cc (vect_reduction_update_partial_vector_usage): New + function. + (vectorizable_reduction): Move partial vectorization checking code to + vect_reduction_update_partial_vector_usage. + +2024-06-01 Feng Xue + + * tree-vectorizer.h (lane_reducing_op_p): New function. + * tree-vect-slp.cc (vect_analyze_slp): Use new function + lane_reducing_op_p to check statement code. + * tree-vect-loop.cc (vect_transform_reduction): Likewise. + (vectorizable_reduction): Likewise, and change name of a local + variable that holds the result flag. + 2024-05-31 Takayuki 'January June' Suwa * config/xtensa/xtensa-protos.h (xtensa_expand_call): diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index fe85bc7903e..de43a34b913 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240601 +20240607 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index c983b0c102a..f5adb647d3f 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1038,6 +1038,7 @@ SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h \ PREDICT_H = predict.h predict.def CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \ $(srcdir)/../libcpp/include/rich-location.h \ + $(srcdir)/../libcpp/include/label-text.h \ $(srcdir)/../libcpp/include/cpplib.h CODYLIB_H = $(srcdir)/../libcody/cody.hh INPUT_H = $(srcdir)/../libcpp/include/line-map.h input.h diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6d44c3514bc..5beaacb2f0d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2024-06-05 Kewen Lin + + * gcc-interface/decl.cc (gnat_to_gnu_entity): Use TYPE_PRECISION of + long_double_type_node to replace LONG_DOUBLE_TYPE_SIZE. + 2024-05-29 Eric Botcazou PR ada/115270 diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc index f6a4c0631b6..8b72c96c439 100644 --- a/gcc/ada/gcc-interface/decl.cc +++ b/gcc/ada/gcc-interface/decl.cc @@ -520,7 +520,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) esize = UI_To_Int (Esize (gnat_entity)); if (IN (kind, Float_Kind)) - max_esize = fp_prec_to_size (LONG_DOUBLE_TYPE_SIZE); + max_esize + = fp_prec_to_size (TYPE_PRECISION (long_double_type_node)); else if (IN (kind, Access_Kind)) max_esize = POINTER_SIZE * 2; else diff --git a/gcc/ada/init.c b/gcc/ada/init.c index 8d5acdd6fb6..7cf77471f1d 100644 --- a/gcc/ada/init.c +++ b/gcc/ada/init.c @@ -2479,10 +2479,7 @@ __gnat_map_signal (int sig, siginfo_t *si, void *mcontext ATTRIBUTE_UNUSED) /* Reset the use of alt stack, so that the alt stack will be used for the next signal delivery. The stack can't be used in case of stack checking. */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" syscall (SYS_sigreturn, NULL, UC_RESET_ALT_STACK); -#pragma GCC diagnostic pop break; case SIGFPE: diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 5fe629d67a4..50f20caeb32 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,44 @@ +2024-06-01 David Malcolm + + PR analyzer/106203 + * checker-event.h: Include "analyzer/event-loc-info.h". + (struct event_loc_info): Move to its own header file. + * diagnostic-manager.cc + (diagnostic_manager::emit_saved_diagnostic): Move creation of + event_loc_info here from add_final_event, and if we have a + stmt_finder, call its update_event_loc_info method. + * engine.cc (leak_stmt_finder::update_event_loc_info): New. + (exploded_node::detect_leaks): Likewise. + (exploded_node::detect_leaks): Pass nullptr as call_stmt arg to + region_model::pop_frame. + * event-loc-info.h: New file, with content taken from + checker-event.h. + * exploded-graph.h (stmt_finder::update_event_loc_info): New pure + virtual function. + * infinite-loop.cc (infinite_loop_diagnostic::add_final_event): + Update for change to vfunc signature. + * infinite-recursion.cc + (infinite_recursion_diagnostic::add_final_event): Likewise. + * pending-diagnostic.cc (pending_diagnostic::add_final_event): + Pass in the event_loc_info from the caller, rather than generating + it from a gimple stmt and enode. + * pending-diagnostic.h (pending_diagnostic::add_final_event): + Likewise. + * region-model.cc (region_model::on_longjmp): Pass nullptr as + call_stmt arg to region_model::pop_frame. + (region_model::update_for_return_gcall): Likewise, but pass + call_stmt. + (class caller_context): New. + (region_model::pop_frame): Add "call_stmt" argument. Use it + and the frame_region with a caller_context when setting + result_dst_reg's value so that any diagnostic is reported at the + call stmt in the caller. + (selftest::test_stack_frames): Pass nullptr as call_stmt arg to + region_model::pop_frame. + (selftest::test_alloca): Likewise. + * region-model.h (region_model::pop_frame): Add "call_stmt" + argument. + 2024-05-30 David Malcolm * infinite-loop.cc (looping_back_event::get_desc): Fix unused diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt index bbf2ba670d8..5335f7e1999 100644 --- a/gcc/analyzer/analyzer.opt +++ b/gcc/analyzer/analyzer.opt @@ -222,6 +222,10 @@ Wanalyzer-tainted-size Common Var(warn_analyzer_tainted_size) Init(1) Warning Warn about code paths in which an unsanitized value is used as a size. +Wanalyzer-undefined-behavior-ptrdiff +Common Var(warn_analyzer_undefined_behavior_ptrdiff) Init(1) Warning +Warn about code paths in which pointer subtraction involves undefined behavior. + Wanalyzer-undefined-behavior-strtok Common Var(warn_analyzer_undefined_behavior_strtok) Init(1) Warning Warn about code paths in which a call is made to strtok with undefined behavior. diff --git a/gcc/analyzer/analyzer.opt.urls b/gcc/analyzer/analyzer.opt.urls index 5fcab720582..18a0d6926de 100644 --- a/gcc/analyzer/analyzer.opt.urls +++ b/gcc/analyzer/analyzer.opt.urls @@ -114,6 +114,9 @@ UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-offset) Wanalyzer-tainted-size UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-tainted-size) +Wanalyzer-undefined-behavior-ptrdiff +UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-undefined-behavior-ptrdiff) + Wanalyzer-undefined-behavior-strtok UrlSuffix(gcc/Static-Analyzer-Options.html#index-Wanalyzer-undefined-behavior-strtok) diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc index 60ca78a334d..46b4e2a3bbd 100644 --- a/gcc/analyzer/call-summary.cc +++ b/gcc/analyzer/call-summary.cc @@ -726,13 +726,12 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg) { const cast_region *summary_cast_reg = as_a (summary_reg); - const region *summary_original_reg - = summary_cast_reg->get_original_region (); - const region *caller_original_reg - = convert_region_from_summary (summary_original_reg); - if (!caller_original_reg) + const region *summary_parent_reg = summary_reg->get_parent_region (); + const region *caller_parent_reg + = convert_region_from_summary (summary_parent_reg); + if (!caller_parent_reg) return NULL; - return mgr->get_cast_region (caller_original_reg, + return mgr->get_cast_region (caller_parent_reg, summary_reg->get_type ()); } break; diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h index 7a4510ee81d..d0935aca985 100644 --- a/gcc/analyzer/checker-event.h +++ b/gcc/analyzer/checker-event.h @@ -23,22 +23,10 @@ along with GCC; see the file COPYING3. If not see #include "tree-logical-location.h" #include "analyzer/program-state.h" +#include "analyzer/event-loc-info.h" namespace ana { -/* A bundle of location information for a checker_event. */ - -struct event_loc_info -{ - event_loc_info (location_t loc, tree fndecl, int depth) - : m_loc (loc), m_fndecl (fndecl), m_depth (depth) - {} - - location_t m_loc; - tree m_fndecl; - int m_depth; -}; - /* An enum for discriminating between the concrete subclasses of checker_event. */ diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index da98b9679cb..20e793d72c1 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -1588,8 +1588,17 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg, We use the final enode from the epath, which might be different from the sd.m_enode, as the dedupe code doesn't care about enodes, just snodes. */ - sd.m_d->add_final_event (sd.m_sm, epath->get_final_enode (), sd.m_stmt, - sd.m_var, sd.m_state, &emission_path); + { + const exploded_node *const enode = epath->get_final_enode (); + const gimple *stmt = sd.m_stmt; + event_loc_info loc_info (get_stmt_location (stmt, enode->get_function ()), + enode->get_function ()->decl, + enode->get_stack_depth ()); + if (sd.m_stmt_finder) + sd.m_stmt_finder->update_event_loc_info (loc_info); + sd.m_d->add_final_event (sd.m_sm, enode, loc_info, + sd.m_var, sd.m_state, &emission_path); + } /* The "final" event might not be final; if the saved_diagnostic has a trailing eedge stashed, add any events for it. This is for use diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 46d9b80f4f7..30c0913c861 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -681,6 +681,11 @@ public: return NULL; } + void update_event_loc_info (event_loc_info &) final override + { + /* No-op. */ + } + private: const exploded_graph &m_eg; tree m_var; @@ -898,7 +903,8 @@ impl_region_model_context::on_state_leak (const state_machine &sm, svalue_set visited; path_var leaked_pv = m_old_state->m_region_model->get_representative_path_var (sval, - &visited); + &visited, + nullptr); /* Strip off top-level casts */ if (leaked_pv.m_tree && TREE_CODE (leaked_pv.m_tree) == NOP_EXPR) @@ -2056,7 +2062,7 @@ exploded_node::detect_leaks (exploded_graph &eg) &old_state, &new_state, &uncertainty, NULL, get_stmt ()); const svalue *result = NULL; - new_state.m_region_model->pop_frame (NULL, &result, &ctxt); + new_state.m_region_model->pop_frame (NULL, &result, &ctxt, nullptr); program_state::detect_leaks (old_state, new_state, result, eg.get_ext_state (), &ctxt); } diff --git a/gcc/analyzer/event-loc-info.h b/gcc/analyzer/event-loc-info.h new file mode 100644 index 00000000000..60b2035bd2c --- /dev/null +++ b/gcc/analyzer/event-loc-info.h @@ -0,0 +1,41 @@ +/* A bundle of location information for a checker_event. + Copyright (C) 2019-2024 Free Software Foundation, Inc. + Contributed by David Malcolm . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#ifndef GCC_ANALYZER_EVENT_LOC_INFO_H +#define GCC_ANALYZER_EVENT_LOC_INFO_H + +namespace ana { + +/* A bundle of location information for a checker_event. */ + +struct event_loc_info +{ + event_loc_info (location_t loc, tree fndecl, int depth) + : m_loc (loc), m_fndecl (fndecl), m_depth (depth) + {} + + location_t m_loc; + tree m_fndecl; + int m_depth; +}; + +} // namespace ana + +#endif /* GCC_ANALYZER_EVENT_LOC_INFO_H */ diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index 642d69bbcc0..f847c01132a 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -1035,6 +1035,7 @@ public: virtual ~stmt_finder () {} virtual std::unique_ptr clone () const = 0; virtual const gimple *find_stmt (const exploded_path &epath) = 0; + virtual void update_event_loc_info (event_loc_info &) = 0; }; // TODO: split the above up? diff --git a/gcc/analyzer/infinite-loop.cc b/gcc/analyzer/infinite-loop.cc index a83b8130e43..8ba8e70acff 100644 --- a/gcc/analyzer/infinite-loop.cc +++ b/gcc/analyzer/infinite-loop.cc @@ -229,7 +229,7 @@ public: /* Customize the location where the warning_event appears. */ void add_final_event (const state_machine *, const exploded_node *enode, - const gimple *, + const event_loc_info &, tree, state_machine::state_t, checker_path *emission_path) final override diff --git a/gcc/analyzer/infinite-recursion.cc b/gcc/analyzer/infinite-recursion.cc index 6103c2b564f..ef8ae90ab08 100644 --- a/gcc/analyzer/infinite-recursion.cc +++ b/gcc/analyzer/infinite-recursion.cc @@ -183,7 +183,7 @@ public: it at the topmost entrypoint to the function. */ void add_final_event (const state_machine *, const exploded_node *enode, - const gimple *, + const event_loc_info &, tree, state_machine::state_t, checker_path *emission_path) final override diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc index ff37ae6f7b4..b0637be179f 100644 --- a/gcc/analyzer/pending-diagnostic.cc +++ b/gcc/analyzer/pending-diagnostic.cc @@ -270,15 +270,13 @@ pending_diagnostic::add_region_creation_events (const region *reg, void pending_diagnostic::add_final_event (const state_machine *sm, const exploded_node *enode, - const gimple *stmt, + const event_loc_info &loc_info, tree var, state_machine::state_t state, checker_path *emission_path) { emission_path->add_event (make_unique - (event_loc_info (get_stmt_location (stmt, enode->get_function ()), - enode->get_function ()->decl, - enode->get_stack_depth ()), + (loc_info, enode, sm, var, state)); } diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h index 288410af71a..ee1f6204f2d 100644 --- a/gcc/analyzer/pending-diagnostic.h +++ b/gcc/analyzer/pending-diagnostic.h @@ -371,7 +371,7 @@ class pending_diagnostic of the called function. */ virtual void add_final_event (const state_machine *sm, const exploded_node *enode, - const gimple *stmt, + const event_loc_info &loc_info, tree var, state_machine::state_t state, checker_path *emission_path); diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index b094b2f7e43..8154d914e81 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -327,7 +327,7 @@ region_model_manager::get_or_create_initial_value (const region *reg, /* The initial value of a cast is a cast of the initial value. */ if (const cast_region *cast_reg = reg->dyn_cast_cast_region ()) { - const region *original_reg = cast_reg->get_original_region (); + const region *original_reg = cast_reg->get_parent_region (); return get_or_create_cast (cast_reg->get_type (), get_or_create_initial_value (original_reg)); } diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index e71c6ec693b..a25181f2a3e 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -841,6 +841,144 @@ private: tree m_count_cst; }; +/* A subclass of pending_diagnostic for complaining about pointer + subtractions involving unrelated buffers. */ + +class undefined_ptrdiff_diagnostic +: public pending_diagnostic_subclass +{ +public: + /* Region_creation_event subclass to give a custom wording when + talking about creation of buffers for LHS and RHS of the + subtraction. */ + class ptrdiff_region_creation_event : public region_creation_event + { + public: + ptrdiff_region_creation_event (const event_loc_info &loc_info, + bool is_lhs) + : region_creation_event (loc_info), + m_is_lhs (is_lhs) + { + } + + label_text get_desc (bool) const + { + if (m_is_lhs) + return label_text::borrow ("underlying object for left-hand side" + " of subtraction created here"); + else + return label_text::borrow ("underlying object for right-hand side" + " of subtraction created here"); + } + + private: + bool m_is_lhs; + }; + + undefined_ptrdiff_diagnostic (const gassign *assign, + const svalue *sval_a, + const svalue *sval_b, + const region *base_reg_a, + const region *base_reg_b) + : m_assign (assign), + m_sval_a (sval_a), + m_sval_b (sval_b), + m_base_reg_a (base_reg_a), + m_base_reg_b (base_reg_b) + { + gcc_assert (m_base_reg_a != m_base_reg_b); + } + + const char *get_kind () const final override + { + return "undefined_ptrdiff_diagnostic"; + } + + bool operator== (const undefined_ptrdiff_diagnostic &other) const + { + return (m_assign == other.m_assign + && m_sval_a == other.m_sval_a + && m_sval_b == other.m_sval_b + && m_base_reg_a == other.m_base_reg_a + && m_base_reg_b == other.m_base_reg_b); + } + + int get_controlling_option () const final override + { + return OPT_Wanalyzer_undefined_behavior_ptrdiff; + } + + bool emit (diagnostic_emission_context &ctxt) final override + { + /* CWE-469: Use of Pointer Subtraction to Determine Size. */ + ctxt.add_cwe (469); + return ctxt.warn ("undefined behavior when subtracting pointers"); + } + + void add_region_creation_events (const region *reg, + tree /*capacity*/, + const event_loc_info &loc_info, + checker_path &emission_path) final override + { + if (reg == m_base_reg_a) + emission_path.add_event + (make_unique (loc_info, true)); + else if (reg == m_base_reg_b) + emission_path.add_event + (make_unique (loc_info, false)); + } + + label_text describe_final_event (const evdesc::final_event &ev) final override + { + return ev.formatted_print + ("subtraction of pointers has undefined behavior if" + " they do not point into the same array object"); + } + + void mark_interesting_stuff (interesting_t *interesting) final override + { + interesting->add_region_creation (m_base_reg_a); + interesting->add_region_creation (m_base_reg_b); + } + +private: + const gassign *m_assign; + const svalue *m_sval_a; + const svalue *m_sval_b; + const region *m_base_reg_a; + const region *m_base_reg_b; +}; + +/* Check the pointer subtraction SVAL_A - SVAL_B at ASSIGN and add + a warning to CTXT if they're not within the same base region. */ + +static void +check_for_invalid_ptrdiff (const gassign *assign, + region_model_context &ctxt, + const svalue *sval_a, const svalue *sval_b) +{ + const region *base_reg_a = sval_a->maybe_get_deref_base_region (); + if (!base_reg_a) + return; + const region *base_reg_b = sval_b->maybe_get_deref_base_region (); + if (!base_reg_b) + return; + + if (base_reg_a == base_reg_b) + return; + + if (base_reg_a->get_kind () == RK_SYMBOLIC) + return; + if (base_reg_b->get_kind () == RK_SYMBOLIC) + return; + + ctxt.warn (make_unique (assign, + sval_a, + sval_b, + base_reg_a, + base_reg_b)); +} + /* If ASSIGN is a stmt that can be modelled via set_value (lhs_reg, SVALUE, CTXT) for some SVALUE, get the SVALUE. @@ -897,6 +1035,9 @@ region_model::get_gassign_result (const gassign *assign, // TODO: perhaps fold to zero if they're known to be equal? + if (ctxt) + check_for_invalid_ptrdiff (assign, *ctxt, rhs1_sval, rhs2_sval); + const svalue *sval_binop = m_mgr->get_or_create_binop (TREE_TYPE (lhs), op, rhs1_sval, rhs2_sval); @@ -2331,7 +2472,7 @@ region_model::on_longjmp (const gcall *longjmp_call, const gcall *setjmp_call, setjmp was called. */ gcc_assert (get_stack_depth () >= setjmp_stack_depth); while (get_stack_depth () > setjmp_stack_depth) - pop_frame (NULL, NULL, ctxt, false); + pop_frame (NULL, NULL, ctxt, nullptr, false); gcc_assert (get_stack_depth () == setjmp_stack_depth); @@ -2792,7 +2933,7 @@ region_model::get_store_value (const region *reg, /* Special-case: read the initial char of a STRING_CST. */ if (const cast_region *cast_reg = reg->dyn_cast_cast_region ()) if (const string_region *str_reg - = cast_reg->get_original_region ()->dyn_cast_string_region ()) + = cast_reg->get_parent_region ()->dyn_cast_string_region ()) { tree string_cst = str_reg->get_string_cst (); tree byte_offset_cst = integer_zero_node; @@ -5202,7 +5343,8 @@ region_model::eval_condition (tree lhs, path_var region_model::get_representative_path_var_1 (const svalue *sval, - svalue_set *visited) const + svalue_set *visited, + logger *logger) const { gcc_assert (sval); @@ -5219,7 +5361,8 @@ region_model::get_representative_path_var_1 (const svalue *sval, /* Handle casts by recursion into get_representative_path_var. */ if (const svalue *cast_sval = sval->maybe_undo_cast ()) { - path_var result = get_representative_path_var (cast_sval, visited); + path_var result = get_representative_path_var (cast_sval, visited, + logger); tree orig_type = sval->get_type (); /* If necessary, wrap the result in a cast. */ if (result.m_tree && orig_type) @@ -5228,7 +5371,7 @@ region_model::get_representative_path_var_1 (const svalue *sval, } auto_vec pvs; - m_store.get_representative_path_vars (this, visited, sval, &pvs); + m_store.get_representative_path_vars (this, visited, sval, logger, &pvs); if (tree cst = sval->maybe_get_constant ()) pvs.safe_push (path_var (cst, 0)); @@ -5237,7 +5380,7 @@ region_model::get_representative_path_var_1 (const svalue *sval, if (const region_svalue *ptr_sval = sval->dyn_cast_region_svalue ()) { const region *reg = ptr_sval->get_pointee (); - if (path_var pv = get_representative_path_var (reg, visited)) + if (path_var pv = get_representative_path_var (reg, visited, logger)) return path_var (build1 (ADDR_EXPR, sval->get_type (), pv.m_tree), @@ -5250,7 +5393,7 @@ region_model::get_representative_path_var_1 (const svalue *sval, const svalue *parent_sval = sub_sval->get_parent (); const region *subreg = sub_sval->get_subregion (); if (path_var parent_pv - = get_representative_path_var (parent_sval, visited)) + = get_representative_path_var (parent_sval, visited, logger)) if (const field_region *field_reg = subreg->dyn_cast_field_region ()) return path_var (build3 (COMPONENT_REF, sval->get_type (), @@ -5263,9 +5406,11 @@ region_model::get_representative_path_var_1 (const svalue *sval, /* Handle binops. */ if (const binop_svalue *binop_sval = sval->dyn_cast_binop_svalue ()) if (path_var lhs_pv - = get_representative_path_var (binop_sval->get_arg0 (), visited)) + = get_representative_path_var (binop_sval->get_arg0 (), visited, + logger)) if (path_var rhs_pv - = get_representative_path_var (binop_sval->get_arg1 (), visited)) + = get_representative_path_var (binop_sval->get_arg1 (), visited, + logger)) return path_var (build2 (binop_sval->get_op (), sval->get_type (), lhs_pv.m_tree, rhs_pv.m_tree), @@ -5288,19 +5433,42 @@ region_model::get_representative_path_var_1 (const svalue *sval, path_var region_model::get_representative_path_var (const svalue *sval, - svalue_set *visited) const + svalue_set *visited, + logger *logger) const { if (sval == NULL) return path_var (NULL_TREE, 0); + LOG_SCOPE (logger); + if (logger) + { + logger->start_log_line (); + logger->log_partial ("sval: "); + sval->dump_to_pp (logger->get_printer (), true); + logger->end_log_line (); + } + tree orig_type = sval->get_type (); - path_var result = get_representative_path_var_1 (sval, visited); + path_var result = get_representative_path_var_1 (sval, visited, logger); /* Verify that the result has the same type as SVAL, if any. */ if (result.m_tree && orig_type) gcc_assert (TREE_TYPE (result.m_tree) == orig_type); + if (logger) + { + logger->start_log_line (); + logger->log_partial ("sval: "); + sval->dump_to_pp (logger->get_printer (), true); + logger->end_log_line (); + + if (result.m_tree) + logger->log ("tree: %qE", result.m_tree); + else + logger->log ("tree: NULL"); + } + return result; } @@ -5311,10 +5479,10 @@ region_model::get_representative_path_var (const svalue *sval, from analyzer diagnostics. */ tree -region_model::get_representative_tree (const svalue *sval) const +region_model::get_representative_tree (const svalue *sval, logger *logger) const { svalue_set visited; - tree expr = get_representative_path_var (sval, &visited).m_tree; + tree expr = get_representative_path_var (sval, &visited, logger).m_tree; /* Strip off any top-level cast. */ if (expr && TREE_CODE (expr) == NOP_EXPR) @@ -5324,10 +5492,10 @@ region_model::get_representative_tree (const svalue *sval) const } tree -region_model::get_representative_tree (const region *reg) const +region_model::get_representative_tree (const region *reg, logger *logger) const { svalue_set visited; - tree expr = get_representative_path_var (reg, &visited).m_tree; + tree expr = get_representative_path_var (reg, &visited, logger).m_tree; /* Strip off any top-level cast. */ if (expr && TREE_CODE (expr) == NOP_EXPR) @@ -5347,7 +5515,8 @@ region_model::get_representative_tree (const region *reg) const path_var region_model::get_representative_path_var_1 (const region *reg, - svalue_set *visited) const + svalue_set *visited, + logger *logger) const { switch (reg->get_kind ()) { @@ -5381,7 +5550,8 @@ region_model::get_representative_path_var_1 (const region *reg, const symbolic_region *symbolic_reg = as_a (reg); const svalue *pointer = symbolic_reg->get_pointer (); - path_var pointer_pv = get_representative_path_var (pointer, visited); + path_var pointer_pv = get_representative_path_var (pointer, visited, + logger); if (!pointer_pv) return path_var (NULL_TREE, 0); tree offset = build_int_cst (pointer->get_type (), 0); @@ -5400,7 +5570,8 @@ region_model::get_representative_path_var_1 (const region *reg, { const field_region *field_reg = as_a (reg); path_var parent_pv - = get_representative_path_var (reg->get_parent_region (), visited); + = get_representative_path_var (reg->get_parent_region (), visited, + logger); if (!parent_pv) return path_var (NULL_TREE, 0); return path_var (build3 (COMPONENT_REF, @@ -5416,11 +5587,13 @@ region_model::get_representative_path_var_1 (const region *reg, const element_region *element_reg = as_a (reg); path_var parent_pv - = get_representative_path_var (reg->get_parent_region (), visited); + = get_representative_path_var (reg->get_parent_region (), visited, + logger); if (!parent_pv) return path_var (NULL_TREE, 0); path_var index_pv - = get_representative_path_var (element_reg->get_index (), visited); + = get_representative_path_var (element_reg->get_index (), visited, + logger); if (!index_pv) return path_var (NULL_TREE, 0); return path_var (build4 (ARRAY_REF, @@ -5435,12 +5608,13 @@ region_model::get_representative_path_var_1 (const region *reg, const offset_region *offset_reg = as_a (reg); path_var parent_pv - = get_representative_path_var (reg->get_parent_region (), visited); + = get_representative_path_var (reg->get_parent_region (), visited, + logger); if (!parent_pv) return path_var (NULL_TREE, 0); path_var offset_pv = get_representative_path_var (offset_reg->get_byte_offset (), - visited); + visited, logger); if (!offset_pv || TREE_CODE (offset_pv.m_tree) != INTEGER_CST) return path_var (NULL_TREE, 0); tree addr_parent = build1 (ADDR_EXPR, @@ -5459,7 +5633,8 @@ region_model::get_representative_path_var_1 (const region *reg, case RK_CAST: { path_var parent_pv - = get_representative_path_var (reg->get_parent_region (), visited); + = get_representative_path_var (reg->get_parent_region (), visited, + logger); if (!parent_pv) return path_var (NULL_TREE, 0); return path_var (build1 (NOP_EXPR, @@ -5500,14 +5675,37 @@ region_model::get_representative_path_var_1 (const region *reg, path_var region_model::get_representative_path_var (const region *reg, - svalue_set *visited) const + svalue_set *visited, + logger *logger) const { - path_var result = get_representative_path_var_1 (reg, visited); + LOG_SCOPE (logger); + if (logger) + { + logger->start_log_line (); + logger->log_partial ("reg: "); + reg->dump_to_pp (logger->get_printer (), true); + logger->end_log_line (); + } + + path_var result = get_representative_path_var_1 (reg, visited, logger); /* Verify that the result has the same type as REG, if any. */ if (result.m_tree && reg->get_type ()) gcc_assert (TREE_TYPE (result.m_tree) == reg->get_type ()); + if (logger) + { + logger->start_log_line (); + logger->log_partial ("reg: "); + reg->dump_to_pp (logger->get_printer (), true); + logger->end_log_line (); + + if (result.m_tree) + logger->log ("tree: %qE", result.m_tree); + else + logger->log ("tree: NULL"); + } + return result; } @@ -5673,7 +5871,7 @@ region_model::update_for_return_gcall (const gcall *call_stmt, so that pop_frame can determine the region with respect to the *caller* frame. */ tree lhs = gimple_call_lhs (call_stmt); - pop_frame (lhs, NULL, ctxt); + pop_frame (lhs, NULL, ctxt, call_stmt); } /* Extract calling information from the superedge and update the model for the @@ -6083,6 +6281,70 @@ region_model::get_current_function () const return &frame->get_function (); } +/* Custom region_model_context for the assignment to the result + at a call statement when popping a frame (PR analyzer/106203). */ + +class caller_context : public region_model_context_decorator +{ +public: + caller_context (region_model_context *inner, + const gcall *call_stmt, + const frame_region &caller_frame) + : region_model_context_decorator (inner), + m_call_stmt (call_stmt), + m_caller_frame (caller_frame) + {} + bool warn (std::unique_ptr d, + const stmt_finder *custom_finder) override + { + if (m_inner && custom_finder == nullptr) + { + /* Custom stmt_finder to use m_call_stmt for the + diagnostic. */ + class my_finder : public stmt_finder + { + public: + my_finder (const gcall *call_stmt, + const frame_region &caller_frame) + : m_call_stmt (call_stmt), + m_caller_frame (caller_frame) + {} + std::unique_ptr clone () const override + { + return ::make_unique (m_call_stmt, m_caller_frame); + } + const gimple *find_stmt (const exploded_path &) override + { + return m_call_stmt; + } + void update_event_loc_info (event_loc_info &loc_info) final override + { + loc_info.m_fndecl = m_caller_frame.get_fndecl (); + loc_info.m_depth = m_caller_frame.get_stack_depth (); + } + + private: + const gcall *m_call_stmt; + const frame_region &m_caller_frame; + }; + my_finder finder (m_call_stmt, m_caller_frame); + return m_inner->warn (std::move (d), &finder); + } + else + return region_model_context_decorator::warn (std::move (d), + custom_finder); + } + const gimple *get_stmt () const override + { + return m_call_stmt; + }; + +private: + const gcall *m_call_stmt; + const frame_region &m_caller_frame; +}; + + /* Pop the topmost frame_region from this region_model's stack; If RESULT_LVALUE is non-null, copy any return value from the frame @@ -6091,6 +6353,9 @@ region_model::get_current_function () const If OUT_RESULT is non-null, copy any return value from the frame into *OUT_RESULT. + If non-null, use CALL_STMT as the location when complaining about + assignment of the return value to RESULT_LVALUE. + If EVAL_RETURN_SVALUE is false, then don't evaluate the return value. This is for use when unwinding frames e.g. due to longjmp, to suppress erroneously reporting uninitialized return values. @@ -6103,6 +6368,7 @@ void region_model::pop_frame (tree result_lvalue, const svalue **out_result, region_model_context *ctxt, + const gcall *call_stmt, bool eval_return_svalue) { gcc_assert (m_current_frame); @@ -6137,7 +6403,13 @@ region_model::pop_frame (tree result_lvalue, /* Compute result_dst_reg using RESULT_LVALUE *after* popping the frame, but before poisoning pointers into the old frame. */ const region *result_dst_reg = get_lvalue (result_lvalue, ctxt); - set_value (result_dst_reg, retval, ctxt); + + /* Assign retval to result_dst_reg, using caller_context + to set the call_stmt and the popped_frame for any diagnostics + due to the assignment. */ + gcc_assert (m_current_frame); + caller_context caller_ctxt (ctxt, call_stmt, *m_current_frame); + set_value (result_dst_reg, retval, call_stmt ? &caller_ctxt : ctxt); } unbind_region_and_descendents (frame_reg,POISON_KIND_POPPED_STACK); @@ -8130,7 +8402,7 @@ test_stack_frames () ASSERT_FALSE (a_in_parent_reg->descendent_of_p (child_frame_reg)); /* Pop the "child_fn" frame from the stack. */ - model.pop_frame (NULL, NULL, &ctxt); + model.pop_frame (NULL, NULL, &ctxt, nullptr); ASSERT_FALSE (model.region_exists_p (child_frame_reg)); ASSERT_TRUE (model.region_exists_p (parent_frame_reg)); @@ -8207,7 +8479,8 @@ test_get_representative_path_var () { svalue_set visited; ASSERT_EQ (model.get_representative_path_var (parm_regs[depth], - &visited), + &visited, + nullptr), path_var (n, depth + 1)); } /* ...and that we can lookup lvalues for locals for all frames, @@ -8218,7 +8491,8 @@ test_get_representative_path_var () { svalue_set visited; ASSERT_EQ (model.get_representative_path_var (parm_svals[depth], - &visited), + &visited, + nullptr), path_var (n, depth + 1)); } } @@ -9243,7 +9517,7 @@ test_alloca () /* Verify that the pointers to the alloca region are replaced by poisoned values when the frame is popped. */ - model.pop_frame (NULL, NULL, &ctxt); + model.pop_frame (NULL, NULL, &ctxt, nullptr); ASSERT_EQ (model.get_rvalue (p, NULL)->get_kind (), SK_POISONED); } diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index 400d80b2568..912b558a18d 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -363,6 +363,7 @@ class region_model void pop_frame (tree result_lvalue, const svalue **out_result, region_model_context *ctxt, + const gcall *call_stmt, bool eval_return_svalue = true); int get_stack_depth () const; const frame_region *get_frame_at_index (int index) const; @@ -434,14 +435,18 @@ class region_model region_model_context *ctxt); void get_referenced_base_regions (auto_bitmap &out_ids) const; - tree get_representative_tree (const svalue *sval) const; - tree get_representative_tree (const region *reg) const; + tree get_representative_tree (const svalue *sval, + logger *logger = nullptr) const; + tree get_representative_tree (const region *reg, + logger *logger = nullptr) const; path_var get_representative_path_var (const svalue *sval, - svalue_set *visited) const; + svalue_set *visited, + logger *logger) const; path_var get_representative_path_var (const region *reg, - svalue_set *visited) const; + svalue_set *visited, + logger *logger) const; /* For selftests. */ constraint_manager *get_constraints () @@ -584,10 +589,12 @@ private: path_var get_representative_path_var_1 (const svalue *sval, - svalue_set *visited) const; + svalue_set *visited, + logger *logger) const; path_var get_representative_path_var_1 (const region *reg, - svalue_set *visited) const; + svalue_set *visited, + logger *logger) const; const known_function *get_known_function (tree fndecl, const call_details &cd) const; diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index 71bae97b6f1..1fc42f2cd97 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -425,10 +425,8 @@ region::get_base_region () const case RK_OFFSET: case RK_SIZED: case RK_BIT_RANGE: - iter = iter->get_parent_region (); - continue; case RK_CAST: - iter = iter->dyn_cast_cast_region ()->get_original_region (); + iter = iter->get_parent_region (); continue; default: return iter; @@ -468,10 +466,7 @@ region::descendent_of_p (const region *elder) const { if (iter == elder) return true; - if (iter->get_kind () == RK_CAST) - iter = iter->dyn_cast_cast_region ()->get_original_region (); - else - iter = iter->get_parent_region (); + iter = iter->get_parent_region (); } return false; } @@ -487,10 +482,7 @@ region::maybe_get_frame_region () const { if (const frame_region *frame_reg = iter->dyn_cast_frame_region ()) return frame_reg; - if (iter->get_kind () == RK_CAST) - iter = iter->dyn_cast_cast_region ()->get_original_region (); - else - iter = iter->get_parent_region (); + iter = iter->get_parent_region (); } return NULL; } @@ -525,10 +517,7 @@ region::get_memory_space () const case RK_PRIVATE: return MEMSPACE_PRIVATE; } - if (iter->get_kind () == RK_CAST) - iter = iter->dyn_cast_cast_region ()->get_original_region (); - else - iter = iter->get_parent_region (); + iter = iter->get_parent_region (); } return MEMSPACE_UNKNOWN; } @@ -958,15 +947,8 @@ region::calc_offset (region_model_manager *mgr) const } continue; case RK_SIZED: - iter_region = iter_region->get_parent_region (); - continue; - case RK_CAST: - { - const cast_region *cast_reg - = as_a (iter_region); - iter_region = cast_reg->get_original_region (); - } + iter_region = iter_region->get_parent_region (); continue; default: @@ -2276,15 +2258,6 @@ sized_region::get_bit_size_sval (region_model_manager *mgr) const /* class cast_region : public region. */ -/* Implementation of region::accept vfunc for cast_region. */ - -void -cast_region::accept (visitor *v) const -{ - region::accept (v); - m_original_region->accept (v); -} - /* Implementation of region::dump_to_pp vfunc for cast_region. */ void @@ -2295,13 +2268,13 @@ cast_region::dump_to_pp (pretty_printer *pp, bool simple) const pp_string (pp, "CAST_REG("); print_quoted_type (pp, get_type ()); pp_string (pp, ", "); - m_original_region->dump_to_pp (pp, simple); + get_parent_region ()->dump_to_pp (pp, simple); pp_string (pp, ")"); } else { pp_string (pp, "cast_region("); - m_original_region->dump_to_pp (pp, simple); + get_parent_region ()->dump_to_pp (pp, simple); pp_string (pp, ", "); print_quoted_type (pp, get_type ()); pp_printf (pp, ")"); @@ -2314,15 +2287,6 @@ cast_region::print_dump_widget_label (pretty_printer *pp) const pp_printf (pp, "cast_region"); } -void -cast_region:: -add_dump_widget_children (text_art::tree_widget &w, - const text_art::dump_widget_info &dwi) const -{ - w.add_child - (m_original_region->make_dump_widget (dwi, "m_original_region")); -} - /* Implementation of region::get_relative_concrete_offset vfunc for cast_region. */ diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h index 5d58abc2693..211dd3458c0 100644 --- a/gcc/analyzer/region.h +++ b/gcc/analyzer/region.h @@ -1170,65 +1170,54 @@ public: /* A support class for uniquifying instances of cast_region. */ struct key_t { - key_t (const region *original_region, tree type) - : m_original_region (original_region), m_type (type) + key_t (const region *parent, tree type) + : m_parent (parent), m_type (type) { - gcc_assert (original_region); + gcc_assert (parent); } hashval_t hash () const { inchash::hash hstate; - hstate.add_ptr (m_original_region); + hstate.add_ptr (m_parent); hstate.add_ptr (m_type); return hstate.end (); } bool operator== (const key_t &other) const { - return (m_original_region == other.m_original_region + return (m_parent == other.m_parent && m_type == other.m_type); } void mark_deleted () { - m_original_region = reinterpret_cast (1); + m_parent = reinterpret_cast (1); } - void mark_empty () { m_original_region = nullptr; } + void mark_empty () { m_parent = nullptr; } bool is_deleted () const { - return m_original_region == reinterpret_cast (1); + return m_parent == reinterpret_cast (1); } - bool is_empty () const { return m_original_region == nullptr; } + bool is_empty () const { return m_parent == nullptr; } - const region *m_original_region; + const region *m_parent; tree m_type; }; - cast_region (symbol::id_t id, const region *original_region, tree type) - : region (complexity (original_region), id, - original_region->get_parent_region (), type), - m_original_region (original_region) + cast_region (symbol::id_t id, const region *parent, tree type) + : region (complexity (parent), id, + parent, type) {} enum region_kind get_kind () const final override { return RK_CAST; } const cast_region * dyn_cast_cast_region () const final override { return this; } - void accept (visitor *v) const final override; void dump_to_pp (pretty_printer *pp, bool simple) const final override; void print_dump_widget_label (pretty_printer *pp) const final override; - void - add_dump_widget_children (text_art::tree_widget &, - const text_art::dump_widget_info &dwi) - const final override; bool get_relative_concrete_offset (bit_offset_t *out) const final override; - - const region *get_original_region () const { return m_original_region; } - -private: - const region *m_original_region; }; } // namespace ana diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc index bd85f0d5611..3bd050f9635 100644 --- a/gcc/analyzer/sm-taint.cc +++ b/gcc/analyzer/sm-taint.cc @@ -1625,14 +1625,6 @@ region_model::check_region_for_taint (const region *reg, } break; - case RK_CAST: - { - const cast_region *cast_reg - = as_a (iter_region); - iter_region = cast_reg->get_original_region (); - continue; - } - case RK_SIZED: { const sized_region *sized_reg diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index d14cfa329b8..d5c1a9f6aff 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -2281,6 +2281,7 @@ binding_cluster::get_representative_path_vars (const region_model *model, svalue_set *visited, const region *base_reg, const svalue *sval, + logger *logger, auto_vec *out_pvs) const { @@ -2308,7 +2309,8 @@ binding_cluster::get_representative_path_vars (const region_model *model, { if (path_var pv = model->get_representative_path_var (subregion, - visited)) + visited, + logger)) append_pathvar_with_type (pv, sval->get_type (), out_pvs); } } @@ -2317,7 +2319,8 @@ binding_cluster::get_representative_path_vars (const region_model *model, const symbolic_binding *skey = (const symbolic_binding *)key; if (path_var pv = model->get_representative_path_var (skey->get_region (), - visited)) + visited, + logger)) append_pathvar_with_type (pv, sval->get_type (), out_pvs); } } @@ -3282,6 +3285,7 @@ void store::get_representative_path_vars (const region_model *model, svalue_set *visited, const svalue *sval, + logger *logger, auto_vec *out_pvs) const { gcc_assert (sval); @@ -3293,6 +3297,7 @@ store::get_representative_path_vars (const region_model *model, const region *base_reg = (*iter).first; binding_cluster *cluster = (*iter).second; cluster->get_representative_path_vars (model, visited, base_reg, sval, + logger, out_pvs); } @@ -3300,7 +3305,8 @@ store::get_representative_path_vars (const region_model *model, { const region *reg = init_sval->get_region (); if (path_var pv = model->get_representative_path_var (reg, - visited)) + visited, + logger)) out_pvs->safe_push (pv); } } diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h index 9be9df72379..affb6e218a6 100644 --- a/gcc/analyzer/store.h +++ b/gcc/analyzer/store.h @@ -681,6 +681,7 @@ public: svalue_set *visited, const region *base_reg, const svalue *sval, + logger *logger, auto_vec *out_pvs) const; const svalue *maybe_get_simple_value (store_manager *mgr) const; @@ -806,6 +807,7 @@ public: void get_representative_path_vars (const region_model *model, svalue_set *visited, const svalue *sval, + logger *logger, auto_vec *out_pvs) const; cluster_map_t::iterator begin () const { return m_cluster_map.begin (); } diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 13f321b6be6..5b5307c67b8 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -3502,7 +3502,7 @@ expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode) return NULL_RTX; wide_int min, max; - value_range r; + int_range_max r; get_global_range_query ()->range_of_expr (r, bound); if (r.varying_p () || r.undefined_p ()) return NULL_RTX; @@ -3576,7 +3576,7 @@ determine_block_size (tree len, rtx len_rtx, if (TREE_CODE (len) == SSA_NAME) { - value_range r; + int_range_max r; tree tmin, tmax; get_global_range_query ()->range_of_expr (r, len); range_type = get_legacy_range (r, tmin, tmax); @@ -5929,13 +5929,6 @@ expand_builtin_trap (void) static void expand_builtin_unreachable (void) { - /* If the target wants a trap in place of the fall-through, use that. */ - if (targetm.unreachable_should_trap ()) - { - expand_builtin_trap (); - return; - } - /* Use gimple_build_builtin_unreachable or builtin_decl_unreachable to avoid this. */ gcc_checking_assert (!sanitize_flags_p (SANITIZE_UNREACHABLE)); @@ -10049,7 +10042,21 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode, tree ctype = build_complex_type (type); tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2, arg0, arg1); - tree tgt = save_expr (call); + tree tgt; + if (ovf_only) + { + tgt = call; + intres = NULL_TREE; + } + else + { + /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1, + as while the call itself is const, the REALPART_EXPR store is + certainly not. And in any case, we want just one call, + not multiple and trying to CSE them later. */ + TREE_SIDE_EFFECTS (call) = 1; + tgt = save_expr (call); + } intres = build1_loc (loc, REALPART_EXPR, type, tgt); ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt); ovfres = fold_convert_loc (loc, boolean_type_node, ovfres); @@ -10361,11 +10368,17 @@ fold_builtin_addc_subc (location_t loc, enum built_in_function fcode, tree ctype = build_complex_type (type); tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2, args[0], args[1]); + /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1, + as while the call itself is const, the REALPART_EXPR store is + certainly not. And in any case, we want just one call, + not multiple and trying to CSE them later. */ + TREE_SIDE_EFFECTS (call) = 1; tree tgt = save_expr (call); tree intres = build1_loc (loc, REALPART_EXPR, type, tgt); tree ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt); call = build_call_expr_internal_loc (loc, ifn, ctype, 2, intres, args[2]); + TREE_SIDE_EFFECTS (call) = 1; tgt = save_expr (call); intres = build1_loc (loc, REALPART_EXPR, type, tgt); tree ovfres2 = build1_loc (loc, IMAGPART_EXPR, type, tgt); diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index acc49065e70..2d75e6995ef 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,25 @@ +2024-06-05 Jakub Jelinek + Frederik Harwath + Sandra Loosemore + + * c-common.h (c_omp_find_generated_loop): Declare. + * c-gimplify.cc (c_genericize_control_stmt): Handle OMP_TILE and + OMP_UNROLL. + * c-omp.cc (c_finish_omp_for): Handle generated loops. + (c_omp_is_loop_iterator): Likewise. + (c_find_nested_loop_xform_r, c_omp_find_generated_loop): New + functions. + (c_omp_check_loop_iv): Handle generated loops. For now sorry + on mixing non-rectangular loop with generated loops. + (c_omp_check_loop_binding_exprs): For now sorry on mixing + imperfect loops with generated loops. + (c_omp_directives): Uncomment tile and unroll entries. + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_TILE and + PRAGMA_OMP_UNROLL, change PRAGMA_OMP__LAST_ to the latter. + (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_FULL and + PRAGMA_OMP_CLAUSE_PARTIAL. + * c-pragma.cc (omp_pragmas_simd): Add tile and unroll omp pragmas. + 2024-05-31 Qing Zhao * c-ubsan.cc (get_bound_from_access_with_size): New function. diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index c9eb352939c..f9b229aba7f 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -670,18 +670,6 @@ attribute_takes_identifier_p (const_tree attr_id) return targetm.attribute_takes_identifier_p (attr_id); } -/* Returns TRUE iff the attribute indicated by ATTR_ID needs its - arguments converted to string constants. */ - -bool -attribute_clang_form_p (const_tree attr_id) -{ - const struct attribute_spec *spec = lookup_attribute_spec (attr_id); - if (spec && !strcmp ("availability", spec->name)) - return true; - return false; -} - /* Verify that argument value POS at position ARGNO to attribute NAME applied to function FN (which is either a function declaration or function type) refers to a function parameter at position POS and the expected type diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 0bdb14b65c5..ae79912c89f 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1304,6 +1304,7 @@ extern void c_finish_omp_taskwait (location_t); extern void c_finish_omp_taskyield (location_t); extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree, tree, tree, tree, tree, bool); +extern int c_omp_find_generated_loop (tree &, int, walk_tree_lh); extern bool c_omp_check_loop_iv (tree, tree, walk_tree_lh); extern bool c_omp_check_loop_iv_exprs (location_t, enum tree_code, tree, int, tree, tree, tree, walk_tree_lh); @@ -1629,7 +1630,6 @@ extern void check_for_xor_used_as_pow (location_t lhs_loc, tree lhs_val, /* In c-attribs.cc. */ extern bool attribute_takes_identifier_p (const_tree); extern tree handle_deprecated_attribute (tree *, tree, tree, int, bool *); -extern bool attribute_clang_form_p (const_tree); extern tree handle_unused_attribute (tree *, tree, tree, int, bool *); extern tree handle_fallthrough_attribute (tree *, tree, tree, int, bool *); extern int parse_tm_stmt_attr (tree, int); diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc index 494da49791d..3e29766e092 100644 --- a/gcc/c-family/c-gimplify.cc +++ b/gcc/c-family/c-gimplify.cc @@ -529,6 +529,8 @@ c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data, case OMP_DISTRIBUTE: case OMP_LOOP: case OMP_TASKLOOP: + case OMP_TILE: + case OMP_UNROLL: case OACC_LOOP: genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh); break; diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc index d5cc6fa43a9..ff5ce2bf729 100644 --- a/gcc/c-family/c-lex.cc +++ b/gcc/c-family/c-lex.cc @@ -584,21 +584,6 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags, case CPP_NUMBER: { - /* If the user wants number-like entities to be returned as a raw - string, then don't try to classify them, which emits unwanted - diagnostics. */ - if (lex_flags & C_LEX_NUMBER_AS_STRING) - { - /* build_string adds a trailing NUL at [len]. */ - tree num_string = build_string (tok->val.str.len + 1, - (const char *) tok->val.str.text); - TREE_TYPE (num_string) = char_array_type_node; - *value = num_string; - /* We will effectively note this as CPP_N_INVALID, because we - made no checks here. */ - break; - } - const char *suffix = NULL; unsigned int flags = cpp_classify_number (parse_in, tok, &suffix, *loc); diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index c0e02aa422f..b5ce1466e5d 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -958,6 +958,19 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv, tree cond = TREE_VEC_ELT (condv, i); tree incr = TREE_VEC_ELT (incrv, i); + if (init == NULL_TREE) + { + gcc_assert (decl == NULL_TREE + && cond == NULL_TREE + && incr == NULL_TREE); + for (i++; i < TREE_VEC_LENGTH (declv); i++) + gcc_assert (TREE_VEC_ELT (declv, i) == NULL_TREE + && TREE_VEC_ELT (initv, i) == NULL_TREE + && TREE_VEC_ELT (condv, i) == NULL_TREE + && TREE_VEC_ELT (incrv, i) == NULL_TREE); + break; + } + elocus = locus; if (EXPR_HAS_LOCATION (init)) elocus = EXPR_LOCATION (init); @@ -1304,9 +1317,11 @@ static int c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d) { for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++) - if (decl == TREE_VEC_ELT (d->declv, i) - || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST - && decl == TREE_PURPOSE (TREE_VEC_ELT (d->declv, i)))) + if (TREE_VEC_ELT (d->declv, i) == NULL_TREE) + continue; + else if (decl == TREE_VEC_ELT (d->declv, i) + || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST + && decl == TREE_PURPOSE (TREE_VEC_ELT (d->declv, i)))) return i; else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST && TREE_CHAIN (TREE_VEC_ELT (d->declv, i)) @@ -1584,6 +1599,68 @@ c_omp_check_nonrect_loop_iv (tree *tp, struct c_omp_check_loop_iv_data *d, return ret; } +/* Callback for walk_tree to find nested loop transforming construct. */ + +static tree +c_find_nested_loop_xform_r (tree *tp, int *walk_subtrees, void *) +{ + *walk_subtrees = 0; + switch (TREE_CODE (*tp)) + { + case OMP_TILE: + case OMP_UNROLL: + return *tp; + case BIND_EXPR: + *walk_subtrees = 1; + break; + case STATEMENT_LIST: + *walk_subtrees = 1; + break; + case TRY_FINALLY_EXPR: + *walk_subtrees = 1; + break; + default: + break; + } + return NULL; +} + +/* Find Jth loop among generated loops of STMT. */ + +int +c_omp_find_generated_loop (tree &stmt, int j, walk_tree_lh lh) +{ + stmt = walk_tree_1 (&stmt, c_find_nested_loop_xform_r, + NULL, NULL, lh); + gcc_assert (stmt); + switch (TREE_CODE (stmt)) + { + case OMP_UNROLL: + gcc_assert (omp_find_clause (OMP_FOR_CLAUSES (stmt), + OMP_CLAUSE_PARTIAL)); + /* FALLTHRU */ + case OMP_TILE: + int k; + k = 0; + for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); ++i) + if (i == j) + { + if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE) + { + stmt = OMP_FOR_BODY (stmt); + return c_omp_find_generated_loop (stmt, k, lh); + } + else + return i; + } + else if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE) + ++k; + gcc_unreachable (); + default: + gcc_unreachable (); + } +} + /* Diagnose invalid references to loop iterators in lb, b and incr expressions. */ @@ -1592,7 +1669,7 @@ c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh) { hash_set pset; struct c_omp_check_loop_iv_data data; - int i; + int i, k = 0; data.declv = declv; data.fail = false; @@ -1602,13 +1679,24 @@ c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh) data.ppset = &pset; for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++) { + tree this_stmt = stmt; + int j = i; tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i); + if (init == NULL_TREE) + { + if (k == 0) + data.declv = copy_node (declv); + this_stmt = OMP_FOR_BODY (stmt); + j = c_omp_find_generated_loop (this_stmt, k++, lh); + init = TREE_VEC_ELT (OMP_FOR_INIT (this_stmt), j); + TREE_VEC_ELT (data.declv, i) = TREE_OPERAND (init, 0); + } gcc_assert (TREE_CODE (init) == MODIFY_EXPR); tree decl = TREE_OPERAND (init, 0); - tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i); + tree cond = TREE_VEC_ELT (OMP_FOR_COND (this_stmt), j); gcc_assert (COMPARISON_CLASS_P (cond)); gcc_assert (TREE_OPERAND (cond, 0) == decl); - tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i); + tree incr = TREE_VEC_ELT (OMP_FOR_INCR (this_stmt), j); data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1)); tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE; int kind = 0; @@ -1636,9 +1724,9 @@ c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh) expression then involves the subtraction and always refers to the original value. The C++ FE needs to warn on those earlier. */ - if (decl == TREE_VEC_ELT (declv, i) - || (TREE_CODE (TREE_VEC_ELT (declv, i)) == TREE_LIST - && decl == TREE_PURPOSE (TREE_VEC_ELT (declv, i)))) + if (decl == TREE_VEC_ELT (data.declv, i) + || (TREE_CODE (TREE_VEC_ELT (data.declv, i)) == TREE_LIST + && decl == TREE_PURPOSE (TREE_VEC_ELT (data.declv, i)))) { data.expr_loc = EXPR_LOCATION (cond); data.kind = kind | 1; @@ -1657,6 +1745,15 @@ c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh) " used in a single loop", vec_outer1, vec_outer2); data.fail = true; } + else if ((vec_outer1 || vec_outer2) && this_stmt != stmt) + { + location_t loc = data.expr_loc; + if (loc == UNKNOWN_LOCATION) + loc = data.stmt_loc; + sorry_at (loc, "non-rectangular loops from generated loops " + "unsupported"); + data.fail = true; + } if (vec_outer1 || vec_outer2) OMP_FOR_NON_RECTANGULAR (stmt) = 1; if (TREE_CODE (incr) == MODIFY_EXPR) @@ -1853,6 +1950,12 @@ c_omp_check_loop_binding_exprs (tree stmt, vec *orig_inits) for (int i = 1; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++) { tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i); + if (init == NULL_TREE) + { + sorry_at (loc, "imperfectly nested loop using generated loops"); + ok = false; + continue; + } tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i); tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i); gcc_assert (TREE_CODE (init) == MODIFY_EXPR); @@ -4268,14 +4371,14 @@ const struct c_omp_directive c_omp_directives[] = { C_OMP_DIR_STANDALONE, false }, { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD, C_OMP_DIR_STANDALONE, false }, - /* { "tile", nullptr, nullptr, PRAGMA_OMP_TILE, - C_OMP_DIR_CONSTRUCT, false }, */ + { "tile", nullptr, nullptr, PRAGMA_OMP_TILE, + C_OMP_DIR_CONSTRUCT, false }, { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS, C_OMP_DIR_CONSTRUCT, true }, { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE, - C_OMP_DIR_DECLARATIVE, false } - /* { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL, - C_OMP_DIR_CONSTRUCT, false }, */ + C_OMP_DIR_DECLARATIVE, false }, + { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL, + C_OMP_DIR_CONSTRUCT, false }, }; /* Find (non-combined/composite) OpenMP directive (if any) which starts diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc index d54d1e57d75..be3058dca63 100644 --- a/gcc/c-family/c-opts.cc +++ b/gcc/c-family/c-opts.cc @@ -1119,7 +1119,7 @@ c_common_post_options (const char **pfilename) if (flag_extern_tls_init) { - if (!SUPPORTS_WEAK) + if (!TARGET_SUPPORTS_ALIASES || !SUPPORTS_WEAK) { /* Lazy TLS initialization for a variable in another TU requires alias and weak reference support. */ diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc index 1237ee6e62b..25251c2b69f 100644 --- a/gcc/c-family/c-pragma.cc +++ b/gcc/c-family/c-pragma.cc @@ -1556,6 +1556,8 @@ static const struct omp_pragma_def omp_pragmas_simd[] = { { "target", PRAGMA_OMP_TARGET }, { "taskloop", PRAGMA_OMP_TASKLOOP }, { "teams", PRAGMA_OMP_TEAMS }, + { "tile", PRAGMA_OMP_TILE }, + { "unroll", PRAGMA_OMP_UNROLL }, }; void diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 95828547713..2ebde06c471 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -81,8 +81,10 @@ enum pragma_kind { PRAGMA_OMP_TASKYIELD, PRAGMA_OMP_THREADPRIVATE, PRAGMA_OMP_TEAMS, + PRAGMA_OMP_TILE, + PRAGMA_OMP_UNROLL, /* PRAGMA_OMP__LAST_ should be equal to the last PRAGMA_OMP_* code. */ - PRAGMA_OMP__LAST_ = PRAGMA_OMP_TEAMS, + PRAGMA_OMP__LAST_ = PRAGMA_OMP_UNROLL, PRAGMA_GCC_PCH_PREPROCESS, PRAGMA_IVDEP, @@ -119,6 +121,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, PRAGMA_OMP_CLAUSE_FOR, PRAGMA_OMP_CLAUSE_FROM, + PRAGMA_OMP_CLAUSE_FULL, PRAGMA_OMP_CLAUSE_GRAINSIZE, PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR, PRAGMA_OMP_CLAUSE_HINT, @@ -142,6 +145,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_ORDER, PRAGMA_OMP_CLAUSE_ORDERED, PRAGMA_OMP_CLAUSE_PARALLEL, + PRAGMA_OMP_CLAUSE_PARTIAL, PRAGMA_OMP_CLAUSE_PRIORITY, PRAGMA_OMP_CLAUSE_PRIVATE, PRAGMA_OMP_CLAUSE_PROC_BIND, @@ -276,9 +280,6 @@ extern void pragma_lex_discard_to_eol (); #define C_LEX_STRING_NO_JOIN 2 /* Do not concatenate strings nor translate them into execution character set. */ -#define C_LEX_NUMBER_AS_STRING 4 /* Do not classify a number, but - instead return it as a raw - string. */ /* This is not actually available to pragma parsers. It's merely a convenient location to declare this function for c-lex, after diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index fb2cf20af87..c91f4927dd9 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,45 @@ +2024-06-06 Jakub Jelinek + + PR c/114493 + * c-decl.cc (c_fixup_may_alias): New function. + (finish_struct): Call it if "may_alias" attribute is + specified. + +2024-06-05 Jakub Jelinek + Frederik Harwath + Sandra Loosemore + + * c-parser.cc (c_parser_skip_std_attribute_spec_seq): New function. + (check_omp_intervening_code): Reject imperfectly nested tile. + (c_parser_compound_statement_nostart): If want_nested_loop, use + c_parser_omp_next_tokens_can_be_canon_loop instead of just checking + for RID_FOR keyword. + (c_parser_omp_clause_name): Handle full and partial clause names. + (c_parser_omp_clause_allocate): Remove spurious semicolon. + (c_parser_omp_clause_full, c_parser_omp_clause_partial): New + functions. + (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FULL and + PRAGMA_OMP_CLAUSE_PARTIAL. + (c_parser_omp_next_tokens_can_be_canon_loop): New function. + (c_parser_omp_loop_nest): Parse C23 attributes. Handle tile/unroll + constructs. Use c_parser_omp_next_tokens_can_be_canon_loop instead + of just checking for RID_FOR keyword. Only add_stmt (body) if it is + non-NULL. + (c_parser_omp_for_loop): Rename tiling variable to oacc_tiling. For + OMP_CLAUSE_SIZES set collapse to list length of OMP_CLAUSE_SIZES_LIST. + Use c_parser_omp_next_tokens_can_be_canon_loop instead of just + checking for RID_FOR keyword. Remove spurious semicolon. Don't call + c_omp_check_loop_binding_exprs if stmt is NULL. Skip generated loops. + (c_parser_omp_tile_sizes, c_parser_omp_tile): New functions. + (OMP_UNROLL_CLAUSE_MASK): Define. + (c_parser_omp_unroll): New function. + (c_parser_omp_construct): Handle PRAGMA_OMP_TILE and + PRAGMA_OMP_UNROLL. + * c-typeck.cc (c_finish_omp_clauses): Adjust wording of some of the + conflicting clause diagnostic messages to include word clause. + Handle OMP_CLAUSE_{FULL,PARTIAL,SIZES} and diagnose full vs. partial + conflict. + 2024-05-31 Qing Zhao * c-typeck.cc (build_access_with_size_for_counted_by): Add the 6th diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 64924b87a91..6c09eb73128 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -9446,6 +9446,17 @@ verify_counted_by_attribute (tree struct_type, tree field_decl) return; } +/* TYPE is a struct or union that we're applying may_alias to after the body is + parsed. Fixup any POINTER_TO types. */ + +static void +c_fixup_may_alias (tree type) +{ + for (tree t = TYPE_POINTER_TO (type); t; t = TYPE_NEXT_PTR_TO (t)) + for (tree v = TYPE_MAIN_VARIANT (t); v; v = TYPE_NEXT_VARIANT (v)) + TYPE_REF_CAN_ALIAS_ALL (v) = true; +} + /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. LOC is the location of the RECORD_TYPE or UNION_TYPE's definition. FIELDLIST is a chain of FIELD_DECL nodes for the fields. @@ -9791,6 +9802,10 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, C_TYPE_BEING_DEFINED (t) = 0; + if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (t))) + for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x)) + c_fixup_may_alias (x); + /* Set type canonical based on equivalence class. */ if (flag_isoc23 && !C_TYPE_VARIABLE_SIZE (t)) { diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 0d265869627..0c5018134cc 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -217,9 +217,6 @@ struct GTY(()) c_parser { should translate them to the execution character set (false inside attributes). */ BOOL_BITFIELD translate_strings_p : 1; - /* True if we want to lex arbitrary number-like sequences as their - string representation. */ - BOOL_BITFIELD lex_number_as_string : 1; /* Objective-C specific parser/lexer information. */ @@ -311,10 +308,10 @@ c_lex_one_token (c_parser *parser, c_token *token, bool raw = false) if (raw || vec_safe_length (parser->raw_tokens) == 0) { - int lex_flags = parser->lex_joined_string ? 0 : C_LEX_STRING_NO_JOIN; - lex_flags |= parser->lex_number_as_string ? C_LEX_NUMBER_AS_STRING : 0; token->type = c_lex_with_flags (&token->value, &token->location, - &token->flags, lex_flags); + &token->flags, + (parser->lex_joined_string + ? 0 : C_LEX_STRING_NO_JOIN)); token->id_kind = C_ID_NONE; token->keyword = RID_MAX; token->pragma_kind = PRAGMA_NONE; @@ -1714,6 +1711,8 @@ static void c_parser_omp_threadprivate (c_parser *); static void c_parser_omp_barrier (c_parser *); static void c_parser_omp_depobj (c_parser *); static void c_parser_omp_flush (c_parser *); +static bool c_parser_omp_next_tokens_can_be_canon_loop (c_parser *, + enum tree_code, bool); static tree c_parser_omp_loop_nest (c_parser *, bool *); static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code, tree, tree *, bool *); @@ -5216,88 +5215,6 @@ c_parser_gnu_attribute_any_word (c_parser *parser) return attr_name; } -/* Handle parsing clang-form attribute arguments, where we need to adjust - the parsing rules to relate to a specific attribute. */ - -static tree -c_parser_clang_attribute_arguments (c_parser *parser, tree /*attr_id*/) -{ - /* We can, if required, alter the parsing on the basis of the attribute. - At present, we handle the availability attr, where ach entry can be : - identifier - identifier=N.MM.Z - identifier="string" - followed by ',' or ) for the last entry*/ - - tree attr_args = NULL_TREE; - do - { - tree name = NULL_TREE; - tree value = NULL_TREE; - - if (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_token (parser)->id_kind == C_ID_ID) - { - name = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - } - else if (c_parser_next_token_is (parser, CPP_COMMA)) - name = error_mark_node; /* Comma handled below. */ - else - { - bool saved_join_state = parser->lex_joined_string; - parser->lex_number_as_string = 1; - parser->lex_joined_string = 1; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected an attribute keyword"); - parser->lex_number_as_string = 0; - parser->lex_joined_string = saved_join_state; - return error_mark_node; - } - if (c_parser_next_token_is (parser, CPP_EQ)) - { - c_parser_consume_token (parser); /* eat the '=' */ - /* We need to bludgeon the lexer into not trying to interpret the - xx.yy.zz form, since that just looks like a malformed float. - Also, as a result of macro processing, we can have strig literals - that are in multiple pieces so, for this specific part of the - parse, we need to join strings. */ - bool saved_join_state = parser->lex_joined_string; - parser->lex_number_as_string = 1; - parser->lex_joined_string = 1; - /* So look at the next token, expecting a string, or something that - looks initially like a number, but might be a version number. */ - c_parser_peek_token (parser); - /* Done with the funky number parsing. */ - parser->lex_number_as_string = 0; - parser->lex_joined_string = saved_join_state; - if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN) - && c_parser_next_token_is_not (parser, CPP_COMMA)) - { - value = c_parser_peek_token (parser)->value; - /* ???: check for error mark and early-return? */ - c_parser_consume_token (parser); - } - /* else value is absent. */ - } - else if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN) - && c_parser_next_token_is_not (parser, CPP_COMMA)) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<,%> or %<=%>"); - return error_mark_node; - } - if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); /* Just skip the comma. */ - tree t = tree_cons (value, name, NULL); - if (!attr_args) - attr_args = t; - else - chainon (attr_args, t); - } while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)); - return attr_args; -} - /* Parse attribute arguments. This is a common form of syntax covering all currently valid GNU and standard attributes. @@ -5463,13 +5380,9 @@ c_parser_gnu_attribute (c_parser *parser, tree attrs, attrs = chainon (attrs, attr); return attrs; } - c_parser_consume_token (parser); /* The '('. */ + c_parser_consume_token (parser); - tree attr_args; - if (attribute_clang_form_p (attr_name)) - attr_args = c_parser_clang_attribute_arguments (parser, attr_name); - else - attr_args + tree attr_args = c_parser_attribute_arguments (parser, attribute_takes_identifier_p (attr_name), false, @@ -6081,6 +5994,37 @@ c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n) return token->type == CPP_CLOSE_SQUARE; } +/* Skip standard attribute tokens starting at Nth token (with 1 as the + next token), return index of the first token after the standard + attribute tokens, or N on failure. */ + +static size_t +c_parser_skip_std_attribute_spec_seq (c_parser *parser, size_t n) +{ + size_t orig_n = n; + while (true) + { + if (c_parser_peek_nth_token_raw (parser, n)->type == CPP_OPEN_SQUARE + && (c_parser_peek_nth_token_raw (parser, n + 1)->type + == CPP_OPEN_SQUARE)) + { + unsigned int m = n + 2; + if (!c_parser_check_balanced_raw_token_sequence (parser, &m)) + return orig_n; + c_token *token = c_parser_peek_nth_token_raw (parser, m); + if (token->type != CPP_CLOSE_SQUARE) + return orig_n; + token = c_parser_peek_nth_token_raw (parser, m + 1); + if (token->type != CPP_CLOSE_SQUARE) + return orig_n; + n = m + 2; + } + else + break; + } + return n; +} + static tree c_parser_std_attribute_specifier_sequence (c_parser *parser) { @@ -6669,7 +6613,13 @@ check_omp_intervening_code (c_parser *parser) "% % clause"); omp_for_parse_state->perfect_nesting_fail = true; } - /* TODO: Also reject loops with TILE directive. */ + else if (omp_for_parse_state->code == OMP_TILE) + { + error_at (omp_for_parse_state->for_loc, + "inner loops must be perfectly nested in " + "%"); + omp_for_parse_state->perfect_nesting_fail = true; + } if (omp_for_parse_state->perfect_nesting_fail) omp_for_parse_state->fail = true; } @@ -7119,8 +7069,10 @@ c_parser_compound_statement_nostart (c_parser *parser) __extension__ before the nested statement. */ if (in_omp_loop_block && !last_label) { + tree_code code = omp_for_parse_state->code; if (want_nested_loop - && c_parser_next_token_is_keyword (parser, RID_FOR)) + && c_parser_omp_next_tokens_can_be_canon_loop (parser, code, + false)) { /* Found the next nested loop. If there were intervening code statements collected before now, wrap them in an @@ -15021,6 +14973,8 @@ c_parser_omp_clause_name (c_parser *parser) result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; else if (!strcmp ("from", p)) result = PRAGMA_OMP_CLAUSE_FROM; + else if (!strcmp ("full", p)) + result = PRAGMA_OMP_CLAUSE_FULL; break; case 'g': if (!strcmp ("gang", p)) @@ -15097,6 +15051,8 @@ c_parser_omp_clause_name (c_parser *parser) case 'p': if (!strcmp ("parallel", p)) result = PRAGMA_OMP_CLAUSE_PARALLEL; + else if (!strcmp ("partial", p)) + result = PRAGMA_OMP_CLAUSE_PARTIAL; else if (!strcmp ("present", p)) result = PRAGMA_OACC_CLAUSE_PRESENT; /* As of OpenACC 2.5, these are now aliases of the non-present_or @@ -18021,7 +17977,7 @@ c_parser_omp_clause_allocate (c_parser *parser, tree list) if (has_modifiers) { c_parser_consume_token (parser); - matching_parens parens2;; + matching_parens parens2; parens2.require_open (parser); location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expr_no_commas (parser, NULL); @@ -19285,6 +19241,61 @@ c_parser_omp_clause_uniform (c_parser *parser, tree list) return list; } +/* OpenMP 5.1 + full */ + +static tree +c_parser_omp_clause_full (c_parser *parser, tree list) +{ + check_no_duplicate_clause (list, OMP_CLAUSE_FULL, "full"); + + location_t loc = c_parser_peek_token (parser)->location; + tree c = build_omp_clause (loc, OMP_CLAUSE_FULL); + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + +/* OpenMP 5.1 + partial ( constant-expression ) */ + +static tree +c_parser_omp_clause_partial (c_parser *parser, tree list) +{ + tree num = NULL_TREE; + location_t loc = c_parser_peek_token (parser)->location; + + check_no_duplicate_clause (list, OMP_CLAUSE_PARTIAL, "partial"); + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + matching_parens parens; + parens.consume_open (parser); + num = c_parser_expr_no_commas (parser, NULL).value; + parens.skip_until_found_close (parser); + + if (num == error_mark_node) + return list; + + mark_exp_read (num); + num = c_fully_fold (num, false, NULL); + HOST_WIDE_INT n; + if (!INTEGRAL_TYPE_P (TREE_TYPE (num)) + || !tree_fits_shwi_p (num) + || (n = tree_to_shwi (num)) <= 0 + || (int) n != n) + { + error_at (loc, "% argument needs positive constant " + "integer expression"); + return list; + } + } + + tree c = build_omp_clause (loc, OMP_CLAUSE_PARTIAL); + OMP_CLAUSE_PARTIAL_EXPR (c) = num; + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + /* OpenMP 5.0: detach ( event-handle ) */ @@ -19896,6 +19907,14 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, clauses); c_name = "enter"; break; + case PRAGMA_OMP_CLAUSE_FULL: + c_name = "full"; + clauses = c_parser_omp_clause_full (parser, clauses); + break; + case PRAGMA_OMP_CLAUSE_PARTIAL: + c_name = "partial"; + clauses = c_parser_omp_clause_partial (parser, clauses); + break; default: c_parser_error (parser, "expected an OpenMP clause"); goto saw_error; @@ -22312,6 +22331,56 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed) } +/* Check if the next tokens can start a canonical loop. Return true if yes, + otherwise diagnose an error if ERROR_P is true, and return false. */ +static bool +c_parser_omp_next_tokens_can_be_canon_loop (c_parser *parser, + enum tree_code code, + bool error_p) +{ + if (code == OACC_LOOP) + { + if (c_parser_next_token_is_keyword (parser, RID_FOR)) + return true; + if (error_p) + c_parser_error (parser, "for statement expected"); + } + else + { + if (c_parser_next_token_is_keyword (parser, RID_FOR)) + return true; + + if (c_parser_next_token_is (parser, CPP_PRAGMA)) + switch (c_parser_peek_token (parser)->pragma_kind) + { + case PRAGMA_OMP_UNROLL: + case PRAGMA_OMP_TILE: + return true; + default: + break; + } + + /* Skip standard attributes on next for in case they are + [[omp::directive (unroll partial (4))]] or + [[omp::directive (tile sizes (1, 2, 3))]] etc. */ + size_t n = c_parser_skip_std_attribute_spec_seq (parser, 1); + c_token *token = c_parser_peek_nth_token_raw (parser, n); + /* TOKEN is a raw token that hasn't been converted to a keyword yet, + we have to do the lookup explicitly. */ + if (token->type == CPP_NAME + && C_IS_RESERVED_WORD (token->value) + && C_RID_CODE (token->value) == RID_FOR) + return true; + if (error_p) + c_parser_error (parser, "loop nest expected"); + } + + return false; +} + +static tree c_parser_omp_tile (location_t, c_parser *, bool *); +static tree c_parser_omp_unroll (location_t, c_parser *, bool *); + /* This function parses a single level of a loop nest, invoking itself recursively if necessary. @@ -22347,8 +22416,107 @@ c_parser_omp_loop_nest (c_parser *parser, bool *if_p) gcc_assert (omp_for_parse_state); int depth = omp_for_parse_state->depth; - /* We have already matched the FOR token but not consumed it yet. */ + /* Arrange for C23 standard attribute syntax to be parsed as regular + pragmas. */ + if (c_parser_nth_token_starts_std_attributes (parser, 1)) + { + tree std_attrs = c_parser_std_attribute_specifier_sequence (parser); + c_parser_handle_statement_omp_attributes (parser, std_attrs, NULL); + if (std_attrs) + error_at (c_parser_peek_token (parser)->location, + "attributes other than OpenMP directives " + "are not allowed on % in loop nest"); + } + loc = c_parser_peek_token (parser)->location; + + /* Handle loop transformations first. */ + if (c_parser_next_token_is (parser, CPP_PRAGMA)) + { + tree transform = NULL_TREE, sizes, body = NULL_TREE; + int count = 0; + switch (c_parser_peek_token (parser)->pragma_kind) + { + case PRAGMA_OMP_UNROLL: + c_parser_consume_pragma (parser); + body = push_stmt_list (); + transform = c_parser_omp_unroll (loc, parser, if_p); + body = pop_stmt_list (body); + if (transform == NULL_TREE || transform == error_mark_node) + { + transform = error_mark_node; + break; + } + gcc_assert (TREE_CODE (transform) == OMP_UNROLL); + if (omp_find_clause (OMP_FOR_CLAUSES (transform), + OMP_CLAUSE_PARTIAL)) + { + if (omp_for_parse_state->count - depth > 1) + { + error_at (loc, "% construct with % " + "clause generates just one loop with " + "canonical form but %d loops are needed", + omp_for_parse_state->count - depth); + transform = error_mark_node; + } + else + count = 1; + } + else + { + error_at (loc, "generated loop of % construct " + "without % clause does not have " + "canonical form"); + transform = error_mark_node; + } + break; + case PRAGMA_OMP_TILE: + c_parser_consume_pragma (parser); + body = push_stmt_list (); + transform = c_parser_omp_tile (loc, parser, if_p); + body = pop_stmt_list (body); + if (transform == NULL_TREE || transform == error_mark_node) + { + transform = error_mark_node; + break; + } + gcc_assert (TREE_CODE (transform) == OMP_TILE); + sizes = omp_find_clause (OMP_FOR_CLAUSES (transform), + OMP_CLAUSE_SIZES); + gcc_assert (sizes); + count = list_length (OMP_CLAUSE_SIZES_LIST (sizes)); + if (depth + count < omp_for_parse_state->count) + { + error_at (loc, "% construct generates %d loops " + "with canonical form but %d loops are needed", + count, omp_for_parse_state->count - depth); + transform = error_mark_node; + } + break; + default: + c_parser_pragma (parser, pragma_stmt, NULL); + break; + } + if (transform == NULL_TREE) + error_at (loc, "expected % loop or OpenMP loop " + "transformation construct"); + if (transform == NULL_TREE || transform == error_mark_node) + { + omp_for_parse_state->fail = true; + return NULL_TREE; + } + for (count = omp_for_parse_state->count; depth < count; ++depth) + { + TREE_VEC_ELT (omp_for_parse_state->declv, depth) = NULL_TREE; + TREE_VEC_ELT (omp_for_parse_state->initv, depth) = NULL_TREE; + TREE_VEC_ELT (omp_for_parse_state->condv, depth) = NULL_TREE; + TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = NULL_TREE; + } + omp_for_parse_state->want_nested_loop = false; + return body; + } + + /* We have already matched the FOR token but not consumed it yet. */ gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR)); c_parser_consume_token (parser); @@ -22481,7 +22649,10 @@ c_parser_omp_loop_nest (c_parser *parser, bool *if_p) parse_next: moreloops = depth < omp_for_parse_state->count - 1; omp_for_parse_state->want_nested_loop = moreloops; - if (moreloops && c_parser_next_token_is_keyword (parser, RID_FOR)) + if (moreloops + && c_parser_omp_next_tokens_can_be_canon_loop (parser, + omp_for_parse_state->code, + false)) { omp_for_parse_state->depth++; body = c_parser_omp_loop_nest (parser, if_p); @@ -22544,7 +22715,8 @@ parse_next: OMP_FOR. That keeps the gimplifier happy later on, and meanwhile we have already resolved all references to the iteration variable in its true scope. */ - add_stmt (body); + if (body) + add_stmt (body); body = c_end_compound_stmt (loc, loop_scope, true); if (decl && TREE_CODE (body) == BIND_EXPR) { @@ -22593,7 +22765,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, tree ret = NULL_TREE; tree ordered_cl = NULL_TREE; int i, collapse = 1, ordered = 0, count; - bool tiling = false; + bool oacc_tiling = false; bool inscan = false; struct omp_for_parse_data data; struct omp_for_parse_data *save_data = parser->omp_for_parse_state; @@ -22603,9 +22775,11 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl)); else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE) { - tiling = true; + oacc_tiling = true; collapse = list_length (OMP_CLAUSE_TILE_LIST (cl)); } + else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_SIZES) + collapse = list_length (OMP_CLAUSE_SIZES_LIST (cl)); else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED && OMP_CLAUSE_ORDERED_EXPR (cl)) { @@ -22626,21 +22800,18 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, ordered = collapse; } - gcc_assert (tiling || (collapse >= 1 && ordered >= 0)); + gcc_assert (oacc_tiling || (collapse >= 1 && ordered >= 0)); count = ordered ? ordered : collapse; - if (!c_parser_next_token_is_keyword (parser, RID_FOR)) - { - c_parser_error (parser, "for statement expected"); - return NULL; - } + if (!c_parser_omp_next_tokens_can_be_canon_loop (parser, code, true)) + return NULL; /* Initialize parse state for recursive descent. */ data.declv = make_tree_vec (count); data.initv = make_tree_vec (count); data.condv = make_tree_vec (count); data.incrv = make_tree_vec (count); - data.pre_body = NULL_TREE;; + data.pre_body = NULL_TREE; data.bindings = NULL_TREE; data.for_loc = c_parser_peek_token (parser)->location; data.count = count; @@ -22684,6 +22855,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, /* Check for errors involving lb/ub/incr expressions referencing variables declared in intervening code. */ if (data.saw_intervening_code + && stmt && !c_omp_check_loop_binding_exprs (stmt, NULL)) stmt = NULL_TREE; @@ -22694,6 +22866,8 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++) { tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i); + if (init == NULL_TREE) + break; gcc_assert (TREE_CODE (init) == MODIFY_EXPR); tree decl = TREE_OPERAND (init, 0); tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i); @@ -26213,6 +26387,119 @@ c_parser_omp_taskloop (location_t loc, c_parser *parser, return ret; } +/* OpenMP 5.1: Parse sizes list for "omp tile sizes" + sizes ( size-expr-list ) */ +static tree +c_parser_omp_tile_sizes (c_parser *parser, location_t loc) +{ + tree sizes = NULL_TREE; + + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + + c_token *tok = c_parser_peek_token (parser); + if (tok->type != CPP_NAME + || strcmp ("sizes", IDENTIFIER_POINTER (tok->value))) + { + c_parser_error (parser, "expected %"); + return error_mark_node; + } + c_parser_consume_token (parser); + + matching_parens parens; + if (!parens.require_open (parser)) + return error_mark_node; + + do + { + if (sizes && !c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + return error_mark_node; + + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr cexpr = c_parser_expr_no_commas (parser, NULL); + cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true); + tree expr = cexpr.value; + + if (expr == error_mark_node) + { + parens.skip_until_found_close (parser); + return error_mark_node; + } + + expr = c_fully_fold (expr, false, NULL); + + HOST_WIDE_INT n; + if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)) + || !tree_fits_shwi_p (expr) + || (n = tree_to_shwi (expr)) <= 0 + || (int) n != n) + { + c_parser_error (parser, "% argument needs positive" + " integral constant"); + expr = integer_one_node; + } + + sizes = tree_cons (NULL_TREE, expr, sizes); + } + while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)); + parens.require_close (parser); + + gcc_assert (sizes); + tree c = build_omp_clause (loc, OMP_CLAUSE_SIZES); + OMP_CLAUSE_SIZES_LIST (c) = nreverse (sizes); + + return c; +} + +/* OpenMP 5.1: + #pragma omp tile sizes ( size-expr-list ) new-line + for-loop + + LOC is the location of the #pragma token. */ + +static tree +c_parser_omp_tile (location_t loc, c_parser *parser, bool *if_p) +{ + tree clauses = c_parser_omp_tile_sizes (parser, loc); + c_parser_skip_to_pragma_eol (parser); + + if (!clauses || clauses == error_mark_node) + return error_mark_node; + + tree block = c_begin_compound_stmt (true); + tree ret = c_parser_omp_for_loop (loc, parser, OMP_TILE, clauses, + NULL, if_p); + block = c_end_compound_stmt (loc, block, true); + add_stmt (block); + + return ret; +} + +#define OMP_UNROLL_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARTIAL) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FULL)) + +/* OpenMP 5.1 + #pragma omp unroll unroll-clause[optseq] new-line + for-loop + + LOC is the location of the #pragma token. */ + +static tree +c_parser_omp_unroll (location_t loc, c_parser *parser, bool *if_p) +{ + tree clauses = c_parser_omp_all_clauses (parser, OMP_UNROLL_CLAUSE_MASK, + "#pragma omp unroll", true); + + tree block = c_begin_compound_stmt (true); + tree ret = c_parser_omp_for_loop (loc, parser, OMP_UNROLL, clauses, + NULL, if_p); + block = c_end_compound_stmt (loc, block, true); + add_stmt (block); + + return ret; +} + /* OpenMP 5.1 #pragma omp nothing new-line */ @@ -26694,6 +26981,12 @@ c_parser_omp_construct (c_parser *parser, bool *if_p) case PRAGMA_OMP_ASSUME: c_parser_omp_assume (parser, if_p); return; + case PRAGMA_OMP_TILE: + stmt = c_parser_omp_tile (loc, parser, if_p); + break; + case PRAGMA_OMP_UNROLL: + stmt = c_parser_omp_unroll (loc, parser, if_p); + break; default: gcc_unreachable (); } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index a0e7dbe1b48..a5ca9ea7db6 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -14984,6 +14984,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) bool allocate_seen = false; bool implicit_moved = false; bool target_in_reduction_seen = false; + tree *full_seen = NULL; + bool partial_seen = false; bool openacc = (ort & C_ORT_ACC) != 0; bitmap_obstack_initialize (NULL); @@ -15298,7 +15300,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { error_at (OMP_CLAUSE_LOCATION (*nowait_clause), "% clause must not be used together " - "with %"); + "with % clause"); *nowait_clause = OMP_CLAUSE_CHAIN (*nowait_clause); nowait_clause = NULL; } @@ -16210,7 +16212,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { error_at (OMP_CLAUSE_LOCATION (c), "% clause must not be used together " - "with %"); + "with % clause"); remove = true; break; } @@ -16223,7 +16225,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { error_at (OMP_CLAUSE_LOCATION (c), "% clause must not be used together " - "with %"); + "with % clause"); remove = true; break; } @@ -16326,7 +16328,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { error_at (OMP_CLAUSE_LOCATION (*order_clause), "% clause must not be used together " - "with %"); + "with % clause"); *order_clause = OMP_CLAUSE_CHAIN (*order_clause); order_clause = NULL; } @@ -16342,6 +16344,20 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_FULL: + full_seen = pc; + pc = &OMP_CLAUSE_CHAIN (c); + continue; + + case OMP_CLAUSE_PARTIAL: + partial_seen = true; + pc = &OMP_CLAUSE_CHAIN (c); + continue; + + case OMP_CLAUSE_SIZES: + pc = &OMP_CLAUSE_CHAIN (c); + continue; + case OMP_CLAUSE_INBRANCH: case OMP_CLAUSE_NOTINBRANCH: if (branch_seen) @@ -16598,6 +16614,14 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) *grainsize_seen = OMP_CLAUSE_CHAIN (*grainsize_seen); } + if (full_seen && partial_seen) + { + error_at (OMP_CLAUSE_LOCATION (*full_seen), + "% clause must not be used together with " + "% clause"); + *full_seen = OMP_CLAUSE_CHAIN (*full_seen); + } + if (detach_seen) { if (mergeable_seen) diff --git a/gcc/calls.cc b/gcc/calls.cc index d84998668a4..21d78f9779f 100644 --- a/gcc/calls.cc +++ b/gcc/calls.cc @@ -1376,8 +1376,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, with those made by function.cc. */ /* See if this argument should be passed by invisible reference. */ - function_arg_info arg (type, argpos < n_named_args, - argpos == n_named_args - 1); + function_arg_info arg (type, argpos < n_named_args); if (pass_by_reference (args_so_far_pnt, arg)) { const bool callee_copies @@ -1497,13 +1496,10 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, unsignedp = TYPE_UNSIGNED (type); arg.type = type; - arg.mode = TYPE_MODE (type); -// arg.mode -// = promote_function_mode (type, TYPE_MODE (type), &unsignedp, -// fndecl ? TREE_TYPE (fndecl) : fntype, 0); - arg.mode = promote_function_mode (args_so_far, arg, - fndecl ? TREE_TYPE (fndecl) : fntype, - &unsignedp, 0); + arg.mode + = promote_function_mode (type, TYPE_MODE (type), &unsignedp, + fndecl ? TREE_TYPE (fndecl) : fntype, 0); + args[i].unsignedp = unsignedp; args[i].mode = arg.mode; @@ -1553,7 +1549,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, #endif reg_parm_stack_space, args[i].pass_on_stack ? 0 : args[i].partial, - args_so_far, fndecl, args_size, &args[i].locate); #ifdef BLOCK_REG_PADDING else @@ -4101,7 +4096,6 @@ split_complex_types (tree types) return types; } -extern void debug_tree (tree); /* Output a library call to function ORGFUN (a SYMBOL_REF rtx) for a value of mode OUTMODE, with NARGS different arguments, passed as ARGS. @@ -4287,7 +4281,6 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, argvec[count].reg != 0, #endif reg_parm_stack_space, 0, - args_so_far, NULL_TREE, &args_size, &argvec[count].locate); if (argvec[count].reg == 0 || argvec[count].partial != 0 @@ -4358,16 +4351,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, val = force_operand (XEXP (slot, 0), NULL_RTX); } -// arg.mode = promote_function_mode (NULL_TREE, arg.mode, &unsigned_p, -// NULL_TREE, 0); - tree t = arg.type; -if (t) - debug_tree (t); -gcc_assert (!t); - arg.type = NULL_TREE; - arg.mode = promote_function_mode (args_so_far, arg, NULL_TREE, - &unsigned_p, 0); - arg.type = t; + arg.mode = promote_function_mode (NULL_TREE, arg.mode, &unsigned_p, + NULL_TREE, 0); argvec[count].mode = arg.mode; argvec[count].value = convert_modes (arg.mode, GET_MODE (val), val, unsigned_p); @@ -4387,7 +4372,6 @@ gcc_assert (!t); argvec[count].reg != 0, #endif reg_parm_stack_space, argvec[count].partial, - args_so_far, NULL_TREE, &args_size, &argvec[count].locate); args_size.constant += argvec[count].locate.size.constant; gcc_assert (!argvec[count].locate.size.var); diff --git a/gcc/calls.h b/gcc/calls.h index 499f7560ee8..464a4e34e33 100644 --- a/gcc/calls.h +++ b/gcc/calls.h @@ -35,43 +35,24 @@ class function_arg_info { public: function_arg_info () - : type (NULL_TREE), mode (VOIDmode), named (false), last_named (false), + : type (NULL_TREE), mode (VOIDmode), named (false), pass_by_reference (false) {} /* Initialize an argument of mode MODE, either before or after promotion. */ function_arg_info (machine_mode mode, bool named) - : type (NULL_TREE), mode (mode), named (named), last_named (false), - pass_by_reference (false) - {} - - function_arg_info (machine_mode mode, bool named, bool last_named) - : type (NULL_TREE), mode (mode), named (named), last_named (last_named), - pass_by_reference (false) + : type (NULL_TREE), mode (mode), named (named), pass_by_reference (false) {} /* Initialize an unpromoted argument of type TYPE. */ function_arg_info (tree type, bool named) - : type (type), mode (TYPE_MODE (type)), named (named), last_named (false), - pass_by_reference (false) - {} - - /* Initialize an unpromoted argument of type TYPE. */ - function_arg_info (tree type, bool named, bool last_named) : type (type), mode (TYPE_MODE (type)), named (named), - last_named (last_named), pass_by_reference (false) - {} - - /* Initialize an argument with explicit properties. */ - function_arg_info (tree type, machine_mode mode, bool named) - : type (type), mode (mode), named (named), last_named (false), pass_by_reference (false) {} /* Initialize an argument with explicit properties. */ - function_arg_info (tree type, machine_mode mode, bool named, bool last_named) - : type (type), mode (mode), named (named), last_named (last_named), - pass_by_reference (false) + function_arg_info (tree type, machine_mode mode, bool named) + : type (type), mode (mode), named (named), pass_by_reference (false) {} /* Return true if the gimple-level type is an aggregate. */ @@ -124,9 +105,6 @@ public: "..."). See also TARGET_STRICT_ARGUMENT_NAMING. */ unsigned int named : 1; - /* True if this is the last named argument. */ - unsigned int last_named : 1; - /* True if we have decided to pass the argument by reference, in which case the function_arg_info describes a pointer to the original argument. */ unsigned int pass_by_reference : 1; diff --git a/gcc/ccmp.cc b/gcc/ccmp.cc index 7cb525addf4..4d50708d986 100644 --- a/gcc/ccmp.cc +++ b/gcc/ccmp.cc @@ -247,7 +247,15 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq) cost2 = seq_cost (prep_seq_2, speed_p); cost2 += seq_cost (gen_seq_2, speed_p); } - if (cost2 < cost1) + + /* It's possible that one expansion succeeds and the other + fails. + For example, x86 has int ccmp but not fp ccmp, and so a + combined fp and int comparison must be ordered such that + the fp comparison happens first. The costs are not + meaningful for failed expansions. */ + + if (ret2 && (!ret || cost2 < cost1)) { *prep_seq = prep_seq_2; *gen_seq = gen_seq_2; diff --git a/gcc/collect2.cc b/gcc/collect2.cc index a7ca609334a..902014a9cc1 100644 --- a/gcc/collect2.cc +++ b/gcc/collect2.cc @@ -73,7 +73,7 @@ along with GCC; see the file COPYING3. If not see In a cross-compiler, this means you need a cross nm, but that is not quite as unpleasant as special headers. */ -#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_MACHO) +#if !defined (OBJECT_FORMAT_COFF) #define OBJECT_FORMAT_NONE #endif @@ -107,7 +107,7 @@ along with GCC; see the file COPYING3. If not see #endif /* OBJECT_FORMAT_COFF */ -#if defined (OBJECT_FORMAT_NONE) || defined (OBJECT_FORMAT_MACHO) +#ifdef OBJECT_FORMAT_NONE /* Default flags to pass to nm. */ #ifndef NM_FLAGS @@ -525,7 +525,7 @@ static const char *const target_machine = TARGET_MACHINE; Return 0 if not found, otherwise return its name, allocated with malloc. */ -#if defined (OBJECT_FORMAT_NONE) || defined (OBJECT_FORMAT_MACHO) +#ifdef OBJECT_FORMAT_NONE /* Add an entry for the object file NAME to object file list LIST. New entries are added at the end of the list. The original pointer @@ -764,12 +764,6 @@ do_link (char **ld_argv, const char *atsuffix) } } -#if defined (OBJECT_FORMAT_MACHO) -# define LLD_NAME "ld64.lld" -#else -# define LLD_NAME "ld.lld" -#endif - /* Main program. */ int @@ -783,19 +777,16 @@ main (int argc, char **argv) USE_BFD_LD, USE_LLD_LD, USE_MOLD_LD, - USE_CLASSIC_LD, USE_LD_MAX } selected_linker = USE_DEFAULT_LD; - static const char *const ld_suffixes[USE_LD_MAX] = { "ld", PLUGIN_LD_SUFFIX, "ld.gold", "ld.bfd", - LLD_NAME, - "ld.mold", - "ld-classic" + "ld.lld", + "ld.mold" }; static const char *const real_ld_suffix = "real-ld"; static const char *const collect_ld_suffix = "collect-ld"; @@ -877,7 +868,7 @@ main (int argc, char **argv) #ifdef CROSS_DIRECTORY_STRUCTURE /* lld and mold are platform-agnostic and not prefixed with target triple. */ - if (!(i == USE_LLD_LD || i == USE_MOLD_LD || i == USE_CLASSIC_LD)) + if (!(i == USE_LLD_LD || i == USE_MOLD_LD)) full_ld_suffixes[i] = concat (target_machine, "-", ld_suffixes[i], NULL); else @@ -965,22 +956,14 @@ main (int argc, char **argv) if (selected_linker == USE_DEFAULT_LD) selected_linker = USE_PLUGIN_LD; } -#if !defined (OBJECT_FORMAT_MACHO) else if (strcmp (argv[i], "-fuse-ld=bfd") == 0) selected_linker = USE_BFD_LD; else if (strcmp (argv[i], "-fuse-ld=gold") == 0) selected_linker = USE_GOLD_LD; -#endif else if (strcmp (argv[i], "-fuse-ld=lld") == 0) selected_linker = USE_LLD_LD; else if (strcmp (argv[i], "-fuse-ld=mold") == 0) selected_linker = USE_MOLD_LD; -#if defined (OBJECT_FORMAT_MACHO) - else if (strcmp (argv[i], "-fuse-ld=classic") == 0) - selected_linker = USE_CLASSIC_LD; -#endif - else if (strcmp (argv[i], "-fuse-ld=") == 0) - selected_linker = USE_DEFAULT_LD; else if (startswith (argv[i], "-o")) { /* Parse the output filename if it's given so that we can make @@ -1072,8 +1055,7 @@ main (int argc, char **argv) ld_file_name = 0; #ifdef DEFAULT_LINKER if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD || - selected_linker == USE_LLD_LD || selected_linker == USE_MOLD_LD || - selected_linker == USE_CLASSIC_LD) + selected_linker == USE_LLD_LD || selected_linker == USE_MOLD_LD) { char *linker_name; # ifdef HOST_EXECUTABLE_SUFFIX @@ -2288,7 +2270,7 @@ write_aix_file (FILE *stream, struct id *list) } #endif -#if defined (OBJECT_FORMAT_NONE) || defined (OBJECT_FORMAT_MACHO) +#ifdef OBJECT_FORMAT_NONE /* Check to make sure the file is an LTO object file. */ diff --git a/gcc/common.opt b/gcc/common.opt index 4ca958a0952..f2bc47fdc5e 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2233,6 +2233,9 @@ Enum(lto_partition_model) String(1to1) Value(LTO_PARTITION_1TO1) EnumValue Enum(lto_partition_model) String(max) Value(LTO_PARTITION_MAX) +EnumValue +Enum(lto_partition_model) String(cache) Value(LTO_PARTITION_CACHE) + flto-partition= Common Joined RejectNegative Enum(lto_partition_model) Var(flag_lto_partition) Init(LTO_PARTITION_BALANCED) Specify the algorithm to partition symbols and vars at linktime. @@ -2929,10 +2932,6 @@ fstack-usage Common RejectNegative Var(flag_stack_usage) Output stack usage information on a per-function basis. -fstack-use-cumulative-args -Common RejectNegative Var(flag_stack_use_cumulative_args) Init(STACK_USE_CUMULATIVE_ARGS_INIT) -Use cumulative args-based stack layout hooks. - fstrength-reduce Common Ignore Does nothing. Preserved for backward compatibility. @@ -3306,10 +3305,6 @@ fuse-ld=mold Common Driver Negative(fuse-ld=mold) Use the Modern linker (MOLD) linker instead of the default linker. -fuse-ld=classic -Common Driver Negative(fuse-ld=classic) -Use the ld-classic linker instead of the default linker. - fuse-linker-plugin Common Undocumented Var(flag_use_linker_plugin) diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc index 496d0d82e05..951d041d310 100644 --- a/gcc/common/config/aarch64/aarch64-common.cc +++ b/gcc/common/config/aarch64/aarch64-common.cc @@ -298,12 +298,8 @@ aarch64_get_extension_string_for_isa_flags However, assemblers with Armv8-R AArch64 support should not have this issue, so we don't need this fix when targeting Armv8-R. */ - aarch64_feature_flags explicit_flags = -#ifndef DISABLE_AARCH64_AS_CRC_BUGFIX - (!(current_flags & AARCH64_ISA_V8R) ? AARCH64_FL_CRC : 0); -#else - 0; -#endif + auto explicit_flags = (!(current_flags & AARCH64_FL_V8R) + ? AARCH64_FL_CRC : 0); /* Add the features in isa_flags & ~current_flags using the smallest possible number of extensions. We can do this by iterating over the @@ -333,10 +329,7 @@ aarch64_get_extension_string_for_isa_flags if (added & opt.flag_canonical) { outstr += "+"; - if (startswith (opt.name, "rdm")) - outstr += "rdm"; - else - outstr += opt.name; + outstr += opt.name; } /* Remove the features in current_flags & ~isa_flags. If the feature does @@ -365,10 +358,7 @@ aarch64_get_extension_string_for_isa_flags { current_flags &= ~opt.flags_off; outstr += "+no"; - if (startswith (opt.name, "rdm")) - outstr += "rdm"; - else - outstr += opt.name; + outstr += opt.name; } } diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc index 895e5fa662d..5d9c188c9c7 100644 --- a/gcc/common/config/i386/i386-common.cc +++ b/gcc/common/config/i386/i386-common.cc @@ -2187,10 +2187,10 @@ const pta processor_alias_table[] = {"meteorlake", PROCESSOR_ALDERLAKE, CPU_HASWELL, PTA_ALDERLAKE, M_CPU_SUBTYPE (INTEL_COREI7_ALDERLAKE), P_PROC_AVX2}, {"graniterapids", PROCESSOR_GRANITERAPIDS, CPU_HASWELL, PTA_GRANITERAPIDS, - M_CPU_SUBTYPE (INTEL_COREI7_GRANITERAPIDS), P_PROC_AVX512F}, + M_CPU_SUBTYPE (INTEL_COREI7_GRANITERAPIDS), P_PROC_AVX10_1_512}, {"graniterapids-d", PROCESSOR_GRANITERAPIDS_D, CPU_HASWELL, PTA_GRANITERAPIDS_D, M_CPU_SUBTYPE (INTEL_COREI7_GRANITERAPIDS_D), - P_PROC_AVX512F}, + P_PROC_AVX10_1_512}, {"arrowlake", PROCESSOR_ARROWLAKE, CPU_HASWELL, PTA_ARROWLAKE, M_CPU_SUBTYPE (INTEL_COREI7_ARROWLAKE), P_PROC_AVX2}, {"arrowlake-s", PROCESSOR_ARROWLAKE_S, CPU_HASWELL, PTA_ARROWLAKE_S, diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h index 9edad96d4fd..3ec9e005a6a 100644 --- a/gcc/common/config/i386/i386-cpuinfo.h +++ b/gcc/common/config/i386/i386-cpuinfo.h @@ -110,7 +110,7 @@ enum processor_subtypes /* Priority of i386 features, greater value is higher priority. This is used to decide the order in which function dispatch must happen. For instance, a version specialized for SSE4.2 should be checked for dispatch - before a version for SSE3, as SSE4.2 implies SSE3. */ + before a version for SSE3. */ enum feature_priority { P_NONE = 0, @@ -146,6 +146,9 @@ enum feature_priority P_AVX512F, P_PROC_AVX512F, P_X86_64_V4, + P_AVX10_1_256, + P_AVX10_1_512, + P_PROC_AVX10_1_512, P_PROC_DYNAMIC }; diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h index 4b4d4b4af99..2a092f740bb 100644 --- a/gcc/common/config/i386/i386-isas.h +++ b/gcc/common/config/i386/i386-isas.h @@ -184,6 +184,6 @@ ISA_NAMES_TABLE_START ISA_NAMES_TABLE_ENTRY("apxf", FEATURE_APX_F, P_NONE, "-mapxf") ISA_NAMES_TABLE_ENTRY("usermsr", FEATURE_USER_MSR, P_NONE, "-musermsr") ISA_NAMES_TABLE_ENTRY("avx10.1", FEATURE_AVX10_1_256, P_NONE, "-mavx10.1") - ISA_NAMES_TABLE_ENTRY("avx10.1-256", FEATURE_AVX10_1_256, P_NONE, "-mavx10.1-256") - ISA_NAMES_TABLE_ENTRY("avx10.1-512", FEATURE_AVX10_1_512, P_NONE, "-mavx10.1-512") + ISA_NAMES_TABLE_ENTRY("avx10.1-256", FEATURE_AVX10_1_256, P_AVX10_1_256, "-mavx10.1-256") + ISA_NAMES_TABLE_ENTRY("avx10.1-512", FEATURE_AVX10_1_512, P_AVX10_1_512, "-mavx10.1-512") ISA_NAMES_TABLE_END diff --git a/gcc/config.gcc b/gcc/config.gcc index d84ad73c3e7..e500ba63e32 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1172,22 +1172,13 @@ case ${target} in ;; esac -# Figure out if we need to enable heap trampolines -# and variadic functions handling. +# Figure out if we need to enable heap trampolines by default case ${target} in -aarch64*-*-darwin2*) - # This applies to arm64 Darwin variadic funtions. - tm_defines="$tm_defines STACK_USE_CUMULATIVE_ARGS_INIT=1" - # Executable stack is forbidden. - tm_defines="$tm_defines HEAP_TRAMPOLINES_INIT=1" - ;; *-*-darwin2*) - tm_defines="$tm_defines STACK_USE_CUMULATIVE_ARGS_INIT=0" # Currently, we do this for macOS 11 and above. tm_defines="$tm_defines HEAP_TRAMPOLINES_INIT=1" ;; *) - tm_defines="$tm_defines STACK_USE_CUMULATIVE_ARGS_INIT=0" tm_defines="$tm_defines HEAP_TRAMPOLINES_INIT=0" ;; esac @@ -1231,14 +1222,6 @@ aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*) done TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'` ;; -aarch64-*-darwin* ) - tm_file="${tm_file} aarch64/aarch64-errata.h" - tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-darwin" - tm_defines="${tm_defines} TARGET_DEFAULT_ASYNC_UNWIND_TABLES=1" - tm_defines="${tm_defines} DISABLE_AARCH64_AS_CRC_BUGFIX=1" - # Choose a default CPU version that will work for all current releases. - with_cpu=${with_cpu:-apple-m1} - ;; aarch64*-*-freebsd*) tm_file="${tm_file} elfos.h ${fbsd_tm_file}" tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-freebsd.h" diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index 6d9c094e855..25189888d17 100644 --- a/gcc/config/aarch64/aarch64-builtins.cc +++ b/gcc/config/aarch64/aarch64-builtins.cc @@ -534,6 +534,15 @@ BUILTIN_VDQ_BHSI (urhadd, uavg, _ceil, 0) BUILTIN_VDQ_BHSI (shadd, avg, _floor, 0) BUILTIN_VDQ_BHSI (uhadd, uavg, _floor, 0) +/* The builtins below should be expanded through the standard optabs + CODE_FOR_extend2. */ +#undef VAR1 +#define VAR1(F,T,N,M) \ + constexpr insn_code CODE_FOR_aarch64_##F##M = CODE_FOR_##T##N##M##2; + +VAR1 (float_extend_lo_, extend, v2sf, v2df) +VAR1 (float_extend_lo_, extend, v4hf, v4sf) + #undef VAR1 #define VAR1(T, N, MAP, FLAG, A) \ {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T, FLAG_##FLAG}, @@ -830,8 +839,6 @@ enum aarch64_builtins AARCH64_PLDX, AARCH64_PLI, AARCH64_PLIX, - /* OS-specific */ - AARCH64_BUILTIN_CFSTRING, AARCH64_BUILTIN_MAX }; @@ -955,9 +962,6 @@ tree aarch64_fp16_ptr_type_node = NULL_TREE; /* Back-end node type for brain float (bfloat) types. */ tree aarch64_bf16_ptr_type_node = NULL_TREE; -/* Pointer to __float128 on Mach-O, where the 128b float is not long double. */ -tree aarch64_float128_ptr_type_node = NULL_TREE; - /* Wrapper around add_builtin_function. NAME is the name of the built-in function, TYPE is the function type, CODE is the function subcode (relative to AARCH64_BUILTIN_GENERAL), and ATTRS is the function @@ -1733,29 +1737,6 @@ aarch64_init_bf16_types (void) aarch64_bf16_ptr_type_node = build_pointer_type (bfloat16_type_node); } -/* Initialize the backend REAL_TYPE type supporting __float128 on Mach-O, - as well as the related built-ins. */ -static void -aarch64_init_float128_types (void) -{ - /* The __float128 type. The node has already been created as - _Float128, so for C we only need to register the __float128 name for - it. For C++, we create a distinct type which will mangle differently - (g) vs. _Float128 (DF128_) and behave backwards compatibly. */ - if (float128t_type_node == NULL_TREE) - { - float128t_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (float128t_type_node) - = TYPE_PRECISION (float128_type_node); - SET_TYPE_MODE (float128t_type_node, TYPE_MODE (float128_type_node)); - layout_type (float128t_type_node); - } - lang_hooks.types.register_builtin_type (float128t_type_node, "__float128"); - - aarch64_float128_ptr_type_node = build_pointer_type (float128t_type_node); -} - - /* Pointer authentication builtins that will become NOP on legacy platform. Currently, these builtins are for internal use only (libgcc EH unwinder). */ @@ -2141,9 +2122,8 @@ aarch64_general_init_builtins (void) aarch64_init_fpsr_fpcr_builtins (); aarch64_init_fp16_types (); + aarch64_init_bf16_types (); - if (TARGET_MACHO) - aarch64_init_float128_types (); { aarch64_simd_switcher simd; @@ -2183,14 +2163,6 @@ aarch64_general_init_builtins (void) handle_arm_acle_h (); } -void -aarch64_init_subtarget_builtins (void) -{ -#ifdef SUBTARGET_INIT_BUILTINS - SUBTARGET_INIT_BUILTINS; -#endif -} - /* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group. */ tree aarch64_general_builtin_decl (unsigned code, bool) diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc index 607d533d08e..d042e5fbd8c 100644 --- a/gcc/config/aarch64/aarch64-c.cc +++ b/gcc/config/aarch64/aarch64-c.cc @@ -75,6 +75,7 @@ aarch64_define_unconditional_macros (cpp_reader *pfile) builtin_define ("__ARM_STATE_ZA"); builtin_define ("__ARM_STATE_ZT0"); + builtin_define ("__ARM_NEON_SVE_BRIDGE"); /* Define keyword attributes like __arm_streaming as macros that expand to the associated [[...]] attribute. Use __extension__ in the attribute @@ -279,16 +280,6 @@ aarch64_cpu_cpp_builtins (cpp_reader *pfile) { aarch64_define_unconditional_macros (pfile); aarch64_update_cpp_builtins (pfile); - - if (TARGET_MACHO) - { - builtin_define ("__builtin_copysignq=__builtin_copysignf128"); - builtin_define ("__builtin_fabsq=__builtin_fabsf128"); - builtin_define ("__builtin_huge_valq=__builtin_huge_valf128"); - builtin_define ("__builtin_infq=__builtin_inff128"); - builtin_define ("__builtin_nanq=__builtin_nanf128"); - builtin_define ("__builtin_nansq=__builtin_nansf128"); - } } /* Hook to validate the current #pragma GCC target and set the state, and @@ -428,8 +419,4 @@ aarch64_register_pragmas (void) targetm.check_builtin_call = aarch64_check_builtin_call; c_register_pragma ("GCC", "aarch64", aarch64_pragma_aarch64); - -#ifdef REGISTER_SUBTARGET_PRAGMAS - REGISTER_SUBTARGET_PRAGMAS (); -#endif } diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def index a6d8d8a3ad7..be60929e400 100644 --- a/gcc/config/aarch64/aarch64-cores.def +++ b/gcc/config/aarch64/aarch64-cores.def @@ -171,17 +171,6 @@ AARCH64_CORE("cortex-a76.cortex-a55", cortexa76cortexa55, cortexa53, V8_2A, (F /* Armv8-R Architecture Processors. */ AARCH64_CORE("cortex-r82", cortexr82, cortexa53, V8R, (), cortexa53, 0x41, 0xd15, -1) -/* Apple (A12 and M) cores. - Apple implementer ID from xnu, - guesses for part #, guesses for scheduler ident, generic_armv8_a for costs. - A12 seems mostly 8.3, - M1 seems to be 8.4 + extras (see comments in option-extensions about f16fml), - M2 mostly 8.5 but with missing mandatory features. */ -AARCH64_CORE("apple-a12", applea12, cortexa53, V8_3A, (), generic_armv8_a, 0x61, 0x12, -1) -AARCH64_CORE("apple-m1", applem1, cortexa57, V8_4A, (F16, SB, SSBS), generic_armv8_a, 0x61, 0x23, -1) -AARCH64_CORE("apple-m2", applem2, cortexa57, V8_4A, (I8MM, BF16, F16, SB, SSBS), generic_armv8_a, 0x61, 0x23, -1) -AARCH64_CORE("apple-m3", applem3, cortexa57, V8_4A, (I8MM, BF16, F16, SB, SSBS), generic_armv8_a, 0x61, 0x23, -1) - /* Armv9.0-A Architecture Processors. */ /* Arm ('A') cores. */ diff --git a/gcc/config/aarch64/aarch64-ldp-fusion.cc b/gcc/config/aarch64/aarch64-ldp-fusion.cc index 0af927231d3..b255dcbe73c 100644 --- a/gcc/config/aarch64/aarch64-ldp-fusion.cc +++ b/gcc/config/aarch64/aarch64-ldp-fusion.cc @@ -75,9 +75,9 @@ struct aarch64_pair_fusion : public pair_fusion return aarch64_ldp_alias_check_limit; } - bool should_handle_writeback (enum writeback which) override final + bool should_handle_writeback (writeback_type which) override final { - if (which == writeback::ALL) + if (which == writeback_type::ALL) return aarch64_ldp_writeback > 1; else return aarch64_ldp_writeback; diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 28508b49cb4..1d3f94c813e 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -109,14 +109,6 @@ enum aarch64_symbol_type SYMBOL_TLSLE24, SYMBOL_TLSLE32, SYMBOL_TLSLE48, - SYMBOL_MO_SMALL_ABS, - SYMBOL_MO_SMALL_PCR, - SYMBOL_MO_SMALL_GOT, - SYMBOL_MO_SMALL_TLS, - SYMBOL_MO_LARGE_ABS, - SYMBOL_MO_LARGE_PCR, - SYMBOL_MO_LARGE_GOT, - SYMBOL_MO_LARGE_TLS, SYMBOL_FORCE_TO_MEM }; @@ -756,7 +748,6 @@ void aarch64_post_cfi_startproc (void); poly_int64 aarch64_initial_elimination_offset (unsigned, unsigned); int aarch64_get_condition_code (rtx); bool aarch64_address_valid_for_prefetch_p (rtx, bool); -bool aarch64_address_valid_for_unscaled_prefetch_p (rtx, bool); bool aarch64_bitmask_imm (unsigned HOST_WIDE_INT val, machine_mode); unsigned HOST_WIDE_INT aarch64_and_split_imm1 (HOST_WIDE_INT val_in); unsigned HOST_WIDE_INT aarch64_and_split_imm2 (HOST_WIDE_INT val_in); @@ -791,11 +782,7 @@ bool aarch64_is_extend_from_extract (scalar_int_mode, rtx, rtx); bool aarch64_is_long_call_p (rtx); bool aarch64_is_noplt_call_p (rtx); bool aarch64_label_mentioned_p (rtx); -#if TARGET_MACHO -void aarch64_darwin_declare_function_name (FILE *, const char*, tree ); -#else void aarch64_declare_function_name (FILE *, const char*, tree); -#endif void aarch64_asm_output_alias (FILE *, const tree, const tree); void aarch64_asm_output_external (FILE *, tree, const char*); bool aarch64_legitimate_pic_operand_p (rtx); @@ -1012,7 +999,6 @@ void aarch64_override_options_internal (struct gcc_options *); const char *aarch64_general_mangle_builtin_type (const_tree); void aarch64_general_init_builtins (void); -void aarch64_init_subtarget_builtins (void); tree aarch64_general_fold_builtin (unsigned int, tree, unsigned int, tree *); gimple *aarch64_general_gimple_fold_builtin (unsigned int, gcall *, gimple_stmt_iterator *); diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 868f4486218..c5e2c9f00d0 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -3132,7 +3132,7 @@ DONE; } ) -(define_insn "aarch64_float_extend_lo_" +(define_insn "extend2" [(set (match_operand: 0 "register_operand" "=w") (float_extend: (match_operand:VDF 1 "register_operand" "w")))] diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md index 0434358122d..d69db34016a 100644 --- a/gcc/config/aarch64/aarch64-sve.md +++ b/gcc/config/aarch64/aarch64-sve.md @@ -1156,76 +1156,96 @@ ;; Likewise with zero predication. (define_insn "aarch64_rdffr_z" - [(set (match_operand:VNx16BI 0 "register_operand" "=Upa") + [(set (match_operand:VNx16BI 0 "register_operand") (and:VNx16BI (reg:VNx16BI FFRT_REGNUM) - (match_operand:VNx16BI 1 "register_operand" "Upa")))] + (match_operand:VNx16BI 1 "register_operand")))] "TARGET_SVE && TARGET_NON_STREAMING" - "rdffr\t%0.b, %1/z" + {@ [ cons: =0, 1 ; attrs: pred_clobber ] + [ &Upa , Upa ; yes ] rdffr\t%0.b, %1/z + [ ?Upa , 0Upa; yes ] ^ + [ Upa , Upa ; no ] ^ + } ) ;; Read the FFR to test for a fault, without using the predicate result. (define_insn "*aarch64_rdffr_z_ptest" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_dup 1) (match_operand:SI 2 "aarch64_sve_ptrue_flag") (and:VNx16BI (reg:VNx16BI FFRT_REGNUM) (match_dup 1))] UNSPEC_PTEST)) - (clobber (match_scratch:VNx16BI 0 "=Upa"))] + (clobber (match_scratch:VNx16BI 0))] "TARGET_SVE && TARGET_NON_STREAMING" - "rdffrs\t%0.b, %1/z" + {@ [ cons: =0, 1 ; attrs: pred_clobber ] + [ &Upa , Upa ; yes ] rdffrs\t%0.b, %1/z + [ ?Upa , 0Upa; yes ] ^ + [ Upa , Upa ; no ] ^ + } ) ;; Same for unpredicated RDFFR when tested with a known PTRUE. (define_insn "*aarch64_rdffr_ptest" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_dup 1) (const_int SVE_KNOWN_PTRUE) (reg:VNx16BI FFRT_REGNUM)] UNSPEC_PTEST)) - (clobber (match_scratch:VNx16BI 0 "=Upa"))] + (clobber (match_scratch:VNx16BI 0))] "TARGET_SVE && TARGET_NON_STREAMING" - "rdffrs\t%0.b, %1/z" + {@ [ cons: =0, 1 ; attrs: pred_clobber ] + [ &Upa , Upa ; yes ] rdffrs\t%0.b, %1/z + [ ?Upa , 0Upa; yes ] ^ + [ Upa , Upa ; no ] ^ + } ) ;; Read the FFR with zero predication and test the result. (define_insn "*aarch64_rdffr_z_cc" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_dup 1) (match_operand:SI 2 "aarch64_sve_ptrue_flag") (and:VNx16BI (reg:VNx16BI FFRT_REGNUM) (match_dup 1))] UNSPEC_PTEST)) - (set (match_operand:VNx16BI 0 "register_operand" "=Upa") + (set (match_operand:VNx16BI 0 "register_operand") (and:VNx16BI (reg:VNx16BI FFRT_REGNUM) (match_dup 1)))] "TARGET_SVE && TARGET_NON_STREAMING" - "rdffrs\t%0.b, %1/z" + {@ [ cons: =0, 1 ; attrs: pred_clobber ] + [ &Upa , Upa ; yes ] rdffrs\t%0.b, %1/z + [ ?Upa , 0Upa; yes ] ^ + [ Upa , Upa ; no ] ^ + } ) ;; Same for unpredicated RDFFR when tested with a known PTRUE. (define_insn "*aarch64_rdffr_cc" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_dup 1) (const_int SVE_KNOWN_PTRUE) (reg:VNx16BI FFRT_REGNUM)] UNSPEC_PTEST)) - (set (match_operand:VNx16BI 0 "register_operand" "=Upa") + (set (match_operand:VNx16BI 0 "register_operand") (reg:VNx16BI FFRT_REGNUM))] "TARGET_SVE && TARGET_NON_STREAMING" - "rdffrs\t%0.b, %1/z" + {@ [ cons: =0, 1 ; attrs: pred_clobber ] + [ &Upa , Upa ; yes ] rdffrs\t%0.b, %1/z + [ ?Upa , 0Upa; yes ] ^ + [ Upa , Upa ; no ] ^ + } ) ;; [R3 in the block comment above about FFR handling] @@ -6637,11 +6657,15 @@ ;; Doubling the second operand is the preferred implementation ;; of the MOV alias, so we use that instead of %1/z, %1, %2. (define_insn "and3" - [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa") - (and:PRED_ALL (match_operand:PRED_ALL 1 "register_operand" "Upa") - (match_operand:PRED_ALL 2 "register_operand" "Upa")))] + [(set (match_operand:PRED_ALL 0 "register_operand") + (and:PRED_ALL (match_operand:PRED_ALL 1 "register_operand") + (match_operand:PRED_ALL 2 "register_operand")))] "TARGET_SVE" - "and\t%0.b, %1/z, %2.b, %2.b" + {@ [ cons: =0, 1 , 2 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa ; yes ] and\t%0.b, %1/z, %2.b, %2.b + [ ?Upa , 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa ; no ] ^ + } ) ;; Unpredicated predicate EOR and ORR. @@ -6660,14 +6684,18 @@ ;; Predicated predicate AND, EOR and ORR. (define_insn "@aarch64_pred__z" - [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa") + [(set (match_operand:PRED_ALL 0 "register_operand") (and:PRED_ALL (LOGICAL:PRED_ALL - (match_operand:PRED_ALL 2 "register_operand" "Upa") - (match_operand:PRED_ALL 3 "register_operand" "Upa")) - (match_operand:PRED_ALL 1 "register_operand" "Upa")))] + (match_operand:PRED_ALL 2 "register_operand") + (match_operand:PRED_ALL 3 "register_operand")) + (match_operand:PRED_ALL 1 "register_operand")))] "TARGET_SVE" - "\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] \t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; Perform a logical operation on operands 2 and 3, using operand 1 as @@ -6676,38 +6704,46 @@ (define_insn "*3_cc" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_operand 4) (match_operand:SI 5 "aarch64_sve_ptrue_flag") (and:PRED_ALL (LOGICAL:PRED_ALL - (match_operand:PRED_ALL 2 "register_operand" "Upa") - (match_operand:PRED_ALL 3 "register_operand" "Upa")) + (match_operand:PRED_ALL 2 "register_operand") + (match_operand:PRED_ALL 3 "register_operand")) (match_dup 4))] UNSPEC_PTEST)) - (set (match_operand:PRED_ALL 0 "register_operand" "=Upa") + (set (match_operand:PRED_ALL 0 "register_operand") (and:PRED_ALL (LOGICAL:PRED_ALL (match_dup 2) (match_dup 3)) (match_dup 4)))] "TARGET_SVE" - "s\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] s\t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; Same with just the flags result. (define_insn "*3_ptest" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_operand 4) (match_operand:SI 5 "aarch64_sve_ptrue_flag") (and:PRED_ALL (LOGICAL:PRED_ALL - (match_operand:PRED_ALL 2 "register_operand" "Upa") - (match_operand:PRED_ALL 3 "register_operand" "Upa")) + (match_operand:PRED_ALL 2 "register_operand") + (match_operand:PRED_ALL 3 "register_operand")) (match_dup 4))] UNSPEC_PTEST)) - (clobber (match_scratch:VNx16BI 0 "=Upa"))] + (clobber (match_scratch:VNx16BI 0))] "TARGET_SVE" - "s\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] s\t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; ------------------------------------------------------------------------- @@ -6720,56 +6756,68 @@ ;; Predicated predicate BIC and ORN. (define_insn "aarch64_pred__z" - [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa") + [(set (match_operand:PRED_ALL 0 "register_operand") (and:PRED_ALL (NLOGICAL:PRED_ALL - (not:PRED_ALL (match_operand:PRED_ALL 3 "register_operand" "Upa")) - (match_operand:PRED_ALL 2 "register_operand" "Upa")) - (match_operand:PRED_ALL 1 "register_operand" "Upa")))] + (not:PRED_ALL (match_operand:PRED_ALL 3 "register_operand")) + (match_operand:PRED_ALL 2 "register_operand")) + (match_operand:PRED_ALL 1 "register_operand")))] "TARGET_SVE" - "\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] \t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; Same, but set the flags as a side-effect. (define_insn "*3_cc" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_operand 4) (match_operand:SI 5 "aarch64_sve_ptrue_flag") (and:PRED_ALL (NLOGICAL:PRED_ALL (not:PRED_ALL - (match_operand:PRED_ALL 3 "register_operand" "Upa")) - (match_operand:PRED_ALL 2 "register_operand" "Upa")) + (match_operand:PRED_ALL 3 "register_operand")) + (match_operand:PRED_ALL 2 "register_operand")) (match_dup 4))] UNSPEC_PTEST)) - (set (match_operand:PRED_ALL 0 "register_operand" "=Upa") + (set (match_operand:PRED_ALL 0 "register_operand") (and:PRED_ALL (NLOGICAL:PRED_ALL (not:PRED_ALL (match_dup 3)) (match_dup 2)) (match_dup 4)))] "TARGET_SVE" - "s\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] s\t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; Same with just the flags result. (define_insn "*3_ptest" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_operand 4) (match_operand:SI 5 "aarch64_sve_ptrue_flag") (and:PRED_ALL (NLOGICAL:PRED_ALL (not:PRED_ALL - (match_operand:PRED_ALL 3 "register_operand" "Upa")) - (match_operand:PRED_ALL 2 "register_operand" "Upa")) + (match_operand:PRED_ALL 3 "register_operand")) + (match_operand:PRED_ALL 2 "register_operand")) (match_dup 4))] UNSPEC_PTEST)) - (clobber (match_scratch:VNx16BI 0 "=Upa"))] + (clobber (match_scratch:VNx16BI 0))] "TARGET_SVE" - "s\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] s\t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; ------------------------------------------------------------------------- @@ -6782,58 +6830,70 @@ ;; Predicated predicate NAND and NOR. (define_insn "aarch64_pred__z" - [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa") + [(set (match_operand:PRED_ALL 0 "register_operand") (and:PRED_ALL (NLOGICAL:PRED_ALL - (not:PRED_ALL (match_operand:PRED_ALL 2 "register_operand" "Upa")) - (not:PRED_ALL (match_operand:PRED_ALL 3 "register_operand" "Upa"))) - (match_operand:PRED_ALL 1 "register_operand" "Upa")))] + (not:PRED_ALL (match_operand:PRED_ALL 2 "register_operand")) + (not:PRED_ALL (match_operand:PRED_ALL 3 "register_operand"))) + (match_operand:PRED_ALL 1 "register_operand")))] "TARGET_SVE" - "\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] \t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; Same, but set the flags as a side-effect. (define_insn "*3_cc" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_operand 4) (match_operand:SI 5 "aarch64_sve_ptrue_flag") (and:PRED_ALL (NLOGICAL:PRED_ALL (not:PRED_ALL - (match_operand:PRED_ALL 2 "register_operand" "Upa")) + (match_operand:PRED_ALL 2 "register_operand")) (not:PRED_ALL - (match_operand:PRED_ALL 3 "register_operand" "Upa"))) + (match_operand:PRED_ALL 3 "register_operand"))) (match_dup 4))] UNSPEC_PTEST)) - (set (match_operand:PRED_ALL 0 "register_operand" "=Upa") + (set (match_operand:PRED_ALL 0 "register_operand") (and:PRED_ALL (NLOGICAL:PRED_ALL (not:PRED_ALL (match_dup 2)) (not:PRED_ALL (match_dup 3))) (match_dup 4)))] "TARGET_SVE" - "s\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] s\t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; Same with just the flags result. (define_insn "*3_ptest" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_operand 4) (match_operand:SI 5 "aarch64_sve_ptrue_flag") (and:PRED_ALL (NLOGICAL:PRED_ALL (not:PRED_ALL - (match_operand:PRED_ALL 2 "register_operand" "Upa")) + (match_operand:PRED_ALL 2 "register_operand")) (not:PRED_ALL - (match_operand:PRED_ALL 3 "register_operand" "Upa"))) + (match_operand:PRED_ALL 3 "register_operand"))) (match_dup 4))] UNSPEC_PTEST)) - (clobber (match_scratch:VNx16BI 0 "=Upa"))] + (clobber (match_scratch:VNx16BI 0))] "TARGET_SVE" - "s\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] s\t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; ========================================================================= @@ -8074,9 +8134,13 @@ UNSPEC_PRED_Z)) (clobber (reg:CC_NZC CC_REGNUM))] "TARGET_SVE" - {@ [ cons: =0 , 1 , 3 , 4 ] - [ Upa , Upl , w , ] cmp\t%0., %1/z, %3., #%4 - [ Upa , Upl , w , w ] cmp\t%0., %1/z, %3., %4. + {@ [ cons: =0 , 1 , 3 , 4 ; attrs: pred_clobber ] + [ &Upa , Upl, w , ; yes ] cmp\t%0., %1/z, %3., #%4 + [ ?Upl , 0 , w , ; yes ] ^ + [ Upa , Upl, w , ; no ] ^ + [ &Upa , Upl, w , w ; yes ] cmp\t%0., %1/z, %3., %4. + [ ?Upl , 0 , w , w ; yes ] ^ + [ Upa , Upl, w , w ; no ] ^ } ) @@ -8106,9 +8170,13 @@ UNSPEC_PRED_Z))] "TARGET_SVE && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])" - {@ [ cons: =0 , 1 , 2 , 3 ] - [ Upa , Upl , w , ] cmp\t%0., %1/z, %2., #%3 - [ Upa , Upl , w , w ] cmp\t%0., %1/z, %2., %3. + {@ [ cons: =0 , 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upl, w , ; yes ] cmp\t%0., %1/z, %2., #%3 + [ ?Upl , 0 , w , ; yes ] ^ + [ Upa , Upl, w , ; no ] ^ + [ &Upa , Upl, w , w ; yes ] cmp\t%0., %1/z, %2., %3. + [ ?Upl , 0 , w , w ; yes ] ^ + [ Upa , Upl, w , w ; no ] ^ } "&& !rtx_equal_p (operands[4], operands[6])" { @@ -8133,12 +8201,16 @@ (match_operand:SVE_I 3 "aarch64_sve_cmp__operand"))] UNSPEC_PRED_Z)] UNSPEC_PTEST)) - (clobber (match_scratch: 0 "=Upa, Upa"))] + (clobber (match_scratch: 0))] "TARGET_SVE && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])" - {@ [ cons: 1 , 2 , 3 ] - [ Upl , w , ] cmp\t%0., %1/z, %2., #%3 - [ Upl , w , w ] cmp\t%0., %1/z, %2., %3. + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upl, w , ; yes ] cmp\t%0., %1/z, %2., #%3 + [ ?Upl , 0 , w , ; yes ] ^ + [ Upa , Upl, w , ; no ] ^ + [ &Upa , Upl, w , w ; yes ] cmp\t%0., %1/z, %2., %3. + [ ?Upl , 0 , w , w ; yes ] ^ + [ Upa , Upl, w , w ; no ] ^ } "&& !rtx_equal_p (operands[4], operands[6])" { @@ -8180,18 +8252,22 @@ ;; Predicated integer wide comparisons. (define_insn "@aarch64_pred_cmp_wide" - [(set (match_operand: 0 "register_operand" "=Upa") + [(set (match_operand: 0 "register_operand") (unspec: - [(match_operand:VNx16BI 1 "register_operand" "Upl") + [(match_operand:VNx16BI 1 "register_operand") (match_operand:SI 2 "aarch64_sve_ptrue_flag") (unspec: - [(match_operand:SVE_FULL_BHSI 3 "register_operand" "w") - (match_operand:VNx2DI 4 "register_operand" "w")] + [(match_operand:SVE_FULL_BHSI 3 "register_operand") + (match_operand:VNx2DI 4 "register_operand")] SVE_COND_INT_CMP_WIDE)] UNSPEC_PRED_Z)) (clobber (reg:CC_NZC CC_REGNUM))] "TARGET_SVE" - "cmp\t%0., %1/z, %3., %4.d" + {@ [ cons: =0, 1 , 2, 3, 4; attrs: pred_clobber ] + [ &Upa , Upl, , w, w; yes ] cmp\t%0., %1/z, %3., %4.d + [ ?Upl , 0 , , w, w; yes ] ^ + [ Upa , Upl, , w, w; no ] ^ + } ) ;; Predicated integer wide comparisons in which both the flag and @@ -8199,19 +8275,19 @@ (define_insn "*aarch64_pred_cmp_wide_cc" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upl") + [(match_operand:VNx16BI 1 "register_operand") (match_operand 4) (match_operand:SI 5 "aarch64_sve_ptrue_flag") (unspec: - [(match_operand:VNx16BI 6 "register_operand" "Upl") + [(match_operand:VNx16BI 6 "register_operand") (match_operand:SI 7 "aarch64_sve_ptrue_flag") (unspec: - [(match_operand:SVE_FULL_BHSI 2 "register_operand" "w") - (match_operand:VNx2DI 3 "register_operand" "w")] + [(match_operand:SVE_FULL_BHSI 2 "register_operand") + (match_operand:VNx2DI 3 "register_operand")] SVE_COND_INT_CMP_WIDE)] UNSPEC_PRED_Z)] UNSPEC_PTEST)) - (set (match_operand: 0 "register_operand" "=Upa") + (set (match_operand: 0 "register_operand") (unspec: [(match_dup 6) (match_dup 7) @@ -8222,7 +8298,11 @@ UNSPEC_PRED_Z))] "TARGET_SVE && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])" - "cmp\t%0., %1/z, %2., %3.d" + {@ [ cons: =0, 1 , 2, 3, 6 ; attrs: pred_clobber ] + [ &Upa , Upl, w, w, Upl; yes ] cmp\t%0., %1/z, %2., %3.d + [ ?Upl , 0 , w, w, Upl; yes ] ^ + [ Upa , Upl, w, w, Upl; no ] ^ + } ) ;; Predicated integer wide comparisons in which only the flags result @@ -8230,22 +8310,26 @@ (define_insn "*aarch64_pred_cmp_wide_ptest" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upl") + [(match_operand:VNx16BI 1 "register_operand") (match_operand 4) (match_operand:SI 5 "aarch64_sve_ptrue_flag") (unspec: - [(match_operand:VNx16BI 6 "register_operand" "Upl") + [(match_operand:VNx16BI 6 "register_operand") (match_operand:SI 7 "aarch64_sve_ptrue_flag") (unspec: - [(match_operand:SVE_FULL_BHSI 2 "register_operand" "w") - (match_operand:VNx2DI 3 "register_operand" "w")] + [(match_operand:SVE_FULL_BHSI 2 "register_operand") + (match_operand:VNx2DI 3 "register_operand")] SVE_COND_INT_CMP_WIDE)] UNSPEC_PRED_Z)] UNSPEC_PTEST)) - (clobber (match_scratch: 0 "=Upa"))] + (clobber (match_scratch: 0))] "TARGET_SVE && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])" - "cmp\t%0., %1/z, %2., %3.d" + {@ [ cons: =0, 1 , 2, 3, 6 ; attrs: pred_clobber ] + [ &Upa , Upl, w, w, Upl; yes ] cmp\t%0., %1/z, %2., %3.d + [ ?Upl , 0 , w, w, Upl; yes ] ^ + [ Upa , Upl, w, w, Upl; no ] ^ + } ) ;; ------------------------------------------------------------------------- @@ -9912,9 +9996,13 @@ (match_operand:VNx16BI 3 "aarch64_simd_reg_or_zero")] SVE_BRK_UNARY))] "TARGET_SVE" - {@ [ cons: =0 , 1 , 2 , 3 ] - [ Upa , Upa , Upa , Dz ] brk\t%0.b, %1/z, %2.b - [ Upa , Upa , Upa , 0 ] brk\t%0.b, %1/m, %2.b + {@ [ cons: =0 , 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Dz; yes ] brk\t%0.b, %1/z, %2.b + [ ?Upa , 0Upa, 0Upa, Dz; yes ] ^ + [ Upa , Upa , Upa , Dz; no ] ^ + [ &Upa , Upa , Upa , 0 ; yes ] brk\t%0.b, %1/m, %2.b + [ ?Upa , 0Upa, 0Upa, 0 ; yes ] ^ + [ Upa , Upa , Upa , 0 ; no ] ^ } ) @@ -9922,41 +10010,49 @@ (define_insn "*aarch64_brk_cc" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_dup 1) (match_operand:SI 4 "aarch64_sve_ptrue_flag") (unspec:VNx16BI [(match_dup 1) - (match_operand:VNx16BI 2 "register_operand" "Upa") + (match_operand:VNx16BI 2 "register_operand") (match_operand:VNx16BI 3 "aarch64_simd_imm_zero")] SVE_BRK_UNARY)] UNSPEC_PTEST)) - (set (match_operand:VNx16BI 0 "register_operand" "=Upa") + (set (match_operand:VNx16BI 0 "register_operand") (unspec:VNx16BI [(match_dup 1) (match_dup 2) (match_dup 3)] SVE_BRK_UNARY))] "TARGET_SVE" - "brks\t%0.b, %1/z, %2.b" + {@ [ cons: =0, 1 , 2 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa ; yes ] brks\t%0.b, %1/z, %2.b + [ ?Upa , 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa ; no ] ^ + } ) ;; Same, but with only the flags result being interesting. (define_insn "*aarch64_brk_ptest" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_dup 1) (match_operand:SI 4 "aarch64_sve_ptrue_flag") (unspec:VNx16BI [(match_dup 1) - (match_operand:VNx16BI 2 "register_operand" "Upa") + (match_operand:VNx16BI 2 "register_operand") (match_operand:VNx16BI 3 "aarch64_simd_imm_zero")] SVE_BRK_UNARY)] UNSPEC_PTEST)) - (clobber (match_scratch:VNx16BI 0 "=Upa"))] + (clobber (match_scratch:VNx16BI 0))] "TARGET_SVE" - "brks\t%0.b, %1/z, %2.b" + {@ [ cons: =0, 1 , 2 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa ; yes ] brks\t%0.b, %1/z, %2.b + [ ?Upa , 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa ; no ] ^ + } ) ;; ------------------------------------------------------------------------- @@ -9973,14 +10069,18 @@ ;; Binary BRKs (BRKN, BRKPA, BRKPB). (define_insn "@aarch64_brk" - [(set (match_operand:VNx16BI 0 "register_operand" "=Upa") + [(set (match_operand:VNx16BI 0 "register_operand") (unspec:VNx16BI - [(match_operand:VNx16BI 1 "register_operand" "Upa") - (match_operand:VNx16BI 2 "register_operand" "Upa") - (match_operand:VNx16BI 3 "register_operand" "")] + [(match_operand:VNx16BI 1 "register_operand") + (match_operand:VNx16BI 2 "register_operand") + (match_operand:VNx16BI 3 "register_operand")] SVE_BRK_BINARY))] "TARGET_SVE" - "brk\t%0.b, %1/z, %2.b, %.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , ; yes ] brk\t%0.b, %1/z, %2.b, %.b + [ ?Upa , 0Upa, 0Upa, 0; yes ] ^ + [ Upa , Upa , Upa , ; no ] ^ + } ) ;; BRKN, producing both a predicate and a flags result. Unlike other @@ -10041,41 +10141,49 @@ (define_insn "*aarch64_brk_cc" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_dup 1) (match_operand:SI 4 "aarch64_sve_ptrue_flag") (unspec:VNx16BI [(match_dup 1) - (match_operand:VNx16BI 2 "register_operand" "Upa") - (match_operand:VNx16BI 3 "register_operand" "Upa")] + (match_operand:VNx16BI 2 "register_operand") + (match_operand:VNx16BI 3 "register_operand")] SVE_BRKP)] UNSPEC_PTEST)) - (set (match_operand:VNx16BI 0 "register_operand" "=Upa") + (set (match_operand:VNx16BI 0 "register_operand") (unspec:VNx16BI [(match_dup 1) (match_dup 2) (match_dup 3)] SVE_BRKP))] "TARGET_SVE" - "brks\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 , 4; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa , ; yes ] brks\t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa, ; yes ] ^ + [ Upa , Upa , Upa , Upa , ; no ] ^ + } ) ;; Same, but with only the flags result being interesting. (define_insn "*aarch64_brk_ptest" [(set (reg:CC_NZC CC_REGNUM) (unspec:CC_NZC - [(match_operand:VNx16BI 1 "register_operand" "Upa") + [(match_operand:VNx16BI 1 "register_operand") (match_dup 1) (match_operand:SI 4 "aarch64_sve_ptrue_flag") (unspec:VNx16BI [(match_dup 1) - (match_operand:VNx16BI 2 "register_operand" "Upa") - (match_operand:VNx16BI 3 "register_operand" "Upa")] + (match_operand:VNx16BI 2 "register_operand") + (match_operand:VNx16BI 3 "register_operand")] SVE_BRKP)] UNSPEC_PTEST)) - (clobber (match_scratch:VNx16BI 0 "=Upa"))] + (clobber (match_scratch:VNx16BI 0))] "TARGET_SVE" - "brks\t%0.b, %1/z, %2.b, %3.b" + {@ [ cons: =0, 1 , 2 , 3 ; attrs: pred_clobber ] + [ &Upa , Upa , Upa , Upa ; yes ] brks\t%0.b, %1/z, %2.b, %3.b + [ ?Upa , 0Upa, 0Upa, 0Upa; yes ] ^ + [ Upa , Upa , Upa , Upa ; no ] ^ + } ) ;; ------------------------------------------------------------------------- diff --git a/gcc/config/aarch64/aarch64-sve2.md b/gcc/config/aarch64/aarch64-sve2.md index 934e57055d3..972b03a4fef 100644 --- a/gcc/config/aarch64/aarch64-sve2.md +++ b/gcc/config/aarch64/aarch64-sve2.md @@ -3338,18 +3338,22 @@ ;; Predicated string matching. (define_insn "@aarch64_pred_" - [(set (match_operand: 0 "register_operand" "=Upa") + [(set (match_operand: 0 "register_operand") (unspec: - [(match_operand: 1 "register_operand" "Upl") + [(match_operand: 1 "register_operand") (match_operand:SI 2 "aarch64_sve_ptrue_flag") (unspec: - [(match_operand:SVE_FULL_BHI 3 "register_operand" "w") - (match_operand:SVE_FULL_BHI 4 "register_operand" "w")] + [(match_operand:SVE_FULL_BHI 3 "register_operand") + (match_operand:SVE_FULL_BHI 4 "register_operand")] SVE2_MATCH)] UNSPEC_PRED_Z)) (clobber (reg:CC_NZC CC_REGNUM))] "TARGET_SVE2 && TARGET_NON_STREAMING" - "\t%0., %1/z, %3., %4." + {@ [ cons: =0, 1 , 3, 4; attrs: pred_clobber ] + [ &Upa , Upl, w, w; yes ] \t%0., %1/z, %3., %4. + [ ?Upl , 0 , w, w; yes ] ^ + [ Upa , Upl, w, w; no ] ^ + } ) ;; Predicated string matching in which both the flag and predicate results diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md index 63cd7d6cac1..ba940f1c890 100644 --- a/gcc/config/aarch64/aarch64-tune.md +++ b/gcc/config/aarch64/aarch64-tune.md @@ -1,5 +1,5 @@ ;; -*- buffer-read-only: t -*- ;; Generated automatically by gentune.sh from aarch64-cores.def (define_attr "tune" - "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,ampere1b,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,oryon1,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,applea12,applem1,applem2,applem3,cortexa510,cortexa520,cortexa710,cortexa715,cortexa720,cortexx2,cortexx3,cortexx4,neoversen2,cobalt100,neoversev2,demeter,generic,generic_armv8_a,generic_armv9_a" + "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,ampere1b,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,oryon1,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa520,cortexa710,cortexa715,cortexa720,cortexx2,cortexx3,cortexx4,neoversen2,cobalt100,neoversev2,demeter,generic,generic_armv8_a,generic_armv9_a" (const (symbol_ref "((enum attr_tune) aarch64_tune)"))) diff --git a/gcc/config/aarch64/aarch64-tuning-flags.def b/gcc/config/aarch64/aarch64-tuning-flags.def index d5bcaebce77..a9f48f5d3d4 100644 --- a/gcc/config/aarch64/aarch64-tuning-flags.def +++ b/gcc/config/aarch64/aarch64-tuning-flags.def @@ -48,4 +48,8 @@ AARCH64_EXTRA_TUNING_OPTION ("avoid_cross_loop_fma", AVOID_CROSS_LOOP_FMA) AARCH64_EXTRA_TUNING_OPTION ("fully_pipelined_fma", FULLY_PIPELINED_FMA) +/* Enable is the target prefers to use a fresh register for predicate outputs + rather than re-use an input predicate register. */ +AARCH64_EXTRA_TUNING_OPTION ("avoid_pred_rmw", AVOID_PRED_RMW) + #undef AARCH64_EXTRA_TUNING_OPTION diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index cc5cb25f671..13191ec8e34 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -333,10 +333,8 @@ static bool aarch64_vfp_is_call_or_return_candidate (machine_mode, const_tree, machine_mode *, int *, bool *, bool); -#if !TARGET_MACHO static void aarch64_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED; static void aarch64_elf_asm_destructor (rtx, int) ATTRIBUTE_UNUSED; -#endif static void aarch64_override_options_after_change (void); static bool aarch64_vector_mode_supported_p (machine_mode); static int aarch64_address_cost (rtx, machine_mode, addr_space_t, bool); @@ -854,9 +852,6 @@ static const attribute_spec aarch64_gnu_attributes[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, affects_type_identity, handler, exclude } */ -#ifdef SUBTARGET_ATTRIBUTE_TABLE - SUBTARGET_ATTRIBUTE_TABLE, -#endif { "aarch64_vector_pcs", 0, 0, false, true, true, true, handle_aarch64_vector_pcs_attribute, NULL }, { "arm_sve_vector_bits", 1, 1, false, true, false, true, @@ -2076,7 +2071,7 @@ aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode) if (known_le (GET_MODE_SIZE (mode), 8)) return true; if (known_le (GET_MODE_SIZE (mode), 16)) - return (regno & 1) == 0 || TARGET_MACHO; /* darwinpcs D.4 */ + return (regno & 1) == 0; } else if (FP_REGNUM_P (regno)) { @@ -2122,10 +2117,8 @@ static bool aarch64_takes_arguments_in_sve_regs_p (const_tree fntype) { CUMULATIVE_ARGS args_so_far_v; - /* This does not apply to variadic functions, so all the (currently - uncounted) arguments must be named. */ aarch64_init_cumulative_args (&args_so_far_v, NULL_TREE, NULL_RTX, - NULL_TREE, -1, true); + NULL_TREE, 0, true); cumulative_args_t args_so_far = pack_cumulative_args (&args_so_far_v); for (tree chain = TYPE_ARG_TYPES (fntype); @@ -2872,7 +2865,6 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, switch (type) { case SYMBOL_SMALL_ABSOLUTE: - case SYMBOL_MO_SMALL_PCR: { /* In ILP32, the mode of dest can be either SImode or DImode. */ rtx tmp_reg = dest; @@ -2883,21 +2875,6 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, if (can_create_pseudo_p ()) tmp_reg = gen_reg_rtx (mode); - if (TARGET_MACHO) - { - rtx sym, off; - split_const (imm, &sym, &off); - /* Negative offsets don't work, whether by intention is TBD. */ - if (INTVAL (off) < 0 || INTVAL (off) > 8 * 1024 * 1024) - { - emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, sym)); - emit_insn (gen_add_losym (dest, tmp_reg, sym)); - /* FIXME: add the SI option if/when we support ilp32. */ - emit_insn (gen_adddi3 (dest, dest, off)); - return; - } - /* else small enough positive offset is OK. */ - } emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, copy_rtx (imm))); emit_insn (gen_add_losym (dest, tmp_reg, imm)); return; @@ -2981,7 +2958,6 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, return; } - case SYMBOL_MO_SMALL_GOT: case SYMBOL_SMALL_GOT_4G: emit_insn (gen_rtx_SET (dest, imm)); return; @@ -6054,7 +6030,6 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) case SYMBOL_SMALL_TLSIE: case SYMBOL_SMALL_GOT_28K: case SYMBOL_SMALL_GOT_4G: - case SYMBOL_MO_SMALL_GOT: case SYMBOL_TINY_GOT: case SYMBOL_TINY_TLSIE: if (const_offset != 0) @@ -6068,7 +6043,6 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) /* FALLTHRU */ case SYMBOL_SMALL_ABSOLUTE: - case SYMBOL_MO_SMALL_PCR: case SYMBOL_TINY_ABSOLUTE: case SYMBOL_TLSLE12: case SYMBOL_TLSLE24: @@ -6658,7 +6632,6 @@ aarch64_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) gcc_unreachable (); } -#if !TARGET_MACHO static bool aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode, const_tree type, int *nregs) @@ -6668,7 +6641,6 @@ aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode, &pcum->aapcs_vfp_rmode, nregs, NULL, pcum->silent_p); } -#endif /* Given MODE and TYPE of a function argument, return the alignment in bits. The idea is to suppress any stronger alignment requested by @@ -6697,7 +6669,7 @@ aarch64_function_arg_alignment (machine_mode mode, const_tree type, if (integer_zerop (TYPE_SIZE (type))) return 0; - gcc_assert (TARGET_MACHO || TYPE_MODE (type) == mode); + gcc_assert (TYPE_MODE (type) == mode); if (!AGGREGATE_TYPE_P (type)) { @@ -6895,14 +6867,6 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) Both behaviors were wrong, but in different cases. */ pcum->aapcs_arg_processed = true; - if (TARGET_MACHO) - { - /* Set suitable defaults for queries. */ - pcum->darwinpcs_arg_boundary - = aarch64_function_arg_alignment (mode, type, &abi_break_gcc_9, - &abi_break_gcc_13, &abi_break_gcc_14); - pcum->darwinpcs_arg_padding = BITS_PER_UNIT; - } pure_scalable_type_info pst_info; if (type && pst_info.analyze_registers (type)) @@ -6962,29 +6926,13 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) /* No frontends can create types with variable-sized modes, so we shouldn't be asked to pass or return them. */ size = GET_MODE_SIZE (mode).to_constant (); - - if (TARGET_MACHO) - /* Since we can pack things on the stack, we need the unrounded size. */ - pcum->darwinpcs_stack_bytes = size; - size = ROUND_UP (size, UNITS_PER_WORD); allocate_ncrn = (type) ? !(FLOAT_TYPE_P (type)) : !FLOAT_MODE_P (mode); - bool is_ha = false; -#if !TARGET_MACHO allocate_nvrn = aarch64_vfp_is_call_candidate (pcum_v, mode, type, &nregs); -#else - /* We care if the value is a homogenous aggregate when laying out the stack, - so use this call directly. */ - allocate_nvrn - = aarch64_vfp_is_call_or_return_candidate (mode, type, - &pcum->aapcs_vfp_rmode, - &nregs, &is_ha, - pcum->silent_p); -#endif gcc_assert (!sve_p || !allocate_nvrn); unsigned int alignment @@ -7013,13 +6961,7 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) if (!pcum->silent_p && !TARGET_FLOAT) aarch64_err_no_fpadvsimd (mode); - if (TARGET_MACHO - && !arg.named) - { - pcum->aapcs_nextnvrn = NUM_FP_ARG_REGS; - goto on_stack; - } - else if (nvrn + nregs <= NUM_FP_ARG_REGS) + if (nvrn + nregs <= NUM_FP_ARG_REGS) { pcum->aapcs_nextnvrn = nvrn + nregs; if (!aarch64_composite_type_p (type, mode)) @@ -7049,7 +6991,6 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) } pcum->aapcs_reg = par; } - pcum->darwinpcs_stack_bytes = 0; return; } else @@ -7066,24 +7007,14 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) /* C6 - C9. though the sign and zero extension semantics are handled elsewhere. This is the case where the argument fits entirely general registers. */ - if (allocate_ncrn && (ncrn + nregs <= NUM_ARG_REGS)) { gcc_assert (nregs == 0 || nregs == 1 || nregs == 2); - if (TARGET_MACHO - && !arg.named) - { - pcum->aapcs_nextncrn = NUM_ARG_REGS; - goto on_stack; - } - /* C.8 if the argument has an alignment of 16 then the NGRN is rounded up to the next even number. */ if (nregs == 2 - && ncrn % 2 - /* Darwin PCS deletes rule C.8. */ - && !TARGET_MACHO) + && ncrn % 2) { /* Emit a warning if the alignment changed when taking the 'packed' attribute into account. */ @@ -7153,8 +7084,8 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) } pcum->aapcs_reg = par; } + pcum->aapcs_nextncrn = ncrn + nregs; - pcum->darwinpcs_stack_bytes = 0; return; } @@ -7164,81 +7095,7 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) /* The argument is passed on stack; record the needed number of words for this argument and align the total size if necessary. */ on_stack: - - if (TARGET_MACHO) - { - /* Darwin does not round up the allocation for smaller entities to 8 - bytes. It only requires the natural alignment for these. - - but we don't do this for: - * unnamed parms in variadic functions - * complex types - * unions - * aggregates (except for homogeneous ones which are handles as the - enclosed type). - each entry starts a new slot. - - 16 byte entities are naturally aligned on the stack. - There was no darwinpcs for GCC 9, so neither the implementation - change nor the warning should fire here (i.e. we do not need to check - if 16byte entities alter the stack size). */ - - gcc_checking_assert (arg.named == pcum->named_p); - pcum->darwinpcs_arg_padding = BITS_PER_UNIT; - if (!pcum->named_p - || TREE_CODE (type) == COMPLEX_TYPE - || (TREE_CODE (type) == RECORD_TYPE - && !is_ha && !SCALAR_FLOAT_MODE_P (pcum->aapcs_vfp_rmode)) - || TREE_CODE (type) == UNION_TYPE) - { - pcum->aapcs_stack_words = size / UNITS_PER_WORD; - pcum->darwinpcs_sub_word_offset = 0; - pcum->darwinpcs_sub_word_pos = 0; - pcum->darwinpcs_arg_boundary = MAX (alignment, PARM_BOUNDARY); - if (!pcum->named_p) - pcum->darwinpcs_arg_padding = PARM_BOUNDARY; - return; - } - - /* Updated sub-word offset aligned for the new object. - We are looking for the case that the new object will fit after some - existing object(s) in the same stack slot. In that case, we do not - need to add any more stack space for it. */ - int new_off - = ROUND_UP (pcum->darwinpcs_sub_word_pos, alignment / BITS_PER_UNIT); - - if (new_off >= UNITS_PER_WORD) - { - /* That exceeds a stack slot, start a new one. */ - pcum->darwinpcs_sub_word_offset = 0; - pcum->darwinpcs_sub_word_pos = 0; - new_off = 0; - } - /* This is the end of the new object. */ - int new_pos = new_off + pcum->darwinpcs_stack_bytes; - - if (pcum->darwinpcs_sub_word_pos == 0) - /* New stack slot, just allocate one or more words, and note where - the next arg will start. */ - pcum->aapcs_stack_words = size / UNITS_PER_WORD; - else if (new_pos <= UNITS_PER_WORD) - /* Old stack slot, object starts at new_off and goes to new_pos, we do - not add any stack space. */ - pcum->darwinpcs_sub_word_offset = new_off; - pcum->darwinpcs_sub_word_pos = new_pos; - pcum->darwinpcs_arg_boundary = alignment ; - if (pcum->last_named_p && new_pos > 0) - { - /* Round the last named arg to the start of the next stack slot. */ - if (new_pos <= 4) - pcum->darwinpcs_arg_padding = PARM_BOUNDARY; - else if (new_pos <= 6) - pcum->darwinpcs_arg_padding = 4 * BITS_PER_UNIT; - else if (pcum->darwinpcs_sub_word_pos <= 7) - pcum->darwinpcs_arg_padding = 2 * BITS_PER_UNIT; - } - return; - } + pcum->aapcs_stack_words = size / UNITS_PER_WORD; if (warn_pcs_change_le_gcc14 && abi_break_gcc_13 @@ -7254,8 +7111,6 @@ on_stack: inform (input_location, "parameter passing for argument of type " "%qT changed in GCC 14.1", type); - /* size was already rounded up to PARM_BOUNDARY. */ - pcum->aapcs_stack_words = size / UNITS_PER_WORD; if (alignment == 16 * BITS_PER_UNIT) { int new_size = ROUND_UP (pcum->aapcs_stack_size, 16 / UNITS_PER_WORD); @@ -7360,33 +7215,12 @@ aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum, pcum->aapcs_arg_processed = false; pcum->aapcs_stack_words = 0; pcum->aapcs_stack_size = 0; - pcum->darwinpcs_stack_bytes = 0; - pcum->darwinpcs_sub_word_offset = 0; - pcum->darwinpcs_sub_word_pos = 0; - pcum->darwinpcs_arg_boundary = BITS_PER_UNIT; - pcum->darwinpcs_arg_padding = BITS_PER_UNIT; - /* If we have been invoked for incoming args, then n_named will have been - set to -1, but we should have a function decl - so pick up the named - count from that. If that fails, and we end up with -1, this effectively - corresponds to assuming that there is an arbitrary number of named - args. */ - pcum->darwinpcs_n_named = n_named; - if (n_named == (unsigned)-1 && fndecl) - { - tree fnt = TREE_TYPE (fndecl); - if (fnt && TYPE_ARG_TYPES (fnt)) - pcum->darwinpcs_n_named = list_length (TYPE_ARG_TYPES (fnt)); - } - pcum->darwinpcs_n_args_processed = 0; - pcum->named_p = pcum->darwinpcs_n_named != 0; - pcum->last_named_p = pcum->darwinpcs_n_named == 1; pcum->silent_p = silent_p; pcum->shared_za_flags = (fntype ? aarch64_fntype_shared_flags (fntype, "za") : 0U); pcum->shared_zt0_flags = (fntype ? aarch64_fntype_shared_flags (fntype, "zt0") : 0U); pcum->num_sme_mode_switch_args = 0; - pcum->aapcs_vfp_rmode = VOIDmode; if (!silent_p && !TARGET_FLOAT @@ -7425,11 +7259,9 @@ aarch64_function_arg_advance (cumulative_args_t pcum_v, || pcum->pcs_variant == ARM_PCS_SVE) { aarch64_layout_arg (pcum_v, arg); - pcum->darwinpcs_n_args_processed++; - gcc_assert (TARGET_MACHO - || (pcum->aapcs_reg != NULL_RTX) - != (pcum->aapcs_stack_words != 0)); - if (pcum->aapcs_reg + gcc_assert ((pcum->aapcs_reg != NULL_RTX) + != (pcum->aapcs_stack_words != 0)); + if (pcum->aapcs_reg && aarch64_call_switches_pstate_sm (pcum->isa_mode)) aarch64_record_sme_mode_switch_args (pcum); @@ -7440,12 +7272,6 @@ aarch64_function_arg_advance (cumulative_args_t pcum_v, pcum->aapcs_stack_size += pcum->aapcs_stack_words; pcum->aapcs_stack_words = 0; pcum->aapcs_reg = NULL_RTX; - pcum->darwinpcs_arg_boundary = BITS_PER_UNIT; - pcum->darwinpcs_arg_padding = BITS_PER_UNIT; - pcum->named_p - = pcum->darwinpcs_n_args_processed < pcum->darwinpcs_n_named; - pcum->last_named_p - = pcum->darwinpcs_n_args_processed + 1 == pcum->darwinpcs_n_named; } } @@ -7457,15 +7283,12 @@ aarch64_function_arg_regno_p (unsigned regno) || (PR_REGNUM_P (regno) && regno < P0_REGNUM + NUM_PR_ARG_REGS)); } -/* Implement FUNCTION_ARG_BOUNDARY. - For AAPCS64, Every parameter gets at least PARM_BOUNDARY bits of - alignment, but will be given anything up to STACK_BOUNDARY bits - if the type requires it. This makes sure that both before and after - the layout of each argument, the Next Stacked Argument Address (NSAA) - will have a minimum alignment of 8 bytes. - - For darwinpcs, this is only called to lower va_arg entries which are - always aligned as for AAPCS64. */ +/* Implement FUNCTION_ARG_BOUNDARY. Every parameter gets at least + PARM_BOUNDARY bits of alignment, but will be given anything up + to STACK_BOUNDARY bits if the type requires it. This makes sure + that both before and after the layout of each argument, the Next + Stacked Argument Address (NSAA) will have a minimum alignment of + 8 bytes. */ static unsigned int aarch64_function_arg_boundary (machine_mode mode, const_tree type) @@ -7479,108 +7302,8 @@ aarch64_function_arg_boundary (machine_mode mode, const_tree type) &abi_break_gcc_14); /* We rely on aarch64_layout_arg and aarch64_gimplify_va_arg_expr to emit warnings about ABI incompatibility. */ -#if TARGET_MACHO - /* This can only work for unnamed args. */ - machine_mode comp_mode = VOIDmode; - int nregs; - bool is_ha; - aarch64_vfp_is_call_or_return_candidate (mode, type, &comp_mode, &nregs, - &is_ha, /*silent*/true); - if (TREE_CODE (type) == COMPLEX_TYPE - || (TREE_CODE (type) == RECORD_TYPE - && !is_ha && !SCALAR_FLOAT_MODE_P (comp_mode)) - || TREE_CODE (type) == UNION_TYPE) - return MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY); - return MIN (alignment, STACK_BOUNDARY); -#else - alignment = MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY); - return alignment; -#endif -} - -/* For Darwin, we want to use the arg boundary computed when laying out the - function arg, to cope with items packed on the stack and the different - rules applied to unnamed parms. */ - -static unsigned int -aarch64_function_arg_boundary_ca (machine_mode mode ATTRIBUTE_UNUSED, - const_tree type ATTRIBUTE_UNUSED, - cumulative_args_t ca ATTRIBUTE_UNUSED) -{ - unsigned int abi_break_gcc_9; - unsigned int abi_break_gcc_13; - unsigned int abi_break_gcc_14; - unsigned int alignment - = aarch64_function_arg_alignment (mode, type, &abi_break_gcc_9, - &abi_break_gcc_13, &abi_break_gcc_14); - /* We rely on aarch64_layout_arg and aarch64_gimplify_va_arg_expr - to emit warnings about ABI incompatibility. */ -#if TARGET_MACHO - CUMULATIVE_ARGS *pcum = get_cumulative_args (ca); -gcc_checking_assert (pcum->aapcs_arg_processed); - - bool named_p = pcum->darwinpcs_n_args_processed < pcum->darwinpcs_n_named; -gcc_checking_assert (named_p == pcum->named_p); - machine_mode comp_mode = VOIDmode; - int nregs; - bool is_ha; - aarch64_vfp_is_call_or_return_candidate (mode, type, &comp_mode, &nregs, - &is_ha, /*silent*/true); - bool no_pack = (TREE_CODE (type) == COMPLEX_TYPE - || (TREE_CODE (type) == RECORD_TYPE - && !is_ha && !SCALAR_FLOAT_MODE_P (comp_mode)) - || TREE_CODE (type) == UNION_TYPE); - - bool in_regs = (pcum->aapcs_reg != NULL_RTX); - - if ((named_p && !no_pack) || in_regs) - ; /* Leave the alignment as natural. */ - else - alignment = MAX (alignment, PARM_BOUNDARY); -gcc_checking_assert (alignment == pcum->darwinpcs_arg_boundary); - return MIN (alignment, STACK_BOUNDARY); - -#else alignment = MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY); return alignment; -#endif -} - -/* Implement TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA for darwinpcs which allows - non-standard passing of byte-aligned items [D.2]. This is done by pulling - the values out of the cumulative args struct. */ - -static unsigned int -aarch64_function_arg_round_boundary_ca (machine_mode mode ATTRIBUTE_UNUSED, - const_tree type ATTRIBUTE_UNUSED, - cumulative_args_t ca) -{ - CUMULATIVE_ARGS *pcum = get_cumulative_args (ca); -gcc_checking_assert (pcum->aapcs_arg_processed); - bool named_p = pcum->darwinpcs_n_args_processed < pcum->darwinpcs_n_named; -gcc_checking_assert (named_p == pcum->named_p); - bool last_named_p = pcum->darwinpcs_n_args_processed + 1 == pcum->darwinpcs_n_named; -gcc_checking_assert (last_named_p == pcum->last_named_p); - - unsigned boundary = BITS_PER_UNIT; - if (last_named_p && pcum->darwinpcs_sub_word_pos > 0) - { - /* Round the last named arg to the start of the next stack slot. */ - if (pcum->darwinpcs_sub_word_pos <= 4) - boundary = PARM_BOUNDARY; - else if (pcum->darwinpcs_sub_word_pos <= 6) - boundary = 4 * BITS_PER_UNIT; - else if (pcum->darwinpcs_sub_word_pos <= 7) - boundary = 2 * BITS_PER_UNIT; - } - else if (named_p) - /* Named args are naturally aligned, but with no rounding. */ - ; - else - /* un-named args are rounded to fill slots. */ - boundary = PARM_BOUNDARY; -gcc_checking_assert (boundary == pcum->darwinpcs_arg_padding); - return boundary; } /* Implement TARGET_GET_RAW_RESULT_MODE and TARGET_GET_RAW_ARG_MODE. */ @@ -10977,7 +10700,6 @@ aarch64_classify_address (struct aarch64_address_info *info, /* load literal: pc-relative constant pool entry. Only supported for SI mode or larger. */ info->type = ADDRESS_SYMBOLIC; - info->offset = NULL_RTX; if (!load_store_pair_p && GET_MODE_SIZE (mode).is_constant (&const_size) @@ -10985,7 +10707,6 @@ aarch64_classify_address (struct aarch64_address_info *info, { poly_int64 offset; rtx sym = strip_offset_and_salt (x, &offset); - return ((LABEL_REF_P (sym) || (SYMBOL_REF_P (sym) && CONSTANT_POOL_ADDRESS_P (sym) @@ -11003,13 +10724,10 @@ aarch64_classify_address (struct aarch64_address_info *info, poly_int64 offset; HOST_WIDE_INT const_offset; rtx sym = strip_offset_and_salt (info->offset, &offset); - if (SYMBOL_REF_P (sym) && offset.is_constant (&const_offset) && (aarch64_classify_symbol (sym, const_offset) - == SYMBOL_SMALL_ABSOLUTE - || aarch64_classify_symbol (sym, const_offset) - == SYMBOL_MO_SMALL_PCR)) + == SYMBOL_SMALL_ABSOLUTE)) { /* The symbol and offset must be aligned to the access size. */ unsigned int align; @@ -11059,55 +10777,6 @@ aarch64_address_valid_for_prefetch_p (rtx x, bool strict_p) if (!res) return false; - /* For ELF targets using GAS, we emit prfm unconditionally; GAS will alter - the instruction to pick the prfum form where possible (i.e. when the - offset is in the range -256..255) and fall back to prfm otherwise. - We can reject cases where the offset exceeds the range usable by both - insns [-256..32760], or for offsets > 255 when the value is not divisible - by 8. - For Mach-O (Darwin) where the assembler uses the LLVM back end, that does - not yet do the substitution, so we must reject all prfum cases. */ - if (addr.offset) - { - HOST_WIDE_INT offs = INTVAL (addr.offset); - if (offs < -256) /* Out of range for both prfum and prfm. */ - return false; - if (offs > 32760) /* Out of range for prfm. */ - return false; - if (offs & 0x07) /* We cannot use prfm. */ - { - if (offs > 255) /* Out of range for prfum. */ - return false; - if (TARGET_MACHO) - return false; - } - if (TARGET_MACHO && offs < 0) - return false; - } - - /* ... except writeback forms. */ - return addr.type != ADDRESS_REG_WB; -} - -/* Return true if the address X is valid for a PRFUM instruction. - STRICT_P is true if we should do strict checking with - aarch64_classify_address. */ - -bool -aarch64_address_valid_for_unscaled_prefetch_p (rtx x, bool strict_p) -{ - struct aarch64_address_info addr; - - /* PRFUM accepts the same addresses as DImode, but constrained to a range - -256..255. */ - bool res = aarch64_classify_address (&addr, x, DImode, strict_p); - if (!res) - return false; - - if (addr.offset && ((INTVAL (addr.offset) > 255) - || (INTVAL (addr.offset) < -256))) - return false; - /* ... except writeback forms. */ return addr.type != ADDRESS_REG_WB; } @@ -12241,144 +11910,6 @@ sizetochar (int size) } } -static void -output_macho_postfix_expr (FILE *file, rtx x, const char *postfix) -{ - char buf[256]; - - restart: - switch (GET_CODE (x)) - { - case PC: - putc ('.', file); - break; - - case SYMBOL_REF: - if (SYMBOL_REF_DECL (x)) - assemble_external (SYMBOL_REF_DECL (x)); - assemble_name (file, XSTR (x, 0)); - fprintf (file, "@%s", postfix); - break; - - case LABEL_REF: - x = label_ref_label (x); - /* Fall through. */ - case CODE_LABEL: - ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); - assemble_name (file, buf); - fprintf (file, "@%s", postfix); - break; - - case CONST_INT: - fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); - break; - - case CONST: - /* This used to output parentheses around the expression, - but that does not work on the 386 (either ATT or BSD assembler). */ - output_macho_postfix_expr (file, XEXP (x, 0), postfix); - break; - - case CONST_WIDE_INT: - /* We do not know the mode here so we have to use a round about - way to build a wide-int to get it printed properly. */ - { - wide_int w = wide_int::from_array (&CONST_WIDE_INT_ELT (x, 0), - CONST_WIDE_INT_NUNITS (x), - CONST_WIDE_INT_NUNITS (x) - * HOST_BITS_PER_WIDE_INT, - false); - print_decs (w, file); - } - break; - - case CONST_DOUBLE: - if (CONST_DOUBLE_AS_INT_P (x)) - { - /* We can use %d if the number is one word and positive. */ - if (CONST_DOUBLE_HIGH (x)) - fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX, - (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x), - (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x)); - else if (CONST_DOUBLE_LOW (x) < 0) - fprintf (file, HOST_WIDE_INT_PRINT_HEX, - (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x)); - else - fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x)); - } - else - /* We can't handle floating point constants; - PRINT_OPERAND must handle them. */ - output_operand_lossage ("floating constant misused"); - break; - - case CONST_FIXED: - fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_FIXED_VALUE_LOW (x)); - break; - - case PLUS: - /* Some assemblers need integer constants to appear last (eg masm). */ - if (CONST_INT_P (XEXP (x, 0))) - { - output_macho_postfix_expr (file, XEXP (x, 1), postfix); - if (INTVAL (XEXP (x, 0)) >= 0) - fprintf (file, "+"); - output_addr_const (file, XEXP (x, 0)); - } - else - { - output_macho_postfix_expr (file, XEXP (x, 0), postfix); - if (!CONST_INT_P (XEXP (x, 1)) - || INTVAL (XEXP (x, 1)) >= 0) - fprintf (file, "+"); - output_addr_const (file, XEXP (x, 1)); - } - break; - - case MINUS: - /* Avoid outputting things like x-x or x+5-x, - since some assemblers can't handle that. */ - x = simplify_subtraction (x); - if (GET_CODE (x) != MINUS) - goto restart; - - output_macho_postfix_expr (file, XEXP (x, 0), postfix); - fprintf (file, "-"); - if ((CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) >= 0) - || GET_CODE (XEXP (x, 1)) == PC - || GET_CODE (XEXP (x, 1)) == SYMBOL_REF) - output_addr_const (file, XEXP (x, 1)); - else - { - fputs (targetm.asm_out.open_paren, file); - output_addr_const (file, XEXP (x, 1)); - fputs (targetm.asm_out.close_paren, file); - } - break; - - case ZERO_EXTEND: - case SIGN_EXTEND: - case SUBREG: - case TRUNCATE: - output_addr_const (file, XEXP (x, 0)); - break; - - case UNSPEC: - if (XINT (x, 1) == UNSPEC_SALT_ADDR) - { - output_macho_postfix_expr (file, XVECEXP (x, 0, 0), postfix); - break; - } - /* FALLTHROUGH */ - default: - if (targetm.asm_out.output_addr_const_extra (file, x)) - break; - - output_operand_lossage ("invalid expression as operand"); - } - -} - /* Print operand X to file F in a target specific manner according to CODE. The acceptable formatting commands given by CODE are: 'c': An integer or symbol address without a preceding # @@ -12452,12 +11983,6 @@ aarch64_print_operand (FILE *f, rtx x, int code) } break; - case 'J': - output_macho_postfix_expr (f, x, "PAGEOFF"); - break; - case 'O': - output_macho_postfix_expr (f, x, "GOTPAGEOFF"); - break; case 'e': { x = unwrap_const_vec_duplicate (x); @@ -12790,7 +12315,7 @@ aarch64_print_operand (FILE *f, rtx x, int code) case 'A': if (GET_CODE (x) == HIGH) x = XEXP (x, 0); -#if !TARGET_MACHO + switch (aarch64_classify_symbolic_expression (x)) { case SYMBOL_SMALL_GOT_4G: @@ -12821,26 +12346,9 @@ aarch64_print_operand (FILE *f, rtx x, int code) break; } output_addr_const (asm_out_file, x); -#endif -#if TARGET_MACHO - switch (aarch64_classify_symbolic_expression (x)) - { - case SYMBOL_MO_SMALL_PCR: - output_macho_postfix_expr (asm_out_file, x, "PAGE"); - break; - case SYMBOL_MO_SMALL_GOT: - output_macho_postfix_expr (asm_out_file, x, "GOTPAGE"); - break; - default: - /* large code model unimplemented. */ - gcc_unreachable (); - break; - } -#endif break; case 'L': -#if !TARGET_MACHO switch (aarch64_classify_symbolic_expression (x)) { case SYMBOL_SMALL_GOT_4G: @@ -12878,12 +12386,10 @@ aarch64_print_operand (FILE *f, rtx x, int code) default: break; } -#endif output_addr_const (asm_out_file, x); break; case 'G': -#if !TARGET_MACHO switch (aarch64_classify_symbolic_expression (x)) { case SYMBOL_TLSLE24: @@ -12892,7 +12398,6 @@ aarch64_print_operand (FILE *f, rtx x, int code) default: break; } -#endif output_addr_const (asm_out_file, x); break; @@ -13058,13 +12563,8 @@ aarch64_print_address_internal (FILE *f, machine_mode mode, rtx x, break; case ADDRESS_LO_SUM: -#if TARGET_MACHO - asm_fprintf (f, "[%s, #", reg_names [REGNO (addr.base)]); - output_macho_postfix_expr (f, addr.offset, "PAGEOFF"); -#else asm_fprintf (f, "[%s, #:lo12:", reg_names [REGNO (addr.base)]); output_addr_const (f, addr.offset); -#endif asm_fprintf (f, "]"); return true; @@ -13372,23 +12872,7 @@ aarch64_frame_pointer_required () { /* If the function needs to record the incoming value of PSTATE.SM, make sure that the slot is accessible from the frame pointer. */ - if (!TARGET_MACHO) - return aarch64_need_old_pstate_sm (); - - /* We could do with some more general test. - gcc_checking_assert (!aarch64_need_old_pstate_sm ());*/ - - if (crtl->calls_eh_return || aarch64_need_old_pstate_sm ()) - return true; - - /* Not used in leaf functions (unless forced). */ - if (flag_omit_leaf_frame_pointer && leaf_function_p ()) - return false; - - /* NOTE: We are allowing the user to force omission of the frame - pointer, (despite that it is not ABI-compliant). */ - - return flag_omit_frame_pointer != 1; + return aarch64_need_old_pstate_sm (); } static bool @@ -13616,8 +13100,6 @@ aarch64_asm_output_labelref (FILE* f, const char *name) asm_fprintf (f, "%U%s", name); } -#if !TARGET_MACHO - static void aarch64_elf_asm_constructor (rtx symbol, int priority) { @@ -13657,7 +13139,6 @@ aarch64_elf_asm_destructor (rtx symbol, int priority) assemble_aligned_integer (POINTER_BYTES, symbol); } } -#endif const char* aarch64_output_casesi (rtx *operands) @@ -13810,11 +13291,7 @@ aarch64_select_rtx_section (machine_mode mode, if (aarch64_can_use_per_function_literal_pools_p ()) return function_section (current_function_decl); -#if TARGET_MACHO - return machopic_select_rtx_section (mode, x, align); -#else return default_elf_select_rtx_section (mode, x, align); -#endif } /* Implement ASM_OUTPUT_POOL_EPILOGUE. */ @@ -16098,17 +15575,15 @@ aarch64_init_builtins () { aarch64_general_init_builtins (); aarch64_sve::init_builtins (); - aarch64_init_subtarget_builtins (); +#ifdef SUBTARGET_INIT_BUILTINS + SUBTARGET_INIT_BUILTINS; +#endif } /* Implement TARGET_FOLD_BUILTIN. */ static tree aarch64_fold_builtin (tree fndecl, int nargs, tree *args, bool) { -#ifdef SUBTARGET_FOLD_BUILTIN - if (tree res = SUBTARGET_FOLD_BUILTIN (fndecl, nargs, args, false)) - return res; -#endif unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; tree type = TREE_TYPE (TREE_TYPE (fndecl)); @@ -19513,14 +18988,10 @@ initialize_aarch64_code_model (struct gcc_options *opts) } break; case AARCH64_CMODEL_LARGE: - if (TARGET_MACHO) - /* We need to implement fPIC here (arm64_32 also accepts the large - model). */ - sorry ("code model %qs not supported yet", "large"); - else if (opts->x_flag_pic) + if (opts->x_flag_pic) sorry ("code model %qs with %<-f%s%>", "large", opts->x_flag_pic > 1 ? "PIC" : "pic"); - else if (opts->x_aarch64_abi == AARCH64_ABI_ILP32) + if (opts->x_aarch64_abi == AARCH64_ABI_ILP32) sorry ("code model %qs not supported in ilp32 mode", "large"); break; case AARCH64_CMODEL_TINY_PIC: @@ -21437,9 +20908,7 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) case AARCH64_CMODEL_SMALL_SPIC: case AARCH64_CMODEL_SMALL_PIC: case AARCH64_CMODEL_SMALL: - return TARGET_MACHO - ? SYMBOL_MO_SMALL_PCR - : SYMBOL_SMALL_ABSOLUTE; + return SYMBOL_SMALL_ABSOLUTE; default: gcc_unreachable (); @@ -21475,22 +20944,10 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) return SYMBOL_TINY_ABSOLUTE; + case AARCH64_CMODEL_SMALL_SPIC: case AARCH64_CMODEL_SMALL_PIC: case AARCH64_CMODEL_SMALL: -#if TARGET_MACHO - if (TARGET_MACHO) - { - /* Constant pool addresses are always TU-local and PC- - relative. We indirect common, external and weak - symbols (but weak only if not hidden). */ - if (!CONSTANT_POOL_ADDRESS_P (x) - && (MACHO_SYMBOL_MUST_INDIRECT_P (x) - || !aarch64_symbol_binds_local_p (x))) - return SYMBOL_MO_SMALL_GOT; - } - else -#endif if ((flag_pic || SYMBOL_REF_WEAK (x)) && !aarch64_symbol_binds_local_p (x)) return aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC @@ -21502,8 +20959,7 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) || offset_within_block_p (x, offset))) return SYMBOL_FORCE_TO_MEM; - return TARGET_MACHO ? SYMBOL_MO_SMALL_PCR - : SYMBOL_SMALL_ABSOLUTE; + return SYMBOL_SMALL_ABSOLUTE; case AARCH64_CMODEL_LARGE: /* This is alright even in PIC code as the constant @@ -21633,10 +21089,7 @@ static GTY(()) tree va_list_type; void *__vr_top; int __gr_offs; int __vr_offs; - }; - - darwinpcs uses 'char *' for the va_list (in common with other platform - ports). */ + }; */ static tree aarch64_build_builtin_va_list (void) @@ -21644,13 +21097,6 @@ aarch64_build_builtin_va_list (void) tree va_list_name; tree f_stack, f_grtop, f_vrtop, f_groff, f_vroff; - /* darwinpcs uses a simple char * for this. */ - if (TARGET_MACHO) - { - va_list_type = build_pointer_type (char_type_node); - return va_list_type; - } - /* Create the type. */ va_list_type = lang_hooks.types.make_type (RECORD_TYPE); /* Give it the required name. */ @@ -21722,13 +21168,6 @@ aarch64_expand_builtin_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) int vr_save_area_size = cfun->va_list_fpr_size; int vr_offset; - /* darwinpcs uses the default, char * va_list impl. */ - if (TARGET_MACHO) - { - std_expand_builtin_va_start (valist, nextarg); - return; - } - cum = &crtl->args.info; if (cfun->va_list_gpr_size) gr_save_area_size = MIN ((NUM_ARG_REGS - cum->aapcs_ncrn) * UNITS_PER_WORD, @@ -21819,9 +21258,6 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, HOST_WIDE_INT size, rsize, adjust, align; tree t, u, cond1, cond2; - if (TARGET_MACHO) - return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); - indirect_p = pass_va_arg_by_reference (type); if (indirect_p) type = build_pointer_type (type); @@ -22026,18 +21462,8 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, field_ptr_t = double_ptr_type_node; break; case E_TFmode: - if (TARGET_MACHO) - { - /* Darwin has __float128, and long double is the same as - double. */ - field_t = float128_type_node; - field_ptr_t = aarch64_float128_ptr_type_node; - } - else - { - field_t = long_double_type_node; - field_ptr_t = long_double_ptr_type_node; - } + field_t = long_double_type_node; + field_ptr_t = long_double_ptr_type_node; break; case E_SDmode: field_t = dfloat32_type_node; @@ -22120,9 +21546,6 @@ aarch64_setup_incoming_varargs (cumulative_args_t cum_v, int gr_saved = cfun->va_list_gpr_size; int vr_saved = cfun->va_list_fpr_size; - if (TARGET_MACHO) - return default_setup_incoming_varargs (cum_v, arg, pretend_size, no_rtl); - /* The caller has advanced CUM up to, but not beyond, the last named argument. Advance a local copy of CUM past the last "real" named argument, to find out how many registers are left over. */ @@ -22966,12 +22389,6 @@ aarch64_autovectorize_vector_modes (vector_modes *modes, bool) static const char * aarch64_mangle_type (const_tree type) { - /* The darwinpcs ABI documents say that "__va_list" has to be - mangled as char *. */ - if (TARGET_MACHO - && lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type)) - return "Pc"; - /* The AArch64 ABI documents say that "__va_list" has to be mangled as if it is in the "std" namespace. */ if (lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type)) @@ -22988,12 +22405,6 @@ aarch64_mangle_type (const_tree type) return "Dh"; } - /* __float128 is mangled as "g" on darwin. _Float128 is not mangled here, - but handled in common code (as "DF128_"). */ - if (TARGET_MACHO && TYPE_MODE (type) == TFmode - && TYPE_MAIN_VARIANT (type) == float128t_type_node) - return "g"; - /* Mangle AArch64-specific internal types. TYPE_NAME is non-NULL_TREE for builtin types. */ if (TYPE_NAME (type) != NULL) @@ -23691,8 +23102,7 @@ aarch64_mov_operand_p (rtx x, machine_mode mode) /* GOT accesses are valid moves. */ if (SYMBOL_REF_P (x) - && (aarch64_classify_symbolic_expression (x) == SYMBOL_SMALL_GOT_4G - || aarch64_classify_symbolic_expression (x) == SYMBOL_MO_SMALL_GOT)) + && aarch64_classify_symbolic_expression (x) == SYMBOL_SMALL_GOT_4G) return true; if (SYMBOL_REF_P (x) && mode == DImode && CONSTANT_ADDRESS_P (x)) @@ -25029,8 +24439,12 @@ aarch64_asm_output_variant_pcs (FILE *stream, const tree decl, const char* name) static std::string aarch64_last_printed_arch_string; static std::string aarch64_last_printed_tune_string; -static void -aarch64_function_options_preamble (tree fndecl) +/* Implement ASM_DECLARE_FUNCTION_NAME. Output the ISA features used + by the function fndecl. */ + +void +aarch64_declare_function_name (FILE *stream, const char* name, + tree fndecl) { tree target_parts = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); @@ -25069,60 +24483,15 @@ aarch64_function_options_preamble (tree fndecl) this_tune->name); aarch64_last_printed_tune_string = this_tune->name; } -} - -/* Implement ASM_DECLARE_FUNCTION_NAME. Output the ISA features used - by the function fndecl. */ - -#if TARGET_MACHO -void -aarch64_darwin_declare_function_name (FILE *stream, const char* name, - tree fndecl) -{ - gcc_checking_assert (TREE_CODE (fndecl) == FUNCTION_DECL); - gcc_checking_assert (!DECL_COMMON (fndecl)); - /* Update .arch and .tune as needed. */ - aarch64_function_options_preamble (fndecl); - - /* Darwin does not emit pcs variant info. */ - - rtx decl_rtx = XEXP (DECL_RTL (fndecl), 0); - if (GET_CODE (decl_rtx) != SYMBOL_REF) - name = IDENTIFIER_POINTER (DECL_NAME (fndecl)); - - if (! DECL_WEAK (fndecl) - && ((TREE_STATIC (fndecl) && !TREE_PUBLIC (fndecl)) - || DECL_INITIAL (fndecl))) - machopic_define_symbol (DECL_RTL (fndecl)); - if ((TREE_STATIC (fndecl) && !TREE_PUBLIC (fndecl)) - || DECL_INITIAL (fndecl)) - (* targetm.encode_section_info) (fndecl, DECL_RTL (fndecl), false); - ASM_OUTPUT_FUNCTION_LABEL (stream, name, fndecl); - - cfun->machine->label_is_assembled = true; -} - -#else - -void -aarch64_declare_function_name (FILE *stream, const char* name, - tree fndecl) -{ - /* Update .arch and .tune as needed. */ - aarch64_function_options_preamble (fndecl); - /* Emit any necessary pcs information. */ aarch64_asm_output_variant_pcs (stream, fndecl, name); /* Don't forget the type directive for ELF. */ -#ifdef ASM_OUTPUT_TYPE_DIRECTIVE ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "function"); -#endif ASM_OUTPUT_FUNCTION_LABEL (stream, name, fndecl); cfun->machine->label_is_assembled = true; } -#endif /* Implement PRINT_PATCHABLE_FUNCTION_ENTRY. */ @@ -25179,17 +24548,12 @@ aarch64_output_patchable_area (unsigned int patch_area_size, bool record_p) /* Implement ASM_OUTPUT_DEF_FROM_DECLS. Output .variant_pcs for aliases. */ void -aarch64_asm_output_alias (FILE *stream, const tree decl, - const tree target ATTRIBUTE_UNUSED) +aarch64_asm_output_alias (FILE *stream, const tree decl, const tree target) { const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); -#ifdef ASM_OUTPUT_DEF const char *value = IDENTIFIER_POINTER (target); -#endif aarch64_asm_output_variant_pcs (stream, decl, name); -#ifdef ASM_OUTPUT_DEF ASM_OUTPUT_DEF (stream, name, value); -#endif } /* Implement ASM_OUTPUT_EXTERNAL. Output .variant_pcs for undefined @@ -25235,9 +24599,6 @@ aarch64_start_file (void) aarch64_last_printed_arch_string.c_str ()); default_file_start (); -#if TARGET_MACHO - darwin_file_start (); -#endif } /* Emit load exclusive. */ @@ -25817,16 +25178,6 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width, } gcc_assert (CONST_INT_P (info.u.mov.value)); - unsigned HOST_WIDE_INT value = UINTVAL (info.u.mov.value); - - /* We have signed chars which can result in a sign-extended 8bit value - which is then emitted as an unsigned hex value, and the LLVM back end - assembler rejects that as being too big. */ - if (TARGET_MACHO && (known_eq (GET_MODE_BITSIZE (info.elt_mode), 8))) - { - unsigned HOST_WIDE_INT mask = (1U << GET_MODE_BITSIZE (info.elt_mode))-1; - value &= mask; - } if (which == AARCH64_CHECK_MOV) { @@ -25835,16 +25186,16 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width, ? "msl" : "lsl"); if (lane_count == 1) snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX, - mnemonic, value); + mnemonic, UINTVAL (info.u.mov.value)); else if (info.u.mov.shift) snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX ", %s %d", mnemonic, lane_count, - element_char, value, shift_op, + element_char, UINTVAL (info.u.mov.value), shift_op, info.u.mov.shift); else snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX, mnemonic, lane_count, - element_char, value); + element_char, UINTVAL (info.u.mov.value)); } else { @@ -25853,12 +25204,12 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width, if (info.u.mov.shift) snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #" HOST_WIDE_INT_PRINT_DEC ", %s #%d", mnemonic, lane_count, - element_char, value, "lsl", + element_char, UINTVAL (info.u.mov.value), "lsl", info.u.mov.shift); else snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #" HOST_WIDE_INT_PRINT_DEC, mnemonic, lane_count, - element_char, value); + element_char, UINTVAL (info.u.mov.value)); } return templ; } @@ -28984,8 +28335,7 @@ aarch64_libgcc_floating_mode_supported_p (scalar_float_mode mode) } /* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE - if MODE is [BH]Fmode, or TFmode on Mach-O, and punt to the generic - implementation otherwise. */ + if MODE is [BH]Fmode, and punt to the generic implementation otherwise. */ static bool aarch64_scalar_mode_supported_p (scalar_mode mode) @@ -28993,7 +28343,7 @@ aarch64_scalar_mode_supported_p (scalar_mode mode) if (DECIMAL_FLOAT_MODE_P (mode)) return default_decimal_float_supported_p (); - return ((mode == HFmode || mode == BFmode || (mode == TFmode && TARGET_MACHO)) + return ((mode == HFmode || mode == BFmode) ? true : default_scalar_mode_supported_p (mode)); } @@ -29810,37 +29160,19 @@ aarch64_sls_emit_shared_blr_thunks (FILE *out_file) continue; const char *name = indirect_symbol_names[regnum]; - /* If the target uses a unique section for this switch to it. */ - if (DECL_SECTION_NAME (decl)) - switch_to_section (get_named_section (decl, NULL, 0)); - else - switch_to_section (text_section); + switch_to_section (get_named_section (decl, NULL, 0)); ASM_OUTPUT_ALIGN (out_file, 2); - if (!TARGET_MACHO) - targetm.asm_out.globalize_label (out_file, name); -#ifdef ASM_OUTPUT_TYPE_DIRECTIVE - ASM_OUTPUT_TYPE_DIRECTIVE (out_file, name, "function"); -#endif - if (TARGET_MACHO) - { -#ifdef ASM_WEAKEN_DECL - if (DECL_WEAK (decl)) - ASM_WEAKEN_DECL (out_file, decl, name, 0); - else -#endif - targetm.asm_out.globalize_decl_name (out_file, decl); - } + targetm.asm_out.globalize_label (out_file, name); /* Only emits if the compiler is configured for an assembler that can handle visibility directives. */ targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN); + ASM_OUTPUT_TYPE_DIRECTIVE (out_file, name, "function"); ASM_OUTPUT_LABEL (out_file, name); aarch64_sls_emit_function_stub (out_file, regnum); /* Use the most conservative target to ensure it can always be used by any function in the translation unit. */ asm_fprintf (out_file, "\tdsb\tsy\n\tisb\n"); -#ifdef ASM_DECLARE_FUNCTION_SIZE ASM_DECLARE_FUNCTION_SIZE (out_file, name, decl); -#endif } } @@ -30932,60 +30264,6 @@ aarch64_retrieve_sysreg (const char *regname, bool write_p, bool is128op) return sysreg->encoding; } -#if TARGET_MACHO -/* This handles the promotion of function return values. - It also handles function args under two specific curcumstances: - - called from combine with a register argument - - caller for a libcall with type == NULL. - The remaining cases for argument promotion are handled with access to - cumulative args data, below. */ -machine_mode -aarch64_darwin_promote_fn_mode (const_tree type, machine_mode mode, - int *punsignedp, - const_tree funtype ATTRIBUTE_UNUSED, - int for_return ATTRIBUTE_UNUSED) -{ - /* With the amended use of promote using cargs, the only cases that arrive - here with for_return == 0 are from combine (where the value is definitely - in a register) and for libcalls, where type == NULL. We want to promote - function return values in the callee, so this becomes pretty much - unconditional now. */ - if (type != NULL_TREE) - return promote_mode (type, mode, punsignedp); - return mode; -} - -/* Ensure that we only promote the mode of named parms when they are passed in - a register. Named values passed on the stack retain their original mode and - alignment. */ -machine_mode -aarch64_darwin_promote_function_mode_ca (cumulative_args_t ca, - function_arg_info arg, - const_tree funtype ATTRIBUTE_UNUSED, - int *punsignedp, - int for_return ATTRIBUTE_UNUSED) -{ - tree type = arg.type; - machine_mode mode = arg.mode; - machine_mode new_mode = promote_mode (type, mode, punsignedp); - if (new_mode == mode || arg.named == false - || GET_MODE_CLASS (new_mode) != MODE_INT - || known_gt (GET_MODE_SIZE (new_mode), 4)) - return new_mode; - - CUMULATIVE_ARGS *pcum = get_cumulative_args (ca); - /* Make sure that changes in assumption do not get missed. */ - gcc_checking_assert (for_return == 0 && new_mode == SImode - && !pcum->aapcs_arg_processed); - /* We have a named integer value that fits in a reg; if there's one available - then promote the value. */ - if (pcum->aapcs_ncrn < 8) - return new_mode; - return mode; -} - -#endif - /* Target-specific selftests. */ #if CHECKING_P @@ -31191,15 +30469,6 @@ aarch64_run_selftests (void) #undef TARGET_ASM_ALIGNED_SI_OP #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" -#if TARGET_MACHO -#undef TARGET_ASM_UNALIGNED_HI_OP -#define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t" -#undef TARGET_ASM_UNALIGNED_SI_OP -#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t" -#undef TARGET_ASM_UNALIGNED_DI_OP -#define TARGET_ASM_UNALIGNED_DI_OP "\t.quad\t" -#endif - #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \ hook_bool_const_tree_hwi_hwi_const_tree_true @@ -31302,12 +30571,6 @@ aarch64_run_selftests (void) #undef TARGET_FUNCTION_ARG_BOUNDARY #define TARGET_FUNCTION_ARG_BOUNDARY aarch64_function_arg_boundary -#undef TARGET_FUNCTION_ARG_BOUNDARY_CA -#define TARGET_FUNCTION_ARG_BOUNDARY_CA aarch64_function_arg_boundary_ca - -#undef TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA -#define TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA aarch64_function_arg_round_boundary_ca - #undef TARGET_FUNCTION_ARG_PADDING #define TARGET_FUNCTION_ARG_PADDING aarch64_function_arg_padding @@ -31648,7 +30911,7 @@ aarch64_libgcc_floating_mode_supported_p /* The architecture reserves bits 0 and 1 so use bit 2 for descriptors. */ #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS -#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS AARCH64_CUSTOM_FUNCTION_TEST +#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 4 #undef TARGET_HARD_REGNO_NREGS #define TARGET_HARD_REGNO_NREGS aarch64_hard_regno_nregs diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 470f1b29846..0997b82dbc0 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -72,10 +72,6 @@ #define TARGET_SIMD (AARCH64_ISA_SIMD && AARCH64_ISA_SM_OFF) #define TARGET_FLOAT (AARCH64_ISA_FP) -/* If this is non-zero then generated code of the object format, ABI and - assembler syntax used by Darwin (Mach-O) platforms. */ -#define TARGET_MACHO 0 - #define UNITS_PER_WORD 8 #define UNITS_PER_VREG 16 @@ -153,12 +149,6 @@ /* Heap alignment (same as BIGGEST_ALIGNMENT and STACK_BOUNDARY). */ #define MALLOC_ABI_ALIGNMENT 128 -/* We will and with this value to test if a custom function descriptor needs - a static chain. The function boundary must the adjusted so that the bit - this represents is no longer part of the address. 0 Disables the custom - function descriptors. */ -#define AARCH64_CUSTOM_FUNCTION_TEST 4 - /* Defined by the ABI */ #define WCHAR_TYPE "unsigned int" #define WCHAR_TYPE_SIZE 32 @@ -505,6 +495,11 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE = AARCH64_FL_SM_OFF; enabled through +gcs. */ #define TARGET_GCS (AARCH64_ISA_GCS) +/* Prefer different predicate registers for the output of a predicated + operation over re-using an existing input predicate. */ +#define TARGET_SVE_PRED_CLOBBER (TARGET_SVE \ + && (aarch64_tune_params.extra_tuning_flags \ + & AARCH64_EXTRA_TUNE_AVOID_PRED_RMW)) /* Standard register usage. */ @@ -1165,24 +1160,6 @@ typedef struct aapcs_reg == NULL_RTX. */ int aapcs_stack_size; /* The total size (in words, per 8 byte) of the stack arg area so far. */ - - /* In the darwinpcs, items smaller than one word are packed onto the stack - naturally aligned. Unnamed parameters passed in a variadic call are, - however, aligned the same way as the AAPCS64. This means that we need to - pad the last named arg to the next parm boundary (and hence notice when - we are processing that arg). */ - int darwinpcs_stack_bytes; /* If the argument is passed on the stack, this - the byte-size. */ - int darwinpcs_sub_word_offset;/* This is the offset of this arg within a word - when placing smaller items for darwinpcs. */ - int darwinpcs_sub_word_pos; /* The next byte available within the word for - darwinpcs. */ - unsigned darwinpcs_arg_boundary; /* The computed argument boundary. */ - unsigned darwinpcs_arg_padding; /* The computed argument padding. */ - unsigned darwinpcs_n_named; /* Number of named arguments. */ - unsigned darwinpcs_n_args_processed; /* Processed so far. */ - bool named_p; /* Is this arg named? */ - bool last_named_p; /* Is this the last named arg? */ bool silent_p; /* True if we should act silently, rather than raise an error for invalid calls. */ @@ -1494,13 +1471,8 @@ extern const char *aarch64_rewrite_mcpu (int argc, const char **argv); #define ASM_CPU_SPEC \ MCPU_TO_MARCH_SPEC -#ifndef SUBTARGET_EXTRA_SPECS -#define SUBTARGET_EXTRA_SPECS -#endif - #define EXTRA_SPECS \ - { "asm_cpu_spec", ASM_CPU_SPEC }, \ - SUBTARGET_EXTRA_SPECS + { "asm_cpu_spec", ASM_CPU_SPEC } #define ASM_OUTPUT_POOL_EPILOGUE aarch64_asm_output_pool_epilogue @@ -1513,10 +1485,6 @@ extern GTY(()) tree aarch64_fp16_ptr_type_node; bfloat16_type_node. Defined in aarch64-builtins.cc. */ extern GTY(()) tree aarch64_bf16_ptr_type_node; -/* A pointer to the user-visible __float128 (on Mach-O). Defined in - aarch64-builtins.c. */ -extern GTY(()) tree aarch64_float128_ptr_type_node; - /* The generic unwind code in libgcc does not initialize the frame pointer. So in order to unwind a function using a frame pointer, the very first function that is unwound must save the frame pointer. That way the frame diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index d1698b5b142..389a1906e23 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -363,7 +363,6 @@ ;; Wraps a constant integer that should be multiplied by the number ;; of quadwords in an SME vector. UNSPEC_SME_VQ - UNSPEC_MACHOPIC_OFFSET ; Common to Mach-O ports. ]) (define_c_enum "unspecv" [ @@ -446,6 +445,10 @@ ;; target-independent code. (define_attr "is_call" "no,yes" (const_string "no")) +;; Indicates whether we want to enable the pattern with an optional early +;; clobber for SVE predicates. +(define_attr "pred_clobber" "any,no,yes" (const_string "any")) + ;; [For compatibility with Arm in pipeline models] ;; Attribute that specifies whether or not the instruction touches fp ;; registers. @@ -461,7 +464,17 @@ (define_attr "arch_enabled" "no,yes" (if_then_else - (ior + (and + (ior + (and + (eq_attr "pred_clobber" "no") + (match_test "!TARGET_SVE_PRED_CLOBBER")) + (and + (eq_attr "pred_clobber" "yes") + (match_test "TARGET_SVE_PRED_CLOBBER")) + (eq_attr "pred_clobber" "any")) + + (ior (eq_attr "arch" "any") (and (eq_attr "arch" "rcpc8_4") @@ -489,7 +502,7 @@ (match_test "TARGET_SVE")) (and (eq_attr "arch" "sme") - (match_test "TARGET_SME"))) + (match_test "TARGET_SME")))) (const_string "yes") (const_string "no"))) @@ -996,37 +1009,6 @@ [(set_attr "type" "load_4")] ) -(define_insn "prefetch_unscaled" - [(prefetch (match_operand:DI 0 "aarch64_unscaled_prefetch_operand" "Du") - (match_operand:QI 1 "const_int_operand" "") - (match_operand:QI 2 "const_int_operand" ""))] - "" - { - const char * pftype[2][4] = - { - {"prfum\\tPLDL1STRM, %0", - "prfum\\tPLDL3KEEP, %0", - "prfum\\tPLDL2KEEP, %0", - "prfum\\tPLDL1KEEP, %0"}, - {"prfum\\tPSTL1STRM, %0", - "prfum\\tPSTL3KEEP, %0", - "prfum\\tPSTL2KEEP, %0", - "prfum\\tPSTL1KEEP, %0"}, - }; - - int locality = INTVAL (operands[2]); - - gcc_assert (IN_RANGE (locality, 0, 3)); - - /* PRFUM accepts the same addresses as a 64-bit LDR so wrap - the address into a DImode MEM so that aarch64_print_operand knows - how to print it. */ - operands[0] = gen_rtx_MEM (DImode, operands[0]); - return pftype[INTVAL(operands[1])][locality]; - } - [(set_attr "type" "load_4")] -) - (define_insn "trap" [(trap_if (const_int 1) (const_int 8))] "" @@ -1479,7 +1461,7 @@ [w , m ; load_4 , fp , 4] ldr\t%s0, %1 [m , r Z; store_4 , * , 4] str\t%w1, %0 [m , w ; store_4 , fp , 4] str\t%s1, %0 - [r , Usw; load_4 , * , 8] << TARGET_MACHO ? \"adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %O1]\" : \"adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %L1]\"; + [r , Usw; load_4 , * , 8] adrp\t%x0, %A1\;ldr\t%w0, [%x0, %L1] [r , Usa; adr , * , 4] adr\t%x0, %c1 [r , Ush; adr , * , 4] adrp\t%x0, %A1 [w , r Z; f_mcr , fp , 4] fmov\t%s0, %w1 @@ -1516,7 +1498,7 @@ [w, m ; load_8 , fp , 4] ldr\t%d0, %1 [m, r Z; store_8 , * , 4] str\t%x1, %0 [m, w ; store_8 , fp , 4] str\t%d1, %0 - [r, Usw; load_8 , * , 8] << TARGET_ILP32 ? (TARGET_MACHO ? \"adrp\\t%0, %A1\;ldr\\t%w0, [%0, %O1]\" : \"adrp\\t%0, %A1\;ldr\\t%w0, [%0, %L1]\") : (TARGET_MACHO ? \"adrp\\t%0, %A1\;ldr\\t%0, [%0, %O1]\" : \"adrp\\t%0, %A1\;ldr\\t%0, [%0, %L1]\"); + [r, Usw; load_8 , * , 8] << TARGET_ILP32 ? "adrp\t%0, %A1\;ldr\t%w0, [%0, %L1]" : "adrp\t%0, %A1\;ldr\t%0, [%0, %L1]"; [r, Usa; adr , * , 4] adr\t%x0, %c1 [r, Ush; adr , * , 4] adrp\t%x0, %A1 [w, r Z; f_mcr , fp , 4] fmov\t%d0, %x1 @@ -7419,10 +7401,7 @@ (lo_sum:P (match_operand:P 1 "register_operand" "r") (match_operand 2 "aarch64_valid_symref" "S")))] "" - { return TARGET_MACHO - ? "add\\t%0, %1, %J2;" - : "add\\t%0, %1, :lo12:%c2"; - } + "add\\t%0, %1, :lo12:%c2" [(set_attr "type" "alu_imm")] ) diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index 5c9bb0a9056..6356c419399 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -193,13 +193,6 @@ Enum(aarch64_abi) String(ilp32) Value(AARCH64_ABI_ILP32) EnumValue Enum(aarch64_abi) String(lp64) Value(AARCH64_ABI_LP64) -EnumValue -Enum(aarch64_abi) String(darwinpcs) Value(AARCH64_ABI_LP64) - -m64 -Target RejectNegative Alias(mabi=, darwinpcs) -On Darwin for compatibility with other platform variants. - mpc-relative-literal-loads Target Save Var(pcrelative_literal_loads) Init(2) Save PC relative literal loads. diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 9ade357cacc..a2569cea510 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -203,9 +203,7 @@ A constraint that matches a small GOT access." (and (match_code "const,symbol_ref") (match_test "aarch64_classify_symbolic_expression (op) - == SYMBOL_SMALL_GOT_4G - || aarch64_classify_symbolic_expression (op) - == SYMBOL_MO_SMALL_GOT"))) + == SYMBOL_SMALL_GOT_4G"))) (define_constraint "Uss" "@internal @@ -576,11 +574,6 @@ An address valid for a prefetch instruction." (match_test "aarch64_address_valid_for_prefetch_p (op, true)")) -(define_address_constraint "Du" - "@internal - An address valid for a prefetch instruction with an unscaled offset." - (match_test "aarch64_address_valid_for_unscaled_prefetch_p (op, true)")) - (define_constraint "vgb" "@internal A constraint that matches an immediate offset valid for SVE LD1B diff --git a/gcc/config/aarch64/darwin.h b/gcc/config/aarch64/darwin.h deleted file mode 100644 index 4b6bac4cf4b..00000000000 --- a/gcc/config/aarch64/darwin.h +++ /dev/null @@ -1,291 +0,0 @@ -/* Target definitions for Arm64/Aarch64 running on macOS/iOS. - -Copyright The GNU Toolchain Authors. -Contributed by Iain Sandoe. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -. */ - -/* Enable Mach-O bits in generic Aarch64 code. */ -#undef TARGET_MACHO -#define TARGET_MACHO 1 - -#undef DARWIN_ARM64 -#define DARWIN_ARM64 1 - -/* This is used in generic code in darwin.cc (at present, we have no support - for the arm64_32 target). */ -#undef TARGET_64BIT -#define TARGET_64BIT 1 - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "long int" - -#undef TARGET_PROMOTE_FUNCTION_MODE -#define TARGET_PROMOTE_FUNCTION_MODE aarch64_darwin_promote_fn_mode - -#undef TARGET_PROMOTE_FUNCTION_MODE_CA -#define TARGET_PROMOTE_FUNCTION_MODE_CA aarch64_darwin_promote_function_mode_ca - -/* NOTE that arm64_32 is a valid thing and corresponds to darwinpcs - and TARGET_ILP32, but we are not implementing that for now. */ -#define TARGET_OS_CPP_BUILTINS() \ - do { \ - builtin_define ("__LITTLE_ENDIAN__"); \ - builtin_define ("__arm64"); \ - builtin_define ("__arm64__"); \ - darwin_cpp_builtins (pfile); \ - } while (0) - -/* In Darwin's Arm64 ABI, chars are signed. */ - -#undef DEFAULT_SIGNED_CHAR -#define DEFAULT_SIGNED_CHAR 1 - -#undef LONG_DOUBLE_TYPE_SIZE -#define LONG_DOUBLE_TYPE_SIZE 64 - -/* Disable custom function descriptors on Darwin (we use heap-based - trampolines). */ -#undef AARCH64_CUSTOM_FUNCTION_TEST -#define AARCH64_CUSTOM_FUNCTION_TEST 0 - -/* Non-PIE executables are forbidden by the Arm64-darwin security model; - remove the option from link-lines since they just produce a warning from - ld64 and are then ignored anyway. */ -#undef DARWIN_NOPIE_SPEC -#define DARWIN_NOPIE_SPEC \ -" % 10years). Any symbol that is not 'global' and does not begin - with 'L' (the local symbol designation) is counted as 'linker visible'. - * does _not_ support 'static' code in the user space - - Everything needs to be invoked using the dynamic linker (`dyld`). There is - neither crt0.o nor a static edition of libc. - -FIXME: CHECK the kernel model here. - -### Darwin Relocations and Assembler syntax - -* `Mach-O` for `Arm64` uses a reduced set of relocations c.f. the ELF set. - - There are only 11 entries but the relocation format allows for multiple sizes -(1, 2, 4, 8) where that's appropriate, and for ancillary data (e.g. a scale), -so the actual number of permutations is larger. - -* Generally, Darwin supports relocations of the form A - B + signed const - - A must be known (i.e. defined in the current TU). - -* `Mach-O` for `Arm64` has postfix assembler syntax. - - Where there's an assembly language representation for the relocation type - it appears after the name (e.g. `foo@PAGE` in contrast to the ELF - `:got:foo`). - -#### Relocs list - -For pointers (no source representation). - -`ARM64_RELOC_UNSIGNED = 0` - -Must be followed by an `ARM64_RELOC_UNSIGNED` - -`ARM64_RELOC_SUBTRACTOR = 1` - -A B/BL instruction with 26-bit displacement. -(no source representation) - -`ARM64_RELOC_BRANCH26 = 2` - -PC-rel distance to page of target [adrp]. - -`foo@PAGE` - -`ARM64_RELOC_PAGE21 = 3` - -Offset within page, scaled by r_length [add imm, ld/st]. - -`foo@PAGEOFF` - -`ARM64_RELOC_PAGEOFF12 = 4` - -PC-rel distance to page of GOT slot [adrp]. - -`foo@GOTPAGE` -`ARM64_RELOC_GOT_LOAD_PAGE21 = 5` - -Offset within page of GOT slot, scaled by r_length [add imm, ld/st]. - -`foo@GOTPAGEOFF` - -`ARM64_RELOC_GOT_LOAD_PAGEOFF12 = 6` - - -For pointers to GOT slots. -(4 and 8 byte versions) - -`foo@GOT` - -`ARM64_RELOC_POINTER_TO_GOT = 7` - - -PC-rel distance to page of TLVP slot [adrp]. - -`foo@TVLPPAGE` - -`ARM64_RELOC_TLVP_LOAD_PAGE21 = 8` - -Offset within page of TLVP slot, scaled by r_length [add imm, ld/st]. - -`foo@TVLPPAGEOFF` - -`ARM64_RELOC_TLVP_LOAD_PAGEOFF12 = 9` - -Must be followed by `ARM64_RELOC_PAGE21` or `ARM64_RELOC_PAGEOFF12`. -(no source representation) - -The addend is a signed 24bit quantity (+/- 8M range). - -`ARM64_RELOC_ADDEND = 10` - -## PART 2 - GCC-12 deviations from the PCS and supporting information. - -### D.3 is not yet supported (github issue #74) - - GCC promotes in the callee not the caller. - -### Support for nested functions - - GCC provides nested functions which are used overtly from C but also to - implement some parts of Ada and Fortran. - - This requires assigning a register to act as the STATIC CHAIN. - For GCC-12 this is X16 - - Support for nested function trampolines is provided by a heap-based table. - -### Support for __float128 - - The darwinpcs has no provision for a 128bit float type. - GCC-12 supports IEEE741 128bit float values by sof-float. - The ABI used for __float128 matches that for AAPCS64 - -## End. diff --git a/gcc/config/aarch64/driver-aarch64.cc b/gcc/config/aarch64/driver-aarch64.cc index e0e8a8fb8a0..b620351e572 100644 --- a/gcc/config/aarch64/driver-aarch64.cc +++ b/gcc/config/aarch64/driver-aarch64.cc @@ -28,74 +28,6 @@ #include "aarch64-protos.h" #include "aarch64-feature-deps.h" -#if TARGET_MACHO -# include -# include -#endif - - -#if TARGET_MACHO - -/* Default architecture to use if -mcpu=native did not detect a known CPU. */ -#define DEFAULT_ARCH "apple-m1" - -/* macOS does not have /proc/cpuinfo and needs a different approach, - based on sysctl. It is much simpler. */ - -const char * -host_detect_local_cpu (ATTRIBUTE_UNUSED int argc, ATTRIBUTE_UNUSED const char **argv) -{ - bool arch = false; - bool tune = false; - bool cpu = false; - const char *res = NULL; - uint32_t family; - size_t len = sizeof(family); - - gcc_assert (argc); - if (!argv[0]) - return NULL; - - /* Are we processing -march, mtune or mcpu? */ - arch = strcmp (argv[0], "arch") == 0; - if (!arch) - tune = strcmp (argv[0], "tune") == 0; - if (!arch && !tune) - cpu = strcmp (argv[0], "cpu") == 0; - if (!arch && !tune && !cpu) - return NULL; - - sysctlbyname("hw.cpufamily", &family, &len, NULL, 0); - - switch (family) - { - case 0x07d34b9f: // Vortex, Tempest - res = "apple-a12"; - break; - case 0x573b5eec: - case 0x1b588bb3: // Firestorm, Icestorm - res = "apple-m1"; - break; - case 0xda33d83d: // Blizzard, Avalanche - res = "apple-m2"; - break; - case 0xfa33415e: // Ibiza (M3) - case 0x5f4dea93: // Lobos (M3 Pro) - case 0x72015832: // Palma (M3 Max) - res = "apple-m3"; - break; - default: - res = DEFAULT_ARCH; - } - - if (res) - return concat ("-m", argv[0], "=", res, NULL); - else - return NULL; -} - -#else - struct aarch64_arch_extension { const char *ext; @@ -545,4 +477,3 @@ not_found: } } -#endif diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 6e7487bcef5..b895f5dcb86 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -352,24 +352,9 @@ (define_predicate "aarch64_prefetch_operand" (match_test "aarch64_address_valid_for_prefetch_p (op, false)")) -(define_predicate "aarch64_unscaled_prefetch_operand" - (match_test "aarch64_address_valid_for_unscaled_prefetch_p (op, false)")) - (define_predicate "aarch64_valid_symref" (match_code "const, symbol_ref, label_ref") { - if (TARGET_MACHO) - { - rtx x = op; - rtx offset; - split_const (x, &x, &offset); - if (GET_CODE (x) == CONST) - x = XEXP (x, 0); - if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_SALT_ADDR) - x = XVECEXP (x, 0, 0); - if (SYMBOL_REF_P (x) && INTVAL (offset) < 0) - return false; - } return (aarch64_classify_symbolic_expression (op) != SYMBOL_FORCE_TO_MEM); }) diff --git a/gcc/config/aarch64/t-aarch64-darwin b/gcc/config/aarch64/t-aarch64-darwin deleted file mode 100644 index e2b8ad9237f..00000000000 --- a/gcc/config/aarch64/t-aarch64-darwin +++ /dev/null @@ -1,25 +0,0 @@ -# Machine description for AArch64 architecture. -# Copyright (C) 2020 Free Software Foundation, Inc. -# -# This file is part of GCC. -# -# GCC is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GCC is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# . - -LIB1ASMSRC = aarch64/lib1funcs.asm -LIB1ASMFUNCS = _aarch64_sync_cache_range - -# TODO - figure out what multilib provisions we should make for -# a) arm64e -# b) arm64_32 diff --git a/gcc/config/aarch64/tuning_models/neoversen2.h b/gcc/config/aarch64/tuning_models/neoversen2.h index 7e799bbe762..be9a48ac3ad 100644 --- a/gcc/config/aarch64/tuning_models/neoversen2.h +++ b/gcc/config/aarch64/tuning_models/neoversen2.h @@ -236,7 +236,8 @@ static const struct tune_params neoversen2_tunings = (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS - | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ + | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT + | AARCH64_EXTRA_TUNE_AVOID_PRED_RMW), /* tune_flags. */ &generic_prefetch_tune, AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ diff --git a/gcc/config/aarch64/tuning_models/neoversev1.h b/gcc/config/aarch64/tuning_models/neoversev1.h index 9363f2ad98a..0fc41ce6a41 100644 --- a/gcc/config/aarch64/tuning_models/neoversev1.h +++ b/gcc/config/aarch64/tuning_models/neoversev1.h @@ -227,7 +227,8 @@ static const struct tune_params neoversev1_tunings = (AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT - | AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ + | AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND + | AARCH64_EXTRA_TUNE_AVOID_PRED_RMW), /* tune_flags. */ &generic_prefetch_tune, AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ diff --git a/gcc/config/aarch64/tuning_models/neoversev2.h b/gcc/config/aarch64/tuning_models/neoversev2.h index bc01ed767c9..f76e4ef358f 100644 --- a/gcc/config/aarch64/tuning_models/neoversev2.h +++ b/gcc/config/aarch64/tuning_models/neoversev2.h @@ -236,7 +236,8 @@ static const struct tune_params neoversev2_tunings = (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS - | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ + | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT + | AARCH64_EXTRA_TUNE_AVOID_PRED_RMW), /* tune_flags. */ &generic_prefetch_tune, AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 449e6935b32..0cd5d733952 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -2111,8 +2111,8 @@ enum arm_auto_incmodes ? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 0, HImode) \ : SImode) \ : (TARGET_THUMB2 \ - ? ((min > 0 && max < 0x200) ? QImode \ - : (min > 0 && max <= 0x20000) ? HImode \ + ? ((min >= 0 && max < 0x200) ? QImode \ + : (min >= 0 && max < 0x20000) ? HImode \ : SImode) \ : ((min >= 0 && max < 1024) \ ? (ADDR_DIFF_VEC_FLAGS (body).offset_unsigned = 1, QImode) \ diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index d4fcff46123..75d35d5e14b 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -292,6 +292,8 @@ (define_mode_iterator SPLIT34 [SI SF PSI SQ USQ SA USA]) +(define_mode_iterator SFDF [SF DF]) + ;; Where the most significant bit is located. (define_mode_attr MSB [(QI "7") (QQ "7") (UQQ "7") (HI "15") (HQ "15") (UHQ "15") (HA "15") (UHA "15") @@ -10047,6 +10049,20 @@ (const_int 1) (match_dup 2)))]) + +;; Work around PR115307: Early passes expand isinf/f/l to a bloat. +;; These passes do not consider costs, and there is no way to +;; hook in or otherwise disable the generated bloat. + +;; isinfsf2 isinfdf2 +(define_expand "isinf2" + [(parallel [(match_operand:HI 0) + (match_operand:SFDF 1)])] + "" + { + FAIL; + }) + ;; Fixed-point instructions (include "avr-fixed.md") diff --git a/gcc/config/darwin-driver.cc b/gcc/config/darwin-driver.cc index 176bcfb6843..eabe9bc970d 100644 --- a/gcc/config/darwin-driver.cc +++ b/gcc/config/darwin-driver.cc @@ -268,13 +268,10 @@ darwin_driver_init (unsigned int *decoded_options_count, bool seenX86_64 = false; bool seenPPC = false; bool seenPPC64 = false; -#if !DARWIN_ARM64 - bool seenArm64 = false; bool seenM32 = false; bool seenM64 = false; bool appendM32 = false; bool appendM64 = false; -#endif const char *vers_string = NULL; bool seen_version_min = false; bool seen_sysroot_p = false; @@ -299,12 +296,6 @@ darwin_driver_init (unsigned int *decoded_options_count, seenPPC = true; else if (!strcmp ((*decoded_options)[i].arg, "ppc64")) seenPPC64 = true; - else if (!strcmp ((*decoded_options)[i].arg, "arm64")) -#if !DARWIN_ARM64 - seenArm64 = true; -#else - ; /* We accept the option, but don't need to act on it. */ -#endif else error ("this compiler does not support %qs", (*decoded_options)[i].arg); @@ -318,7 +309,7 @@ darwin_driver_init (unsigned int *decoded_options_count, --i; --*decoded_options_count; break; -#if !DARWIN_ARM64 + case OPT_m32: seenM32 = true; break; @@ -326,7 +317,6 @@ darwin_driver_init (unsigned int *decoded_options_count, case OPT_m64: seenM64 = true; break; -#endif case OPT_mmacosx_version_min_: seen_version_min = true; @@ -376,9 +366,6 @@ darwin_driver_init (unsigned int *decoded_options_count, if (seenPPC || seenPPC64) warning (0, "this compiler does not support PowerPC" " (%<-arch%> option ignored)"); - else if (seenArm64) - warning (0, "this compiler does not support Arm64" - " (%<-arch%> option ignored)"); if (seenX86) { if (seenX86_64 || seenM64) @@ -402,9 +389,6 @@ darwin_driver_init (unsigned int *decoded_options_count, if (seenX86 || seenX86_64) warning (0, "this compiler does not support x86" " (%<-arch%> option ignored)"); - else if (seenArm64) - warning (0, "this compiler does not support Arm64" - " (%<-arch%> option ignored)"); if (seenPPC) { if (seenPPC64 || seenM64) @@ -424,20 +408,12 @@ darwin_driver_init (unsigned int *decoded_options_count, if (! seenM64) /* Add -m64 if the User didn't. */ appendM64 = true; } -#elif DARWIN_ARM64 - if (seenPPC || seenPPC64) - warning (0, "this compiler does not support PowerPC" - " (%<-arch%> option ignored)"); - if (seenX86 || seenX86_64) - warning (0, "this compiler does not support x86" - " (%<-arch%> option ignored)"); #endif /* If there is nothing else on the command line, do not add sysroot etc. */ if (*decoded_options_count <= 1) return; -#if !DARWIN_ARM64 if (appendM32 || appendM64) { ++*decoded_options_count; @@ -447,7 +423,6 @@ darwin_driver_init (unsigned int *decoded_options_count, generate_option (appendM32 ? OPT_m32 : OPT_m64, NULL, 1, CL_DRIVER, &(*decoded_options)[*decoded_options_count - 1]); } -#endif if (!seen_sysroot_p) { diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h index 35116317b59..b67e05264e1 100644 --- a/gcc/config/darwin-protos.h +++ b/gcc/config/darwin-protos.h @@ -86,12 +86,9 @@ extern void darwin_asm_lto_end (void); extern void darwin_mark_decl_preserved (const char *); extern tree darwin_handle_kext_attribute (tree *, tree, tree, int, bool *); -extern tree darwin_handle_weak_import_attribute (tree *, tree, tree, int, - bool *); -extern tree darwin_handle_availability_attribute (tree *, tree, tree, - int, bool *); -extern bool darwin_attribute_takes_identifier_p (const_tree); - +extern tree darwin_handle_weak_import_attribute (tree *node, tree name, + tree args, int flags, + bool * no_add_attrs); extern void machopic_output_stub (FILE *, const char *, const char *); extern void darwin_globalize_label (FILE *, const char *); extern void darwin_assemble_visibility (tree, int); @@ -127,7 +124,6 @@ extern void darwin_enter_string_into_cfstring_table (tree); extern void darwin_asm_output_anchor (rtx symbol); extern bool darwin_use_anchors_for_symbol_p (const_rtx symbol); extern bool darwin_kextabi_p (void); -extern bool darwin_unreachable_traps_p (void); extern void darwin_override_options (void); extern void darwin_patch_builtins (void); extern void darwin_rename_builtins (void); diff --git a/gcc/config/darwin.cc b/gcc/config/darwin.cc index f33a30d74ca..9129378be37 100644 --- a/gcc/config/darwin.cc +++ b/gcc/config/darwin.cc @@ -29,7 +29,6 @@ along with GCC; see the file COPYING3. If not see #include "cfghooks.h" #include "df.h" #include "memmodel.h" -#include "c-family/c-common.h" /* enum rid. */ #include "tm_p.h" #include "stringpool.h" #include "attribs.h" @@ -50,7 +49,6 @@ along with GCC; see the file COPYING3. If not see #include "optabs.h" #include "flags.h" #include "opts.h" -#include "c-family/c-objc.h" /* for objc_method_decl(). */ /* Fix and Continue. @@ -104,7 +102,6 @@ int darwin_running_cxx; /* Some code-gen now depends on OS major version numbers (at least). */ int generating_for_darwin_version ; -unsigned long current_os_version = 0; /* For older linkers we need to emit special sections (marked 'coalesced') for for weak or single-definition items. */ @@ -134,7 +131,7 @@ struct { section * darwin_sections[NUM_DARWIN_SECTIONS]; /* While we transition to using in-tests instead of ifdef'd code. */ -#if !HAVE_lo_sum || DARWIN_ARM64 +#if !HAVE_lo_sum #define gen_macho_high(m,a,b) (a) #define gen_macho_low(m,a,b,c) (a) #endif @@ -1107,7 +1104,6 @@ machopic_legitimize_pic_address (rtx orig, machine_mode mode, rtx reg) return pic_ref; } -#if !DARWIN_ARM64 /* Callbacks to output the stub or non-lazy pointers. Each works on the item in *SLOT,if it has been used. DATA is the FILE* for assembly output. @@ -1263,7 +1259,6 @@ machopic_finish (FILE *out_file) machopic_indirections->traverse_noresize (out_file); } -#endif int machopic_operand_p (rtx op) @@ -2199,122 +2194,6 @@ darwin_handle_kext_attribute (tree *node, tree name, return NULL_TREE; } -enum version_components { MAJOR, MINOR, TINY }; - -/* Parse a version number in x.y.z form and validate it as a macOS - version. Ideally, we'd put this in a common place usable by the - Darwin backend. */ - -static bool -parse_version (unsigned version_array[3], const char *version_str) -{ - size_t version_len; - char *end, last = '\0', delimiter = '.', alt_delim = '_'; - - if (!version_str) - return false; - - /* Handle the odd situation in which we get STRING_CST which contain the - starting and ending quotes. */ - if (version_str[0] == '"') - { - version_str++; - version_len = strrchr (&version_str[1], '"') - version_str; - last = '"'; - } - else - version_len = strlen (version_str); - - if (version_len < 1) - return false; - - /* Version string must consist of digits and periods only. */ - if (strspn (version_str, "0123456789._") != version_len) - return false; - - if (!ISDIGIT (version_str[0]) || !ISDIGIT (version_str[version_len - 1])) - return false; - - version_array[MAJOR] = strtoul (version_str, &end, 10); - if (*end == '_') - { - delimiter = '_'; - alt_delim = '.'; - } - version_str = end + ((*end == delimiter) ? 1 : 0); - if (version_array[MAJOR] == 100000) - return true; - if (version_array[MAJOR] > 99) - return false; - - /* Version string must not contain adjacent delimiters. */ - if (*version_str == delimiter || *version_str == alt_delim) - return false; - - version_array[MINOR] = strtoul (version_str, &end, 10); - if (*end == alt_delim) - return false; - version_str = end + ((*end == delimiter) ? 1 : 0); - if (version_array[MINOR] > 99) - return false; - - version_array[TINY] = strtoul (version_str, &end, 10); - if (version_array[TINY] > 99) - return false; - - /* Version string must contain no more than three tokens. */ - if (*end != last) - return false; - - return true; -} - -/* Turn a version expressed as maj.min.tiny into an unsigned long - integer representing the value used in macOS availability macros. */ - -static unsigned long -version_from_version_array (unsigned vers[3]) -{ - unsigned long res = 0; - /* There seems to be a special "unknown" value. */ - if (vers[0] == 100000) - return 999999; - - /* Here, we follow the 'modern' / 'legacy' numbering scheme for versions. */ - if (vers[0] > 10 || vers[1] >= 10) - res = vers[0] * 10000 + vers[1] * 100 + vers[2]; - else - { - res = vers[0] * 100; - if (vers[1] > 9) - res += 90; - else - res += vers[1] * 10; - if (vers[2] > 9) - res += 9; - else - res += vers[1]; - } - return res; -} - -/* Extract a macOS version from an availability attribute argument. */ - -static unsigned long -os_version_from_avail_value (tree value) -{ - unsigned long res = 0; - unsigned vers[3] = {0,0,0}; - if (TREE_CODE (value) == STRING_CST) - { - if (parse_version (&vers[0], TREE_STRING_POINTER (value))) - res = version_from_version_array (&vers[0]); - } - else - gcc_unreachable (); - return res; -} - /* Handle a "weak_import" attribute; arguments as in struct attribute_spec.handler. */ @@ -2336,231 +2215,6 @@ darwin_handle_weak_import_attribute (tree *node, tree name, return NULL_TREE; } -#define NUM_AV_OSES 13 -const char *availability_os[NUM_AV_OSES] - = { "macos", "macosx", "ios", "tvos", "watchos", "driverkit", "swift", - "maccatalyst", "macCatalyst", "xros", "visionos", "android", "zos" }; - -#define NUM_AV_CLAUSES 6 -const char *availability_clause[NUM_AV_CLAUSES] - = { "unavailable", "introduced", "deprecated", "obsoleted", "message", - "replacement" }; - -/* Validate and act upon the arguments to an 'availability' attribute. */ - -tree -darwin_handle_availability_attribute (tree *node, tree name, tree args, - int flags, bool * no_add_attrs) -{ - tree decl = *node; - *no_add_attrs = true; - - if (!decl || (!TYPE_P (decl) && !DECL_P (decl))) - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - return NULL_TREE; - } - else if (decl == error_mark_node) - return NULL_TREE; - - location_t loc = DECL_SOURCE_LOCATION (decl); - if (args == NULL_TREE) - { - error_at (loc, "%qE attribute requires at least one argument", - name); - return NULL_TREE; - } - else if (args == error_mark_node) - return NULL_TREE; - - /* The first argument must name a supported OS - although we could choose - to ignore any OS we don't recognise. */ - gcc_checking_assert (TREE_CODE (args) == TREE_LIST); - tree platform = TREE_VALUE (args); - if (platform == error_mark_node) - return NULL_TREE; - - gcc_checking_assert (TREE_CODE (platform) == IDENTIFIER_NODE); - bool platform_ok = false; - unsigned plat_num = 0; - for (; plat_num < (unsigned) NUM_AV_OSES; plat_num++) - if (strcmp (availability_os[plat_num], IDENTIFIER_POINTER (platform)) == 0) - { - platform_ok = true; - break; - } - if (!platform_ok) - { - error_at (input_location, - "platform %qE is not recognised for the % " - "attribute", platform); - return NULL_TREE; - } - else if (plat_num > 1) /* We only compile for macos so far. */ - return NULL_TREE; - - /* We might be dealing with an object or type. */ - tree target_decl = NULL_TREE; - tree type = NULL_TREE; - bool warn = false; - if (DECL_P (*node)) - { - type = TREE_TYPE (decl); - - if (TREE_CODE (decl) == TYPE_DECL - || TREE_CODE (decl) == PARM_DECL - || VAR_OR_FUNCTION_DECL_P (decl) - || TREE_CODE (decl) == FIELD_DECL - || TREE_CODE (decl) == CONST_DECL - /*|| objc_method_decl (TREE_CODE (decl))*/) - target_decl = decl; - else - warn = true; - } - else if (TYPE_P (*node)) - type = target_decl = *node; - else - warn = true; - - tree what = NULL_TREE; - if (warn) - { - if (type && TYPE_NAME (type)) - { - if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) - what = TYPE_NAME (*node); - else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && DECL_NAME (TYPE_NAME (type))) - what = DECL_NAME (TYPE_NAME (type)); - } - if (what) - warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what); - else - warning (OPT_Wattributes, "%qE attribute ignored", name); - return NULL_TREE; - } - - /* Now we have to parse the availability clauses. */ - tree msg = NULL_TREE; - tree replacement = NULL_TREE; - bool unavailable = false; - unsigned introduced = 1000; - unsigned deprecated = current_os_version + 1; - unsigned obsoleted = current_os_version + 1; - for (tree arg = TREE_CHAIN (args); arg; arg = TREE_CHAIN (arg)) - { - tree clause_name = TREE_VALUE (arg); - tree clause_value = TREE_PURPOSE (arg); - if (clause_name == error_mark_node - || clause_value == error_mark_node) - continue; - unsigned clause_num = 0; - for (; clause_num < (unsigned) NUM_AV_CLAUSES; clause_num++) - if (strcmp (availability_clause[clause_num], - IDENTIFIER_POINTER (clause_name)) == 0) - break; - switch (clause_num) - { - default: - error_at (input_location, - "clause %qE is not recognised for the % " - "attribute", clause_name); - break; - case 0: - unavailable = true; - break; - case 1: - case 2: - case 3: - if (!clause_value) - error_at (input_location, "%<%E=%> requires a value", clause_name); - else - { - unsigned version = os_version_from_avail_value (clause_value); - if (version == 0) - error_at (input_location, "the value %qE provided to %qE is " - "not a valid OS version", clause_value, clause_name); - else if (clause_num == 1) - introduced = version; - else if (clause_num == 2) - deprecated = version; - else if (clause_num == 3) - obsoleted = version; - } - break; - case 4: - case 5: - if (!clause_value || TREE_CODE (clause_value) != STRING_CST) - error_at (input_location, "%<%E=%> requires a string", clause_name); - else if (clause_num == 4) - msg = clause_value; - else - replacement = clause_value; - break; - } - } - /* Now figure out what to do. */ - tree maybe_text = NULL_TREE; - if (replacement) - maybe_text = tree_cons (NULL_TREE, replacement, NULL_TREE); - else if (msg) - maybe_text = tree_cons (NULL_TREE, msg, NULL_TREE); - - if (unavailable || current_os_version >= obsoleted) - { - TREE_UNAVAILABLE (*node) = true; - /* We do not handle the availability attribute at diagnostics-time, so - if we want the informational messages, then attach them to additional - attributes for the deprecation or unavailability. TODO; maybe we can - fabricate the composite here. */ - if (maybe_text) - { - *no_add_attrs = false; - tree new_attr = tree_cons (get_identifier ("unavailable"), - maybe_text, NULL_TREE); - /* This is the actual consequence of the evaluation. */ - if (TYPE_P (target_decl) && !(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - { - *node = build_variant_type_copy (*node); - TYPE_ATTRIBUTES (*node) = chainon (TYPE_ATTRIBUTES (*node), - new_attr); - } - else - DECL_ATTRIBUTES (*node) = chainon (DECL_ATTRIBUTES (*node), - new_attr); - } - } - else if (current_os_version > deprecated) - { - TREE_DEPRECATED (*node) = true; - if (maybe_text) - { - *no_add_attrs = false; - tree new_attr = tree_cons (get_identifier ("deprecated"), - maybe_text, NULL_TREE); - /* This is the actual consequence of the evaluation. */ - if (TYPE_P (target_decl) && !(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - { - *node = build_variant_type_copy (*node); - TYPE_ATTRIBUTES (*node) = chainon (TYPE_ATTRIBUTES (*node), - new_attr); - } - else - DECL_ATTRIBUTES (*node) = chainon (DECL_ATTRIBUTES (*node), - new_attr); - } - } - else if (current_os_version < introduced) - *no_add_attrs = false; - return NULL_TREE; -} - -bool -darwin_attribute_takes_identifier_p (const_tree attr_id) -{ - return is_attribute_p ("availability", attr_id); -} - /* Emit a label for an FDE, making it global and/or weak if appropriate. The third parameter is nonzero if this is for exception handling. The fourth parameter is nonzero if this is just a placeholder for an @@ -2652,8 +2306,6 @@ darwin_emit_except_table_label (FILE *file) rtx darwin_make_eh_symbol_indirect (rtx orig, bool ARG_UNUSED (pubvis)) { - if (DARWIN_ARM64) - return orig; if (DARWIN_PPC == 0 && TARGET_64BIT) return orig; @@ -3502,12 +3154,7 @@ darwin_file_end (void) fprintf (asm_out_file, "\t.long\t0\n\t.long\t%u\n", flags); } -#if !DARWIN_ARM64 machopic_finish (asm_out_file); -#else - gcc_checking_assert (!machopic_indirections); -#endif - if (flag_apple_kext) { /* These sections are only used for kernel code. */ @@ -3683,13 +3330,6 @@ darwin_kextabi_p (void) { return flag_apple_kext; } -/* True, iff we want to map __builtin_unreachable to a trap. */ - -bool -darwin_unreachable_traps_p (void) { - return darwin_unreachable_traps; -} - void darwin_override_options (void) { @@ -3710,14 +3350,7 @@ darwin_override_options (void) generating_for_darwin_version = 8; /* Earlier versions are not specifically accounted, until required. */ - unsigned vers[3] = {0,0,0}; - if (!parse_version (vers, darwin_macosx_version_min)) - error_at (UNKNOWN_LOCATION, "how did we get a bad OS version? (%s)", - darwin_macosx_version_min); - current_os_version = version_from_version_array (vers); } - else - current_os_version = 1058; /* Some codegen needs to account for the capabilities of the target linker. */ @@ -3987,7 +3620,7 @@ darwin_patch_builtin (enum built_in_function fncode) void darwin_patch_builtins (void) { - if (LONG_DOUBLE_TYPE_SIZE != 128) + if (TYPE_PRECISION (long_double_type_node) != 128) return; #define PATCH_BUILTIN(fncode) darwin_patch_builtin (fncode); diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index 4572c7e5e7a..c09b9e9dc94 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -42,7 +42,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define DARWIN_X86 0 #define DARWIN_PPC 0 -#define DARWIN_ARM64 0 #define OBJECT_FORMAT_MACHO 1 @@ -372,8 +371,7 @@ extern GTY(()) int darwin_ms_struct; */ #define DARWIN_NOCOMPACT_UNWIND \ -"%{!fuse-ld=lld: \ - %:version-compare(>= 10.6 mmacosx-version-min= -no_compact_unwind)}" +" %:version-compare(>= 10.6 mmacosx-version-min= -no_compact_unwind) " /* In Darwin linker specs we can put -lcrt0.o and ld will search the library path for crt0.o or -lcrtx.a and it will search for libcrtx.a. As for @@ -397,8 +395,7 @@ extern GTY(()) int darwin_ms_struct; LINK_PLUGIN_SPEC \ "%{flto*:% Specify that ld64 is the toolchain linker for the current invocation. -munreachable-traps -Target Var(darwin_unreachable_traps) Init(1) -When set (the default) this makes __builtin_unreachable render as a trap. - ; Driver options. all_load diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 215a998fc26..9b60264dce2 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -588,7 +588,7 @@ ix86_expand_move (machine_mode mode, rtx operands[]) /* OP is a memref of CONST_VECTOR, return scalar constant mem if CONST_VECTOR is a vec_duplicate, else return NULL. */ -static rtx +rtx ix86_broadcast_from_constant (machine_mode mode, rtx op) { int nunits = GET_MODE_NUNITS (mode); @@ -11707,6 +11707,8 @@ ix86_expand_args_builtin (const struct builtin_description *d, tree arg = CALL_EXPR_ARG (exp, i); rtx op = expand_normal (arg); machine_mode mode = insn_p->operand[i + 1].mode; + /* Need to fixup modeless constant before testing predicate. */ + op = fixup_modeless_constant (op, mode); bool match = insn_p->operand[i + 1].predicate (op, mode); if (second_arg_count && i == 1) @@ -11873,13 +11875,15 @@ ix86_expand_args_builtin (const struct builtin_description *d, /* If we aren't optimizing, only allow one memory operand to be generated. */ if (memory_operand (op, mode)) - num_memory++; - - op = fixup_modeless_constant (op, mode); + { + num_memory++; + if (!optimize && num_memory > 1) + op = copy_to_mode_reg (mode, op); + } if (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) { - if (optimize || !match || num_memory > 1) + if (!match) op = copy_to_mode_reg (mode, op); } else @@ -25352,4 +25356,714 @@ ix86_expand_fast_convert_bf_to_sf (rtx val) return ret; } +rtx +ix86_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn **gen_seq, + rtx_code code, tree treeop0, tree treeop1) +{ + if (!TARGET_APX_CCMP) + return NULL_RTX; + + rtx op0, op1, res; + machine_mode op_mode; + + start_sequence (); + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); + + op_mode = GET_MODE (op0); + if (op_mode == VOIDmode) + op_mode = GET_MODE (op1); + + /* We only supports following scalar comparisons that use just 1 + instruction: DI/SI/QI/HI/DF/SF/HF. + Unordered/Ordered compare cannot be corretly indentified by + ccmp so they are not supported. */ + if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode + || op_mode == QImode || op_mode == DFmode || op_mode == SFmode + || op_mode == HFmode) + || code == ORDERED + || code == UNORDERED) + { + end_sequence (); + return NULL_RTX; + } + + /* Canonicalize the operands according to mode. */ + if (SCALAR_INT_MODE_P (op_mode)) + { + if (!nonimmediate_operand (op0, op_mode)) + op0 = force_reg (op_mode, op0); + if (!x86_64_general_operand (op1, op_mode)) + op1 = force_reg (op_mode, op1); + } + else + { + /* op0/op1 can be canonicallized from expand_fp_compare, so + just adjust the code to make it generate supported fp + condition. */ + if (ix86_fp_compare_code_to_integer (code) == UNKNOWN) + { + /* First try to split condition if we don't need to honor + NaNs, as the ORDERED/UNORDERED check always fall + through. */ + if (!HONOR_NANS (op_mode)) + { + rtx_code first_code; + split_comparison (code, op_mode, &first_code, &code); + } + /* Otherwise try to swap the operand order and check if + the comparison is supported. */ + else + { + code = swap_condition (code); + std::swap (op0, op1); + } + + if (ix86_fp_compare_code_to_integer (code) == UNKNOWN) + { + end_sequence (); + return NULL_RTX; + } + } + } + + *prep_seq = get_insns (); + end_sequence (); + + start_sequence (); + + res = ix86_expand_compare (code, op0, op1); + + if (!res) + { + end_sequence (); + return NULL_RTX; + } + *gen_seq = get_insns (); + end_sequence (); + + return res; +} + +rtx +ix86_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev, + rtx_code cmp_code, tree treeop0, tree treeop1, + rtx_code bit_code) +{ + if (!TARGET_APX_CCMP) + return NULL_RTX; + + rtx op0, op1, target; + machine_mode op_mode, cmp_mode, cc_mode = CCmode; + int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0)); + insn_code icode; + rtx_code prev_code; + struct expand_operand ops[5]; + int dfv; + + push_to_sequence (*prep_seq); + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); + + cmp_mode = op_mode = GET_MODE (op0); + + if (!(op_mode == DImode || op_mode == SImode || op_mode == HImode + || op_mode == QImode)) + { + end_sequence (); + return NULL_RTX; + } + + icode = code_for_ccmp (op_mode); + + op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp); + op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp); + if (!op0 || !op1) + { + end_sequence (); + return NULL_RTX; + } + + *prep_seq = get_insns (); + end_sequence (); + + target = gen_rtx_REG (cc_mode, FLAGS_REG); + dfv = ix86_get_flags_cc ((rtx_code) cmp_code); + + prev_code = GET_CODE (prev); + /* Fixup FP compare code here. */ + if (GET_MODE (XEXP (prev, 0)) == CCFPmode) + prev_code = ix86_fp_compare_code_to_integer (prev_code); + + if (bit_code != AND) + prev_code = reverse_condition (prev_code); + else + dfv = (int)(dfv ^ 1); + + prev = gen_rtx_fmt_ee (prev_code, VOIDmode, XEXP (prev, 0), + const0_rtx); + + create_fixed_operand (&ops[0], target); + create_fixed_operand (&ops[1], prev); + create_fixed_operand (&ops[2], op0); + create_fixed_operand (&ops[3], op1); + create_fixed_operand (&ops[4], GEN_INT (dfv)); + + push_to_sequence (*gen_seq); + if (!maybe_expand_insn (icode, 5, ops)) + { + end_sequence (); + return NULL_RTX; + } + + *gen_seq = get_insns (); + end_sequence (); + + return gen_rtx_fmt_ee ((rtx_code) cmp_code, VOIDmode, target, const0_rtx); +} + +/* Attempt to convert a CONST_VECTOR into a bcst_mem_operand. + Returns NULL_RTX if X is cannot be expressed as a suitable + VEC_DUPLICATE in mode MODE. */ + +static rtx +ix86_gen_bcst_mem (machine_mode mode, rtx x) +{ + if (!TARGET_AVX512F + || GET_CODE (x) != CONST_VECTOR + || (!TARGET_AVX512VL + && (GET_MODE_SIZE (mode) != 64 || !TARGET_EVEX512)) + || !VALID_BCST_MODE_P (GET_MODE_INNER (mode)) + /* Disallow HFmode broadcast. */ + || GET_MODE_SIZE (GET_MODE_INNER (mode)) < 4) + return NULL_RTX; + + rtx cst = CONST_VECTOR_ELT (x, 0); + if (!CONST_SCALAR_INT_P (cst) + && !CONST_DOUBLE_P (cst) + && !CONST_FIXED_P (cst)) + return NULL_RTX; + + int n_elts = GET_MODE_NUNITS (mode); + if (CONST_VECTOR_NUNITS (x) != n_elts) + return NULL_RTX; + + for (int i = 1; i < n_elts; i++) + if (!rtx_equal_p (cst, CONST_VECTOR_ELT (x, i))) + return NULL_RTX; + + rtx mem = force_const_mem (GET_MODE_INNER (mode), cst); + return gen_rtx_VEC_DUPLICATE (mode, validize_mem (mem)); +} + +/* Determine the ternlog immediate index that implements 3-operand + ternary logic expression OP. This uses and modifies the 3 element + array ARGS to record and check the leaves, either 3 REGs, or 2 REGs + and MEM. Returns an index between 0 and 255 for a valid ternlog, + or -1 if the expression isn't suitable. */ + +int +ix86_ternlog_idx (rtx op, rtx *args) +{ + int idx0, idx1; + + if (!op) + return -1; + + switch (GET_CODE (op)) + { + case REG: + if (!args[0]) + { + args[0] = op; + return 0xf0; + } + if (REGNO (op) == REGNO (args[0])) + return 0xf0; + if (!args[1]) + { + args[1] = op; + return 0xcc; + } + if (REGNO (op) == REGNO (args[1])) + return 0xcc; + if (!args[2]) + { + args[2] = op; + return 0xaa; + } + if (REG_P (args[2]) && REGNO (op) == REGNO (args[2])) + return 0xaa; + return -1; + + case VEC_DUPLICATE: + if (!bcst_mem_operand (op, GET_MODE (op))) + return -1; + /* FALLTHRU */ + + case MEM: + if (!memory_operand (op, GET_MODE (op))) + return -1; + if (MEM_P (op) + && MEM_VOLATILE_P (op) + && !volatile_ok) + return -1; + /* FALLTHRU */ + + case CONST_VECTOR: + if (!args[2]) + { + args[2] = op; + return 0xaa; + } + /* Maximum of one volatile memory reference per expression. */ + if (side_effects_p (op) && side_effects_p (args[2])) + return -1; + if (rtx_equal_p (op, args[2])) + return 0xaa; + /* Check if one CONST_VECTOR is the ones-complement of the other. */ + if (GET_CODE (op) == CONST_VECTOR + && GET_CODE (args[2]) == CONST_VECTOR + && rtx_equal_p (simplify_const_unary_operation (NOT, GET_MODE (op), + op, GET_MODE (op)), + args[2])) + return 0x55; + return -1; + + case SUBREG: + if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) + != GET_MODE_SIZE (GET_MODE (op))) + return -1; + return ix86_ternlog_idx (SUBREG_REG (op), args); + + case NOT: + idx0 = ix86_ternlog_idx (XEXP (op, 0), args); + return (idx0 >= 0) ? idx0 ^ 0xff : -1; + + case AND: + idx0 = ix86_ternlog_idx (XEXP (op, 0), args); + if (idx0 < 0) + return -1; + idx1 = ix86_ternlog_idx (XEXP (op, 1), args); + return (idx1 >= 0) ? idx0 & idx1 : -1; + + case IOR: + idx0 = ix86_ternlog_idx (XEXP (op, 0), args); + if (idx0 < 0) + return -1; + idx1 = ix86_ternlog_idx (XEXP (op, 1), args); + return (idx1 >= 0) ? idx0 | idx1 : -1; + + case XOR: + idx0 = ix86_ternlog_idx (XEXP (op, 0), args); + if (idx0 < 0) + return -1; + if (vector_all_ones_operand (XEXP (op, 1), GET_MODE (op))) + return idx0 ^ 0xff; + idx1 = ix86_ternlog_idx (XEXP (op, 1), args); + return (idx1 >= 0) ? idx0 ^ idx1 : -1; + + case UNSPEC: + if (XINT (op, 1) != UNSPEC_VTERNLOG + || XVECLEN (op, 0) != 4 + || !CONST_INT_P (XVECEXP (op, 0, 3))) + return -1; + + /* TODO: Handle permuted operands. */ + if (ix86_ternlog_idx (XVECEXP (op, 0, 0), args) != 0xf0 + || ix86_ternlog_idx (XVECEXP (op, 0, 1), args) != 0xcc + || ix86_ternlog_idx (XVECEXP (op, 0, 2), args) != 0xaa) + return -1; + return INTVAL (XVECEXP (op, 0, 3)); + + default: + return -1; + } +} + +/* Return TRUE if OP (in mode MODE) is the leaf of a ternary logic + expression, such as a register or a memory reference. */ + +bool +ix86_ternlog_leaf_p (rtx op, machine_mode mode) +{ + /* We can't use memory_operand here, as it may return a different + value before and after reload (for volatile MEMs) which creates + problems splitting instructions. */ + return register_operand (op, mode) + || MEM_P (op) + || GET_CODE (op) == CONST_VECTOR + || bcst_mem_operand (op, mode); +} + +/* Test whether OP is a 3-operand ternary logic expression suitable + for use in a ternlog instruction. */ + +bool +ix86_ternlog_operand_p (rtx op) +{ + rtx op0, op1; + rtx args[3]; + + args[0] = NULL_RTX; + args[1] = NULL_RTX; + args[2] = NULL_RTX; + int idx = ix86_ternlog_idx (op, args); + if (idx < 0) + return false; + + /* Don't match simple (binary or unary) expressions. */ + machine_mode mode = GET_MODE (op); + switch (GET_CODE (op)) + { + case AND: + op0 = XEXP (op, 0); + op1 = XEXP (op, 1); + + /* Prefer pand. */ + if (ix86_ternlog_leaf_p (op0, mode) + && ix86_ternlog_leaf_p (op1, mode)) + return false; + /* Prefer pandn. */ + if (GET_CODE (op0) == NOT + && register_operand (XEXP (op0, 0), mode) + && ix86_ternlog_leaf_p (op1, mode)) + return false; + break; + + case IOR: + /* Prefer por. */ + if (ix86_ternlog_leaf_p (XEXP (op, 0), mode) + && ix86_ternlog_leaf_p (XEXP (op, 1), mode)) + return false; + break; + + case XOR: + op1 = XEXP (op, 1); + /* Prefer pxor, or one_cmpl2. */ + if (ix86_ternlog_leaf_p (XEXP (op, 0), mode) + && (ix86_ternlog_leaf_p (op1, mode) + || vector_all_ones_operand (op1, mode))) + return false; + break; + + default: + break; + } + return true; +} + +/* Helper function for ix86_expand_ternlog. */ +static rtx +ix86_expand_ternlog_binop (enum rtx_code code, machine_mode mode, + rtx op0, rtx op1, rtx target) +{ + if (GET_MODE (op0) != mode) + op0 = gen_lowpart (mode, op0); + if (GET_MODE (op1) != mode) + op1 = gen_lowpart (mode, op1); + + if (GET_CODE (op0) == CONST_VECTOR) + op0 = validize_mem (force_const_mem (mode, op0)); + if (GET_CODE (op1) == CONST_VECTOR) + op1 = validize_mem (force_const_mem (mode, op1)); + + if (memory_operand (op0, mode)) + { + if (memory_operand (op1, mode)) + op0 = force_reg (mode, op0); + else + std::swap (op0, op1); + } + rtx ops[3] = { target, op0, op1 }; + ix86_expand_vector_logical_operator (code, mode, ops); + return target; +} + + +/* Helper function for ix86_expand_ternlog. */ +static rtx +ix86_expand_ternlog_andnot (machine_mode mode, rtx op0, rtx op1, rtx target) +{ + if (GET_MODE (op0) != mode) + op0 = gen_lowpart (mode, op0); + op0 = gen_rtx_NOT (mode, op0); + if (GET_MODE (op1) != mode) + op1 = gen_lowpart (mode, op1); + emit_move_insn (target, gen_rtx_AND (mode, op0, op1)); + return target; +} + +/* Expand a 3-operand ternary logic expression. Return TARGET. */ +rtx +ix86_expand_ternlog (machine_mode mode, rtx op0, rtx op1, rtx op2, int idx, + rtx target) +{ + rtx tmp0, tmp1, tmp2; + + if (!target) + target = gen_reg_rtx (mode); + + /* Canonicalize ternlog index for degenerate (duplicated) operands. */ + if (rtx_equal_p (op0, op1) && rtx_equal_p (op0, op2)) + switch (idx & 0x81) + { + case 0x00: + idx = 0x00; + break; + case 0x01: + idx = 0x0f; + break; + case 0x80: + idx = 0xf0; + break; + case 0x81: + idx = 0xff; + break; + } + + switch (idx & 0xff) + { + case 0x00: + if ((!op0 || !side_effects_p (op0)) + && (!op1 || !side_effects_p (op1)) + && (!op2 || !side_effects_p (op2))) + { + emit_move_insn (target, CONST0_RTX (mode)); + return target; + } + break; + + case 0x0a: /* ~a&c */ + if ((!op1 || !side_effects_p (op1)) + && op0 && register_operand (op0, mode) + && op2 && register_operand (op2, mode)) + return ix86_expand_ternlog_andnot (mode, op0, op2, target); + break; + + case 0x0c: /* ~a&b */ + if ((!op2 || !side_effects_p (op2)) + && op0 && register_operand (op0, mode) + && op1 && register_operand (op1, mode)) + return ix86_expand_ternlog_andnot (mode, op0, op1, target); + break; + + case 0x0f: /* ~a */ + if ((!op1 || !side_effects_p (op1)) + && (!op2 || !side_effects_p (op2)) + && op0) + { + if (GET_MODE (op0) != mode) + op0 = gen_lowpart (mode, op0); + if (!TARGET_64BIT && !register_operand (op0, mode)) + op0 = force_reg (mode, op0); + emit_move_insn (target, gen_rtx_XOR (mode, op0, CONSTM1_RTX (mode))); + return target; + } + break; + + case 0x22: /* ~b&c */ + if ((!op0 || !side_effects_p (op0)) + && op1 && register_operand (op1, mode) + && op2 && register_operand (op2, mode)) + return ix86_expand_ternlog_andnot (mode, op1, op2, target); + break; + + case 0x30: /* ~b&a */ + if ((!op2 || !side_effects_p (op2)) + && op0 && register_operand (op0, mode) + && op1 && register_operand (op1, mode)) + return ix86_expand_ternlog_andnot (mode, op1, op0, target); + break; + + case 0x33: /* ~b */ + if ((!op0 || !side_effects_p (op0)) + && (!op2 || !side_effects_p (op2)) + && op1) + { + if (GET_MODE (op1) != mode) + op1 = gen_lowpart (mode, op1); + if (!TARGET_64BIT && !register_operand (op1, mode)) + op1 = force_reg (mode, op1); + emit_move_insn (target, gen_rtx_XOR (mode, op1, CONSTM1_RTX (mode))); + return target; + } + break; + + case 0x3c: /* a^b */ + if (op0 && op1 + && (!op2 || !side_effects_p (op2))) + return ix86_expand_ternlog_binop (XOR, mode, op0, op1, target); + break; + + case 0x44: /* ~c&b */ + if ((!op0 || !side_effects_p (op0)) + && op1 && register_operand (op1, mode) + && op2 && register_operand (op2, mode)) + return ix86_expand_ternlog_andnot (mode, op2, op1, target); + break; + + case 0x50: /* ~c&a */ + if ((!op1 || !side_effects_p (op1)) + && op0 && register_operand (op0, mode) + && op2 && register_operand (op2, mode)) + return ix86_expand_ternlog_andnot (mode, op2, op0, target); + break; + + case 0x55: /* ~c */ + if ((!op0 || !side_effects_p (op0)) + && (!op1 || !side_effects_p (op1)) + && op2) + { + if (GET_MODE (op2) != mode) + op2 = gen_lowpart (mode, op2); + if (!TARGET_64BIT && !register_operand (op2, mode)) + op2 = force_reg (mode, op2); + emit_move_insn (target, gen_rtx_XOR (mode, op2, CONSTM1_RTX (mode))); + return target; + } + break; + + case 0x5a: /* a^c */ + if (op0 && op2 + && (!op1 || !side_effects_p (op1))) + return ix86_expand_ternlog_binop (XOR, mode, op0, op2, target); + break; + + case 0x66: /* b^c */ + if ((!op0 || !side_effects_p (op0)) + && op1 && op2) + return ix86_expand_ternlog_binop (XOR, mode, op1, op2, target); + break; + + case 0x88: /* b&c */ + if ((!op0 || !side_effects_p (op0)) + && op1 && op2) + return ix86_expand_ternlog_binop (AND, mode, op1, op2, target); + break; + + case 0xa0: /* a&c */ + if ((!op1 || !side_effects_p (op1)) + && op0 && op2) + return ix86_expand_ternlog_binop (AND, mode, op0, op2, target); + break; + + case 0xaa: /* c */ + if ((!op0 || !side_effects_p (op0)) + && (!op1 || !side_effects_p (op1)) + && op2) + { + if (GET_MODE (op2) != mode) + op2 = gen_lowpart (mode, op2); + emit_move_insn (target, op2); + return target; + } + break; + + case 0xc0: /* a&b */ + if (op0 && op1 + && (!op2 || !side_effects_p (op2))) + return ix86_expand_ternlog_binop (AND, mode, op0, op1, target); + break; + + case 0xcc: /* b */ + if ((!op0 || !side_effects_p (op0)) + && op1 + && (!op2 || !side_effects_p (op2))) + { + if (GET_MODE (op1) != mode) + op1 = gen_lowpart (mode, op1); + emit_move_insn (target, op1); + return target; + } + break; + + case 0xee: /* b|c */ + if ((!op0 || !side_effects_p (op0)) + && op1 && op2) + return ix86_expand_ternlog_binop (IOR, mode, op1, op2, target); + break; + + case 0xf0: /* a */ + if (op0 + && (!op1 || !side_effects_p (op1)) + && (!op2 || !side_effects_p (op2))) + { + if (GET_MODE (op0) != mode) + op0 = gen_lowpart (mode, op0); + emit_move_insn (target, op0); + return target; + } + break; + + case 0xfa: /* a|c */ + if (op0 && op2 + && (!op1 || !side_effects_p (op1))) + return ix86_expand_ternlog_binop (IOR, mode, op0, op2, target); + break; + + case 0xfc: /* a|b */ + if (op0 && op1 + && (!op2 || !side_effects_p (op2))) + return ix86_expand_ternlog_binop (IOR, mode, op0, op1, target); + break; + + case 0xff: + if ((!op0 || !side_effects_p (op0)) + && (!op1 || !side_effects_p (op1)) + && (!op2 || !side_effects_p (op2))) + { + emit_move_insn (target, CONSTM1_RTX (mode)); + return target; + } + break; + } + + tmp0 = register_operand (op0, mode) ? op0 : force_reg (mode, op0); + if (GET_MODE (tmp0) != mode) + tmp0 = gen_lowpart (mode, tmp0); + + if (!op1 || rtx_equal_p (op0, op1)) + tmp1 = copy_rtx (tmp0); + else if (!register_operand (op1, mode)) + tmp1 = force_reg (mode, op1); + else + tmp1 = op1; + if (GET_MODE (tmp1) != mode) + tmp1 = gen_lowpart (mode, tmp1); + + if (!op2 || rtx_equal_p (op0, op2)) + tmp2 = copy_rtx (tmp0); + else if (rtx_equal_p (op1, op2)) + tmp2 = copy_rtx (tmp1); + else if (GET_CODE (op2) == CONST_VECTOR) + { + if (GET_MODE (op2) != mode) + op2 = gen_lowpart (mode, op2); + tmp2 = ix86_gen_bcst_mem (mode, op2); + if (!tmp2) + { + tmp2 = validize_mem (force_const_mem (mode, op2)); + rtx bcast = ix86_broadcast_from_constant (mode, tmp2); + if (bcast) + { + rtx reg2 = gen_reg_rtx (mode); + bool ok = ix86_expand_vector_init_duplicate (false, mode, + reg2, bcast); + if (ok) + tmp2 = reg2; + } + } + } + else + tmp2 = op2; + if (GET_MODE (tmp2) != mode) + tmp2 = gen_lowpart (mode, tmp2); + /* Some memory_operands are not vector_memory_operands. */ + if (!bcst_vector_operand (tmp2, mode)) + tmp2 = force_reg (mode, tmp2); + + rtvec vec = gen_rtvec (4, tmp0, tmp1, tmp2, GEN_INT (idx)); + emit_move_insn (target, gen_rtx_UNSPEC (mode, vec, UNSPEC_VTERNLOG)); + return target; +} + #include "gt-i386-expand.h" diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h index ef2825803b3..5fcc4927978 100644 --- a/gcc/config/i386/i386-opts.h +++ b/gcc/config/i386/i386-opts.h @@ -140,7 +140,10 @@ enum apx_features { apx_push2pop2 = 1 << 1, apx_ndd = 1 << 2, apx_ppx = 1 << 3, - apx_all = apx_egpr | apx_push2pop2 | apx_ndd | apx_ppx, + apx_nf = 1 << 4, + apx_ccmp = 1 << 5, + apx_all = apx_egpr | apx_push2pop2 | apx_ndd + | apx_ppx | apx_nf | apx_ccmp, }; #endif diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index dbc861fb1ea..f37d207ae64 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -107,6 +107,7 @@ extern void ix86_expand_clear (rtx); extern void ix86_expand_move (machine_mode, rtx[]); extern void ix86_expand_vector_move (machine_mode, rtx[]); extern void ix86_expand_vector_move_misalign (machine_mode, rtx[]); +extern rtx ix86_broadcast_from_constant (machine_mode, rtx); extern rtx ix86_fixup_binary_operands (enum rtx_code, machine_mode, rtx[], bool = false); extern void ix86_fixup_binary_operands_no_copy (enum rtx_code, machine_mode, @@ -242,9 +243,19 @@ extern void ix86_expand_atomic_fetch_op_loop (rtx, rtx, rtx, enum rtx_code, extern void ix86_expand_cmpxchg_loop (rtx *, rtx, rtx, rtx, rtx, rtx, bool, rtx_code_label *); extern rtx ix86_expand_fast_convert_bf_to_sf (rtx); +extern rtx ix86_gen_ccmp_first (rtx_insn **, rtx_insn **, enum rtx_code, + tree, tree); +extern rtx ix86_gen_ccmp_next (rtx_insn **, rtx_insn **, rtx, + enum rtx_code, tree, tree, enum rtx_code); +extern int ix86_get_flags_cc (enum rtx_code); extern rtx ix86_memtag_untagged_pointer (rtx, rtx); extern bool ix86_memtag_can_tag_addresses (void); +extern int ix86_ternlog_idx (rtx op, rtx *args); +extern bool ix86_ternlog_operand_p (rtx op); +extern rtx ix86_expand_ternlog (machine_mode mode, rtx op0, rtx op1, rtx op2, + int idx, rtx target); + #ifdef TREE_CODE extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); #endif /* TREE_CODE */ diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 1a0206ab573..173db213d14 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -433,6 +433,22 @@ static bool i386_asm_output_addr_const_extra (FILE *, rtx); static bool ix86_can_inline_p (tree, tree); static unsigned int ix86_minimum_incoming_stack_boundary (bool); +typedef enum ix86_flags_cc +{ + X86_CCO = 0, X86_CCNO, X86_CCB, X86_CCNB, + X86_CCE, X86_CCNE, X86_CCBE, X86_CCNBE, + X86_CCS, X86_CCNS, X86_CCP, X86_CCNP, + X86_CCL, X86_CCNL, X86_CCLE, X86_CCNLE +} ix86_cc; + +static const char *ix86_ccmp_dfv_mapping[] = +{ + "{dfv=of}", "{dfv=}", "{dfv=cf}", "{dfv=}", + "{dfv=zf}", "{dfv=}", "{dfv=cf, zf}", "{dfv=}", + "{dfv=sf}", "{dfv=}", "{dfv=cf}", "{dfv=}", + "{dfv=sf}", "{dfv=sf, of}", "{dfv=sf, of, zf}", "{dfv=sf, of}" +}; + /* Whether -mtune= or -march= were specified */ int ix86_tune_defaulted; @@ -13690,6 +13706,7 @@ print_reg (rtx x, int code, FILE *file) M -- print addr32 prefix for TARGET_X32 with VSIB address. ! -- print NOTRACK prefix for jxx/call/ret instructions if required. N -- print maskz if it's constant 0 operand. + G -- print embedded flag for ccmp/ctest. */ void @@ -14083,6 +14100,14 @@ ix86_print_operand (FILE *file, rtx x, int code) file); return; + case 'G': + { + int dfv = INTVAL (x); + const char *dfv_suffix = ix86_ccmp_dfv_mapping[dfv]; + fputs (dfv_suffix, file); + } + return; + case 'H': if (!offsettable_memref_p (x)) { @@ -16466,6 +16491,24 @@ ix86_convert_const_vector_to_integer (rtx op, machine_mode mode) return val.to_shwi (); } +int ix86_get_flags_cc (rtx_code code) +{ + switch (code) + { + case NE: return X86_CCNE; + case EQ: return X86_CCE; + case GE: return X86_CCNL; + case GT: return X86_CCNLE; + case LE: return X86_CCLE; + case LT: return X86_CCL; + case GEU: return X86_CCNB; + case GTU: return X86_CCNBE; + case LEU: return X86_CCBE; + case LTU: return X86_CCB; + default: return -1; + } +} + /* Return TRUE or FALSE depending on whether the first SET in INSN has source and destination with matching CC modes, and that the CC mode is at least as constrained as REQ_MODE. */ @@ -21869,6 +21912,49 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno, } *total = ix86_vec_cost (mode, cost->sse_op); } + else if (TARGET_64BIT + && mode == TImode + && GET_CODE (XEXP (x, 0)) == ASHIFT + && GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND + && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == DImode + && CONST_INT_P (XEXP (XEXP (x, 0), 1)) + && INTVAL (XEXP (XEXP (x, 0), 1)) == 64 + && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND + && GET_MODE (XEXP (XEXP (x, 1), 0)) == DImode) + { + /* *concatditi3 is cheap. */ + rtx op0 = XEXP (XEXP (XEXP (x, 0), 0), 0); + rtx op1 = XEXP (XEXP (x, 1), 0); + *total = (SUBREG_P (op0) && GET_MODE (SUBREG_REG (op0)) == DFmode) + ? COSTS_N_INSNS (1) /* movq. */ + : set_src_cost (op0, DImode, speed); + *total += (SUBREG_P (op1) && GET_MODE (SUBREG_REG (op1)) == DFmode) + ? COSTS_N_INSNS (1) /* movq. */ + : set_src_cost (op1, DImode, speed); + return true; + } + else if (TARGET_64BIT + && mode == TImode + && GET_CODE (XEXP (x, 0)) == AND + && REG_P (XEXP (XEXP (x, 0), 0)) + && CONST_WIDE_INT_P (XEXP (XEXP (x, 0), 1)) + && CONST_WIDE_INT_NUNITS (XEXP (XEXP (x, 0), 1)) == 2 + && CONST_WIDE_INT_ELT (XEXP (XEXP (x, 0), 1), 0) == -1 + && CONST_WIDE_INT_ELT (XEXP (XEXP (x, 0), 1), 1) == 0 + && GET_CODE (XEXP (x, 1)) == ASHIFT + && GET_CODE (XEXP (XEXP (x, 1), 0)) == ZERO_EXTEND + && GET_MODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == DImode + && CONST_INT_P (XEXP (XEXP (x, 1), 1)) + && INTVAL (XEXP (XEXP (x, 1), 1)) == 64) + { + /* *insvti_highpart is cheap. */ + rtx op = XEXP (XEXP (XEXP (x, 1), 0), 0); + *total = COSTS_N_INSNS (1) + 1; + *total += (SUBREG_P (op) && GET_MODE (SUBREG_REG (op)) == DFmode) + ? COSTS_N_INSNS (1) /* movq. */ + : set_src_cost (op, DImode, speed); + return true; + } else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) *total = cost->add * 2; else @@ -22191,6 +22277,19 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno, return true; case MEM: + /* CONST_VECTOR_DUPLICATE_P in constant_pool is just broadcast. + or variants in ix86_vector_duplicate_simode_const. */ + + if (GET_MODE_SIZE (mode) >= 16 + && VECTOR_MODE_P (mode) + && SYMBOL_REF_P (XEXP (x, 0)) + && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)) + && ix86_broadcast_from_constant (mode, x)) + { + *total = COSTS_N_INSNS (2) + speed; + return true; + } + /* An insn that accesses memory is slightly more expensive than one that does not. */ if (speed) @@ -24879,6 +24978,23 @@ ix86_noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info) return false; } } + + /* W/o TARGET_SSE4_1, it takes 3 instructions (pand, pandn and por) + for movdfcc/movsfcc, and could possibly fail cost comparison. + Increase branch cost will hurt performance for other modes, so + specially add some preference for floating point ifcvt. */ + if (!TARGET_SSE4_1 && if_info->x + && GET_MODE_CLASS (GET_MODE (if_info->x)) == MODE_FLOAT + && if_info->speed_p) + { + unsigned cost = seq_cost (seq, true); + + if (cost <= if_info->original_cost) + return true; + + return cost <= (if_info->max_seq_cost + COSTS_N_INSNS (2)); + } + return default_noce_conversion_profitable_p (seq, if_info); } @@ -26921,6 +27037,13 @@ ix86_libgcc_floating_mode_supported_p #undef TARGET_MEMTAG_TAG_SIZE #define TARGET_MEMTAG_TAG_SIZE ix86_memtag_tag_size +#undef TARGET_GEN_CCMP_FIRST +#define TARGET_GEN_CCMP_FIRST ix86_gen_ccmp_first + +#undef TARGET_GEN_CCMP_NEXT +#define TARGET_GEN_CCMP_NEXT ix86_gen_ccmp_next + + static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED) { diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 359a8408263..7051c6c13e4 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -55,6 +55,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_APX_PUSH2POP2 (ix86_apx_features & apx_push2pop2) #define TARGET_APX_NDD (ix86_apx_features & apx_ndd) #define TARGET_APX_PPX (ix86_apx_features & apx_ppx) +#define TARGET_APX_NF (ix86_apx_features & apx_nf) +#define TARGET_APX_CCMP (ix86_apx_features & apx_ccmp) #include "config/vxworks-dummy.h" diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 375654cf74e..ffcf63e1cba 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -217,6 +217,10 @@ ;; For APX PPX support UNSPEC_APX_PPX + + ;; For APX CCMP support + ;; DFV = default flag value + UNSPEC_APX_DFV ]) (define_c_enum "unspecv" [ @@ -575,7 +579,7 @@ noavx512dq,fma_or_avx512vl,avx512vl,noavx512vl,avxvnni, avx512vnnivl,avx512fp16,avxifma,avx512ifmavl,avxneconvert, avx512bf16vl,vpclmulqdqvl,avx_noavx512f,avx_noavx512vl, - vaes_avx512vl" + vaes_avx512vl,noapx_nf" (const_string "base")) ;; The (bounding maximum) length of an instruction immediate. @@ -981,6 +985,7 @@ (symbol_ref "TARGET_MMX_WITH_SSE && !TARGET_AVX") (eq_attr "mmx_isa" "avx") (symbol_ref "TARGET_MMX_WITH_SSE && TARGET_AVX") + (eq_attr "isa" "noapx_nf") (symbol_ref "!TARGET_APX_NF") ] (const_int 1))) @@ -1504,6 +1509,25 @@ DONE; }) +(define_insn "@ccmp" + [(set (match_operand:CC 0 "flags_reg_operand") + (if_then_else:CC + (match_operator 1 "comparison_operator" + [(reg:CC FLAGS_REG) (const_int 0)]) + (compare:CC + (minus:SWI (match_operand:SWI 2 "nonimmediate_operand" "m,") + (match_operand:SWI 3 "" ",")) + (const_int 0)) + (unspec:SI + [(match_operand:SI 4 "const_0_to_15_operand")] + UNSPEC_APX_DFV)))] + "TARGET_APX_CCMP" + "ccmp%C1{}\t%G4 {%3, %2|%2, %3}" + [(set_attr "type" "icmp") + (set_attr "mode" "") + (set_attr "length_immediate" "1") + (set_attr "prefix" "evex")]) + (define_expand "@cmp_1" [(set (reg:CC FLAGS_REG) (compare:CC (match_operand:SWI48 0 "nonimmediate_operand") @@ -1850,10 +1874,18 @@ DONE; }) -(define_expand "cstorecc4" +;; For conditonal compare, the middle-end hook will convert +;; CCmode to sub-CCmode using SELECT_CC_MODE macro and try +;; to find cstore in optab. Add ALL_CC to support +;; the cstore after ccmp sequence. + +(define_mode_iterator ALL_CC + [CCGC CCGOC CCNO CCGZ CCA CCC CCO CCP CCS CCZ CC]) + +(define_expand "cstore4" [(set (match_operand:QI 0 "register_operand") (match_operator 1 "comparison_operator" - [(match_operand 2 "flags_reg_operand") + [(match_operand:ALL_CC 2 "flags_reg_operand") (match_operand 3 "const0_operand")]))] "" { @@ -6290,6 +6322,13 @@ [(parallel [(set (match_dup 0) (ashift:SWI48 (match_dup 0) (match_dup 1))) (clobber (reg:CC FLAGS_REG))])] "operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));") + +(define_split + [(set (match_operand:SWI48 0 "general_reg_operand") + (mult:SWI48 (match_dup 0) (match_operand:SWI48 1 "const1248_operand")))] + "TARGET_APX_NF && reload_completed" + [(set (match_dup 0) (ashift:SWI48 (match_dup 0) (match_dup 1)))] + "operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));") ;; Add instructions @@ -6437,48 +6476,67 @@ (clobber (reg:CC FLAGS_REG))])] "split_double_mode (mode, &operands[0], 1, &operands[0], &operands[5]);") -(define_insn "*add_1" - [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r,r") +(define_subst_attr "nf_name" "nf_subst" "_nf" "") +(define_subst_attr "nf_prefix" "nf_subst" "%{nf%} " "") +(define_subst_attr "nf_condition" "nf_subst" "TARGET_APX_NF" "true") +(define_subst_attr "nf_mem_constraint" "nf_subst" "je" "m") +(define_subst_attr "nf_applied" "nf_subst" "true" "false") +(define_subst_attr "nf_nonf_attr" "nf_subst" "noapx_nf" "*") +(define_subst_attr "nf_nonf_x64_attr" "nf_subst" "noapx_nf" "x64") + +(define_subst "nf_subst" + [(set (match_operand:SWI 0) + (match_operand:SWI 1))] + "" + [(set (match_dup 0) + (match_dup 1)) + (clobber (reg:CC FLAGS_REG))]) + +(define_insn "*add_1" + [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r,r,r") (plus:SWI48 - (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r,rje,jM,r") - (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le,r,e,BM"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, mode, operands, TARGET_APX_NDD)" + (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,0,r,r,rje,jM,r") + (match_operand:SWI48 2 "x86_64_general_operand" "r,e,BM,0,le,r,e,BM")))] + "ix86_binary_operator_ok (PLUS, mode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_LEA: - return "#"; + if (TARGET_APX_NDD && ) + return "%{nf%} add{}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; case TYPE_INCDEC: if (operands[2] == const1_rtx) - return use_ndd ? "inc{}\t{%1, %0|%0, %1}" - : "inc{}\t%0"; + return use_ndd ? "inc{}\t{%1, %0|%0, %1}" + : "inc{}\t%0"; else { gcc_assert (operands[2] == constm1_rtx); - return use_ndd ? "dec{}\t{%1, %0|%0, %1}" - : "dec{}\t%0"; + return use_ndd ? "dec{}\t{%1, %0|%0, %1}" + : "dec{}\t%0"; } default: /* For most processors, ADD is faster than LEA. This alternative was added to use ADD as much as possible. */ - if (which_alternative == 2) + if (which_alternative == 3) std::swap (operands[1], operands[2]); if (x86_maybe_negate_const_int (&operands[2], mode)) - return use_ndd ? "sub{}\t{%2, %1, %0|%0, %1, %2}" - : "sub{}\t{%2, %0|%0, %2}"; + return use_ndd ? "sub{}\t{%2, %1, %0|%0, %1, %2}" + : "sub{}\t{%2, %0|%0, %2}"; - return use_ndd ? "add{}\t{%2, %1, %0|%0, %1, %2}" - : "add{}\t{%2, %0|%0, %2}"; + return use_ndd ? "add{}\t{%2, %1, %0|%0, %1, %2}" + : "add{}\t{%2, %0|%0, %2}"; } } - [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd,apx_ndd") + [(set_attr "isa" "*,*,*,*,*,apx_ndd,apx_ndd,apx_ndd") (set (attr "type") - (cond [(eq_attr "alternative" "3") + (cond [(eq_attr "alternative" "4") (const_string "lea") (match_operand:SWI48 2 "incdec_operand") (const_string "incdec") @@ -6552,26 +6610,31 @@ (const_string "*"))) (set_attr "mode" "SI")]) -(define_insn "*addhi_1" +(define_insn "*addhi_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r,Yp,r,r") (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r,Yp,rm,r") - (match_operand:HI 2 "general_operand" "rn,m,0,ln,rn,m"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, HImode, operands, TARGET_APX_NDD)" + (match_operand:HI 2 "general_operand" "rn,m,0,ln,rn,m")))] + "ix86_binary_operator_ok (PLUS, HImode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_LEA: - return "#"; + if (TARGET_APX_NDD && ) + return "%{nf%} add{w}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; case TYPE_INCDEC: if (operands[2] == const1_rtx) - return use_ndd ? "inc{w}\t{%1, %0|%0, %1}" : "inc{w}\t%0"; + return use_ndd ? "inc{w}\t{%1, %0|%0, %1}" + : "inc{w}\t%0"; else { gcc_assert (operands[2] == constm1_rtx); - return use_ndd ? "dec{w}\t{%1, %0|%0, %1}" : "dec{w}\t%0"; + return use_ndd ? "dec{w}\t{%1, %0|%0, %1}" + : "dec{w}\t%0"; } default: @@ -6581,11 +6644,11 @@ std::swap (operands[1], operands[2]); if (x86_maybe_negate_const_int (&operands[2], HImode)) - return use_ndd ? "sub{w}\t{%2, %1, %0|%0, %1, %2}" - : "sub{w}\t{%2, %0|%0, %2}"; + return use_ndd ? "sub{w}\t{%2, %1, %0|%0, %1, %2}" + : "sub{w}\t{%2, %0|%0, %2}"; - return use_ndd ? "add{w}\t{%2, %1, %0|%0, %1, %2}" - : "add{w}\t{%2, %0|%0, %2}"; + return use_ndd ? "add{w}\t{%2, %1, %0|%0, %1, %2}" + : "add{w}\t{%2, %0|%0, %2}"; } } [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd") @@ -6603,33 +6666,36 @@ (const_string "*"))) (set_attr "mode" "HI,HI,HI,SI,HI,HI")]) -(define_insn "*addqi_1" +(define_insn "*addqi_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,q,r,r,Yp,r,r") (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,q,0,r,Yp,rm,r") - (match_operand:QI 2 "general_operand" "qn,m,0,rn,0,ln,rn,m"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, QImode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "general_operand" "qn,m,0,rn,0,ln,rn,m")))] + "ix86_binary_operator_ok (PLUS, QImode, operands, TARGET_APX_NDD) + && " { bool widen = (get_attr_mode (insn) != MODE_QI); bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_LEA: - return "#"; + if (TARGET_APX_NDD && ) + return "%{nf%} add{b}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; case TYPE_INCDEC: if (operands[2] == const1_rtx) if (use_ndd) - return "inc{b}\t{%1, %0|%0, %1}"; + return "inc{b}\t{%1, %0|%0, %1}"; else - return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; + return widen ? "inc{l}\t%k0" : "inc{b}\t%0"; else { gcc_assert (operands[2] == constm1_rtx); if (use_ndd) - return "dec{b}\t{%1, %0|%0, %1}"; + return "dec{b}\t{%1, %0|%0, %1}"; else - return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; + return widen ? "dec{l}\t%k0" : "dec{b}\t%0"; } default: @@ -6641,16 +6707,16 @@ if (x86_maybe_negate_const_int (&operands[2], QImode)) { if (use_ndd) - return "sub{b}\t{%2, %1, %0|%0, %1, %2}"; + return "sub{b}\t{%2, %1, %0|%0, %1, %2}"; else - return widen ? "sub{l}\t{%2, %k0|%k0, %2}" - : "sub{b}\t{%2, %0|%0, %2}"; + return widen ? "sub{l}\t{%2, %k0|%k0, %2}" + : "sub{b}\t{%2, %0|%0, %2}"; } if (use_ndd) - return "add{b}\t{%2, %1, %0|%0, %1, %2}"; + return "add{b}\t{%2, %1, %0|%0, %1, %2}"; else - return widen ? "add{l}\t{%k2, %k0|%k0, %k2}" - : "add{b}\t{%2, %0|%0, %2}"; + return widen ? "add{l}\t{%k2, %k0|%k0, %k2}" + : "add{b}\t{%2, %0|%0, %2}"; } } [(set_attr "isa" "*,*,*,*,*,*,apx_ndd,apx_ndd") @@ -6824,6 +6890,23 @@ } }) +(define_split + [(set (match_operand:SWI 0 "register_operand") + (plus:SWI (match_operand:SWI 1 "register_operand") + (match_operand:SWI 2 "")))] + "TARGET_APX_NF && reload_completed + && ix86_lea_for_add_ok (insn, operands)" + [(set (match_dup 0) + (plus: (match_dup 1) (match_dup 2)))] +{ + if (mode != mode) + { + operands[0] = gen_lowpart (mode, operands[0]); + operands[1] = gen_lowpart (mode, operands[1]); + operands[2] = gen_lowpart (mode, operands[2]); + } +}) + ;; Convert add to the lea pattern to avoid flags dependency. (define_split [(set (match_operand:DI 0 "register_operand") @@ -7846,20 +7929,21 @@ "split_double_mode (mode, &operands[0], 2, &operands[0], &operands[3]);" [(set_attr "isa" "*,*,apx_ndd,apx_ndd")]) -(define_insn "*sub_1" - [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,,r,r,r") +(define_insn "*sub_1" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,r,,r,r,r") (minus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "0,0,rm,rjM,r") - (match_operand:SWI 2 "" ",,r,,"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (MINUS, mode, operands, TARGET_APX_NDD)" + (match_operand:SWI 1 "nonimmediate_operand" "0,0,0,rm,rjM,r") + (match_operand:SWI 2 "" ",,,r,,")))] + "ix86_binary_operator_ok (MINUS, mode, operands, TARGET_APX_NDD) + && " "@ - sub{}\t{%2, %0|%0, %2} - sub{}\t{%2, %0|%0, %2} - sub{}\t{%2, %1, %0|%0, %1, %2} - sub{}\t{%2, %1, %0|%0, %1, %2} - sub{}\t{%2, %1, %0|%0, %1, %2}" - [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd") + sub{}\t{%2, %0|%0, %2} + sub{}\t{%2, %0|%0, %2} + sub{}\t{%2, %0|%0, %2} + sub{}\t{%2, %1, %0|%0, %1, %2} + sub{}\t{%2, %1, %0|%0, %1, %2} + sub{}\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "*,*,*,apx_ndd,apx_ndd,apx_ndd") (set_attr "type" "alu") (set_attr "mode" "")]) @@ -9847,17 +9931,17 @@ ;; ;; On BDVER1, all HI MULs use DoublePath -(define_insn "*mul3_1" +(define_insn "*mul3_1" [(set (match_operand:SWIM248 0 "register_operand" "=r,r,r") (mult:SWIM248 (match_operand:SWIM248 1 "nonimmediate_operand" "%rm,rm,0") - (match_operand:SWIM248 2 "" "K,,r"))) - (clobber (reg:CC FLAGS_REG))] - "!(MEM_P (operands[1]) && MEM_P (operands[2]))" + (match_operand:SWIM248 2 "" "K,,r")))] + "!(MEM_P (operands[1]) && MEM_P (operands[2])) + && " "@ - imul{}\t{%2, %1, %0|%0, %1, %2} - imul{}\t{%2, %1, %0|%0, %1, %2} - imul{}\t{%2, %0|%0, %2}" + imul{}\t{%2, %1, %0|%0, %1, %2} + imul{}\t{%2, %1, %0|%0, %1, %2} + imul{}\t{%2, %0|%0, %2}" [(set_attr "type" "imul") (set_attr "prefix_0f" "0,0,1") (set (attr "athlon_decode") @@ -9918,14 +10002,14 @@ ;; MUL reg8 Direct ;; MUL mem8 Direct -(define_insn "*mulqi3_1" +(define_insn "*mulqi3_1" [(set (match_operand:QI 0 "register_operand" "=a") (mult:QI (match_operand:QI 1 "nonimmediate_operand" "%0") - (match_operand:QI 2 "nonimmediate_operand" "qm"))) - (clobber (reg:CC FLAGS_REG))] + (match_operand:QI 2 "nonimmediate_operand" "qm")))] "TARGET_QIMODE_MATH - && !(MEM_P (operands[1]) && MEM_P (operands[2]))" - "mul{b}\t%2" + && !(MEM_P (operands[1]) && MEM_P (operands[2])) + && " + "mul{b}\t%2" [(set_attr "type" "imul") (set_attr "length_immediate" "0") (set (attr "athlon_decode") @@ -11068,6 +11152,19 @@ [(set_attr "type" "multi") (set_attr "mode" "SI")]) +(define_insn "*divmod4_noext_nf" + [(set (match_operand:SWIM248 0 "register_operand" "=a") + (any_div:SWIM248 + (match_operand:SWIM248 2 "register_operand" "0") + (match_operand:SWIM248 3 "nonimmediate_operand" "rm"))) + (set (match_operand:SWIM248 1 "register_operand" "=d") + (:SWIM248 (match_dup 2) (match_dup 3))) + (use (match_operand:SWIM248 4 "register_operand" "1"))] + "TARGET_APX_NF" + "%{nf%} div{}\t%3" + [(set_attr "type" "idiv") + (set_attr "mode" "")]) + (define_insn "*divmod4_noext" [(set (match_operand:SWIM248 0 "register_operand" "=a") (any_div:SWIM248 @@ -11215,7 +11312,7 @@ ;; Change div/mod to HImode and extend the second argument to HImode ;; so that mode of div/mod matches with mode of arguments. Otherwise ;; combine may fail. -(define_insn "divmodhiqi3" +(define_insn "divmodhiqi3" [(set (match_operand:HI 0 "register_operand" "=a") (ior:HI (ashift:HI @@ -11227,10 +11324,10 @@ (const_int 8)) (zero_extend:HI (truncate:QI - (div:HI (match_dup 1) (any_extend:HI (match_dup 2))))))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_QIMODE_MATH" - "div{b}\t%2" + (div:HI (match_dup 1) (any_extend:HI (match_dup 2)))))))] + "TARGET_QIMODE_MATH + && " + "div{b}\t%2" [(set_attr "type" "idiv") (set_attr "mode" "QI")]) @@ -11748,27 +11845,28 @@ } [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")]) -(define_insn "*anddi_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm,r,r,r,r,r,?k") +(define_insn "*anddi_1" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm,r,r,r,r,r,r,?k") (and:DI - (match_operand:DI 1 "nonimmediate_operand" "%0,r,0,0,rm,rjM,r,qm,k") - (match_operand:DI 2 "x86_64_szext_general_operand" "Z,Z,re,m,r,e,m,L,k"))) - (clobber (reg:CC FLAGS_REG))] + (match_operand:DI 1 "nonimmediate_operand" "%0,r,0,0,0,rm,rjM,r,qm,k") + (match_operand:DI 2 "x86_64_szext_general_operand" "Z,Z,r,e,m,r,e,m,L,k")))] "TARGET_64BIT - && ix86_binary_operator_ok (AND, DImode, operands, TARGET_APX_NDD)" + && ix86_binary_operator_ok (AND, DImode, operands, TARGET_APX_NDD) + && " "@ - and{l}\t{%k2, %k0|%k0, %k2} - and{l}\t{%k2, %k1, %k0|%k0, %k1, %k2} - and{q}\t{%2, %0|%0, %2} - and{q}\t{%2, %0|%0, %2} - and{q}\t{%2, %1, %0|%0, %1, %2} - and{q}\t{%2, %1, %0|%0, %1, %2} - and{q}\t{%2, %1, %0|%0, %1, %2} + and{l}\t{%k2, %k0|%k0, %k2} + and{l}\t{%k2, %k1, %k0|%k0, %k1, %k2} + and{q}\t{%2, %0|%0, %2} + and{q}\t{%2, %0|%0, %2} + and{q}\t{%2, %0|%0, %2} + and{q}\t{%2, %1, %0|%0, %1, %2} + and{q}\t{%2, %1, %0|%0, %1, %2} + and{q}\t{%2, %1, %0|%0, %1, %2} # #" - [(set_attr "isa" "x64,apx_ndd,x64,x64,apx_ndd,apx_ndd,apx_ndd,x64,avx512bw") - (set_attr "type" "alu,alu,alu,alu,alu,alu,alu,imovx,msklog") - (set_attr "length_immediate" "*,*,*,*,*,*,*,0,*") + [(set_attr "isa" "x64,apx_ndd,x64,x64,x64,apx_ndd,apx_ndd,apx_ndd,,avx512bw") + (set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,imovx,msklog") + (set_attr "length_immediate" "*,*,*,*,*,*,*,*,0,*") (set (attr "prefix_rex") (if_then_else (and (eq_attr "type" "imovx") @@ -11776,7 +11874,7 @@ (match_operand 1 "ext_QIreg_operand"))) (const_string "1") (const_string "*"))) - (set_attr "mode" "SI,SI,DI,DI,DI,DI,DI,SI,DI")]) + (set_attr "mode" "SI,SI,DI,DI,DI,DI,DI,DI,SI,DI")]) (define_insn_and_split "*anddi_1_btr" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") @@ -11847,31 +11945,34 @@ (set_attr "isa" "*,apx_ndd,apx_ndd,apx_ndd") (set_attr "mode" "SI")]) -(define_insn "*and_1" - [(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,r,r,r,Ya,?k") - (and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,rm,rjM,r,qm,k") - (match_operand:SWI24 2 "" "r,,r,,,L,k"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (AND, mode, operands, TARGET_APX_NDD)" +(define_insn "*and_1" + [(set (match_operand:SWI24 0 "nonimmediate_operand" "=rm,r,r,r,r,r,Ya,?k") + (and:SWI24 (match_operand:SWI24 1 "nonimmediate_operand" "%0,0,0,rm,rjM,r,qm,k") + (match_operand:SWI24 2 "" "r,,,r,,,L,k")))] + "ix86_binary_operator_ok (AND, mode, operands, TARGET_APX_NDD) + && " "@ - and{}\t{%2, %0|%0, %2} - and{}\t{%2, %0|%0, %2} - and{}\t{%2, %1, %0|%0, %1, %2} - and{}\t{%2, %1, %0|%0, %1, %2} - and{}\t{%2, %1, %0|%0, %1, %2} + and{}\t{%2, %0|%0, %2} + and{}\t{%2, %0|%0, %2} + and{}\t{%2, %0|%0, %2} + and{}\t{%2, %1, %0|%0, %1, %2} + and{}\t{%2, %1, %0|%0, %1, %2} + and{}\t{%2, %1, %0|%0, %1, %2} # #" [(set (attr "isa") - (cond [(eq_attr "alternative" "2,3,4") + (cond [(eq_attr "alternative" "3,4,5") (const_string "apx_ndd") (eq_attr "alternative" "6") + (const_string "") + (eq_attr "alternative" "7") (if_then_else (eq_attr "mode" "SI") (const_string "avx512bw") (const_string "avx512f")) ] (const_string "*"))) - (set_attr "type" "alu,alu,alu,alu,alu,imovx,msklog") - (set_attr "length_immediate" "*,*,*,*,*,0,*") + (set_attr "type" "alu,alu,alu,alu,alu,alu,imovx,msklog") + (set_attr "length_immediate" "*,*,*,*,*,*,0,*") (set (attr "prefix_rex") (if_then_else (and (eq_attr "type" "imovx") @@ -11879,20 +11980,20 @@ (match_operand 1 "ext_QIreg_operand"))) (const_string "1") (const_string "*"))) - (set_attr "mode" ",,,,,SI,")]) + (set_attr "mode" ",,,,,,SI,")]) -(define_insn "*andqi_1" +(define_insn "*andqi_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r,r,?k") (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,rm,r,k") - (match_operand:QI 2 "general_operand" "qn,m,rn,rn,m,k"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (AND, QImode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "general_operand" "qn,m,rn,rn,m,k")))] + "ix86_binary_operator_ok (AND, QImode, operands, TARGET_APX_NDD) + && " "@ - and{b}\t{%2, %0|%0, %2} - and{b}\t{%2, %0|%0, %2} - and{l}\t{%k2, %k0|%k0, %k2} - and{b}\t{%2, %1, %0|%0, %1, %2} - and{b}\t{%2, %1, %0|%0, %1, %2} + and{b}\t{%2, %0|%0, %2} + and{b}\t{%2, %0|%0, %2} + and{l}\t{%k2, %k0|%k0, %k2} + and{b}\t{%2, %1, %0|%0, %1, %2} + and{b}\t{%2, %1, %0|%0, %1, %2} #" [(set_attr "type" "alu,alu,alu,alu,alu,msklog") (set_attr "isa" "*,*,*,apx_ndd,apx_ndd,*") @@ -12755,22 +12856,23 @@ } [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,apx_ndd_64,apx_ndd")]) -(define_insn "*_1" - [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,r,r,r,?k") +(define_insn "*_1" + [(set (match_operand:SWI248 0 "nonimmediate_operand" "=rm,r,r,r,r,r,?k") (any_or:SWI248 - (match_operand:SWI248 1 "nonimmediate_operand" "%0,0,rm,rjM,r,k") - (match_operand:SWI248 2 "" "r,,r,,,k"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (, mode, operands, TARGET_APX_NDD)" + (match_operand:SWI248 1 "nonimmediate_operand" "%0,0,0,rm,rjM,r,k") + (match_operand:SWI248 2 "" "r,,,r,,,k")))] + "ix86_binary_operator_ok (, mode, operands, TARGET_APX_NDD) + && " "@ - {}\t{%2, %0|%0, %2} - {}\t{%2, %0|%0, %2} - {}\t{%2, %1, %0|%0, %1, %2} - {}\t{%2, %1, %0|%0, %1, %2} - {}\t{%2, %1, %0|%0, %1, %2} + {}\t{%2, %0|%0, %2} + {}\t{%2, %0|%0, %2} + {}\t{%2, %0|%0, %2} + {}\t{%2, %1, %0|%0, %1, %2} + {}\t{%2, %1, %0|%0, %1, %2} + {}\t{%2, %1, %0|%0, %1, %2} #" - [(set_attr "isa" "*,*,apx_ndd,apx_ndd,apx_ndd,") - (set_attr "type" "alu, alu, alu, alu, alu, msklog") + [(set_attr "isa" "*,*,*,apx_ndd,apx_ndd,apx_ndd,") + (set_attr "type" "alu,alu, alu, alu, alu, alu, msklog") (set_attr "mode" "")]) (define_insn_and_split "*notxor_1" @@ -12916,18 +13018,18 @@ (set_attr "isa" "*,apx_ndd") (set_attr "mode" "SI")]) -(define_insn "*qi_1" +(define_insn "*qi_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,r,r,r,?k") (any_or:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,rm,r,k") - (match_operand:QI 2 "general_operand" "qn,m,rn,rn,m,k"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (, QImode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "general_operand" "qn,m,rn,rn,m,k")))] + "ix86_binary_operator_ok (, QImode, operands, TARGET_APX_NDD) + && " "@ - {b}\t{%2, %0|%0, %2} - {b}\t{%2, %0|%0, %2} - {l}\t{%k2, %k0|%k0, %k2} - {b}\t{%2, %1, %0|%0, %1, %2} - {b}\t{%2, %1, %0|%0, %1, %2} + {b}\t{%2, %0|%0, %2} + {b}\t{%2, %0|%0, %2} + {l}\t{%k2, %k0|%k0, %k2} + {b}\t{%2, %1, %0|%0, %1, %2} + {b}\t{%2, %1, %0|%0, %1, %2} #" [(set_attr "isa" "*,*,*,apx_ndd,apx_ndd,avx512f") (set_attr "type" "alu,alu,alu,alu,alu,msklog") @@ -13487,14 +13589,14 @@ (const_int 0))) (clobber (reg:CC FLAGS_REG))])]) -(define_insn "*neg_1" +(define_insn "*neg_1" [(set (match_operand:SWI 0 "nonimmediate_operand" "=m,r") - (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0,rm"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_unary_operator_ok (NEG, mode, operands, TARGET_APX_NDD)" + (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0,rm")))] + "ix86_unary_operator_ok (NEG, mode, operands, TARGET_APX_NDD) + && " "@ - neg{}\t%0 - neg{}\t{%1, %0|%0, %1}" + neg{}\t%0 + neg{}\t{%1, %0|%0, %1}" [(set_attr "type" "negnot") (set_attr "isa" "*,apx_ndd") (set_attr "mode" "")]) @@ -14495,7 +14597,7 @@ DONE; }) -(define_insn "x86_64_shld" +(define_insn "x86_64_shld" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") (ior:DI (ashift:DI (match_dup 0) (and:QI (match_operand:QI 2 "nonmemory_operand" "Jc") @@ -14505,10 +14607,9 @@ (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) (minus:QI (const_int 64) - (and:QI (match_dup 2) (const_int 63)))) 0))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "shld{q}\t{%2, %1, %0|%0, %1, %2}" + (and:QI (match_dup 2) (const_int 63)))) 0)))] + "TARGET_64BIT && " + "shld{q}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") (set_attr "mode" "DI") @@ -14516,7 +14617,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_64_shld_ndd" +(define_insn "x86_64_shld_ndd" [(set (match_operand:DI 0 "register_operand" "=r") (ior:DI (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "rm") (and:QI (match_operand:QI 3 "nonmemory_operand" "Jc") @@ -14526,14 +14627,13 @@ (zero_extend:TI (match_operand:DI 2 "register_operand" "r")) (minus:QI (const_int 64) - (and:QI (match_dup 3) (const_int 63)))) 0))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_APX_NDD" - "shld{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" + (and:QI (match_dup 3) (const_int 63)))) 0)))] + "TARGET_APX_NDD && " + "shld{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") (set_attr "mode" "DI")]) -(define_insn "x86_64_shld_1" +(define_insn "x86_64_shld_1" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") (ior:DI (ashift:DI (match_dup 0) (match_operand:QI 2 "const_0_to_63_operand")) @@ -14541,11 +14641,11 @@ (lshiftrt:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) - (match_operand:QI 3 "const_0_to_255_operand")) 0))) - (clobber (reg:CC FLAGS_REG))] + (match_operand:QI 3 "const_0_to_255_operand")) 0)))] "TARGET_64BIT - && INTVAL (operands[3]) == 64 - INTVAL (operands[2])" - "shld{q}\t{%2, %1, %0|%0, %1, %2}" + && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) + && " + "shld{q}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") (set_attr "mode" "DI") @@ -14554,7 +14654,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_64_shld_ndd_1" +(define_insn "x86_64_shld_ndd_1" [(set (match_operand:DI 0 "register_operand" "=r") (ior:DI (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "rm") (match_operand:QI 3 "const_0_to_63_operand")) @@ -14562,15 +14662,69 @@ (lshiftrt:TI (zero_extend:TI (match_operand:DI 2 "register_operand" "r")) - (match_operand:QI 4 "const_0_to_255_operand")) 0))) - (clobber (reg:CC FLAGS_REG))] + (match_operand:QI 4 "const_0_to_255_operand")) 0)))] "TARGET_APX_NDD - && INTVAL (operands[4]) == 64 - INTVAL (operands[3])" - "shld{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" + && INTVAL (operands[4]) == 64 - INTVAL (operands[3]) + && " + "shld{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") (set_attr "mode" "DI") (set_attr "length_immediate" "1")]) +(define_insn_and_split "*x86_64_shld_shrd_1_nozext_nf" + [(set (match_operand:DI 0 "nonimmediate_operand") + (ior:DI (ashift:DI (match_operand:DI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_63_operand")) + (lshiftrt:DI + (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_63_operand"))))] + "TARGET_64BIT && TARGET_APX_NF + && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)] +{ + if (rtx_equal_p (operands[4], operands[0])) + { + operands[1] = force_reg (DImode, operands[1]); + emit_insn (gen_x86_64_shld_1_nf (operands[0], operands[1], + operands[2], operands[3])); + } + else if (rtx_equal_p (operands[1], operands[0])) + { + operands[4] = force_reg (DImode, operands[4]); + emit_insn (gen_x86_64_shrd_1_nf (operands[0], operands[4], + operands[3], operands[2])); + } + else if (TARGET_APX_NDD) + { + rtx tmp = gen_reg_rtx (DImode); + if (MEM_P (operands[4])) + { + operands[1] = force_reg (DImode, operands[1]); + emit_insn (gen_x86_64_shld_ndd_1_nf (tmp, operands[4], operands[1], + operands[2], operands[3])); + } + else if (MEM_P (operands[1])) + emit_insn (gen_x86_64_shrd_ndd_1_nf (tmp, operands[1], operands[4], + operands[3], operands[2])); + else + emit_insn (gen_x86_64_shld_ndd_1_nf (tmp, operands[4], operands[1], + operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + else + { + operands[1] = force_reg (DImode, operands[1]); + rtx tmp = gen_reg_rtx (DImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_64_shld_1_nf (tmp, operands[1], + operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; +}) (define_insn_and_split "*x86_64_shld_shrd_1_nozext" [(set (match_operand:DI 0 "nonimmediate_operand") @@ -14673,7 +14827,7 @@ emit_move_insn (operands[4], operands[0]); }) -(define_insn "x86_shld" +(define_insn "x86_shld" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") (ior:SI (ashift:SI (match_dup 0) (and:QI (match_operand:QI 2 "nonmemory_operand" "Ic") @@ -14683,10 +14837,9 @@ (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) (minus:QI (const_int 32) - (and:QI (match_dup 2) (const_int 31)))) 0))) - (clobber (reg:CC FLAGS_REG))] - "" - "shld{l}\t{%2, %1, %0|%0, %1, %2}" + (and:QI (match_dup 2) (const_int 31)))) 0)))] + "" + "shld{l}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") (set_attr "mode" "SI") @@ -14695,7 +14848,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_shld_ndd" +(define_insn "x86_shld_ndd" [(set (match_operand:SI 0 "nonimmediate_operand" "=r") (ior:SI (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "rm") (and:QI (match_operand:QI 3 "nonmemory_operand" "Ic") @@ -14705,15 +14858,14 @@ (zero_extend:DI (match_operand:SI 2 "register_operand" "r")) (minus:QI (const_int 32) - (and:QI (match_dup 3) (const_int 31)))) 0))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_APX_NDD" - "shld{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" + (and:QI (match_dup 3) (const_int 31)))) 0)))] + "TARGET_APX_NDD && " + "shld{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) -(define_insn "x86_shld_1" +(define_insn "x86_shld_1" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") (ior:SI (ashift:SI (match_dup 0) (match_operand:QI 2 "const_0_to_31_operand")) @@ -14721,10 +14873,10 @@ (lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) - (match_operand:QI 3 "const_0_to_63_operand")) 0))) - (clobber (reg:CC FLAGS_REG))] - "INTVAL (operands[3]) == 32 - INTVAL (operands[2])" - "shld{l}\t{%2, %1, %0|%0, %1, %2}" + (match_operand:QI 3 "const_0_to_63_operand")) 0)))] + "INTVAL (operands[3]) == 32 - INTVAL (operands[2]) + && " + "shld{l}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") (set_attr "length_immediate" "1") @@ -14734,7 +14886,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_shld_ndd_1" +(define_insn "x86_shld_ndd_1" [(set (match_operand:SI 0 "register_operand" "=r") (ior:SI (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "rm") (match_operand:QI 3 "const_0_to_31_operand")) @@ -14742,15 +14894,69 @@ (lshiftrt:DI (zero_extend:DI (match_operand:SI 2 "register_operand" "r")) - (match_operand:QI 4 "const_0_to_63_operand")) 0))) - (clobber (reg:CC FLAGS_REG))] + (match_operand:QI 4 "const_0_to_63_operand")) 0)))] "TARGET_APX_NDD - && INTVAL (operands[4]) == 32 - INTVAL (operands[3])" - "shld{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" + && INTVAL (operands[4]) == 32 - INTVAL (operands[3]) + && " + "shld{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") (set_attr "length_immediate" "1") (set_attr "mode" "SI")]) +(define_insn_and_split "*x86_shld_shrd_1_nozext_nf" + [(set (match_operand:SI 0 "nonimmediate_operand") + (ior:SI (ashift:SI (match_operand:SI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_31_operand")) + (lshiftrt:SI + (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_31_operand"))))] + "TARGET_APX_NF + && INTVAL (operands[3]) == 32 - INTVAL (operands[2]) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)] +{ + if (rtx_equal_p (operands[4], operands[0])) + { + operands[1] = force_reg (SImode, operands[1]); + emit_insn (gen_x86_shld_1_nf (operands[0], operands[1], + operands[2], operands[3])); + } + else if (rtx_equal_p (operands[1], operands[0])) + { + operands[4] = force_reg (SImode, operands[4]); + emit_insn (gen_x86_shrd_1_nf (operands[0], operands[4], + operands[3], operands[2])); + } + else if (TARGET_APX_NDD) + { + rtx tmp = gen_reg_rtx (SImode); + if (MEM_P (operands[4])) + { + operands[1] = force_reg (SImode, operands[1]); + emit_insn (gen_x86_shld_ndd_1_nf (tmp, operands[4], operands[1], + operands[2], operands[3])); + } + else if (MEM_P (operands[1])) + emit_insn (gen_x86_shrd_ndd_1_nf (tmp, operands[1], operands[4], + operands[3], operands[2])); + else + emit_insn (gen_x86_shld_ndd_1_nf (tmp, operands[4], operands[1], + operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + else + { + operands[1] = force_reg (SImode, operands[1]); + rtx tmp = gen_reg_rtx (SImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_shld_1_nf (tmp, operands[1], operands[2], + operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; +}) (define_insn_and_split "*x86_shld_shrd_1_nozext" [(set (match_operand:SI 0 "nonimmediate_operand") @@ -14955,17 +15161,22 @@ [(set_attr "type" "ishiftx") (set_attr "mode" "")]) -(define_insn "*ashl3_1" +(define_insn "*ashl3_1" [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,?k,r") (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "0,l,rm,k,rm") - (match_operand:QI 2 "nonmemory_operand" "c,M,r,,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFT, mode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "c,M,r,,c")))] + "ix86_binary_operator_ok (ASHIFT, mode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_LEA: + if (TARGET_APX_NDD && ) + return "%{nf%} sal{}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; + case TYPE_ISHIFTX: case TYPE_MSKLOG: return "#"; @@ -14973,7 +15184,7 @@ case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); gcc_assert (rtx_equal_p (operands[0], operands[1])); - return "add{}\t%0, %0"; + return "add{}\t%0, %0"; default: if (operands[2] == const1_rtx @@ -14981,11 +15192,11 @@ /* For NDD form instructions related to TARGET_SHIFT1, the $1 immediate do not need to be omitted as assembler will map it to use shorter encoding. */ - && !use_ndd) + && !use_ndd && !) return "sal{}\t%0"; else - return use_ndd ? "sal{}\t{%2, %1, %0|%0, %1, %2}" - : "sal{}\t{%2, %0|%0, %2}"; + return use_ndd ? "sal{}\t{%2, %1, %0|%0, %1, %2}" + : "sal{}\t{%2, %0|%0, %2}"; } } [(set_attr "isa" "*,*,bmi2,avx512bw,apx_ndd") @@ -15016,6 +15227,17 @@ (set_attr "mode" "")]) ;; Convert shift to the shiftx pattern to avoid flags dependency. +;; For NF/NDD doesn't support shift count as r, it just support c, +;; and it has no flag. +(define_split + [(set (match_operand:SWI48 0 "register_operand") + (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") + (match_operand:QI 2 "register_operand")))] + "TARGET_BMI2 && reload_completed" + [(set (match_dup 0) + (ashift:SWI48 (match_dup 1) (match_dup 2)))] + "operands[2] = gen_lowpart (mode, operands[2]);") + (define_split [(set (match_operand:SWI48 0 "register_operand") (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") @@ -15102,32 +15324,37 @@ (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))] "operands[2] = gen_lowpart (SImode, operands[2]);") -(define_insn "*ashlhi3_1" +(define_insn "*ashlhi3_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,Yp,?k,r") (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,l,k,rm") - (match_operand:QI 2 "nonmemory_operand" "cI,M,Ww,cI"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFT, HImode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "cI,M,Ww,cI")))] + "ix86_binary_operator_ok (ASHIFT, HImode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_LEA: + if (TARGET_APX_NDD && ) + return "%{nf%} sal{w}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; + case TYPE_MSKLOG: return "#"; case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); - return "add{w}\t%0, %0"; + return "add{w}\t%0, %0"; default: if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !) return "sal{w}\t%0"; else - return use_ndd ? "sal{w}\t{%2, %1, %0|%0, %1, %2}" - : "sal{w}\t{%2, %0|%0, %2}"; + return use_ndd ? "sal{w}\t{%2, %1, %0|%0, %1, %2}" + : "sal{w}\t{%2, %0|%0, %2}"; } } [(set_attr "isa" "*,*,avx512f,apx_ndd") @@ -15155,31 +15382,36 @@ (const_string "*"))) (set_attr "mode" "HI,SI,HI,HI")]) -(define_insn "*ashlqi3_1" +(define_insn "*ashlqi3_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,r,Yp,?k,r") (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,l,k,rm") - (match_operand:QI 2 "nonmemory_operand" "cI,cI,M,Wb,cI"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFT, QImode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "cI,cI,M,Wb,cI")))] + "ix86_binary_operator_ok (ASHIFT, QImode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_LEA: + if (TARGET_APX_NDD && ) + return "%{nf%} sal{b}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; + case TYPE_MSKLOG: return "#"; case TYPE_ALU: gcc_assert (operands[2] == const1_rtx); if (REG_P (operands[1]) && !ANY_QI_REGNO_P (REGNO (operands[1]))) - return "add{l}\t%k0, %k0"; + return "add{l}\t%k0, %k0"; else - return "add{b}\t%0, %0"; + return "add{b}\t%0, %0"; default: if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !) { if (get_attr_mode (insn) == MODE_SI) return "sal{l}\t%k0"; @@ -15189,10 +15421,10 @@ else { if (get_attr_mode (insn) == MODE_SI) - return "sal{l}\t{%2, %k0|%k0, %2}"; + return "sal{l}\t{%2, %k0|%k0, %2}"; else - return use_ndd ? "sal{b}\t{%2, %1, %0|%0, %1, %2}" - : "sal{b}\t{%2, %0|%0, %2}"; + return use_ndd ? "sal{b}\t{%2, %1, %0|%0, %1, %2}" + : "sal{b}\t{%2, %0|%0, %2}"; } } } @@ -15295,6 +15527,24 @@ operands[2] = GEN_INT (1 << INTVAL (operands[2])); }) +(define_split + [(set (match_operand:SWI 0 "general_reg_operand") + (ashift:SWI (match_operand:SWI 1 "index_reg_operand") + (match_operand 2 "const_0_to_3_operand")))] + "reload_completed + && REGNO (operands[0]) != REGNO (operands[1]) + && !TARGET_APX_NDD" + [(set (match_dup 0) + (mult: (match_dup 1) (match_dup 2)))] +{ + if (mode != mode) + { + operands[0] = gen_lowpart (mode, operands[0]); + operands[1] = gen_lowpart (mode, operands[1]); + } + operands[2] = GEN_INT (1 << INTVAL (operands[2])); +}) + ;; Convert ashift to the lea pattern to avoid flags dependency. (define_split [(set (match_operand:DI 0 "general_reg_operand") @@ -15761,6 +16011,26 @@ }) ;; Split truncations of double word right shifts into x86_shrd_1. +(define_insn_and_split "3_doubleword_lowpart_nf" + [(set (match_operand:DWIH 0 "register_operand" "=&r") + (subreg:DWIH + (any_shiftrt: (match_operand: 1 "register_operand" "r") + (match_operand:QI 2 "const_int_operand")) 0))] + "TARGET_APX_NF && UINTVAL (operands[2]) < * BITS_PER_UNIT" + "#" + "&& reload_completed" + [(set (match_dup 0) + (ior:DWIH (lshiftrt:DWIH (match_dup 0) (match_dup 2)) + (subreg:DWIH + (ashift: (zero_extend: (match_dup 3)) + (match_dup 4)) 0)))] +{ + split_double_mode (mode, &operands[1], 1, &operands[1], &operands[3]); + operands[4] = GEN_INT (( * BITS_PER_UNIT) - INTVAL (operands[2])); + if (!rtx_equal_p (operands[0], operands[1])) + emit_move_insn (operands[0], operands[1]); +}) + (define_insn_and_split "3_doubleword_lowpart" [(set (match_operand:DWIH 0 "register_operand" "=&r") (subreg:DWIH @@ -15784,7 +16054,7 @@ emit_move_insn (operands[0], operands[1]); }) -(define_insn "x86_64_shrd" +(define_insn "x86_64_shrd" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") (ior:DI (lshiftrt:DI (match_dup 0) (and:QI (match_operand:QI 2 "nonmemory_operand" "Jc") @@ -15794,10 +16064,9 @@ (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) (minus:QI (const_int 64) - (and:QI (match_dup 2) (const_int 63)))) 0))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT" - "shrd{q}\t{%2, %1, %0|%0, %1, %2}" + (and:QI (match_dup 2) (const_int 63)))) 0)))] + "TARGET_64BIT && " + "shrd{q}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") (set_attr "mode" "DI") @@ -15805,7 +16074,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_64_shrd_ndd" +(define_insn "x86_64_shrd_ndd" [(set (match_operand:DI 0 "register_operand" "=r") (ior:DI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "rm") (and:QI (match_operand:QI 3 "nonmemory_operand" "Jc") @@ -15815,15 +16084,13 @@ (zero_extend:TI (match_operand:DI 2 "register_operand" "r")) (minus:QI (const_int 64) - (and:QI (match_dup 3) (const_int 63)))) 0))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_APX_NDD" - "shrd{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" + (and:QI (match_dup 3) (const_int 63)))) 0)))] + "TARGET_APX_NDD && " + "shrd{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") (set_attr "mode" "DI")]) - -(define_insn "x86_64_shrd_1" +(define_insn "x86_64_shrd_1" [(set (match_operand:DI 0 "nonimmediate_operand" "+r*m") (ior:DI (lshiftrt:DI (match_dup 0) (match_operand:QI 2 "const_0_to_63_operand")) @@ -15831,11 +16098,11 @@ (ashift:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) - (match_operand:QI 3 "const_0_to_255_operand")) 0))) - (clobber (reg:CC FLAGS_REG))] + (match_operand:QI 3 "const_0_to_255_operand")) 0)))] "TARGET_64BIT - && INTVAL (operands[3]) == 64 - INTVAL (operands[2])" - "shrd{q}\t{%2, %1, %0|%0, %1, %2}" + && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) + && " + "shrd{q}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") (set_attr "length_immediate" "1") @@ -15844,7 +16111,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_64_shrd_ndd_1" +(define_insn "x86_64_shrd_ndd_1" [(set (match_operand:DI 0 "register_operand" "=r") (ior:DI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "rm") (match_operand:QI 3 "const_0_to_63_operand")) @@ -15852,15 +16119,69 @@ (ashift:TI (zero_extend:TI (match_operand:DI 2 "register_operand" "r")) - (match_operand:QI 4 "const_0_to_255_operand")) 0))) - (clobber (reg:CC FLAGS_REG))] + (match_operand:QI 4 "const_0_to_255_operand")) 0)))] "TARGET_APX_NDD - && INTVAL (operands[4]) == 64 - INTVAL (operands[3])" - "shrd{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" + && INTVAL (operands[4]) == 64 - INTVAL (operands[3]) + && " + "shrd{q}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") (set_attr "length_immediate" "1") (set_attr "mode" "DI")]) +(define_insn_and_split "*x86_64_shrd_shld_1_nozext_nf" + [(set (match_operand:DI 0 "nonimmediate_operand") + (ior:DI (lshiftrt:DI (match_operand:DI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_63_operand")) + (ashift:DI + (match_operand:DI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_63_operand"))))] + "TARGET_64BIT && TARGET_APX_NF + && INTVAL (operands[3]) == 64 - INTVAL (operands[2]) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)] +{ + if (rtx_equal_p (operands[4], operands[0])) + { + operands[1] = force_reg (DImode, operands[1]); + emit_insn (gen_x86_64_shrd_1_nf (operands[0], operands[1], + operands[2], operands[3])); + } + else if (rtx_equal_p (operands[1], operands[0])) + { + operands[4] = force_reg (DImode, operands[4]); + emit_insn (gen_x86_64_shld_1_nf (operands[0], operands[4], + operands[3], operands[2])); + } + else if (TARGET_APX_NDD) + { + rtx tmp = gen_reg_rtx (DImode); + if (MEM_P (operands[4])) + { + operands[1] = force_reg (DImode, operands[1]); + emit_insn (gen_x86_64_shrd_ndd_1_nf (tmp, operands[4], operands[1], + operands[2], operands[3])); + } + else if (MEM_P (operands[1])) + emit_insn (gen_x86_64_shld_ndd_1_nf (tmp, operands[1], operands[4], + operands[3], operands[2])); + else + emit_insn (gen_x86_64_shrd_ndd_1_nf (tmp, operands[4], operands[1], + operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + else + { + operands[1] = force_reg (DImode, operands[1]); + rtx tmp = gen_reg_rtx (DImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_64_shrd_1_nf (tmp, operands[1], + operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; +}) (define_insn_and_split "*x86_64_shrd_shld_1_nozext" [(set (match_operand:DI 0 "nonimmediate_operand") @@ -15963,7 +16284,7 @@ emit_move_insn (operands[4], operands[0]); }) -(define_insn "x86_shrd" +(define_insn "x86_shrd" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") (ior:SI (lshiftrt:SI (match_dup 0) (and:QI (match_operand:QI 2 "nonmemory_operand" "Ic") @@ -15973,10 +16294,9 @@ (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) (minus:QI (const_int 32) - (and:QI (match_dup 2) (const_int 31)))) 0))) - (clobber (reg:CC FLAGS_REG))] - "" - "shrd{l}\t{%2, %1, %0|%0, %1, %2}" + (and:QI (match_dup 2) (const_int 31)))) 0)))] + "" + "shrd{l}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") (set_attr "mode" "SI") @@ -15985,7 +16305,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_shrd_ndd" +(define_insn "x86_shrd_ndd" [(set (match_operand:SI 0 "register_operand" "=r") (ior:SI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "rm") (and:QI (match_operand:QI 3 "nonmemory_operand" "Ic") @@ -15995,14 +16315,13 @@ (zero_extend:DI (match_operand:SI 2 "register_operand" "r")) (minus:QI (const_int 32) - (and:QI (match_dup 3) (const_int 31)))) 0))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_APX_NDD" - "shrd{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" + (and:QI (match_dup 3) (const_int 31)))) 0)))] + "TARGET_APX_NDD && " + "shrd{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) -(define_insn "x86_shrd_1" +(define_insn "x86_shrd_1" [(set (match_operand:SI 0 "nonimmediate_operand" "+r*m") (ior:SI (lshiftrt:SI (match_dup 0) (match_operand:QI 2 "const_0_to_31_operand")) @@ -16010,10 +16329,10 @@ (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) - (match_operand:QI 3 "const_0_to_63_operand")) 0))) - (clobber (reg:CC FLAGS_REG))] - "INTVAL (operands[3]) == 32 - INTVAL (operands[2])" - "shrd{l}\t{%2, %1, %0|%0, %1, %2}" + (match_operand:QI 3 "const_0_to_63_operand")) 0)))] + "INTVAL (operands[3]) == 32 - INTVAL (operands[2]) + && " + "shrd{l}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ishift") (set_attr "prefix_0f" "1") (set_attr "length_immediate" "1") @@ -16023,7 +16342,7 @@ (set_attr "amdfam10_decode" "vector") (set_attr "bdver1_decode" "vector")]) -(define_insn "x86_shrd_ndd_1" +(define_insn "x86_shrd_ndd_1" [(set (match_operand:SI 0 "register_operand" "=r") (ior:SI (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "rm") (match_operand:QI 3 "const_0_to_31_operand")) @@ -16031,15 +16350,69 @@ (ashift:DI (zero_extend:DI (match_operand:SI 2 "register_operand" "r")) - (match_operand:QI 4 "const_0_to_63_operand")) 0))) - (clobber (reg:CC FLAGS_REG))] + (match_operand:QI 4 "const_0_to_63_operand")) 0)))] "TARGET_APX_NDD - && (INTVAL (operands[4]) == 32 - INTVAL (operands[3]))" - "shrd{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" + && (INTVAL (operands[4]) == 32 - INTVAL (operands[3])) + && " + "shrd{l}\t{%3, %2, %1, %0|%0, %1, %2, %3}" [(set_attr "type" "ishift") (set_attr "length_immediate" "1") (set_attr "mode" "SI")]) +(define_insn_and_split "*x86_shrd_shld_1_nozext_nf" + [(set (match_operand:SI 0 "nonimmediate_operand") + (ior:SI (lshiftrt:SI (match_operand:SI 4 "nonimmediate_operand") + (match_operand:QI 2 "const_0_to_31_operand")) + (ashift:SI + (match_operand:SI 1 "nonimmediate_operand") + (match_operand:QI 3 "const_0_to_31_operand"))))] + "TARGET_APX_NF + && INTVAL (operands[3]) == 32 - INTVAL (operands[2]) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)] +{ + if (rtx_equal_p (operands[4], operands[0])) + { + operands[1] = force_reg (SImode, operands[1]); + emit_insn (gen_x86_shrd_1_nf (operands[0], operands[1], + operands[2], operands[3])); + } + else if (rtx_equal_p (operands[1], operands[0])) + { + operands[4] = force_reg (SImode, operands[4]); + emit_insn (gen_x86_shld_1_nf (operands[0], operands[4], + operands[3], operands[2])); + } + else if (TARGET_APX_NDD) + { + rtx tmp = gen_reg_rtx (SImode); + if (MEM_P (operands[4])) + { + operands[1] = force_reg (SImode, operands[1]); + emit_insn (gen_x86_shrd_ndd_1_nf (tmp, operands[4], operands[1], + operands[2], operands[3])); + } + else if (MEM_P (operands[1])) + emit_insn (gen_x86_shld_ndd_1_nf (tmp, operands[1], operands[4], + operands[3], operands[2])); + else + emit_insn (gen_x86_shrd_ndd_1_nf (tmp, operands[4], operands[1], + operands[2], operands[3])); + emit_move_insn (operands[0], tmp); + } + else + { + operands[1] = force_reg (SImode, operands[1]); + rtx tmp = gen_reg_rtx (SImode); + emit_move_insn (tmp, operands[4]); + emit_insn (gen_x86_shrd_1_nf (tmp, operands[1], operands[2], + operands[3])); + emit_move_insn (operands[0], tmp); + } + DONE; +}) (define_insn_and_split "*x86_shrd_shld_1_nozext" [(set (match_operand:SI 0 "nonimmediate_operand") @@ -16145,19 +16518,19 @@ (define_mode_attr cvt_mnemonic [(SI "{cltd|cdq}") (DI "{cqto|cqo}")]) -(define_insn "ashr3_cvt" +(define_insn "ashr3_cvt" [(set (match_operand:SWI48 0 "nonimmediate_operand" "=*d,rm,r") (ashiftrt:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "*a,0,rm") - (match_operand:QI 2 "const_int_operand"))) - (clobber (reg:CC FLAGS_REG))] + (match_operand:QI 2 "const_int_operand")))] "INTVAL (operands[2]) == GET_MODE_BITSIZE (mode)-1 && (TARGET_USE_CLTD || optimize_function_for_size_p (cfun)) - && ix86_binary_operator_ok (ASHIFTRT, mode, operands, TARGET_APX_NDD)" + && ix86_binary_operator_ok (ASHIFTRT, mode, operands, TARGET_APX_NDD) + && " "@ - sar{}\t{%2, %0|%0, %2} - sar{}\t{%2, %1, %0|%0, %1, %2}" + sar{}\t{%2, %0|%0, %2} + sar{}\t{%2, %1, %0|%0, %1, %2}" [(set_attr "isa" "*,*,apx_ndd") (set_attr "type" "imovx,ishift,ishift") (set_attr "prefix_0f" "0,*,*") @@ -16223,13 +16596,13 @@ [(set_attr "type" "ishiftx") (set_attr "mode" "")]) -(define_insn "*ashr3_1" +(define_insn "*ashr3_1" [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r") (ashiftrt:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "0,rm,rm") - (match_operand:QI 2 "nonmemory_operand" "c,r,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFTRT, mode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "c,r,c")))] + "ix86_binary_operator_ok (ASHIFTRT, mode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) @@ -16240,11 +16613,11 @@ default: if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !) return "sar{}\t%0"; else - return use_ndd ? "sar{}\t{%2, %1, %0|%0, %1, %2}" - : "sar{}\t{%2, %0|%0, %2}"; + return use_ndd ? "sar{}\t{%2, %1, %0|%0, %1, %2}" + : "sar{}\t{%2, %0|%0, %2}"; } } [(set_attr "isa" "*,bmi2,apx_ndd") @@ -16284,14 +16657,13 @@ } [(set_attr "isa" "*,*,*,apx_ndd")]) - -(define_insn "*lshr3_1" +(define_insn "*lshr3_1" [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,?k,r") (lshiftrt:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "0,rm,k,rm") - (match_operand:QI 2 "nonmemory_operand" "c,r,,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (LSHIFTRT, mode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "c,r,,c")))] + "ix86_binary_operator_ok (LSHIFTRT, mode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) @@ -16303,11 +16675,11 @@ default: if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !) return "shr{}\t%0"; else - return use_ndd ? "shr{}\t{%2, %1, %0|%0, %1, %2}" - : "shr{}\t{%2, %0|%0, %2}"; + return use_ndd ? "shr{}\t{%2, %1, %0|%0, %1, %2}" + : "shr{}\t{%2, %0|%0, %2}"; } } [(set_attr "isa" "*,bmi2,avx512bw,apx_ndd") @@ -16323,6 +16695,17 @@ (set_attr "mode" "")]) ;; Convert shift to the shiftx pattern to avoid flags dependency. +;; For NF/NDD doesn't support shift count as r, it just support c, +;; and it has no flag. +(define_split + [(set (match_operand:SWI48 0 "register_operand") + (any_shiftrt:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") + (match_operand:QI 2 "register_operand")))] + "TARGET_BMI2 && reload_completed" + [(set (match_dup 0) + (any_shiftrt:SWI48 (match_dup 1) (match_dup 2)))] + "operands[2] = gen_lowpart (mode, operands[2]);") + (define_split [(set (match_operand:SWI48 0 "register_operand") (any_shiftrt:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") @@ -16391,22 +16774,22 @@ (zero_extend:DI (any_shiftrt:SI (match_dup 1) (match_dup 2))))] "operands[2] = gen_lowpart (SImode, operands[2]);") -(define_insn "*ashr3_1" +(define_insn "*ashr3_1" [(set (match_operand:SWI12 0 "nonimmediate_operand" "=m, r") (ashiftrt:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "0, rm") - (match_operand:QI 2 "nonmemory_operand" "c, c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (ASHIFTRT, mode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "c, c")))] + "ix86_binary_operator_ok (ASHIFTRT, mode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !) return "sar{}\t%0"; else - return use_ndd ? "sar{}\t{%2, %1, %0|%0, %1, %2}" - : "sar{}\t{%2, %0|%0, %2}"; + return use_ndd ? "sar{}\t{%2, %1, %0|%0, %1, %2}" + : "sar{}\t{%2, %0|%0, %2}"; } [(set_attr "isa" "*, apx_ndd") (set_attr "type" "ishift") @@ -16419,13 +16802,13 @@ (const_string "*"))) (set_attr "mode" "")]) -(define_insn "*lshrqi3_1" +(define_insn "*lshrqi3_1" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,?k,r") (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0, k, rm") - (match_operand:QI 2 "nonmemory_operand" "cI,Wb,cI"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (LSHIFTRT, QImode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "cI,Wb,cI")))] + "ix86_binary_operator_ok (LSHIFTRT, QImode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) @@ -16433,11 +16816,11 @@ case TYPE_ISHIFT: if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !) return "shr{b}\t%0"; else - return use_ndd ? "shr{b}\t{%2, %1, %0|%0, %1, %2}" - : "shr{b}\t{%2, %0|%0, %2}"; + return use_ndd ? "shr{b}\t{%2, %1, %0|%0, %1, %2}" + : "shr{b}\t{%2, %0|%0, %2}"; case TYPE_MSKLOG: return "#"; default: @@ -16456,13 +16839,13 @@ (const_string "*"))) (set_attr "mode" "QI")]) -(define_insn "*lshrhi3_1" +(define_insn "*lshrhi3_1" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm, ?k, r") (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0, k, rm") - (match_operand:QI 2 "nonmemory_operand" "cI, Ww, cI"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (LSHIFTRT, HImode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "cI, Ww, cI")))] + "ix86_binary_operator_ok (LSHIFTRT, HImode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) @@ -16470,11 +16853,11 @@ case TYPE_ISHIFT: if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !) return "shr{w}\t%0"; else - return use_ndd ? "shr{w}\t{%2, %1, %0|%0, %1, %2}" - : "shr{w}\t{%2, %0|%0, %2}"; + return use_ndd ? "shr{w}\t{%2, %1, %0|%0, %1, %2}" + : "shr{w}\t{%2, %0|%0, %2}"; case TYPE_MSKLOG: return "#"; default: @@ -16999,28 +17382,31 @@ [(set_attr "type" "rotatex") (set_attr "mode" "")]) -(define_insn "*3_1" +(define_insn "*3_1" [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r") (any_rotate:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "0,rm,rm") - (match_operand:QI 2 "nonmemory_operand" "c,,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (, mode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "c,,c")))] + "ix86_binary_operator_ok (, mode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; switch (get_attr_type (insn)) { case TYPE_ROTATEX: - return "#"; + if (TARGET_APX_NDD && ) + return "%{nf%} {}\t{%2, %1, %0|%0, %1, %2}"; + else + return "#"; default: if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !) return "{}\t%0"; else - return use_ndd ? "{}\t{%2, %1, %0|%0, %1, %2}" - : "{}\t{%2, %0|%0, %2}"; + return use_ndd ? "{}\t{%2, %1, %0|%0, %1, %2}" + : "{}\t{%2, %0|%0, %2}"; } } [(set_attr "isa" "*,bmi2,apx_ndd") @@ -17054,6 +17440,20 @@ operands[2] = GEN_INT ((bitsize - INTVAL (operands[2])) % bitsize); }) +(define_split + [(set (match_operand:SWI48 0 "register_operand") + (rotate:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") + (match_operand:QI 2 "const_int_operand")))] + "TARGET_BMI2 && reload_completed && !optimize_function_for_size_p (cfun) + && !TARGET_APX_NDD" + [(set (match_dup 0) + (rotatert:SWI48 (match_dup 1) (match_dup 2)))] +{ + int bitsize = GET_MODE_BITSIZE (mode); + + operands[2] = GEN_INT ((bitsize - INTVAL (operands[2])) % bitsize); +}) + (define_split [(set (match_operand:SWI48 0 "register_operand") (rotatert:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") @@ -17141,22 +17541,22 @@ [(set (match_dup 0) (zero_extend:DI (rotatert:SI (match_dup 1) (match_dup 2))))]) -(define_insn "*3_1" +(define_insn "*3_1" [(set (match_operand:SWI12 0 "nonimmediate_operand" "=m,r") (any_rotate:SWI12 (match_operand:SWI12 1 "nonimmediate_operand" "0,rm") - (match_operand:QI 2 "nonmemory_operand" "c,c"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (, mode, operands, TARGET_APX_NDD)" + (match_operand:QI 2 "nonmemory_operand" "c,c")))] + "ix86_binary_operator_ok (, mode, operands, TARGET_APX_NDD) + && " { bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD; if (operands[2] == const1_rtx && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)) - && !use_ndd) + && !use_ndd && !) return "{}\t%0"; else return use_ndd - ? "{}\t{%2, %1, %0|%0, %1, %2}" - : "{}\t{%2, %0|%0, %2}"; + ? "{}\t{%2, %1, %0|%0, %1, %2}" + : "{}\t{%2, %0|%0, %2}"; } [(set_attr "isa" "*,apx_ndd") (set_attr "type" "rotate") @@ -19914,6 +20314,24 @@ operands[3] = gen_reg_rtx (mode); }) +(define_insn_and_split "clz2_lzcnt_nf" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (clz:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "rm")))] + "TARGET_APX_NF && TARGET_LZCNT" + "%{nf%} lzcnt{}\t{%1, %0|%0, %1}" + "&& TARGET_AVOID_FALSE_DEP_FOR_BMI && epilogue_completed + && optimize_function_for_speed_p (cfun) + && !reg_mentioned_p (operands[0], operands[1])" + [(parallel + [(set (match_dup 0) + (clz:SWI48 (match_dup 1))) + (unspec [(match_dup 0)] UNSPEC_INSN_FALSE_DEP)])] + "ix86_expand_clear (operands[0]);" + [(set_attr "prefix_rep" "1") + (set_attr "type" "bitmanip") + (set_attr "mode" "")]) + (define_insn_and_split "clz2_lzcnt" [(set (match_operand:SWI48 0 "register_operand" "=r") (clz:SWI48 @@ -19937,6 +20355,18 @@ ; False dependency happens when destination is only updated by tzcnt, ; lzcnt or popcnt. There is no false dependency when destination is ; also used in source. +(define_insn "*clz2_lzcnt_falsedep_nf" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (clz:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "rm"))) + (unspec [(match_operand:SWI48 2 "register_operand" "0")] + UNSPEC_INSN_FALSE_DEP)] + "TARGET_APX_NF && TARGET_LZCNT" + "%{nf%} lzcnt{}\t{%1, %0|%0, %1}" + [(set_attr "prefix_rep" "1") + (set_attr "type" "bitmanip") + (set_attr "mode" "")]) + (define_insn "*clz2_lzcnt_falsedep" [(set (match_operand:SWI48 0 "register_operand" "=r") (clz:SWI48 @@ -20043,6 +20473,25 @@ ;; Version of lzcnt/tzcnt that is expanded from intrinsics. This version ;; provides operand size as output when source operand is zero. +(define_insn_and_split "__nf" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (unspec:SWI48 + [(match_operand:SWI48 1 "nonimmediate_operand" "rm")] LT_ZCNT))] + "TARGET_APX_NF" + "%{nf%} {}\t{%1, %0|%0, %1}" + "&& TARGET_AVOID_FALSE_DEP_FOR_BMI && epilogue_completed + && optimize_function_for_speed_p (cfun) + && !reg_mentioned_p (operands[0], operands[1])" + [(parallel + [(set (match_dup 0) + (unspec:SWI48 [(match_dup 1)] LT_ZCNT)) + (unspec [(match_dup 0)] UNSPEC_INSN_FALSE_DEP)])] + "ix86_expand_clear (operands[0]);" + [(set_attr "type" "") + (set_attr "prefix_0f" "1") + (set_attr "prefix_rep" "1") + (set_attr "mode" "")]) + (define_insn_and_split "_" [(set (match_operand:SWI48 0 "register_operand" "=r") (unspec:SWI48 @@ -20067,6 +20516,19 @@ ; False dependency happens when destination is only updated by tzcnt, ; lzcnt or popcnt. There is no false dependency when destination is ; also used in source. +(define_insn "*__falsedep_nf" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (unspec:SWI48 + [(match_operand:SWI48 1 "nonimmediate_operand" "rm")] LT_ZCNT)) + (unspec [(match_operand:SWI48 2 "register_operand" "0")] + UNSPEC_INSN_FALSE_DEP)] + "TARGET_APX_NF" + "%{nf%} {}\t{%1, %0|%0, %1}" + [(set_attr "type" "") + (set_attr "prefix_0f" "1") + (set_attr "prefix_rep" "1") + (set_attr "mode" "")]) + (define_insn "*__falsedep" [(set (match_operand:SWI48 0 "register_operand" "=r") (unspec:SWI48 @@ -20081,13 +20543,12 @@ (set_attr "prefix_rep" "1") (set_attr "mode" "")]) -(define_insn "_hi" +(define_insn "_hi" [(set (match_operand:HI 0 "register_operand" "=r") (unspec:HI - [(match_operand:HI 1 "nonimmediate_operand" "rm")] LT_ZCNT)) - (clobber (reg:CC FLAGS_REG))] - "" - "{w}\t{%1, %0|%0, %1}" + [(match_operand:HI 1 "nonimmediate_operand" "rm")] LT_ZCNT))] + "" + "{w}\t{%1, %0|%0, %1}" [(set_attr "type" "") (set_attr "prefix_0f" "1") (set_attr "prefix_rep" "1") @@ -20505,6 +20966,30 @@ [(set_attr "type" "bitmanip") (set_attr "mode" "")]) +(define_insn_and_split "popcount2_nf" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (popcount:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "rm")))] + "TARGET_APX_NF && TARGET_POPCNT" +{ +#if TARGET_MACHO + return "%{nf%} popcnt\t{%1, %0|%0, %1}"; +#else + return "%{nf%} popcnt{}\t{%1, %0|%0, %1}"; +#endif +} + "&& TARGET_AVOID_FALSE_DEP_FOR_BMI && epilogue_completed + && optimize_function_for_speed_p (cfun) + && !reg_mentioned_p (operands[0], operands[1])" + [(parallel + [(set (match_dup 0) + (popcount:SWI48 (match_dup 1))) + (unspec [(match_dup 0)] UNSPEC_INSN_FALSE_DEP)])] + "ix86_expand_clear (operands[0]);" + [(set_attr "prefix_rep" "1") + (set_attr "type" "bitmanip") + (set_attr "mode" "")]) + (define_insn_and_split "popcount2" [(set (match_operand:SWI48 0 "register_operand" "=r") (popcount:SWI48 @@ -20534,6 +21019,24 @@ ; False dependency happens when destination is only updated by tzcnt, ; lzcnt or popcnt. There is no false dependency when destination is ; also used in source. +(define_insn "*popcount2_falsedep_nf" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (popcount:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "rm"))) + (unspec [(match_operand:SWI48 2 "register_operand" "0")] + UNSPEC_INSN_FALSE_DEP)] + "TARGET_APX_NF && TARGET_POPCNT" +{ +#if TARGET_MACHO + return "%{nf%} popcnt\t{%1, %0|%0, %1}"; +#else + return "%{nf%} popcnt{}\t{%1, %0|%0, %1}"; +#endif +} + [(set_attr "prefix_rep" "1") + (set_attr "type" "bitmanip") + (set_attr "mode" "")]) + (define_insn "*popcount2_falsedep" [(set (match_operand:SWI48 0 "register_operand" "=r") (popcount:SWI48 @@ -20691,17 +21194,16 @@ DONE; }) -(define_insn "popcounthi2" +(define_insn "popcounthi2" [(set (match_operand:HI 0 "register_operand" "=r") (popcount:HI - (match_operand:HI 1 "nonimmediate_operand" "rm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_POPCNT" + (match_operand:HI 1 "nonimmediate_operand" "rm")))] + "TARGET_POPCNT && " { #if TARGET_MACHO - return "popcnt\t{%1, %0|%0, %1}"; + return "popcnt\t{%1, %0|%0, %1}"; #else - return "popcnt{w}\t{%1, %0|%0, %1}"; + return "popcnt{w}\t{%1, %0|%0, %1}"; #endif } [(set_attr "prefix_rep" "1") @@ -20722,18 +21224,19 @@ (bswap:SI (match_operand:SI 1 "nonimmediate_operand")))] "" { - if (TARGET_MOVBE) - ; - else if (TARGET_BSWAP) - operands[1] = force_reg (SImode, operands[1]); - else + if (!TARGET_MOVBE) { - rtx x = gen_reg_rtx (SImode); + operands[1] = force_reg (SImode, operands[1]); - emit_insn (gen_bswaphisi2_lowpart (x, operands[1])); - emit_insn (gen_rotlsi3 (x, x, GEN_INT (16))); - emit_insn (gen_bswaphisi2_lowpart (operands[0], x)); - DONE; + if (!TARGET_BSWAP) + { + rtx x = gen_reg_rtx (SImode); + + emit_insn (gen_bswaphisi2_lowpart (x, operands[1])); + emit_insn (gen_rotlsi3 (x, x, GEN_INT (16))); + emit_insn (gen_bswaphisi2_lowpart (operands[0], x)); + DONE; + } } }) diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 7151fb1b147..7017cc87cec 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -1336,6 +1336,12 @@ Enum(apx_features) String(ndd) Value(apx_ndd) Set(4) EnumValue Enum(apx_features) String(ppx) Value(apx_ppx) Set(5) +EnumValue +Enum(apx_features) String(nf) Value(apx_nf) Set(6) + +EnumValue +Enum(apx_features) String(ccmp) Value(apx_ccmp) Set(7) + EnumValue Enum(apx_features) String(all) Value(apx_all) Set(1) diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 2a97776fc32..7afe3100cb7 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1098,6 +1098,11 @@ (and (match_code "not") (match_test "nonimmediate_operand (XEXP (op, 0), mode)")))) +;; True for expressions valid for 3-operand ternlog instructions. +(define_predicate "ternlog_operand" + (and (match_code "not,and,ior,xor") + (match_test "ix86_ternlog_operand_p (op)"))) + ;; True if OP is acceptable as operand of DImode shift expander. (define_predicate "shiftdi_operand" (if_then_else (match_test "TARGET_64BIT") diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 7cd912eeeb1..680a46a0b08 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -1986,6 +1986,17 @@ ] (const_string "")))]) +(define_split + [(set (match_operand:SWI1248_AVX512BW 0 "mask_reg_operand") + (any_logic:SWI1248_AVX512BW + (match_operand:SWI1248_AVX512BW 1 "mask_reg_operand") + (match_operand:SWI1248_AVX512BW 2 "mask_reg_operand")))] + "TARGET_AVX512F && reload_completed" + [(parallel + [(set (match_dup 0) + (any_logic:SWI1248_AVX512BW (match_dup 1) (match_dup 2))) + (unspec [(const_int 0)] UNSPEC_MASKOP)])]) + (define_split [(set (match_operand:SWI1248_AVX512BW 0 "mask_reg_operand") (any_logic:SWI1248_AVX512BW @@ -2139,6 +2150,19 @@ (set_attr "prefix" "vex") (set_attr "mode" "")]) +(define_split + [(set (match_operand:SWI1248_AVX512BW 0 "mask_reg_operand") + (any_lshift:SWI1248_AVX512BW + (match_operand:SWI1248_AVX512BW 1 "mask_reg_operand") + (match_operand 2 "const_int_operand")))] + "TARGET_AVX512F && reload_completed" + [(parallel + [(set (match_dup 0) + (any_lshift:SWI1248_AVX512BW + (match_dup 1) + (match_dup 2))) + (unspec [(const_int 0)] UNSPEC_MASKOP)])]) + (define_split [(set (match_operand:SWI1248_AVX512BW 0 "mask_reg_operand") (any_lshift:SWI1248_AVX512BW @@ -2201,6 +2225,73 @@ UNSPEC_KORTEST))] "TARGET_AVX512F") +;; Optimize cmp + setcc with mask register by kortest + setcc. +(define_insn_and_split "*kortest_cmp_setcc" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm, qm") + (match_operator:QI 1 "bt_comparison_operator" + [(match_operand:SWI1248_AVX512BWDQ_64 2 "register_operand" "?k, ") + (const_int -1)])) + (clobber (reg:CC FLAGS_REG))] + "TARGET_AVX512BW" + "#" + "&& reload_completed" + [(const_int 0)] +{ + if (MASK_REGNO_P (REGNO (operands[2]))) + { + emit_insn (gen_kortest_ccc (operands[2], operands[2])); + operands[4] = gen_rtx_REG (CCCmode, FLAGS_REG); + } + else + { + operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG); + emit_insn (gen_rtx_SET (operands[4], + gen_rtx_COMPARE (CCZmode, + operands[2], + constm1_rtx))); + } + ix86_expand_setcc (operands[0], + GET_CODE (operands[1]), + operands[4], + const0_rtx); + DONE; +}) + +;; Optimize cmp + jcc with mask register by kortest + jcc. +(define_insn_and_split "*kortest_cmp_jcc" + [(set (pc) + (if_then_else + (match_operator 0 "bt_comparison_operator" + [(match_operand:SWI1248_AVX512BWDQ_64 1 "register_operand" "?k, ") + (const_int -1)]) + (label_ref (match_operand 2)) + (pc))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_AVX512BW" + "#" + "&& reload_completed" + [(const_int 0)] +{ + if (MASK_REGNO_P (REGNO (operands[1]))) + { + emit_insn (gen_kortest_ccc (operands[1], operands[1])); + operands[4] = gen_rtx_REG (CCCmode, FLAGS_REG); + } + else + { + operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG); + emit_insn (gen_rtx_SET (operands[4], + gen_rtx_COMPARE (CCZmode, + operands[1], + constm1_rtx))); + } + ix86_expand_branch (GET_CODE (operands[0]), + operands[4], + const0_rtx, + operands[2]); + DONE; +}) + (define_insn "kunpckhi" [(set (match_operand:HI 0 "register_operand" "=k") (ior:HI @@ -12941,6 +13032,26 @@ ;; ;; and so on. +(define_insn_and_split "*_vpternlog_0" + [(set (match_operand:V 0 "register_operand") + (match_operand:V 1 "ternlog_operand"))] + "( == 64 || TARGET_AVX512VL + || (TARGET_AVX512F && TARGET_EVEX512 && !TARGET_PREFER_AVX256)) + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)] +{ + rtx args[3]; + args[0] = NULL_RTX; + args[1] = NULL_RTX; + args[2] = NULL_RTX; + int idx = ix86_ternlog_idx (operands[1], args); + ix86_expand_ternlog (mode, args[0], args[1], args[2], idx, + operands[0]); + DONE; +}) + (define_code_iterator any_logic1 [and ior xor]) (define_code_iterator any_logic2 [and ior xor]) (define_code_attr logic_op [(and "&") (ior "|") (xor "^")]) @@ -13161,7 +13272,33 @@ }) -(define_insn "_vternlog_mask" +(define_expand "_vternlog_mask" + [(set (match_operand:VI48_AVX512VL 0 "register_operand") + (vec_merge:VI48_AVX512VL + (unspec:VI48_AVX512VL + [(match_operand:VI48_AVX512VL 1 "register_operand") + (match_operand:VI48_AVX512VL 2 "register_operand") + (match_operand:VI48_AVX512VL 3 "bcst_vector_operand") + (match_operand:SI 4 "const_0_to_255_operand")] + UNSPEC_VTERNLOG) + (match_dup 1) + (match_operand: 5 "general_operand")))] + "TARGET_AVX512F" +{ + unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (mode); + if (CONST_INT_P (operands[5]) + && (UINTVAL (operands[5]) & mode_mask) == mode_mask) + { + ix86_expand_ternlog (mode, operands[1], operands[2], + operands[3], INTVAL (operands[4]), + operands[0]); + DONE; + } + if (!register_operand (operands[5], mode)) + operands[5] = force_reg (mode, operands[5]); +}) + +(define_insn "*_vternlog_mask" [(set (match_operand:VI48_AVX512VL 0 "register_operand" "=v") (vec_merge:VI48_AVX512VL (unspec:VI48_AVX512VL diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index b478cddc8ad..278d9446482 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -4199,7 +4199,7 @@ mips_insn_cost (rtx_insn *x, bool speed) count = get_attr_insn_count (x); ratio = get_attr_perf_ratio (x); - cost = count * ratio; + cost = COSTS_N_INSNS (count) * ratio; if (cost > 0) return cost; diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md index ef7e3fb00fa..7878a3b6f09 100644 --- a/gcc/config/nvptx/nvptx.md +++ b/gcc/config/nvptx/nvptx.md @@ -2316,14 +2316,11 @@ { const char *insns[] = { "{", - "\\t" ".reg.b32" "\\t" "%%r_act;", - "%.\\t" "vote.ballot.b32" "\\t" "%%r_act,1;", - "\\t" ".reg.pred" "\\t" "%%r_do_abort;", - "\\t" "mov.pred" "\\t" "%%r_do_abort,0;", - "%.\\t" "setp.ne.b32" "\\t" "%%r_do_abort,%%r_act," - "0xffffffff;", - "@ %%r_do_abort\\t" "trap;", - "@ %%r_do_abort\\t" "exit;", + "\\t" ".reg.pred" "\\t" "%%r_sync;", + "\\t" "mov.pred" "\\t" "%%r_sync, 1;", + "%.\\t" "vote.all.pred" "\\t" "%%r_sync, 1;", + "@!%%r_sync\\t" "trap;", + "@!%%r_sync\\t" "exit;", "}", NULL }; diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index 3c139bc2e30..1e37e843023 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -78,9 +78,13 @@ ;; Iterator for floating-point modes that can be loaded into X registers. (define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")]) -;; Iterator for floating-point modes of BF16 +;; Iterator for floating-point modes of BF16. (define_mode_iterator HFBF [HF BF]) +;; Conversion between floating-point modes and BF16. +;; SF to BF16 have hardware instructions. +(define_mode_iterator FBF [HF DF TF]) + ;; ------------------------------------------------------------------- ;; Mode attributes ;; ------------------------------------------------------------------- diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h index 1b2dd5757a8..f58a07abffc 100644 --- a/gcc/config/riscv/riscv-opts.h +++ b/gcc/config/riscv/riscv-opts.h @@ -147,9 +147,6 @@ enum rvv_vector_bits_enum { ? 0 \ : 32 << (__builtin_popcount (opts->x_riscv_zvl_flags) - 1)) -/* TODO: Enable RVV movmisalign by default for now. */ -#define TARGET_VECTOR_MISALIGN_SUPPORTED 1 - /* The maximmum LMUL according to user configuration. */ #define TARGET_MAX_LMUL \ (int) (rvv_max_lmul == RVV_DYNAMIC ? RVV_M8 : rvv_max_lmul) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 10af38a5a81..9704ff9c6a0 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -288,6 +288,7 @@ struct riscv_tune_param unsigned short memory_cost; unsigned short fmv_cost; bool slow_unaligned_access; + bool vector_unaligned_access; bool use_divmod_expansion; bool overlap_op_by_pieces; unsigned int fusible_ops; @@ -300,6 +301,10 @@ struct riscv_tune_param /* Whether unaligned accesses execute very slowly. */ bool riscv_slow_unaligned_access_p; +/* Whether misaligned vector accesses are supported (i.e. do not + throw an exception). */ +bool riscv_vector_unaligned_access_p; + /* Whether user explicitly passed -mstrict-align. */ bool riscv_user_wants_strict_align; @@ -442,6 +447,7 @@ static const struct riscv_tune_param rocket_tune_info = { 5, /* memory_cost */ 8, /* fmv_cost */ true, /* slow_unaligned_access */ + false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ RISCV_FUSE_NOTHING, /* fusible_ops */ @@ -460,6 +466,7 @@ static const struct riscv_tune_param sifive_7_tune_info = { 3, /* memory_cost */ 8, /* fmv_cost */ true, /* slow_unaligned_access */ + false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ RISCV_FUSE_NOTHING, /* fusible_ops */ @@ -478,6 +485,7 @@ static const struct riscv_tune_param sifive_p400_tune_info = { 3, /* memory_cost */ 4, /* fmv_cost */ true, /* slow_unaligned_access */ + false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ RISCV_FUSE_LUI_ADDI | RISCV_FUSE_AUIPC_ADDI, /* fusible_ops */ @@ -496,6 +504,7 @@ static const struct riscv_tune_param sifive_p600_tune_info = { 3, /* memory_cost */ 4, /* fmv_cost */ true, /* slow_unaligned_access */ + false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ RISCV_FUSE_LUI_ADDI | RISCV_FUSE_AUIPC_ADDI, /* fusible_ops */ @@ -514,6 +523,7 @@ static const struct riscv_tune_param thead_c906_tune_info = { 5, /* memory_cost */ 8, /* fmv_cost */ false, /* slow_unaligned_access */ + false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ RISCV_FUSE_NOTHING, /* fusible_ops */ @@ -532,6 +542,7 @@ static const struct riscv_tune_param xiangshan_nanhu_tune_info = { 3, /* memory_cost */ 3, /* fmv_cost */ true, /* slow_unaligned_access */ + false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ RISCV_FUSE_ZEXTW | RISCV_FUSE_ZEXTH, /* fusible_ops */ @@ -550,6 +561,7 @@ static const struct riscv_tune_param generic_ooo_tune_info = { 4, /* memory_cost */ 4, /* fmv_cost */ false, /* slow_unaligned_access */ + true, /* vector_unaligned_access */ false, /* use_divmod_expansion */ true, /* overlap_op_by_pieces */ RISCV_FUSE_NOTHING, /* fusible_ops */ @@ -568,6 +580,7 @@ static const struct riscv_tune_param optimize_size_tune_info = { 2, /* memory_cost */ 8, /* fmv_cost */ false, /* slow_unaligned_access */ + false, /* vector_unaligned_access */ false, /* use_divmod_expansion */ false, /* overlap_op_by_pieces */ RISCV_FUSE_NOTHING, /* fusible_ops */ @@ -4310,7 +4323,7 @@ riscv_output_move (rtx dest, rtx src) switch (width) { case 2: - if (TARGET_ZFHMIN) + if (TARGET_ZFHMIN || TARGET_ZFBFMIN) return "fmv.x.h\t%0,%1"; /* Using fmv.x.s + sign-extend to emulate fmv.x.h. */ return "fmv.x.s\t%0,%1;slli\t%0,%0,16;srai\t%0,%0,16"; @@ -4366,7 +4379,7 @@ riscv_output_move (rtx dest, rtx src) switch (width) { case 2: - if (TARGET_ZFHMIN) + if (TARGET_ZFHMIN || TARGET_ZFBFMIN) return "fmv.h.x\t%0,%z1"; /* High 16 bits should be all-1, otherwise HW will treated as a n-bit canonical NaN, but isn't matter for softfloat. */ @@ -9714,6 +9727,12 @@ riscv_override_options_internal (struct gcc_options *opts) riscv_slow_unaligned_access_p = (cpu->tune_param->slow_unaligned_access || TARGET_STRICT_ALIGN); + /* By default, when -mno-vector-strict-align is not specified, do not allow + unaligned vector memory accesses except if -mtune's setting explicitly + allows it. */ + riscv_vector_unaligned_access_p = opts->x_rvv_vector_strict_align == 0 + || cpu->tune_param->vector_unaligned_access; + /* Make a note if user explicitly passed -mstrict-align for later builtin macro generation. Can't use target_flags_explicitly since it is set even for -mno-strict-align. */ diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index d6b14c4d620..57910eecd3e 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -934,6 +934,10 @@ extern enum riscv_cc get_riscv_cc (const rtx use); || (riscv_microarchitecture == sifive_p400) \ || (riscv_microarchitecture == sifive_p600)) +/* True if the target supports misaligned vector loads and stores. */ +#define TARGET_VECTOR_MISALIGN_SUPPORTED \ + riscv_vector_unaligned_access_p + #define LOGICAL_OP_NON_SHORT_CIRCUIT 0 /* Control the assembler format that we output. */ @@ -1161,6 +1165,7 @@ while (0) #ifndef USED_FOR_TARGET extern const enum reg_class riscv_regno_to_class[]; extern bool riscv_slow_unaligned_access_p; +extern bool riscv_vector_unaligned_access_p; extern bool riscv_user_wants_strict_align; extern unsigned riscv_stack_boundary; extern unsigned riscv_bytes_per_vector_chunk; diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 25d341ec987..e57bfcf616a 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1763,6 +1763,31 @@ [(set_attr "type" "fcvt") (set_attr "mode" "HF")]) +(define_insn "truncsfbf2" + [(set (match_operand:BF 0 "register_operand" "=f") + (float_truncate:BF + (match_operand:SF 1 "register_operand" " f")))] + "TARGET_ZFBFMIN" + "fcvt.bf16.s\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "BF")]) + +;; The conversion of HF/DF/TF to BF needs to be done with SF if there is a +;; chance to generate at least one instruction, otherwise just using +;; libfunc __trunc[h|d|t]fbf2. +(define_expand "truncbf2" + [(set (match_operand:BF 0 "register_operand" "=f") + (float_truncate:BF + (match_operand:FBF 1 "register_operand" " f")))] + "TARGET_ZFBFMIN" + { + convert_move (operands[0], + convert_modes (SFmode, mode, operands[1], 0), 0); + DONE; + } + [(set_attr "type" "fcvt") + (set_attr "mode" "BF")]) + ;; ;; .................... ;; @@ -1907,6 +1932,15 @@ [(set_attr "type" "fcvt") (set_attr "mode" "SF")]) +(define_insn "extendbfsf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (float_extend:SF + (match_operand:BF 1 "register_operand" " f")))] + "TARGET_ZFBFMIN" + "fcvt.s.bf16\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "SF")]) + (define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF @@ -1936,16 +1970,17 @@ DONE; }) -(define_insn "*movhf_hardfloat" - [(set (match_operand:HF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m") - (match_operand:HF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))] - "TARGET_ZFHMIN - && (register_operand (operands[0], HFmode) - || reg_or_0_operand (operands[1], HFmode))" +(define_insn "*mov_hardfloat" + [(set (match_operand:HFBF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m") + (match_operand:HFBF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))] + "((TARGET_ZFHMIN && mode == HFmode) + || (TARGET_ZFBFMIN && mode == BFmode)) + && (register_operand (operands[0], mode) + || reg_or_0_operand (operands[1], mode))" { return riscv_output_move (operands[0], operands[1]); } [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") (set_attr "type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") - (set_attr "mode" "HF")]) + (set_attr "mode" "")]) (define_insn "*mov_softfloat" [(set (match_operand:HFBF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r") diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index 87f58332016..78cb1c37e69 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -128,6 +128,14 @@ mstrict-align Target Mask(STRICT_ALIGN) Save Do not generate unaligned memory accesses. +mscalar-strict-align +Target Save Alias(mstrict-align) +Do not generate unaligned scalar memory accesses. + +mvector-strict-align +Target Save Var(rvv_vector_strict_align) Init(1) +Do not create element-misaligned vector memory accesses. + Enum Name(code_model) Type(enum riscv_code_model) Known code models (for use with the -mcmodel= option): diff --git a/gcc/config/riscv/riscv.opt.urls b/gcc/config/riscv/riscv.opt.urls index d87e9d5c9a8..622cb6e7b44 100644 --- a/gcc/config/riscv/riscv.opt.urls +++ b/gcc/config/riscv/riscv.opt.urls @@ -47,6 +47,12 @@ UrlSuffix(gcc/RISC-V-Options.html#index-mcmodel_003d-4) mstrict-align UrlSuffix(gcc/RISC-V-Options.html#index-mstrict-align-4) +mscalar-strict-align +UrlSuffix(gcc/RISC-V-Options.html#index-mscalar-strict-align) + +mvector-strict-align +UrlSuffix(gcc/RISC-V-Options.html#index-mvector-strict-align) + ; skipping UrlSuffix for 'mexplicit-relocs' due to finding no URLs mrelax diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc index 320affd79e3..e96d5157e4d 100644 --- a/gcc/config/rs6000/rs6000-builtin.cc +++ b/gcc/config/rs6000/rs6000-builtin.cc @@ -845,7 +845,7 @@ rs6000_init_builtins (void) enum rs6000_gen_builtins fn_code = (enum rs6000_gen_builtins) i; if (!rs6000_builtin_is_supported (fn_code)) continue; - tree fntype = rs6000_builtin_info[i].fntype; + tree fntype = rs6000_builtin_info_fntype[i]; tree t = TREE_TYPE (fntype); fprintf (stderr, "%s %s (", rs6000_type_string (t), rs6000_builtin_info[i].bifname); diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc index bd493ab87c5..6229c503bd0 100644 --- a/gcc/config/rs6000/rs6000-c.cc +++ b/gcc/config/rs6000/rs6000-c.cc @@ -1664,22 +1664,25 @@ resolve_vec_step (resolution *res, vec *arglist, unsigned nargs) true. If we don't match, return error_mark_node and leave UNSUPPORTED_BUILTIN alone. */ -tree -find_instance (bool *unsupported_builtin, ovlddata **instance, +static tree +find_instance (bool *unsupported_builtin, int *instance, rs6000_gen_builtins instance_code, rs6000_gen_builtins fcode, tree *types, tree *args, int nargs) { - while (*instance && (*instance)->bifid != instance_code) - *instance = (*instance)->next; + while (*instance != -1 + && rs6000_instance_info[*instance].bifid != instance_code) + *instance = rs6000_instance_info[*instance].next; - ovlddata *inst = *instance; - gcc_assert (inst != NULL); + int inst = *instance; + gcc_assert (inst != -1); /* It is possible for an instance to require a data type that isn't - defined on this target, in which case inst->fntype will be NULL. */ - if (!inst->fntype) + defined on this target, in which case rs6000_instance_info_fntype[inst] + will be NULL. */ + if (!rs6000_instance_info_fntype[inst]) return error_mark_node; - tree fntype = rs6000_builtin_info[inst->bifid].fntype; + rs6000_gen_builtins bifid = rs6000_instance_info[inst].bifid; + tree fntype = rs6000_builtin_info_fntype[bifid]; tree argtype = TYPE_ARG_TYPES (fntype); bool args_compatible = true; @@ -1696,12 +1699,12 @@ find_instance (bool *unsupported_builtin, ovlddata **instance, if (args_compatible) { - if (rs6000_builtin_decl (inst->bifid, false) != error_mark_node - && rs6000_builtin_is_supported (inst->bifid)) + if (rs6000_builtin_decl (bifid, false) != error_mark_node + && rs6000_builtin_is_supported (bifid)) { - tree ret_type = TREE_TYPE (inst->fntype); + tree ret_type = TREE_TYPE (rs6000_instance_info_fntype[inst]); return altivec_build_resolved_builtin (args, nargs, fntype, ret_type, - inst->bifid, fcode); + bifid, fcode); } else *unsupported_builtin = true; @@ -1884,11 +1887,11 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, bool unsupported_builtin = false; rs6000_gen_builtins instance_code; bool supported = false; - ovlddata *instance = rs6000_overload_info[adj_fcode].first_instance; - gcc_assert (instance != NULL); + int instance = rs6000_overload_info[adj_fcode].first_instance; + gcc_assert (instance != -1); /* Functions with no arguments can have only one overloaded instance. */ - gcc_assert (nargs > 0 || !instance->next); + gcc_assert (nargs > 0 || rs6000_instance_info[instance].next == -1); /* Standard overload processing involves determining whether an instance exists that is type-compatible with the overloaded function call. In @@ -1989,16 +1992,18 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, /* Standard overload processing. Look for an instance with compatible parameter types. If it is supported in the current context, resolve the overloaded call to that instance. */ - for (; instance != NULL; instance = instance->next) + for (; instance != -1; instance = rs6000_instance_info[instance].next) { + tree fntype = rs6000_instance_info_fntype[instance]; + rs6000_gen_builtins bifid = rs6000_instance_info[instance].bifid; /* It is possible for an instance to require a data type that isn't - defined on this target, in which case instance->fntype will be + defined on this target, in which case fntype will be NULL. */ - if (!instance->fntype) + if (!fntype) continue; bool mismatch = false; - tree nextparm = TYPE_ARG_TYPES (instance->fntype); + tree nextparm = TYPE_ARG_TYPES (fntype); for (unsigned int arg_i = 0; arg_i < nargs && nextparm != NULL; @@ -2016,15 +2021,14 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, if (mismatch) continue; - supported = rs6000_builtin_is_supported (instance->bifid); - if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node + supported = rs6000_builtin_is_supported (bifid); + if (rs6000_builtin_decl (bifid, false) != error_mark_node && supported) { - tree fntype = rs6000_builtin_info[instance->bifid].fntype; - tree ret_type = TREE_TYPE (instance->fntype); + tree ret_type = TREE_TYPE (fntype); + fntype = rs6000_builtin_info_fntype[bifid]; return altivec_build_resolved_builtin (args, nargs, fntype, - ret_type, instance->bifid, - fcode); + ret_type, bifid, fcode); } else { @@ -2041,12 +2045,12 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, { /* Indicate that the instantiation of the overloaded builtin name is not available with the target flags in effect. */ - rs6000_gen_builtins fcode = (rs6000_gen_builtins) instance->bifid; + rs6000_gen_builtins bifid = rs6000_instance_info[instance].bifid; + rs6000_gen_builtins fcode = (rs6000_gen_builtins) bifid; rs6000_invalid_builtin (fcode); /* Provide clarity of the relationship between the overload and the instantiation. */ - const char *internal_name - = rs6000_builtin_info[instance->bifid].bifname; + const char *internal_name = rs6000_builtin_info[bifid].bifname; rich_location richloc (line_table, input_location); inform (&richloc, "overloaded builtin %qs is implemented by builtin %qs", diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc b/gcc/config/rs6000/rs6000-gen-builtins.cc index e32d1e2d134..7ae932220bb 100644 --- a/gcc/config/rs6000/rs6000-gen-builtins.cc +++ b/gcc/config/rs6000/rs6000-gen-builtins.cc @@ -2261,20 +2261,19 @@ write_decls (void) fprintf (header_file, "};\n\n"); fprintf (header_file, "#define PPC_MAXRESTROPNDS 3\n"); - fprintf (header_file, "struct GTY(()) bifdata\n"); + fprintf (header_file, "struct bifdata\n"); fprintf (header_file, "{\n"); - fprintf (header_file, " const char *GTY((skip(\"\"))) bifname;\n"); - fprintf (header_file, " bif_enable GTY((skip(\"\"))) enable;\n"); - fprintf (header_file, " tree fntype;\n"); - fprintf (header_file, " insn_code GTY((skip(\"\"))) icode;\n"); - fprintf (header_file, " int nargs;\n"); - fprintf (header_file, " int bifattrs;\n"); - fprintf (header_file, " int restr_opnd[PPC_MAXRESTROPNDS];\n"); - fprintf (header_file, " restriction GTY((skip(\"\"))) restr[PPC_MAXRESTROPNDS];\n"); - fprintf (header_file, " int restr_val1[PPC_MAXRESTROPNDS];\n"); - fprintf (header_file, " int restr_val2[PPC_MAXRESTROPNDS];\n"); - fprintf (header_file, " const char *GTY((skip(\"\"))) attr_string;\n"); - fprintf (header_file, " rs6000_gen_builtins GTY((skip(\"\"))) assoc_bif;\n"); + fprintf (header_file, " const char *bifname;\n"); + fprintf (header_file, " bif_enable enable;\n"); + fprintf (header_file, " insn_code icode;\n"); + fprintf (header_file, " int nargs;\n"); + fprintf (header_file, " int bifattrs;\n"); + fprintf (header_file, " int restr_opnd[PPC_MAXRESTROPNDS];\n"); + fprintf (header_file, " restriction restr[PPC_MAXRESTROPNDS];\n"); + fprintf (header_file, " int restr_val1[PPC_MAXRESTROPNDS];\n"); + fprintf (header_file, " int restr_val2[PPC_MAXRESTROPNDS];\n"); + fprintf (header_file, " const char *attr_string;\n"); + fprintf (header_file, " rs6000_gen_builtins assoc_bif;\n"); fprintf (header_file, "};\n\n"); fprintf (header_file, "#define bif_init_bit\t\t(0x00000001)\n"); @@ -2353,24 +2352,28 @@ write_decls (void) fprintf (header_file, "\n"); fprintf (header_file, - "extern GTY(()) bifdata rs6000_builtin_info[RS6000_BIF_MAX];\n\n"); + "extern bifdata rs6000_builtin_info[RS6000_BIF_MAX];\n\n"); - fprintf (header_file, "struct GTY(()) ovlddata\n"); + fprintf (header_file, + "extern GTY(()) tree rs6000_builtin_info_fntype[RS6000_BIF_MAX];\n\n"); + + fprintf (header_file, "struct ovlddata\n"); fprintf (header_file, "{\n"); - fprintf (header_file, " const char *GTY((skip(\"\"))) bifname;\n"); - fprintf (header_file, " rs6000_gen_builtins GTY((skip(\"\"))) bifid;\n"); - fprintf (header_file, " tree fntype;\n"); - fprintf (header_file, " ovlddata *GTY((skip(\"\"))) next;\n"); + fprintf (header_file, " const char *bifname;\n"); + fprintf (header_file, " rs6000_gen_builtins bifid;\n"); + fprintf (header_file, " int next;\n"); fprintf (header_file, "};\n\n"); fprintf (header_file, "struct ovldrecord\n"); fprintf (header_file, "{\n"); fprintf (header_file, " const char *ovld_name;\n"); - fprintf (header_file, " ovlddata *first_instance;\n"); + fprintf (header_file, " int first_instance;\n"); fprintf (header_file, "};\n\n"); fprintf (header_file, - "extern GTY(()) ovlddata rs6000_instance_info[RS6000_INST_MAX];\n"); + "extern ovlddata rs6000_instance_info[RS6000_INST_MAX];\n"); + fprintf (header_file, "extern GTY(()) tree " + "rs6000_instance_info_fntype[RS6000_INST_MAX];\n"); fprintf (header_file, "extern ovldrecord rs6000_overload_info[];\n\n"); fprintf (header_file, "extern void rs6000_init_generated_builtins ();\n\n"); @@ -2481,7 +2484,7 @@ write_bif_static_init (void) fprintf (init_file, "bifdata rs6000_builtin_info[RS6000_BIF_MAX] =\n"); fprintf (init_file, " {\n"); fprintf (init_file, " { /* RS6000_BIF_NONE: */\n"); - fprintf (init_file, " \"\", ENB_ALWAYS, 0, CODE_FOR_nothing, 0,\n"); + fprintf (init_file, " \"\", ENB_ALWAYS, CODE_FOR_nothing, 0,\n"); fprintf (init_file, " 0, {0, 0, 0}, {RES_NONE, RES_NONE, RES_NONE},\n"); fprintf (init_file, " {0, 0, 0}, {0, 0, 0}, \"\", RS6000_BIF_NONE\n"); fprintf (init_file, " },\n"); @@ -2493,8 +2496,6 @@ write_bif_static_init (void) bifp->proto.bifname); fprintf (init_file, " /* enable*/\t%s,\n", enable_string[bifp->stanza]); - /* Type must be instantiated at run time. */ - fprintf (init_file, " /* fntype */\t0,\n"); fprintf (init_file, " /* icode */\tCODE_FOR_%s,\n", bifp->patname); fprintf (init_file, " /* nargs */\t%d,\n", @@ -2586,6 +2587,8 @@ write_bif_static_init (void) fprintf (init_file, " },\n"); } fprintf (init_file, " };\n\n"); + + fprintf (init_file, "tree rs6000_builtin_info_fntype[RS6000_BIF_MAX];\n\n"); } /* Write the decls and initializers for rs6000_overload_info[] and @@ -2598,7 +2601,7 @@ write_ovld_static_init (void) "- RS6000_OVLD_NONE] =\n"); fprintf (init_file, " {\n"); fprintf (init_file, " { /* RS6000_OVLD_NONE: */\n"); - fprintf (init_file, " \"\", NULL\n"); + fprintf (init_file, " \"\", -1\n"); fprintf (init_file, " },\n"); for (int i = 0; i <= curr_ovld_stanza; i++) { @@ -2607,7 +2610,7 @@ write_ovld_static_init (void) fprintf (init_file, " /* ovld_name */\t\"%s\",\n", ovld_stanzas[i].intern_name); /* First-instance must currently be instantiated at run time. */ - fprintf (init_file, " /* first_instance */\tNULL\n"); + fprintf (init_file, " /* first_instance */\t-1\n"); fprintf (init_file, " },\n"); } fprintf (init_file, " };\n\n"); @@ -2615,7 +2618,7 @@ write_ovld_static_init (void) fprintf (init_file, "ovlddata rs6000_instance_info[RS6000_INST_MAX] =\n"); fprintf (init_file, " {\n"); fprintf (init_file, " { /* RS6000_INST_NONE: */\n"); - fprintf (init_file, " \"\", RS6000_BIF_NONE, NULL_TREE, NULL\n"); + fprintf (init_file, " \"\", RS6000_BIF_NONE, -1\n"); fprintf (init_file, " },\n"); for (int i = 0; i <= curr_ovld; i++) { @@ -2625,19 +2628,20 @@ write_ovld_static_init (void) ovlds[i].proto.bifname); fprintf (init_file, " /* bifid */\tRS6000_BIF_%s,\n", ovlds[i].bif_id_name); - /* Type must be instantiated at run time. */ - fprintf (init_file, " /* fntype */\t0,\n"); fprintf (init_file, " /* next */\t"); if (i < curr_ovld && !strcmp (ovlds[i+1].proto.bifname, ovlds[i].proto.bifname)) fprintf (init_file, - "&rs6000_instance_info[RS6000_INST_%s]\n", + "RS6000_INST_%s\n", ovlds[i+1].ovld_id_name); else - fprintf (init_file, "NULL\n"); + fprintf (init_file, "-1\n"); fprintf (init_file, " },\n"); } fprintf (init_file, " };\n\n"); + + fprintf (init_file, + "tree rs6000_instance_info_fntype[RS6000_INST_MAX];\n\n"); } /* Write code to initialize the built-in function table. */ @@ -2647,7 +2651,7 @@ write_init_bif_table (void) for (int i = 0; i <= curr_bif; i++) { fprintf (init_file, - " rs6000_builtin_info[RS6000_BIF_%s].fntype" + " rs6000_builtin_info_fntype[RS6000_BIF_%s]" "\n = %s;\n", bifs[i].idname, bifs[i].fndecl); @@ -2736,7 +2740,7 @@ write_init_ovld_table (void) for (int i = 0; i <= curr_ovld; i++) { fprintf (init_file, - " rs6000_instance_info[RS6000_INST_%s].fntype" + " rs6000_instance_info_fntype[RS6000_INST_%s]" "\n = %s;\n", ovlds[i].ovld_id_name, ovlds[i].fndecl); @@ -2793,7 +2797,7 @@ write_init_ovld_table (void) ".first_instance\n", stanza->stanza_id); fprintf (init_file, - " = &rs6000_instance_info[RS6000_INST_%s];\n\n", + " = RS6000_INST_%s;\n\n", ovlds[i].ovld_id_name); } } diff --git a/gcc/configure b/gcc/configure index b67845971c8..aaf5899cc03 100755 --- a/gcc/configure +++ b/gcc/configure @@ -740,8 +740,6 @@ ORIGINAL_NM_FOR_TARGET gcc_cv_nm ORIGINAL_LD_GOLD_FOR_TARGET ORIGINAL_LD_BFD_FOR_TARGET -ORIGINAL_CLASSIC_LD_FOR_TARGET -ORIGINAL_LLD_FOR_TARGET ORIGINAL_LD_FOR_TARGET ORIGINAL_PLUGIN_LD_FOR_TARGET gcc_cv_ld @@ -3804,19 +3802,20 @@ gcc_gxx_libcxx_include_dir= # Check whether --with-gxx-libcxx-include-dir was given. if test "${with_gxx_libcxx_include_dir+set}" = set; then : - withval=$with_gxx_libcxx_include_dir; gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir + withval=$with_gxx_libcxx_include_dir; case "${withval}" in +yes) as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;; +*) gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;; +esac fi # --with-gxx-libcxx-include-dir controls the enabling of the -stdlib option. # if --with-gxx-libcxx-include-dir is 'no' we disable the stdlib option. -# if --with-gxx-libcxx-include-dir is 'yes' we enable the stdlib option and use -# the default path within the installation. # if --with-gxx-libcxx-include-dir is unset we enable the stdlib option -# based on the platform (to be available on platform versions where it is the +# based on the platform (to be available on platform versions where it is the # default for the system tools). We also use a default path within the compiler -# install tree. -# Otherwise, we use the path provided and enable the stdlib option. +# install tree. +# Otherwise, we use the path provided and enable the stdlib option. # If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we # check to see if the latter starts with the former and, upon success, compute # gcc_gxx_libcxx_include_dir as relative to the sysroot. @@ -3824,20 +3823,16 @@ gcc_gxx_libcxx_include_dir_add_sysroot=0 gcc_enable_stdlib_opt=0 if test x${gcc_gxx_libcxx_include_dir} != x; then if test x${gcc_gxx_libcxx_include_dir} = xno; then - # set defaults for the dir, but the option is disabled anyway. - gcc_gxx_libcxx_include_dir= - elif test x${gcc_gxx_libcxx_include_dir} = xyes; then - # set defaults for the dir, and enable. + # set defaults for the dir, but the option is disabled anyway. gcc_gxx_libcxx_include_dir= - gcc_enable_stdlib_opt=1 else gcc_enable_stdlib_opt=1 fi else case $target in *-darwin1[1-9]* | *-darwin2*) - # Default this on for Darwin versions which default to libcxx, - # and embed the path in the compiler install so that we get a + # Default this on for Darwin versions which default to libcxx, + # and embed the path in the compiler install so that we get a # self-contained toolchain. gcc_enable_stdlib_opt=1 ;; @@ -21415,7 +21410,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 21418 "configure" +#line 21413 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -21521,7 +21516,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 21524 "configure" +#line 21519 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -25146,14 +25141,6 @@ fi $as_echo "$gold_non_default" >&6; } ORIGINAL_LD_FOR_TARGET=$gcc_cv_ld -if test x"$ld64_flag" = x"yes"; then -ORIGINAL_LLD_FOR_TARGET=${gcc_cv_ld}64.lld -else -ORIGINAL_LLD_FOR_TARGET=$gcc_cv_lld -fi -ORIGINAL_CLASSIC_LD_FOR_TARGET=$gcc_cv_ld-classic - - case "$ORIGINAL_LD_FOR_TARGET" in ./collect-ld | ./collect-ld$build_exeext) ;; diff --git a/gcc/configure.ac b/gcc/configure.ac index fb0bfc2f694..f8d67efeb98 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -235,17 +235,18 @@ gcc_gxx_libcxx_include_dir= AC_ARG_WITH(gxx-libcxx-include-dir, [AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR], [specifies directory to find libc++ header files])], -[gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir]) +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for libc++ include directory) ;; +*) gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;; +esac]) # --with-gxx-libcxx-include-dir controls the enabling of the -stdlib option. # if --with-gxx-libcxx-include-dir is 'no' we disable the stdlib option. -# if --with-gxx-libcxx-include-dir is 'yes' we enable the stdlib option and use -# the default path within the installation. # if --with-gxx-libcxx-include-dir is unset we enable the stdlib option -# based on the platform (to be available on platform versions where it is the +# based on the platform (to be available on platform versions where it is the # default for the system tools). We also use a default path within the compiler -# install tree. -# Otherwise, we use the path provided and enable the stdlib option. +# install tree. +# Otherwise, we use the path provided and enable the stdlib option. # If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we # check to see if the latter starts with the former and, upon success, compute # gcc_gxx_libcxx_include_dir as relative to the sysroot. @@ -253,20 +254,16 @@ gcc_gxx_libcxx_include_dir_add_sysroot=0 gcc_enable_stdlib_opt=0 if test x${gcc_gxx_libcxx_include_dir} != x; then if test x${gcc_gxx_libcxx_include_dir} = xno; then - # set defaults for the dir, but the option is disabled anyway. + # set defaults for the dir, but the option is disabled anyway. gcc_gxx_libcxx_include_dir= - elif test x${gcc_gxx_libcxx_include_dir} = xyes; then - # set defaults for the dir, and enable. - gcc_gxx_libcxx_include_dir= - gcc_enable_stdlib_opt=1 else gcc_enable_stdlib_opt=1 fi else case $target in *-darwin1[[1-9]]* | *-darwin2*) - # Default this on for Darwin versions which default to libcxx, - # and embed the path in the compiler install so that we get a + # Default this on for Darwin versions which default to libcxx, + # and embed the path in the compiler install so that we get a # self-contained toolchain. gcc_enable_stdlib_opt=1 ;; @@ -2811,15 +2808,7 @@ fi AC_MSG_RESULT($gold_non_default) ORIGINAL_LD_FOR_TARGET=$gcc_cv_ld -if test x"$ld64_flag" = x"yes"; then -ORIGINAL_LLD_FOR_TARGET=${gcc_cv_ld}64.lld -else -ORIGINAL_LLD_FOR_TARGET=$gcc_cv_lld -fi -ORIGINAL_CLASSIC_LD_FOR_TARGET=$gcc_cv_ld-classic AC_SUBST(ORIGINAL_LD_FOR_TARGET) -AC_SUBST(ORIGINAL_LLD_FOR_TARGET) -AC_SUBST(ORIGINAL_CLASSIC_LD_FOR_TARGET) case "$ORIGINAL_LD_FOR_TARGET" in ./collect-ld | ./collect-ld$build_exeext) ;; *) AC_CONFIG_FILES(collect-ld:exec-tool.in, [chmod +x collect-ld]) ;; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 172dffe55d0..4a389e22881 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,94 @@ +2024-06-05 Jakub Jelinek + Frederik Harwath + Sandra Loosemore + + * cp-tree.h (dependent_omp_for_p): Add another tree argument. + * parser.cc (check_omp_intervening_code): Reject imperfectly nested + tile. + (cp_parser_statement_seq_opt): If want_nested_loop, use + cp_parser_next_tokens_can_be_canon_loop instead of just checking + for RID_FOR keyword. + (cp_parser_omp_clause_name): Handle full and partial clause names. + (cp_parser_omp_clause_full, cp_parser_omp_clause_partial): New + functions. + (cp_parser_omp_all_clauses): Formatting fix. Handle + PRAGMA_OMP_CLAUSE_PARTIAL and PRAGMA_OMP_CLAUSE_FULL. + (cp_parser_next_tokens_can_be_canon_loop): New function. + (cp_parser_omp_loop_nest): Parse C++11 attributes. Handle tile/unroll + constructs. Use cp_parser_next_tokens_can_be_canon_loop instead + of just checking for RID_FOR keyword. Only add_stmt + cp_parser_omp_loop_nest result if it is non-NULL. + (cp_parser_omp_for_loop): Rename tiling variable to oacc_tiling. For + OMP_CLAUSE_SIZES set collapse to list length of OMP_CLAUSE_SIZES_LIST. + Use cp_parser_next_tokens_can_be_canon_loop instead of just + checking for RID_FOR keyword. Remove spurious semicolon. Don't call + c_omp_check_loop_binding_exprs if stmt is NULL. Skip and/or handle + generated loops. Remove spurious ()s around & operands. + (cp_parser_omp_tile_sizes, cp_parser_omp_tile): New functions. + (OMP_UNROLL_CLAUSE_MASK): Define. + (cp_parser_omp_unroll): New function. + (cp_parser_omp_construct): Handle PRAGMA_OMP_TILE and + PRAGMA_OMP_UNROLL. + (cp_parser_pragma): Likewise. + * semantics.cc (finish_omp_clauses): Don't call + fold_build_cleanup_point_expr for cases which obviously won't need it, + like checked INTEGER_CSTs. Handle OMP_CLAUSE_{FULL,PARTIAL,SIZES} + and diagnose full vs. partial conflict. Adjust wording of some of the + conflicting clause diagnostic messages to include word clause. + (finish_omp_for): Use decl equal to global_namespace as a marker for + generated loop. Pass also body to dependent_omp_for_p. Skip + generated loops. + (finish_omp_for_block): Skip generated loops. + * pt.cc (tsubst_omp_clauses): Handle OMP_CLAUSE_{FULL,PARTIAL,SIZES}. + (tsubst_stmt): Handle OMP_TILE and OMP_UNROLL. Handle or skip + generated loops. + (dependent_omp_for_p): Add body argument. If declv vector element + is NULL, find generated loop. + * cp-gimplify.cc (cp_gimplify_expr): Handle OMP_TILE and OMP_UNROLL. + (cp_fold_r): Likewise. + (cp_genericize_r): Likewise. Skip generated loops. + +2024-06-04 Simon Martin + + * pt.cc (tsubst_expr): Add missing space after seen_error. + (dependent_type_p): Likewise. + +2024-06-04 Simon Martin + + PR c++/111106 + * pt.cc (dependent_type_p): Don't fail assert during error recovery. + +2024-06-03 Jakub Jelinek + + PR c++/115012 + * parser.cc (cp_parser_direct_declarator): Handle + abstract declarator starting with ... followed by opening paren. + +2024-06-02 Simon Martin + + PR c++/109958 + * typeck.cc (build_class_member_access_expr): Handle single OVERLOADs. + (cp_build_addr_expr_1): Likewise. + +2024-06-01 Nathaniel Shead + + PR c++/114867 + * cp-tree.h (OVL_PURVIEW_P): New. + (ovl_iterator::purview_p): New. + * module.cc (depset::hash::add_binding_entity): Only ignore + entities not within module purview. Set OVL_PURVIEW_P on new + OVERLOADs for emitted declarations. + (module_state::read_cluster): Imported using-decls are always + in purview, mark as OVL_PURVIEW_P. + * name-lookup.h (enum WMB_Flags): New WMB_Purview flag. + * name-lookup.cc (walk_module_binding): Set WMB_Purview as + needed. + (do_nonmember_using_decl): Don't remove from existing OVERLOADs. + Also reveal non-exported decls. Also reveal 'extern "C"' decls. + Add workaround to reveal non-function decls. + * tree.cc (ovl_insert): Adjust to also set OVL_PURVIEW_P when + needed. + 2024-05-29 Jason Merrill PR c++/109753 diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 5cbdf0ea498..e6629dea5fd 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -759,6 +759,8 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) case OMP_DISTRIBUTE: case OMP_LOOP: case OMP_TASKLOOP: + case OMP_TILE: + case OMP_UNROLL: ret = cp_gimplify_omp_for (expr_p, pre_p); break; @@ -1396,6 +1398,8 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_) case OMP_DISTRIBUTE: case OMP_LOOP: case OMP_TASKLOOP: + case OMP_TILE: + case OMP_UNROLL: case OACC_LOOP: cp_walk_tree (&OMP_FOR_BODY (stmt), cp_fold_r, data, NULL); cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_fold_r, data, NULL); @@ -2169,7 +2173,8 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) && TREE_CODE (inner) == OMP_FOR) { for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner)); i++) - if (OMP_FOR_ORIG_DECLS (inner) + if (TREE_VEC_ELT (OMP_FOR_INIT (inner), i) + && OMP_FOR_ORIG_DECLS (inner) && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner), i)) == TREE_LIST && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner), @@ -2229,6 +2234,8 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) case OMP_FOR: case OMP_SIMD: case OMP_LOOP: + case OMP_TILE: + case OMP_UNROLL: case OACC_LOOP: case STATEMENT_LIST: /* These cases are handled by shared code. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 565e4a9290e..1ac31d073d1 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7612,7 +7612,7 @@ extern bool type_dependent_expression_p_push (tree); extern bool value_dependent_expression_p (tree); extern bool instantiation_dependent_uneval_expression_p (tree); extern bool any_value_dependent_elements_p (const_tree); -extern bool dependent_omp_for_p (tree, tree, tree, tree); +extern bool dependent_omp_for_p (tree, tree, tree, tree, tree); extern tree resolve_typename_type (tree, bool); extern tree template_for_substitution (tree); extern bool reregister_specialization (tree, tree, tree); diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index d481e1ec074..03deb1493a4 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -2792,10 +2792,13 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) retrofit_lang_decl (newdecl); tree alias = DECL_LOCAL_DECL_ALIAS (newdecl) = DECL_LOCAL_DECL_ALIAS (olddecl); - DECL_ATTRIBUTES (alias) - = (*targetm.merge_decl_attributes) (alias, newdecl); - if (TREE_CODE (newdecl) == FUNCTION_DECL) - merge_attribute_bits (newdecl, alias); + if (alias != error_mark_node) + { + DECL_ATTRIBUTES (alias) + = (*targetm.merge_decl_attributes) (alias, newdecl); + if (TREE_CODE (newdecl) == FUNCTION_DECL) + merge_attribute_bits (newdecl, alias); + } } } diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 515ed0d7c46..7baff46a192 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -3878,8 +3878,9 @@ get_tls_init_fn (tree var) if (!flag_extern_tls_init && DECL_EXTERNAL (var)) return NULL_TREE; - /* If the variable is internal call the local init function directly. */ - if (!TREE_PUBLIC (var)) + /* If the variable is internal, or if we can't generate aliases, + call the local init function directly. */ + if (!TREE_PUBLIC (var) || !TARGET_SUPPORTS_ALIASES) return get_local_tls_init_fn (DECL_SOURCE_LOCATION (var)); tree sname = mangle_tls_init_fn (var); @@ -4043,25 +4044,6 @@ generate_tls_wrapper (tree fn) expand_or_defer_fn (finish_function (/*inline_p=*/false)); } -/* A dummy init function to act as a weak placeholder for a (possibly non- - existent) dynamic init. */ -static void -generate_tls_dummy_init (tree fn) -{ - tree var = DECL_BEFRIENDING_CLASSES (fn); - tree init_fn = get_tls_init_fn (var); - /* If have no init fn, or it is non-weak, then we do not need to make a - dummy. */ - if (!init_fn || !lookup_attribute ("weak", DECL_ATTRIBUTES (init_fn))) - return; - start_preparsed_function (init_fn, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); - tree body = begin_function_body (); - declare_weak (init_fn); - finish_return_stmt (NULL_TREE); - finish_function_body (body); - expand_or_defer_fn (finish_function (/*inline_p=*/false)); -} - /* Start a global constructor or destructor function. */ static tree @@ -4880,24 +4862,22 @@ handle_tls_init (void) finish_expr_stmt (cp_build_modify_expr (loc, guard, NOP_EXPR, boolean_true_node, tf_warning_or_error)); - auto_vec direct_calls; for (; vars; vars = TREE_CHAIN (vars)) { tree var = TREE_VALUE (vars); tree init = TREE_PURPOSE (vars); one_static_initialization_or_destruction (/*initp=*/true, var, init); - /* Output inits even with -fno-extern-tls-init. - We save the list here and output either an alias or a stub function - below. */ - if (TREE_PUBLIC (var)) + /* Output init aliases even with -fno-extern-tls-init. */ + if (TARGET_SUPPORTS_ALIASES && TREE_PUBLIC (var)) { - tree single_init_fn = get_tls_init_fn (var); + tree single_init_fn = get_tls_init_fn (var); if (single_init_fn == NULL_TREE) continue; - if (single_init_fn == fn) - continue; - direct_calls.safe_push (single_init_fn); + cgraph_node *alias + = cgraph_node::get_create (fn)->create_same_body_alias + (single_init_fn, fn); + gcc_assert (alias != NULL); } } @@ -4905,30 +4885,6 @@ handle_tls_init (void) finish_if_stmt (if_stmt); finish_function_body (body); expand_or_defer_fn (finish_function (/*inline_p=*/false)); - - /* For each TLS var that we have an init function, we either emit an alias - between that and the tls_init, or a stub function that just calls the - tls_init. */ - while (!direct_calls.is_empty()) - { - tree single_init_fn = direct_calls.pop (); - if (TARGET_SUPPORTS_ALIASES) - { - cgraph_node *alias - = cgraph_node::get_create (fn)->create_same_body_alias - (single_init_fn, fn); - gcc_assert (alias != NULL); - } - else - { - start_preparsed_function (single_init_fn, NULL_TREE, SF_PRE_PARSED); - tree body = begin_function_body (); - tree r = build_call_expr (fn, 0); - finish_expr_stmt (r); - finish_function_body (body); - expand_or_defer_fn (finish_function (/*inline_p=*/false)); - } - } } /* We're at the end of compilation, so generate any mangling aliases that @@ -5348,14 +5304,7 @@ c_parse_final_cleanups (void) } if (!DECL_INITIAL (decl) && decl_tls_wrapper_p (decl)) - { - generate_tls_wrapper (decl); - /* The wrapper might have a weak reference to an init, we provide - a dummy function to satisfy that here. The linker/dynamic - loader will override this with the actual init, if one is - required. */ - generate_tls_dummy_init (decl); - } + generate_tls_wrapper (decl); if (!DECL_SAVED_TREE (decl)) continue; diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc index 630cc4eade1..0770417810e 100644 --- a/gcc/cp/lambda.cc +++ b/gcc/cp/lambda.cc @@ -223,7 +223,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p, outermost CV qualifiers of EXPR. */ type = build_reference_type (type); if (uses_parameter_packs (expr)) - /* Stick with 'auto' even if the type could be deduced. */; + /* Stick with 'auto' even if the type could be deduced. */ + TEMPLATE_TYPE_PARAMETER_PACK (auto_node) = true; else type = do_auto_deduction (type, expr, auto_node); } diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index ed24814b601..21fc85150c9 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -19976,10 +19976,6 @@ maybe_translate_include (cpp_reader *reader, line_maps *lmaps, location_t loc, return nullptr; } - if (!spans.init_p ()) - /* Before the main file, don't divert. */ - return nullptr; - dump.push (NULL); dump () && dump ("Checking include translation '%s'", path); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 4ac614dde24..bc4a2359153 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -707,91 +707,6 @@ cp_lexer_handle_early_pragma (cp_lexer *lexer) static cp_parser *cp_parser_new (cp_lexer *); static GTY (()) cp_parser *the_parser; -/* Context-sensitive parse-checking for clang-style attributes. */ - -enum clang_attr_state { - CA_NONE = 0, - CA_ATTR, - CA_BR1, CA_BR2, - CA_LIST, - CA_LIST_ARGS, - CA_IS_CA, - CA_CA_ARGS, - CA_LIST_CONT -}; - -/* State machine tracking context of attribute lexing. */ - -static enum clang_attr_state -cp_lexer_attribute_state (cp_token& token, enum clang_attr_state attr_state) -{ - /* Implement a context-sensitive parser for clang attributes. - We detect __attribute__((clang_style_attribute (ARGS))) and lex the - args ARGS with the following differences from GNU attributes: - (a) number-like values are lexed as strings [this allows lexing XX.YY.ZZ - version numbers]. - (b) we concatenate strings, since clang attributes allow this too. */ - switch (attr_state) - { - case CA_NONE: - if (token.type == CPP_KEYWORD - && token.keyword == RID_ATTRIBUTE) - attr_state = CA_ATTR; - break; - case CA_ATTR: - if (token.type == CPP_OPEN_PAREN) - attr_state = CA_BR1; - else - attr_state = CA_NONE; - break; - case CA_BR1: - if (token.type == CPP_OPEN_PAREN) - attr_state = CA_BR2; - else - attr_state = CA_NONE; - break; - case CA_BR2: - if (token.type == CPP_NAME) - { - tree identifier = (token.type == CPP_KEYWORD) - /* For keywords, use the canonical spelling, not the - parsed identifier. */ - ? ridpointers[(int) token.keyword] - : token.u.value; - identifier = canonicalize_attr_name (identifier); - if (attribute_clang_form_p (identifier)) - attr_state = CA_IS_CA; - else - attr_state = CA_LIST; - } - else - attr_state = CA_NONE; - break; - case CA_IS_CA: - case CA_LIST: - if (token.type == CPP_COMMA) - attr_state = CA_BR2; /* Back to the list outer. */ - else if (token.type == CPP_OPEN_PAREN) - attr_state = attr_state == CA_IS_CA ? CA_CA_ARGS - : CA_LIST_ARGS; - else - attr_state = CA_NONE; - break; - case CA_CA_ARGS: /* We will special-case args in this state. */ - case CA_LIST_ARGS: - if (token.type == CPP_CLOSE_PAREN) - attr_state = CA_LIST_CONT; - break; - case CA_LIST_CONT: - if (token.type == CPP_COMMA) - attr_state = CA_BR2; /* Back to the list outer. */ - else - attr_state = CA_NONE; - break; - } - return attr_state; -} - /* Create a new main C++ lexer, the lexer that gets tokens from the preprocessor, and also create the main parser. */ @@ -808,8 +723,6 @@ cp_lexer_new_main (void) c_common_no_more_pch (); cp_lexer *lexer = cp_lexer_alloc (); - enum clang_attr_state attr_state = CA_NONE; - /* Put the first token in the buffer. */ cp_token *tok = lexer->buffer->quick_push (token); @@ -833,14 +746,8 @@ cp_lexer_new_main (void) if (tok->type == CPP_PRAGMA_EOL) cp_lexer_handle_early_pragma (lexer); - attr_state = cp_lexer_attribute_state (*tok, attr_state); tok = vec_safe_push (lexer->buffer, cp_token ()); - unsigned int flags = C_LEX_STRING_NO_JOIN; - /* If we are processing clang-style attribute args, lex numbers as - potential version strings; NN .. NN.MM .. NN.MM.OO */ - if (attr_state == CA_CA_ARGS) - flags |= C_LEX_NUMBER_AS_STRING; - cp_lexer_get_preprocessor_token (flags, tok); + cp_lexer_get_preprocessor_token (C_LEX_STRING_NO_JOIN, tok); } lexer->next_token = lexer->buffer->address (); @@ -1057,7 +964,7 @@ cp_lexer_get_preprocessor_token (unsigned flags, cp_token *token) { static int is_extern_c = 0; - /* Get a new token from the preprocessor. */ + /* Get a new token from the preprocessor. */ token->type = c_lex_with_flags (&token->u.value, &token->location, &token->flags, flags); @@ -3132,6 +3039,8 @@ static bool cp_parser_skip_up_to_closing_square_bracket static bool cp_parser_skip_to_closing_square_bracket (cp_parser *); static size_t cp_parser_skip_balanced_tokens (cp_parser *, size_t); +static bool cp_parser_next_tokens_can_be_canon_loop (cp_parser *, + enum tree_code, bool); static tree cp_parser_omp_loop_nest (cp_parser *, bool *); // -------------------------------------------------------------------------- // @@ -13438,7 +13347,13 @@ check_omp_intervening_code (cp_parser *parser) "% % clause"); omp_for_parse_state->perfect_nesting_fail = true; } - /* TODO: Also reject loops with TILE directive. */ + else if (omp_for_parse_state->code == OMP_TILE) + { + error_at (omp_for_parse_state->for_loc, + "inner loops must be perfectly nested " + "with % directive"); + omp_for_parse_state->perfect_nesting_fail = true; + } if (omp_for_parse_state->perfect_nesting_fail) omp_for_parse_state->fail = true; } @@ -13489,8 +13404,9 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr) else if (in_omp_loop_block) { bool want_nested_loop = omp_for_parse_state->want_nested_loop; + tree_code code = omp_for_parse_state->code; if (want_nested_loop - && token->type == CPP_KEYWORD && token->keyword == RID_FOR) + && cp_parser_next_tokens_can_be_canon_loop (parser, code, false)) { /* Found the nested loop. */ omp_for_parse_state->depth++; @@ -24084,7 +24000,12 @@ cp_parser_direct_declarator (cp_parser* parser, { /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); - if (token->type == CPP_OPEN_PAREN) + if (token->type == CPP_OPEN_PAREN + || (first + && dcl_kind != CP_PARSER_DECLARATOR_NAMED + && token->type == CPP_ELLIPSIS + && cxx_dialect > cxx98 + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN))) { /* This is either a parameter-declaration-clause, or a parenthesized declarator. When we know we are parsing a @@ -24123,6 +24044,11 @@ cp_parser_direct_declarator (cp_parser* parser, Thus again, we try a parameter-declaration-clause, and if that fails, we back out and return. */ + bool pack_expansion_p = token->type == CPP_ELLIPSIS; + + if (pack_expansion_p) + /* Consume the `...' */ + cp_lexer_consume_token (parser->lexer); if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) { @@ -24266,6 +24192,7 @@ cp_parser_direct_declarator (cp_parser* parser, attrs, parens_loc); declarator->attributes = gnu_attrs; + declarator->parameter_pack_p |= pack_expansion_p; /* Any subsequent parameter lists are to do with return type, so are not those of the declared function. */ @@ -24289,7 +24216,7 @@ cp_parser_direct_declarator (cp_parser* parser, /* If this is the first, we can try a parenthesized declarator. */ - if (first) + if (first && !pack_expansion_p) { bool saved_in_type_id_in_expr_p; @@ -30051,91 +29978,6 @@ cp_parser_gnu_attributes_opt (cp_parser* parser) return attributes; } -/* Parse the arguments list for a clang attribute. */ -static tree -cp_parser_clang_attribute (cp_parser *parser, tree/*attr_id*/) -{ - /* Each entry can be : - identifier - identifier=N.MM.Z - identifier="string" - followed by ',' or ) for the last entry*/ - - matching_parens parens; - if (!parens.require_open (parser)) - return NULL; - - bool save_translate_strings_p = parser->translate_strings_p; - parser->translate_strings_p = false; - tree attr_args = NULL_TREE; - cp_token *token; - do - { - tree name = NULL_TREE; - tree value = NULL_TREE; - - token = cp_lexer_peek_token (parser->lexer); - if (token->type == CPP_NAME) - name = token->u.value; - else if (token->type == CPP_KEYWORD) - name = ridpointers[(int) token->keyword]; - else if (token->flags & NAMED_OP) - name = get_identifier (cpp_type2name (token->type, token->flags)); - else - { - /* FIXME: context-sensitive for that attrib. */ - error_at (token->location, "expected an attribute keyword"); - cp_parser_skip_to_closing_parenthesis (parser, - /*recovering=*/true, - /*or_comma=*/false, - /*consume_paren=*/false); - attr_args = error_mark_node; - break; - } - cp_lexer_consume_token (parser->lexer); - - if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) - { - cp_lexer_consume_token (parser->lexer); /* eat the '=' */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN) - && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) - { - token = cp_lexer_peek_token (parser->lexer); - if (token->type == CPP_STRING) - value = cp_parser_string_literal (parser, /*translate=*/false, - /*wide_ok=*/false); - else - { - value = token->u.value; - cp_lexer_consume_token (parser->lexer); - } - } - /* else value is missing. */ - } - else if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN) - && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) - { - error_at (token->location, "expected %<,%>, %<=%> or %<)%>"); - cp_parser_skip_to_closing_parenthesis (parser, - /*recovering=*/true, - /*or_comma=*/false, - /*consume_paren=*/false); - attr_args = error_mark_node; - break; - } - if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) - cp_lexer_consume_token (parser->lexer); - tree t = tree_cons (value, name, NULL_TREE); - attr_args = chainon (attr_args, t); - } while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)); - - parser->translate_strings_p = save_translate_strings_p; - if (!parens.require_close (parser)) - return error_mark_node; - - return attr_args; -} - /* Parse a GNU attribute-list. attribute-list: @@ -30195,12 +30037,9 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */) /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); - if (token->type == CPP_OPEN_PAREN - && attribute_clang_form_p (identifier)) - arguments = cp_parser_clang_attribute (parser, identifier); - else if (token->type == CPP_OPEN_PAREN) + /* If it's an `(', then parse the attribute arguments. */ + if (token->type == CPP_OPEN_PAREN) { - /* If it's an `(', then parse the attribute arguments. */ vec *vec; int attr_flag = (attribute_takes_identifier_p (identifier) ? id_attr : normal_attr); @@ -30217,12 +30056,12 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */) arguments = build_tree_list_vec (vec); release_tree_vector (vec); } + /* Save the arguments away. */ + TREE_VALUE (attribute) = arguments; } if (arguments != error_mark_node) { - /* Save the arguments away. */ - TREE_VALUE (attribute) = arguments; /* Add this attribute to the list. */ TREE_CHAIN (attribute) = attribute_list; attribute_list = attribute; @@ -38372,6 +38211,8 @@ cp_parser_omp_clause_name (cp_parser *parser) result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; else if (!strcmp ("from", p)) result = PRAGMA_OMP_CLAUSE_FROM; + else if (!strcmp ("full", p)) + result = PRAGMA_OMP_CLAUSE_FULL; break; case 'g': if (!strcmp ("gang", p)) @@ -38448,6 +38289,8 @@ cp_parser_omp_clause_name (cp_parser *parser) case 'p': if (!strcmp ("parallel", p)) result = PRAGMA_OMP_CLAUSE_PARALLEL; + if (!strcmp ("partial", p)) + result = PRAGMA_OMP_CLAUSE_PARTIAL; else if (!strcmp ("present", p)) result = PRAGMA_OACC_CLAUSE_PRESENT; else if (!strcmp ("present_or_copy", p) @@ -40828,6 +40671,48 @@ cp_parser_omp_clause_thread_limit (cp_parser *parser, tree list, return c; } +/* OpenMP 5.1 + full */ + +static tree +cp_parser_omp_clause_full (tree list, location_t loc) +{ + check_no_duplicate_clause (list, OMP_CLAUSE_FULL, "full", loc); + + tree c = build_omp_clause (loc, OMP_CLAUSE_FULL); + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + +/* OpenMP 5.1 + partial ( constant-expression ) */ + +static tree +cp_parser_omp_clause_partial (cp_parser *parser, tree list, location_t loc) +{ + tree num = NULL_TREE; + check_no_duplicate_clause (list, OMP_CLAUSE_PARTIAL, "partial", loc); + + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + { + matching_parens parens; + parens.consume_open (parser); + num = cp_parser_constant_expression (parser); + if (num == error_mark_node + || !parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + if (num == error_mark_node) + return list; + } + + tree c = build_omp_clause (loc, OMP_CLAUSE_PARTIAL); + OMP_CLAUSE_PARTIAL_EXPR (c) = num; + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + /* OpenMP 4.0: aligned ( variable-list ) aligned ( variable-list : constant-expression ) */ @@ -42579,7 +42464,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, else if (nested == 2) error_at (cp_lexer_peek_token (parser->lexer)->location, "clauses in % trait should be separated " - "by %<,%>"); + "by %<,%>"); } token = cp_lexer_peek_token (parser->lexer); @@ -42926,6 +42811,15 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, clauses); c_name = "enter"; break; + case PRAGMA_OMP_CLAUSE_PARTIAL: + clauses = cp_parser_omp_clause_partial (parser, clauses, + token->location); + c_name = "partial"; + break; + case PRAGMA_OMP_CLAUSE_FULL: + clauses = cp_parser_omp_clause_full (clauses, token->location); + c_name = "full"; + break; default: cp_parser_error (parser, "expected an OpenMP clause"); goto saw_error; @@ -45149,6 +45043,50 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) } +/* Check that the next token starts a loop nest. Return true if yes, + otherwise diagnose an error if ERROR_P is true and return false. */ +static bool +cp_parser_next_tokens_can_be_canon_loop (cp_parser *parser, enum tree_code code, + bool error_p) +{ + if (code == OACC_LOOP) + { + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) + return true; + if (error_p) + cp_parser_error (parser, "for statement expected"); + } + else + { + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) + return true; + if (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA) + && ((cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer)) + == PRAGMA_OMP_UNROLL) + || (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer)) + == PRAGMA_OMP_TILE))) + return true; + /* Skip standard attributes on next for in case they are + [[omp::directive (unroll partial (4))]] or + [[omp::directive (tile sizes (1, 2, 3))]] etc. */ + size_t n = cp_parser_skip_std_attribute_spec_seq (parser, 1); + if (cp_lexer_nth_token_is_keyword (parser->lexer, n, RID_FOR)) + return true; + if (error_p) + { + if (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA)) + error_at (cp_lexer_peek_token (parser->lexer)->location, + "loop nest expected"); + else + cp_parser_error (parser, "loop nest expected"); + } + } + return false; +} + +static tree cp_parser_omp_unroll (cp_parser *, cp_token *, bool *); +static tree cp_parser_omp_tile (cp_parser *, cp_token *, bool *); + /* This function parses a single level of a loop nest, invoking itself recursively if necessary. @@ -45201,8 +45139,142 @@ cp_parser_omp_loop_nest (cp_parser *parser, bool *if_p) gcc_assert (omp_for_parse_state); int depth = omp_for_parse_state->depth; - /* We have already matched the FOR token but not consumed it yet. */ - gcc_assert (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)); + /* Handle loop transformations first. Note that when we get here + omp_for_parse_state->depth has already been incremented to indicate + the depth of the *next* loop, not the level of the loop body the + transformation directive appears in. */ + + /* Arrange for C++ standard attribute syntax to be parsed as regular + pragmas. Give an error if there are other random attributes present. */ + cp_token *token = cp_lexer_peek_token (parser->lexer); + tree std_attrs = cp_parser_std_attribute_spec_seq (parser); + std_attrs = cp_parser_handle_statement_omp_attributes (parser, std_attrs); + if (std_attrs) + error_at (token->location, + "attributes other than OpenMP directives " + "are not allowed on % in loop nest"); + + if (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA)) + { + tree transform = NULL_TREE, sizes, body = NULL_TREE; + int count = 0; + cp_token *pragma_tok; + tree stmt; + loc = cp_lexer_peek_token (parser->lexer)->location; + switch (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer))) + { + case PRAGMA_OMP_UNROLL: + pragma_tok = cp_lexer_consume_token (parser->lexer); + parser->lexer->in_pragma = true; + body = push_stmt_list (); + stmt = push_omp_privatization_clauses (false); + transform = cp_parser_omp_unroll (parser, pragma_tok, if_p); + pop_omp_privatization_clauses (stmt); + body = pop_stmt_list (body); + if (transform == NULL_TREE || transform == error_mark_node) + { + transform = error_mark_node; + break; + } + gcc_assert (TREE_CODE (transform) == OMP_UNROLL); + if (omp_find_clause (OMP_FOR_CLAUSES (transform), + OMP_CLAUSE_PARTIAL)) + { + if (omp_for_parse_state->count - depth > 1) + { + error_at (loc, "% construct with % " + "clause generates just one loop with " + "canonical form but %d loops are needed", + omp_for_parse_state->count - depth); + transform = error_mark_node; + } + else + count = 1; + } + else + { + error_at (loc, "generated loop of % construct " + "without % clause does not have " + "canonical form"); + transform = error_mark_node; + } + break; + case PRAGMA_OMP_TILE: + pragma_tok = cp_lexer_consume_token (parser->lexer); + parser->lexer->in_pragma = true; + body = push_stmt_list (); + stmt = push_omp_privatization_clauses (false); + transform = cp_parser_omp_tile (parser, pragma_tok, if_p); + pop_omp_privatization_clauses (stmt); + body = pop_stmt_list (body); + if (transform == NULL_TREE || transform == error_mark_node) + { + transform = error_mark_node; + break; + } + gcc_assert (TREE_CODE (transform) == OMP_TILE); + sizes = omp_find_clause (OMP_FOR_CLAUSES (transform), + OMP_CLAUSE_SIZES); + gcc_assert (sizes); + count = list_length (OMP_CLAUSE_SIZES_LIST (sizes)); + if (depth + count < omp_for_parse_state->count) + { + error_at (loc, "% construct generates %d loops " + "with canonical form but %d loops are needed", + count, omp_for_parse_state->count - depth); + transform = error_mark_node; + } + break; + default: + cp_parser_pragma (parser, pragma_stmt, NULL); + break; + } + if (transform == NULL_TREE) + error_at (loc, "expected % loop or OpenMP loop " + "transformation construct"); + if (transform == NULL_TREE || transform == error_mark_node) + { + omp_for_parse_state->fail = true; + return NULL_TREE; + } + for (count = omp_for_parse_state->count; depth < count; ++depth) + { + TREE_VEC_ELT (omp_for_parse_state->declv, depth) = global_namespace; + TREE_VEC_ELT (omp_for_parse_state->initv, depth) = NULL_TREE; + TREE_VEC_ELT (omp_for_parse_state->condv, depth) = NULL_TREE; + TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = NULL_TREE; + if (omp_for_parse_state->orig_declv) + TREE_VEC_ELT (omp_for_parse_state->incrv, depth) = NULL_TREE; + vec_safe_push (omp_for_parse_state->init_blockv, NULL_TREE); + vec_safe_push (omp_for_parse_state->body_blockv, NULL_TREE); + vec_safe_push (omp_for_parse_state->init_placeholderv, NULL_TREE); + vec_safe_push (omp_for_parse_state->body_placeholderv, NULL_TREE); + } + omp_for_parse_state->want_nested_loop = false; + return body; + } + + /* Diagnose errors if we don't have a "for" loop following the + optional loop transforms. Otherwise, consume the token. */ + if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) + { + omp_for_parse_state->fail = true; + cp_token *token = cp_lexer_peek_token (parser->lexer); + /* Don't call cp_parser_error here since it overrides the + provided message with a more confusing one if there was + a bad pragma or attribute directive. */ + error_at (token->location, "loop nest expected"); + /* See if we can recover by skipping over bad pragma(s). */ + while (token->type == CPP_PRAGMA) + { + cp_parser_skip_to_pragma_eol (parser, token); + if (cp_parser_next_tokens_can_be_canon_loop (parser, omp_for_parse_state->code, + false)) + return cp_parser_omp_loop_nest (parser, if_p); + token = cp_lexer_peek_token (parser->lexer); + } + return NULL_TREE; + } loc = cp_lexer_consume_token (parser->lexer)->location; /* Forbid break/continue in the loop initializer, condition, and @@ -45457,10 +45529,15 @@ cp_parser_omp_loop_nest (cp_parser *parser, bool *if_p) moreloops = depth < omp_for_parse_state->count - 1; omp_for_parse_state->want_nested_loop = moreloops; - if (moreloops && cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) + if (moreloops + && cp_parser_next_tokens_can_be_canon_loop (parser, + omp_for_parse_state->code, + false)) { omp_for_parse_state->depth++; - add_stmt (cp_parser_omp_loop_nest (parser, if_p)); + tree nest = cp_parser_omp_loop_nest (parser, if_p); + if (nest) + add_stmt (nest); omp_for_parse_state->depth--; } else if (moreloops @@ -45742,7 +45819,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, tree cl, ordered_cl = NULL_TREE; int collapse = 1, ordered = 0; unsigned int count; - bool tiling = false; + bool oacc_tiling = false; bool inscan = false; struct omp_for_parse_data data; struct omp_for_parse_data *save_data = parser->omp_for_parse_state; @@ -45754,9 +45831,11 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl)); else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE) { - tiling = true; + oacc_tiling = true; collapse = list_length (OMP_CLAUSE_TILE_LIST (cl)); } + else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_SIZES) + collapse = list_length (OMP_CLAUSE_SIZES_LIST (cl)); else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED && OMP_CLAUSE_ORDERED_EXPR (cl)) { @@ -45777,14 +45856,11 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, ordered = collapse; } - gcc_assert (tiling || (collapse >= 1 && ordered >= 0)); + gcc_assert (oacc_tiling || (collapse >= 1 && ordered >= 0)); count = ordered ? ordered : collapse; - if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) - { - cp_parser_error (parser, "for statement expected"); - return NULL; - } + if (!cp_parser_next_tokens_can_be_canon_loop (parser, code, true)) + return NULL; /* Initialize parse state for recursive descent. */ data.declv = make_tree_vec (count); @@ -45809,7 +45885,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, data.ordered_cl = ordered_cl; parser->omp_for_parse_state = &data; - cp_parser_omp_loop_nest (parser, if_p); + tree body = cp_parser_omp_loop_nest (parser, if_p); /* Bomb out early if there was an error (not enough loops, etc). */ if (data.fail || data.declv == NULL_TREE) @@ -45845,66 +45921,93 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, /* First insert markers for structured blocks for intervening code in the loop bodies. */ for (unsigned int i = 0; i < count - 1; i++) - { - bool good = find_structured_blocks (&(data.body_blockv[i]), - data.init_placeholderv[i+1]); - gcc_assert (good); - } + if (data.body_blockv[i]) + for (unsigned int j = i + 1; j < count; j++) + if (data.init_placeholderv[j]) + { + bool good = find_structured_blocks (&data.body_blockv[i], + data.init_placeholderv[j]); + gcc_assert (good); + break; + } /* Do the substitution from the inside out. */ for (unsigned int i = count - 1; i > 0; i--) - { - substitute_in_tree (&(data.body_blockv[i-1]), - data.init_placeholderv[i], - data.body_blockv[i], false); - substitute_in_tree (&(data.init_blockv[i-1]), - data.body_placeholderv[i-1], - data.init_blockv[i], true); - } + if (data.init_placeholderv[i]) + for (unsigned int j = i; j > 0; j--) + if (data.body_blockv[j - 1]) + { + substitute_in_tree (&data.body_blockv[j - 1], + data.init_placeholderv[i], + data.body_blockv[i], false); + substitute_in_tree (&data.init_blockv[j - 1], + data.body_placeholderv[j - 1], + data.init_blockv[i], true); + break; + } + + for (unsigned int i = 0; i < count; ++i) + if (data.body_blockv[i]) + { + body = data.body_blockv[i]; + break; + } /* Generate the OMP_FOR. Note finish_omp_for adds the OMP_FOR (and possibly other stuff) to the current statement list but returns a pointer to the OMP_FOR itself, or null in case of error. */ result = push_stmt_list (); ret = finish_omp_for (loc_first, code, data.declv, data.orig_declv, - data.initv, data.condv, data.incrv, - data.body_blockv[0], + data.initv, data.condv, data.incrv, body, data.pre_body, &data.orig_inits, data.clauses); result = pop_stmt_list (result); /* Check for errors involving lb/ub/incr expressions referencing variables declared in intervening code. */ if (data.saw_intervening_code + && ret && !c_omp_check_loop_binding_exprs (ret, &data.orig_inits)) ret = NULL_TREE; if (ret) - { - /* Splice the omp_for into the nest of init blocks. */ - substitute_in_tree (&(data.init_blockv[0]), - data.body_placeholderv[count - 1], - result, true); - - /* Some later processing for combined directives assumes - that the BIND_EXPR containing range for variables appears - at top level in the OMP_FOR body. Fix that up if it's - not the case, e.g. because there is intervening code. */ - if (code != OACC_LOOP) - finish_omp_for_block (data.init_blockv[0], ret); - - /* Clean up the block subblock/superblock links. Per comment in - begin_compound_stmt, "we don't build BLOCK nodes when processing - templates", so skip this step in that case. */ - if (!processing_template_decl) + for (unsigned int i = 0; i < count; ++i) + if (data.init_blockv[i]) { - tree superblock = NULL_TREE; - cp_walk_tree (&data.init_blockv[0], fixup_blocks_walker, - (void *)&superblock, NULL); - } + int j; + for (j = count - 1; j >= 0; --j) + if (data.body_placeholderv[j]) + break; + gcc_assert (j >= 0); + + /* Splice the omp_for into the nest of init blocks. */ + substitute_in_tree (&data.init_blockv[i], + data.body_placeholderv[j], + result, true); + + /* Some later processing for combined directives assumes + that the BIND_EXPR containing range for variables appears + at top level in the OMP_FOR body. Fix that up if it's + not the case, e.g. because there is intervening code. */ + if (code != OACC_LOOP) + finish_omp_for_block (data.init_blockv[i], ret); + + /* Clean up the block subblock/superblock links. Per comment in + begin_compound_stmt, "we don't build BLOCK nodes when processing + templates", so skip this step in that case. */ + if (!processing_template_decl) + { + tree superblock = NULL_TREE; + cp_walk_tree (&data.init_blockv[i], fixup_blocks_walker, + (void *)&superblock, NULL); + } - /* Finally record the result. */ - add_stmt (data.init_blockv[0]); - } + /* Finally record the result. */ + add_stmt (data.init_blockv[0]); + result = NULL_TREE; + break; + } + if (ret && result) + add_stmt (result); parser->omp_for_parse_state = save_data; return ret; @@ -47634,6 +47737,98 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok, return true; } + +/* OpenMP 5.1: Parse sizes list for "omp tile sizes" + sizes ( size-expr-list ) */ +static tree +cp_parser_omp_tile_sizes (cp_parser *parser, location_t loc) +{ + tree sizes = NULL_TREE; + + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + + cp_token *tok = cp_lexer_peek_token (parser->lexer); + if (tok->type != CPP_NAME + || strcmp ("sizes", IDENTIFIER_POINTER (tok->u.value))) + { + cp_parser_error (parser, "expected %"); + return error_mark_node; + } + cp_lexer_consume_token (parser->lexer); + + matching_parens parens; + if (!parens.require_open (parser)) + return error_mark_node; + + do + { + if (sizes && !cp_parser_require (parser, CPP_COMMA, RT_COMMA)) + return error_mark_node; + + tree expr = cp_parser_constant_expression (parser); + if (expr == error_mark_node) + { + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return error_mark_node; + } + + sizes = tree_cons (NULL_TREE, expr, sizes); + } + while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)); + parens.require_close (parser); + + gcc_assert (sizes); + tree c = build_omp_clause (loc, OMP_CLAUSE_SIZES); + OMP_CLAUSE_SIZES_LIST (c) = nreverse (sizes); + return c; +} + +/* OpenMP 5.1: + #pragma omp tile sizes ( size-expr-list ) */ + +static tree +cp_parser_omp_tile (cp_parser *parser, cp_token *tok, bool *if_p) +{ + tree clauses = cp_parser_omp_tile_sizes (parser, tok->location); + cp_parser_require_pragma_eol (parser, tok); + + if (!clauses || clauses == error_mark_node) + return error_mark_node; + + tree block = begin_omp_structured_block (); + clauses = finish_omp_clauses (clauses, C_ORT_OMP); + tree ret = cp_parser_omp_for_loop (parser, OMP_TILE, clauses, NULL, if_p); + block = finish_omp_structured_block (block); + add_stmt (block); + + return ret; +} + +#define OMP_UNROLL_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARTIAL) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FULL)) + +/* OpenMP 5.1: + #pragma omp unroll unroll-clause[optseq] */ + +static tree +cp_parser_omp_unroll (cp_parser *parser, cp_token *tok, bool *if_p) +{ + tree clauses = cp_parser_omp_all_clauses (parser, OMP_UNROLL_CLAUSE_MASK, + "#pragma omp unroll", tok, true); + + tree block = begin_omp_structured_block (); + tree ret = cp_parser_omp_for_loop (parser, OMP_UNROLL, clauses, NULL, if_p); + block = finish_omp_structured_block (block); + add_stmt (block); + + return ret; +} + /* OpenACC 2.0: # pragma acc cache (variable-list) new-line @@ -50826,6 +51021,12 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p) case PRAGMA_OMP_ASSUME: cp_parser_omp_assume (parser, pragma_tok, if_p); return; + case PRAGMA_OMP_TILE: + stmt = cp_parser_omp_tile (parser, pragma_tok, if_p); + break; + case PRAGMA_OMP_UNROLL: + stmt = cp_parser_omp_unroll (parser, pragma_tok, if_p); + break; default: gcc_unreachable (); } @@ -51448,6 +51649,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) case PRAGMA_OMP_TASKGROUP: case PRAGMA_OMP_TASKLOOP: case PRAGMA_OMP_TEAMS: + case PRAGMA_OMP_TILE: + case PRAGMA_OMP_UNROLL: if (context != pragma_stmt && context != pragma_compound) goto bad_stmt; stmt = push_omp_privatization_clauses (false); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index dfce1b3c359..607753ae6b7 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -3940,7 +3940,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data) parameter pack (14.6.3), or the type-specifier-seq of a type-id that is a pack expansion, the invented template parameter is a template parameter pack. */ - if (ppd->type_pack_expansion_p && is_auto (t) + if (flag_concepts_ts && ppd->type_pack_expansion_p && is_auto (t) && TEMPLATE_TYPE_LEVEL (t) != 0) TEMPLATE_TYPE_PARAMETER_PACK (t) = true; if (TEMPLATE_TYPE_PARAMETER_PACK (t)) @@ -17691,6 +17691,16 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, OMP_CLAUSE_OPERAND (nc, 0) = tsubst_stmt (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl); break; + case OMP_CLAUSE_PARTIAL: + OMP_CLAUSE_PARTIAL_EXPR (nc) + = tsubst_expr (OMP_CLAUSE_PARTIAL_EXPR (oc), args, complain, + in_decl); + break; + case OMP_CLAUSE_SIZES: + OMP_CLAUSE_SIZES_LIST (nc) + = tsubst_expr (OMP_CLAUSE_SIZES_LIST (oc), args, complain, + in_decl); + break; case OMP_CLAUSE_REDUCTION: case OMP_CLAUSE_IN_REDUCTION: case OMP_CLAUSE_TASK_REDUCTION: @@ -17771,6 +17781,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_IF_PRESENT: case OMP_CLAUSE_FINALIZE: case OMP_CLAUSE_NOHOST: + case OMP_CLAUSE_FULL: break; default: gcc_unreachable (); @@ -19034,6 +19045,8 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl) case OMP_SIMD: case OMP_DISTRIBUTE: case OMP_TASKLOOP: + case OMP_TILE: + case OMP_UNROLL: case OACC_LOOP: { tree clauses, body, pre_body; @@ -19069,10 +19082,22 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (OMP_FOR_INIT (t) != NULL_TREE) for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++) - any_range_for - |= tsubst_omp_for_iterator (t, i, declv, orig_declv, initv, - condv, incrv, &clauses, args, - complain, in_decl); + { + if (TREE_VEC_ELT (OMP_FOR_INIT (t), i)) + any_range_for + |= tsubst_omp_for_iterator (t, i, declv, orig_declv, initv, + condv, incrv, &clauses, args, + complain, in_decl); + else + { + TREE_VEC_ELT (declv, i) = global_namespace; + TREE_VEC_ELT (initv, i) = NULL_TREE; + TREE_VEC_ELT (condv, i) = NULL_TREE; + TREE_VEC_ELT (incrv, i) = NULL_TREE; + if (orig_declv) + TREE_VEC_ELT (orig_declv, i) = NULL_TREE; + } + } omp_parallel_combined_clauses = NULL; if (any_range_for) @@ -19080,7 +19105,8 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl) gcc_assert (orig_declv); body = begin_omp_structured_block (); for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++) - if (TREE_VEC_ELT (orig_declv, i) != TREE_VEC_ELT (declv, i) + if (TREE_VEC_ELT (declv, i) != global_namespace + && TREE_VEC_ELT (orig_declv, i) != TREE_VEC_ELT (declv, i) && TREE_CODE (TREE_VEC_ELT (orig_declv, i)) == TREE_LIST && TREE_CHAIN (TREE_VEC_ELT (orig_declv, i))) cp_finish_omp_range_for (TREE_VEC_ELT (orig_declv, i), @@ -20918,7 +20944,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) be using lambdas anyway, so it's ok to be stricter. Be strict with C++20 template-id ADL too. And be strict if we're already failing anyway. */ - bool strict = in_lambda || template_id_p || seen_error(); + bool strict = in_lambda || template_id_p || seen_error (); bool diag = true; if (strict) error_at (cp_expr_loc_or_input_loc (t), @@ -28019,7 +28045,8 @@ dependent_type_p (tree type) /* If we are not processing a template, then nobody should be providing us with a dependent type. */ gcc_assert (type); - gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto (type)); + gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto (type) + || seen_error ()); return false; } @@ -29107,23 +29134,34 @@ dependent_template_id_p (tree tmpl, tree args) } /* Returns TRUE if OMP_FOR with DECLV, INITV, CONDV and INCRV vectors - are dependent. */ + are dependent. BODY is the body to use for loop transforming + constructs. */ bool -dependent_omp_for_p (tree declv, tree initv, tree condv, tree incrv) +dependent_omp_for_p (tree declv, tree initv, tree condv, tree incrv, tree body) { - int i; + int i, k; if (!processing_template_decl) return false; - for (i = 0; i < TREE_VEC_LENGTH (declv); i++) + for (i = 0, k = 0; i < TREE_VEC_LENGTH (declv); i++) { tree decl = TREE_VEC_ELT (declv, i); tree init = TREE_VEC_ELT (initv, i); tree cond = TREE_VEC_ELT (condv, i); tree incr = TREE_VEC_ELT (incrv, i); + if (decl == NULL_TREE) + { + tree stmt = body; + int j = c_omp_find_generated_loop (stmt, k++, cp_walk_subtrees); + init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), j); + decl = TREE_OPERAND (init, 0); + cond = TREE_VEC_ELT (OMP_FOR_INIT (stmt), j); + incr = TREE_VEC_ELT (OMP_FOR_INIT (stmt), j); + } + if (type_dependent_expression_p (decl) || TREE_CODE (decl) == SCOPE_REF) return true; diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index f90c304a65b..44cc4289f39 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -7099,6 +7099,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) bool implicit_moved = false; bool target_in_reduction_seen = false; bool num_tasks_seen = false; + bool partial_seen = false; bitmap_obstack_initialize (NULL); bitmap_initialize (&generic_head, &bitmap_default_obstack); @@ -8031,8 +8032,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) "be positive constant integer expression"); remove = true; } - else - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); } OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t; } @@ -8886,7 +8885,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (!processing_template_decl) { t = maybe_constant_value (t); - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); if (TREE_CODE (t) != INTEGER_CST) { error_at (OMP_CLAUSE_LOCATION (c), @@ -9051,7 +9049,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) "integral constant"); remove = true; } - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); } } @@ -9060,6 +9057,47 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } break; + case OMP_CLAUSE_SIZES: + for (tree list = OMP_CLAUSE_SIZES_LIST (c); + !remove && list; list = TREE_CHAIN (list)) + { + t = TREE_VALUE (list); + + if (t == error_mark_node) + t = integer_one_node; + else if (!type_dependent_expression_p (t) + && !INTEGRAL_TYPE_P (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% argument needs positive integral " + "constant"); + t = integer_one_node; + } + else + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + { + t = maybe_constant_value (t); + HOST_WIDE_INT n; + if (!tree_fits_shwi_p (t) + || !INTEGRAL_TYPE_P (TREE_TYPE (t)) + || (n = tree_to_shwi (t)) <= 0 + || (int)n != n) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% argument needs positive " + "integral constant"); + t = integer_one_node; + } + } + } + + /* Update list item. */ + TREE_VALUE (list) = t; + } + break; + case OMP_CLAUSE_ORDERED: ordered_seen = true; break; @@ -9114,6 +9152,49 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } break; + case OMP_CLAUSE_FULL: + break; + + case OMP_CLAUSE_PARTIAL: + partial_seen = true; + t = OMP_CLAUSE_PARTIAL_EXPR (c); + if (!t) + break; + + if (t == error_mark_node) + t = NULL_TREE; + else if (!type_dependent_expression_p (t) + && !INTEGRAL_TYPE_P (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% argument needs positive constant " + "integer expression"); + t = NULL_TREE; + } + else + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + { + t = maybe_constant_value (t); + + HOST_WIDE_INT n; + if (!INTEGRAL_TYPE_P (TREE_TYPE (t)) + || !tree_fits_shwi_p (t) + || (n = tree_to_shwi (t)) <= 0 + || (int)n != n) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% argument needs positive " + "constant integer expression"); + t = NULL_TREE; + } + } + } + + OMP_CLAUSE_PARTIAL_EXPR (c) = t; + break; + default: gcc_unreachable (); } @@ -9274,7 +9355,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { error_at (OMP_CLAUSE_LOCATION (c), "% clause must not be used together " - "with %"); + "with % clause"); *pc = OMP_CLAUSE_CHAIN (c); continue; } @@ -9307,12 +9388,23 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_FULL: + if (partial_seen) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% clause must not be used together " + "with % clause"); + *pc = OMP_CLAUSE_CHAIN (c); + continue; + } + pc = &OMP_CLAUSE_CHAIN (c); + continue; case OMP_CLAUSE_NOWAIT: if (copyprivate_seen) { error_at (OMP_CLAUSE_LOCATION (c), "% clause must not be used together " - "with %"); + "with % clause"); *pc = OMP_CLAUSE_CHAIN (c); continue; } @@ -10753,16 +10845,14 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv)); if (TREE_VEC_LENGTH (declv) > 1) { - tree c; - - c = omp_find_clause (clauses, OMP_CLAUSE_TILE); - if (c) - collapse = list_length (OMP_CLAUSE_TILE_LIST (c)); + if (tree ti = omp_find_clause (clauses, OMP_CLAUSE_TILE)) + collapse = list_length (OMP_CLAUSE_TILE_LIST (ti)); else { - c = omp_find_clause (clauses, OMP_CLAUSE_COLLAPSE); - if (c) - collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c)); + if (tree co = omp_find_clause (clauses, OMP_CLAUSE_COLLAPSE)) + collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (co)); + else if (tree si = omp_find_clause (clauses, OMP_CLAUSE_SIZES)) + collapse = list_length (OMP_CLAUSE_SIZES_LIST (si)); if (collapse != TREE_VEC_LENGTH (declv)) ordered = TREE_VEC_LENGTH (declv); } @@ -10775,6 +10865,13 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, incr = TREE_VEC_ELT (incrv, i); elocus = locus; + if (decl == global_namespace) + { + gcc_assert (init == NULL_TREE && cond == NULL_TREE && incr == NULL_TREE); + TREE_VEC_ELT (declv, i) = NULL_TREE; + init_locv.safe_push (UNKNOWN_LOCATION); + continue; + } /* We are going to throw out the init's original MODIFY_EXPR or MODOP_EXPR below. Save its location so we can use it when reconstructing the expression farther down. Alternatively, if the @@ -10859,7 +10956,7 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, return NULL; } - if (dependent_omp_for_p (declv, initv, condv, incrv)) + if (dependent_omp_for_p (declv, initv, condv, incrv, body)) { tree stmt; @@ -10867,6 +10964,8 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, for (i = 0; i < TREE_VEC_LENGTH (declv); i++) { + if (TREE_VEC_ELT (declv, i) == NULL_TREE) + continue; /* This is really just a place-holder. We'll be decomposing this again and going through the cp_build_modify_expr path below when we instantiate the thing. */ @@ -10903,6 +11002,12 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, TREE_VEC_ELT (orig_incr, i) = incr; elocus = init_locv[i]; + if (decl == NULL_TREE) + { + i++; + continue; + } + if (!DECL_P (decl)) { error_at (elocus, "expected iteration declaration or initialization"); @@ -10976,6 +11081,8 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++) { init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i); + if (init == NULL_TREE) + continue; decl = TREE_OPERAND (init, 0); cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), i); incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i); @@ -11173,7 +11280,9 @@ finish_omp_for_block (tree bind, tree omp_for) fofb.b = NULL_TREE; fofb.omp_for = omp_for; for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (omp_for)); i++) - if (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)) == TREE_LIST + if (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i) + && (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)) + == TREE_LIST) && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i))) { tree v = TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)); diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 1b7a31d32f3..5970ac3d398 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -3025,6 +3025,8 @@ build_class_member_access_expr (cp_expr object, tree member, know the type of the expression. Otherwise, we must wait until overload resolution has been performed. */ functions = BASELINK_FUNCTIONS (member); + if (TREE_CODE (functions) == OVERLOAD && OVL_SINGLE_P (functions)) + functions = OVL_FIRST (functions); if (TREE_CODE (functions) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (functions)) type = TREE_TYPE (functions); @@ -7333,6 +7335,9 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) { tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); + if (TREE_CODE (fn) == OVERLOAD && OVL_SINGLE_P (fn)) + fn = OVL_FIRST (fn); + /* We can only get here with a single static member function. */ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL diff --git a/gcc/cumulative-args.h b/gcc/cumulative-args.h deleted file mode 100644 index b60928e37f9..00000000000 --- a/gcc/cumulative-args.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef GCC_CUMULATIVE_ARGS_H -#define GCC_CUMULATIVE_ARGS_H - -#if CHECKING_P - -struct cumulative_args_t { void *magic; void *p; }; - -#else /* !CHECKING_P */ - -/* When using a GCC build compiler, we could use - __attribute__((transparent_union)) to get cumulative_args_t function - arguments passed like scalars where the ABI would mandate a less - efficient way of argument passing otherwise. However, that would come - at the cost of less type-safe !CHECKING_P compilation. */ - -union cumulative_args_t { void *p; }; - -#endif /* !CHECKING_P */ - -#endif /* GCC_CUMULATIVE_ARGS_H */ diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 98d94d4338d..5688ce07f8b 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,10 @@ +2024-06-05 Kewen Lin + Iain Buclaw + + * d-target.cc (Target::_init): Use int_size_in_bytes of + long_double_type_node to replace the expression with + LONG_DOUBLE_TYPE_SIZE for c.long_doublesize assignment. + 2024-04-19 Iain Buclaw PR d/111650 diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index 127b9d7ce7c..dd46e535891 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -163,7 +163,7 @@ Target::_init (const Param &) this->c.intsize = (INT_TYPE_SIZE / BITS_PER_UNIT); this->c.longsize = (LONG_TYPE_SIZE / BITS_PER_UNIT); this->c.long_longsize = (LONG_LONG_TYPE_SIZE / BITS_PER_UNIT); - this->c.long_doublesize = (LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT); + this->c.long_doublesize = int_size_in_bytes (long_double_type_node); this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT); this->c.bitFieldStyle = targetm.ms_bitfield_layout_p (unknown_type_node) diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc index 97c5943cd33..79116f051bc 100644 --- a/gcc/diagnostic-format-sarif.cc +++ b/gcc/diagnostic-format-sarif.cc @@ -33,6 +33,8 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-diagram.h" #include "text-art/canvas.h" #include "diagnostic-format-sarif.h" +#include "ordered-hash-map.h" +#include "sbitmap.h" class sarif_builder; @@ -57,6 +59,51 @@ private: bool m_success; }; +/* Corresponds to values for the SARIF artifact objects "roles" property. + (SARIF v2.1.0 section 3.24.6). */ + +enum class diagnostic_artifact_role +{ + analysis_target, /* "analysisTarget". */ + debug_output_file, /* "debugOutputFile". */ + result_file, /* "resultFile". */ + traced_file, /* "tracedFile". */ + + NUM_ROLES +}; + +/* Subclass of sarif_object for SARIF artifact objects + (SARIF v2.1.0 section 3.24). */ + +class sarif_artifact : public sarif_object +{ +public: + sarif_artifact (const char *filename) + : m_filename (filename), + m_roles ((unsigned)diagnostic_artifact_role::NUM_ROLES), + m_embed_contents (false) + { + bitmap_clear (m_roles); + } + + void add_role (enum diagnostic_artifact_role role, + bool embed_contents); + + bool embed_contents_p () const { return m_embed_contents; } + void populate_contents (sarif_builder &builder); + void populate_roles (); + +private: + const char *m_filename; + auto_sbitmap m_roles; + + /* Flag to track whether this artifact should have a "contents" property + (SARIF v2.1.0 section 3.24.8). + We only add the contents for those artifacts that have a location + referencing them (so that a consumer might want to quote the source). */ + bool m_embed_contents; +}; + /* Subclass of sarif_object for SARIF result objects (SARIF v2.1.0 section 3.27). */ @@ -158,6 +205,7 @@ class sarif_builder { public: sarif_builder (diagnostic_context *context, + const char *main_input_filename_, bool formatted); void end_diagnostic (diagnostic_context *context, @@ -169,13 +217,16 @@ public: void flush_to_file (FILE *outf); - json::array *make_locations_arr (const diagnostic_info &diagnostic); + json::array *make_locations_arr (const diagnostic_info &diagnostic, + enum diagnostic_artifact_role role); json::object *make_location_object (const rich_location &rich_loc, - const logical_location *logical_loc); + const logical_location *logical_loc, + enum diagnostic_artifact_role role); json::object *make_message_object (const char *msg) const; json::object * make_message_object_for_diagram (diagnostic_context *context, const diagnostic_diagram &diagram); + json::object *maybe_make_artifact_content_object (const char *filename) const; private: sarif_result *make_result_object (diagnostic_context *context, @@ -183,13 +234,16 @@ private: diagnostic_t orig_diag_kind); void set_any_logical_locs_arr (json::object *location_obj, const logical_location *logical_loc); - json::object *make_location_object (const diagnostic_event &event); + json::object *make_location_object (const diagnostic_event &event, + enum diagnostic_artifact_role role); json::object *make_code_flow_object (const diagnostic_path &path); json::object * make_thread_flow_location_object (const diagnostic_event &event, int path_event_idx); json::array *maybe_make_kinds_array (diagnostic_event::meaning m) const; - json::object *maybe_make_physical_location_object (location_t loc); + json::object * + maybe_make_physical_location_object (location_t loc, + enum diagnostic_artifact_role role); json::object *make_artifact_location_object (location_t loc); json::object *make_artifact_location_object (const char *filename); json::object *make_artifact_location_object_for_pwd () const; @@ -214,11 +268,12 @@ private: json::object *make_reporting_descriptor_object_for_cwe_id (int cwe_id) const; json::object * make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id); - json::object *make_artifact_object (const char *filename); + sarif_artifact &get_or_create_artifact (const char *filename, + enum diagnostic_artifact_role role, + bool embed_contents); char *get_source_lines (const char *filename, int start_line, int end_line) const; - json::object *maybe_make_artifact_content_object (const char *filename) const; json::object *maybe_make_artifact_content_object (const char *filename, int start_line, int end_line) const; @@ -240,7 +295,8 @@ private: diagnostic group. */ sarif_result *m_cur_group_result; - hash_set m_filenames; + ordered_hash_map m_filename_to_artifact_map; bool m_seen_any_relative_paths; hash_set m_rule_id_set; json::array *m_rules_arr; @@ -302,6 +358,86 @@ sarif_invocation::prepare_to_flush (diagnostic_context *context) client_data_hooks->add_sarif_invocation_properties (*this); } +/* class sarif_artifact : public sarif_object. */ + +/* Add ROLE to this artifact's roles. + If EMBED_CONTENTS is true, then flag that we will attempt to embed the + contents of this artifact when writing it out. */ + +void +sarif_artifact::add_role (enum diagnostic_artifact_role role, + bool embed_contents) +{ + if (embed_contents) + m_embed_contents = true; + + /* In SARIF v2.1.0 section 3.24.6 "roles" property: + "resultFile" is for an artifact + "which the analysis tool was not explicitly instructed to scan", + whereas "analysisTarget" is for one where the + "analysis tool was instructed to scan this artifact". + Hence the latter excludes the former. */ + if (role == diagnostic_artifact_role::result_file) + if (bitmap_bit_p (m_roles, (int)diagnostic_artifact_role::analysis_target)) + return; + + bitmap_set_bit (m_roles, (int)role); +} + +/* Populate the "contents" property (SARIF v2.1.0 section 3.24.8). + We do this after initialization to + (a) ensure that any charset options have been set + (b) only populate it for artifacts that are referenced by a location. */ + +void +sarif_artifact::populate_contents (sarif_builder &builder) +{ + if (json::object *artifact_content_obj + = builder.maybe_make_artifact_content_object (m_filename)) + set ("contents", artifact_content_obj); +} + +/* Get a string for ROLE corresponding to the + SARIF v2.1.0 section 3.24.6 "roles" property. */ + +static const char * +get_artifact_role_string (enum diagnostic_artifact_role role) +{ + switch (role) + { + default: + gcc_unreachable (); + case diagnostic_artifact_role::analysis_target: + return "analysisTarget"; + case diagnostic_artifact_role::debug_output_file: + return "debugOutputFile"; + case diagnostic_artifact_role::result_file: + return "resultFile"; + case diagnostic_artifact_role::traced_file: + return "tracedFile"; + } +} + +/* Populate the "roles" property of this json::object with a new + json::array for the artifact.roles property (SARIF v2.1.0 section 3.24.6) + containing strings such as "analysisTarget", "resultFile" + and/or "tracedFile". */ + +void +sarif_artifact::populate_roles () +{ + if (bitmap_empty_p (m_roles)) + return; + json::array *roles_arr = new json::array (); + for (int i = 0; i < (int)diagnostic_artifact_role::NUM_ROLES; i++) + if (bitmap_bit_p (m_roles, i)) + { + enum diagnostic_artifact_role role = (enum diagnostic_artifact_role)i; + roles_arr->append (new json::string (get_artifact_role_string (role))); + } + set ("roles", roles_arr); +} + /* class sarif_result : public sarif_object. */ /* Handle secondary diagnostics that occur within a diagnostic group. @@ -320,7 +456,8 @@ sarif_result::on_nested_diagnostic (diagnostic_context *context, sometimes these will related to current_function_decl, but often they won't. */ json::object *location_obj - = builder->make_location_object (*diagnostic.richloc, NULL); + = builder->make_location_object (*diagnostic.richloc, NULL, + diagnostic_artifact_role::result_file); json::object *message_obj = builder->make_message_object (pp_formatted_text (context->printer)); pp_clear_output_area (context->printer); @@ -372,7 +509,9 @@ sarif_ice_notification::sarif_ice_notification (diagnostic_context *context, sarif_builder *builder) { /* "locations" property (SARIF v2.1.0 section 3.58.4). */ - json::array *locations_arr = builder->make_locations_arr (diagnostic); + json::array *locations_arr + = builder->make_locations_arr (diagnostic, + diagnostic_artifact_role::result_file); set ("locations", locations_arr); /* "message" property (SARIF v2.1.0 section 3.85.5). */ @@ -403,6 +542,7 @@ sarif_thread_flow::sarif_thread_flow (const diagnostic_thread &thread) /* sarif_builder's ctor. */ sarif_builder::sarif_builder (diagnostic_context *context, + const char *main_input_filename_, bool formatted) : m_context (context), m_invocation_obj (new sarif_invocation ()), @@ -414,6 +554,15 @@ sarif_builder::sarif_builder (diagnostic_context *context, m_tabstop (context->m_tabstop), m_formatted (formatted) { + /* Mark MAIN_INPUT_FILENAME_ as the artifact that the tool was + instructed to scan. + Only quote the contents if it gets referenced by physical locations, + since otherwise the "no diagnostics" case would quote the main input + file, and doing so noticeably bloated the output seen in analyzer + integration testing (build directory went from 20G -> 21G). */ + get_or_create_artifact (main_input_filename_, + diagnostic_artifact_role::analysis_target, + false); } /* Implementation of "end_diagnostic" for SARIF output. */ @@ -599,7 +748,9 @@ sarif_builder::make_result_object (diagnostic_context *context, result_obj->set ("message", message_obj); /* "locations" property (SARIF v2.1.0 section 3.27.12). */ - json::array *locations_arr = make_locations_arr (diagnostic); + json::array *locations_arr + = make_locations_arr (diagnostic, + diagnostic_artifact_role::result_file); result_obj->set ("locations", locations_arr); /* "codeFlows" property (SARIF v2.1.0 section 3.27.18). */ @@ -729,7 +880,8 @@ make_tool_component_reference_object_for_cwe () const - a "notification" object (SARIF v2.1.0 section 3.58.4). */ json::array * -sarif_builder::make_locations_arr (const diagnostic_info &diagnostic) +sarif_builder::make_locations_arr (const diagnostic_info &diagnostic, + enum diagnostic_artifact_role role) { json::array *locations_arr = new json::array (); const logical_location *logical_loc = NULL; @@ -737,7 +889,7 @@ sarif_builder::make_locations_arr (const diagnostic_info &diagnostic) logical_loc = client_data_hooks->get_current_logical_location (); json::object *location_obj - = make_location_object (*diagnostic.richloc, logical_loc); + = make_location_object (*diagnostic.richloc, logical_loc, role); locations_arr->append (location_obj); return locations_arr; } @@ -763,7 +915,8 @@ set_any_logical_locs_arr (json::object *location_obj, json::object * sarif_builder::make_location_object (const rich_location &rich_loc, - const logical_location *logical_loc) + const logical_location *logical_loc, + enum diagnostic_artifact_role role) { json::object *location_obj = new json::object (); @@ -771,7 +924,8 @@ sarif_builder::make_location_object (const rich_location &rich_loc, location_t loc = rich_loc.get_loc (); /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3). */ - if (json::object *phs_loc_obj = maybe_make_physical_location_object (loc)) + if (json::object *phs_loc_obj = maybe_make_physical_location_object (loc, + role)) location_obj->set ("physicalLocation", phs_loc_obj); /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4). */ @@ -784,13 +938,15 @@ sarif_builder::make_location_object (const rich_location &rich_loc, within a diagnostic_path. */ json::object * -sarif_builder::make_location_object (const diagnostic_event &event) +sarif_builder::make_location_object (const diagnostic_event &event, + enum diagnostic_artifact_role role) { json::object *location_obj = new json::object (); /* "physicalLocation" property (SARIF v2.1.0 section 3.28.3). */ location_t loc = event.get_location (); - if (json::object *phs_loc_obj = maybe_make_physical_location_object (loc)) + if (json::object *phs_loc_obj + = maybe_make_physical_location_object (loc, role)) location_obj->set ("physicalLocation", phs_loc_obj); /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4). */ @@ -806,11 +962,15 @@ sarif_builder::make_location_object (const diagnostic_event &event) } /* Make a physicalLocation object (SARIF v2.1.0 section 3.29) for LOC, - or return NULL; - Add any filename to the m_artifacts. */ + + Ensure that we have an artifact object for the file, adding ROLE to it, + and flagging that we will attempt to embed the contents of the artifact + when writing it out. */ json::object * -sarif_builder::maybe_make_physical_location_object (location_t loc) +sarif_builder:: +maybe_make_physical_location_object (location_t loc, + enum diagnostic_artifact_role role) { if (loc <= BUILTINS_LOCATION || LOCATION_FILE (loc) == NULL) return NULL; @@ -820,7 +980,7 @@ sarif_builder::maybe_make_physical_location_object (location_t loc) /* "artifactLocation" property (SARIF v2.1.0 section 3.29.3). */ json::object *artifact_loc_obj = make_artifact_location_object (loc); phys_loc_obj->set ("artifactLocation", artifact_loc_obj); - m_filenames.add (LOCATION_FILE (loc)); + get_or_create_artifact (LOCATION_FILE (loc), role, true); /* "region" property (SARIF v2.1.0 section 3.29.4). */ if (json::object *region_obj = maybe_make_region_object (loc)) @@ -1167,7 +1327,8 @@ sarif_builder::make_thread_flow_location_object (const diagnostic_event &ev, ev.maybe_add_sarif_properties (*thread_flow_loc_obj); /* "location" property (SARIF v2.1.0 section 3.38.3). */ - json::object *location_obj = make_location_object (ev); + json::object *location_obj + = make_location_object (ev, diagnostic_artifact_role::traced_file); thread_flow_loc_obj->set ("location", location_obj); /* "kinds" property (SARIF v2.1.0 section 3.38.8). */ @@ -1335,9 +1496,12 @@ sarif_builder::make_run_object (sarif_invocation *invocation_obj, /* "artifacts" property (SARIF v2.1.0 section 3.14.15). */ json::array *artifacts_arr = new json::array (); - for (auto iter : m_filenames) + for (auto iter : m_filename_to_artifact_map) { - json::object *artifact_obj = make_artifact_object (iter); + sarif_artifact *artifact_obj = iter.second; + if (artifact_obj->embed_contents_p ()) + artifact_obj->populate_contents (*this); + artifact_obj->populate_roles (); artifacts_arr->append (artifact_obj); } run_obj->set ("artifacts", artifacts_arr); @@ -1508,29 +1672,52 @@ sarif_builder::maybe_make_cwe_taxonomy_object () const return taxonomy_obj; } -/* Make an artifact object (SARIF v2.1.0 section 3.24). */ +/* Ensure that we have an artifact object (SARIF v2.1.0 section 3.24) + for FILENAME, adding it to m_filename_to_artifact_map if not already + found, and adding ROLE to it. + If EMBED_CONTENTS is true, then flag that we will attempt to embed the + contents of this artifact when writing it out. */ -json::object * -sarif_builder::make_artifact_object (const char *filename) +sarif_artifact & +sarif_builder::get_or_create_artifact (const char *filename, + enum diagnostic_artifact_role role, + bool embed_contents) { - json::object *artifact_obj = new json::object (); + if (auto *slot = m_filename_to_artifact_map.get (filename)) + { + (*slot)->add_role (role, embed_contents); + return **slot; + } + + sarif_artifact *artifact_obj = new sarif_artifact (filename); + artifact_obj->add_role (role, embed_contents); + m_filename_to_artifact_map.put (filename, artifact_obj); /* "location" property (SARIF v2.1.0 section 3.24.2). */ json::object *artifact_loc_obj = make_artifact_location_object (filename); artifact_obj->set ("location", artifact_loc_obj); - /* "contents" property (SARIF v2.1.0 section 3.24.8). */ - if (json::object *artifact_content_obj - = maybe_make_artifact_content_object (filename)) - artifact_obj->set ("contents", artifact_content_obj); - /* "sourceLanguage" property (SARIF v2.1.0 section 3.24.10). */ - if (auto client_data_hooks = m_context->get_client_data_hooks ()) - if (const char *source_lang - = client_data_hooks->maybe_get_sarif_source_language (filename)) - artifact_obj->set_string ("sourceLanguage", source_lang); + switch (role) + { + default: + gcc_unreachable (); + case diagnostic_artifact_role::analysis_target: + case diagnostic_artifact_role::result_file: + case diagnostic_artifact_role::traced_file: + /* Assume that these are in the source language. */ + if (auto client_data_hooks = m_context->get_client_data_hooks ()) + if (const char *source_lang + = client_data_hooks->maybe_get_sarif_source_language (filename)) + artifact_obj->set_string ("sourceLanguage", source_lang); + break; + + case diagnostic_artifact_role::debug_output_file: + /* Assume that these are not in the source language. */ + break; + } - return artifact_obj; + return *artifact_obj; } /* Make an artifactContent object (SARIF v2.1.0 section 3.3) for the @@ -1728,9 +1915,10 @@ public: protected: sarif_output_format (diagnostic_context &context, + const char *main_input_filename_, bool formatted) : diagnostic_output_format (context), - m_builder (&context, formatted) + m_builder (&context, main_input_filename_, formatted) {} sarif_builder m_builder; @@ -1740,9 +1928,10 @@ class sarif_stream_output_format : public sarif_output_format { public: sarif_stream_output_format (diagnostic_context &context, + const char *main_input_filename_, bool formatted, FILE *stream) - : sarif_output_format (context, formatted), + : sarif_output_format (context, main_input_filename_, formatted), m_stream (stream) { } @@ -1762,9 +1951,10 @@ class sarif_file_output_format : public sarif_output_format { public: sarif_file_output_format (diagnostic_context &context, + const char *main_input_filename_, bool formatted, const char *base_file_name) - : sarif_output_format (context, formatted), + : sarif_output_format (context, main_input_filename_, formatted), m_base_file_name (xstrdup (base_file_name)) { } @@ -1820,12 +2010,15 @@ diagnostic_output_format_init_sarif (diagnostic_context *context) void diagnostic_output_format_init_sarif_stderr (diagnostic_context *context, + const char *main_input_filename_, bool formatted) { diagnostic_output_format_init_sarif (context); - context->set_output_format (new sarif_stream_output_format (*context, - formatted, - stderr)); + context->set_output_format + (new sarif_stream_output_format (*context, + main_input_filename_, + formatted, + stderr)); } /* Populate CONTEXT in preparation for SARIF output to a file named @@ -1833,24 +2026,30 @@ diagnostic_output_format_init_sarif_stderr (diagnostic_context *context, void diagnostic_output_format_init_sarif_file (diagnostic_context *context, + const char *main_input_filename_, bool formatted, const char *base_file_name) { diagnostic_output_format_init_sarif (context); - context->set_output_format (new sarif_file_output_format (*context, - formatted, - base_file_name)); + context->set_output_format + (new sarif_file_output_format (*context, + main_input_filename_, + formatted, + base_file_name)); } /* Populate CONTEXT in preparation for SARIF output to STREAM. */ void diagnostic_output_format_init_sarif_stream (diagnostic_context *context, + const char *main_input_filename_, bool formatted, FILE *stream) { diagnostic_output_format_init_sarif (context); - context->set_output_format (new sarif_stream_output_format (*context, - formatted, - stream)); + context->set_output_format + (new sarif_stream_output_format (*context, + main_input_filename_, + formatted, + stream)); } diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index f27b2f1a492..1b4def06f72 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -2446,6 +2446,7 @@ diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram) void diagnostic_output_format_init (diagnostic_context *context, + const char *main_input_filename_, const char *base_file_name, enum diagnostics_output_format format, bool json_formatting) @@ -2471,11 +2472,13 @@ diagnostic_output_format_init (diagnostic_context *context, case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR: diagnostic_output_format_init_sarif_stderr (context, + main_input_filename_, json_formatting); break; case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE: diagnostic_output_format_init_sarif_file (context, + main_input_filename_, json_formatting, base_file_name); break; diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 7431f5a6e12..4632aac73c6 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -1082,6 +1082,7 @@ extern char *file_name_as_prefix (diagnostic_context *, const char *); extern char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1; extern void diagnostic_output_format_init (diagnostic_context *, + const char *main_input_filename_, const char *base_file_name, enum diagnostics_output_format, bool json_formatting); @@ -1091,11 +1092,14 @@ extern void diagnostic_output_format_init_json_file (diagnostic_context *context bool formatted, const char *base_file_name); extern void diagnostic_output_format_init_sarif_stderr (diagnostic_context *context, + const char *main_input_filename_, bool formatted); extern void diagnostic_output_format_init_sarif_file (diagnostic_context *context, + const char *main_input_filename_, bool formatted, const char *base_file_name); extern void diagnostic_output_format_init_sarif_stream (diagnostic_context *context, + const char *main_input_filename_, bool formatted, FILE *stream); diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 42b462a2ce2..906c78aaca5 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -339,8 +339,7 @@ work when configuring GCC@. @item A POSIX or SVR4 awk Necessary for creating some of the generated source files for GCC@. -If in doubt, use a recent GNU awk version, as some of the older ones -are broken. GNU awk version 3.1.5 is known to work. +If in doubt, use a recent GNU awk version. @item GNU binutils @@ -3950,7 +3949,7 @@ by specifying a @code{--with-multilib-list=} that does not list @code{gfx1100} and @code{gfx1103}. Use Newlib (4.3.0 or newer; 4.4.0 contains some improvements and git commit -7dd4eb1db (2025-03-25, post-4.4.0) fixes device console output for GFX10 and +7dd4eb1db (2024-03-25, post-4.4.0) fixes device console output for GFX10 and GFX11 devices). To run the binaries, install the HSA Runtime from the diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 691fb09d32e..a0b37564646 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -496,6 +496,7 @@ Objective-C and Objective-C++ Dialects}. -Wno-analyzer-tainted-size -Wanalyzer-symbol-too-complex -Wanalyzer-too-complex +-Wno-analyzer-undefined-behavior-ptrdiff -Wno-analyzer-undefined-behavior-strtok -Wno-analyzer-unsafe-call-within-signal-handler -Wno-analyzer-use-after-free @@ -733,7 +734,7 @@ Objective-C and Objective-C++ Dialects}. -freg-struct-return -fshort-enums -fshort-wchar -fverbose-asm -fpack-struct[=@var{n}] -fleading-underscore -ftls-model=@var{model} --fstack-reuse=@var{reuse_level} -fstack-use-cumulative-args +-fstack-reuse=@var{reuse_level} -ftrampolines -ftrampoline-impl=@r{[}stack@r{|}heap@r{]} -ftrapv -fwrapv -fvisibility=@r{[}default@r{|}internal@r{|}hidden@r{|}protected@r{]} @@ -955,7 +956,7 @@ Objective-C and Objective-C++ Dialects}. -twolevel_namespace -umbrella -undefined -unexported_symbols_list -weak_reference_mismatches -whatsloaded -F -gused -gfull -mmacosx-version-min=@var{version} --mkernel -mone-byte-bool -munreachable-traps} +-mkernel -mone-byte-bool} @emph{DEC Alpha Options} @gccoptlist{-mno-fp-regs -msoft-float @@ -10766,6 +10767,7 @@ Enabling this option effectively enables the following warnings: -Wanalyzer-tainted-divisor -Wanalyzer-tainted-offset -Wanalyzer-tainted-size +-Wanalyzer-undefined-behavior-ptrdiff -Wanalyzer-undefined-behavior-strtok -Wanalyzer-unsafe-call-within-signal-handler -Wanalyzer-use-after-free @@ -11416,6 +11418,20 @@ attacker could inject an out-of-bounds access. See @uref{https://cwe.mitre.org/data/definitions/129.html, CWE-129: Improper Validation of Array Index}. +@opindex Wanalyzer-undefined-behavior-ptrdiff +@opindex Wno-analyzer-undefined-behavior-ptrdiff +@item -Wno-analyzer-undefined-behavior-ptrdiff +This warning requires @option{-fanalyzer}, which enables it; use +@option{-Wno-analyzer-undefined-behavior-ptrdiff} to disable it. + +This diagnostic warns for paths through the code in which a pointer +subtraction occurs where the pointers refer to different chunks of +memory. Such code relies on undefined behavior, as pointer subtraction +is only defined for cases where both pointers point to within (or just +after) the same array. + +See @uref{https://cwe.mitre.org/data/definitions/469.html, CWE-469: Use of Pointer Subtraction to Determine Size}. + @opindex Wanalyzer-undefined-behavior-strtok @opindex Wno-analyzer-undefined-behavior-strtok @item -Wno-analyzer-undefined-behavior-strtok @@ -19193,17 +19209,6 @@ the behavior of older compilers in which temporaries' stack space is not reused, the aggressive stack reuse can lead to runtime errors. This option is used to control the temporary stack reuse optimization. -@opindex fstack_use_cumulative_args -@item -fstack-use-cumulative-args -This option instructs the compiler to use the -@code{cumulative_args_t}-based stack layout target hooks, -@code{TARGET_FUNCTION_ARG_BOUNDARY_CA} and -@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA}. If a given target does -not define these hooks, the default behaviour is to fallback to using -the standard non-@code{_CA} variants instead. Certain targets (such as -AArch64 Darwin) require using the more advanced @code{_CA}-based -hooks: For these targets this option should be enabled by default. - @opindex ftrapv @item -ftrapv This option generates traps for signed overflow on addition, subtraction, @@ -25223,11 +25228,6 @@ without that switch. Using this switch may require recompiling all other modules in a program, including system libraries. Use this switch to conform to a non-default data model. -@opindex munreachable-traps -@item -munreachable-traps -Causes @code{__builtin_unreachable} to be rendered as a trap. This is the -default for all Darwin architectures. - @opindex mfix-and-continue @opindex ffix-and-continue @opindex findirect-data @@ -31120,6 +31120,23 @@ Do not or do generate unaligned memory accesses. The default is set depending on whether the processor we are optimizing for supports fast unaligned access or not. +@opindex mscalar-strict-align +@opindex mno-scalar-strict-align +@item -mscalar-strict-align +@itemx -mno-scalar-strict-align +Do not or do generate unaligned memory accesses. The default is set depending +on whether the processor we are optimizing for supports fast unaligned access +or not. This is an alias for @option{-mstrict-align}. + +@opindex mvector-strict-align +@opindex mno-vector-strict-align +@item -mvector-strict-align +@itemx -mno-vector-strict-align +Do not or do generate unaligned vector memory accesses. The default is set +to off unless the processor we are optimizing for explicitly supports +element-misaligned vector memory access. + + @opindex mcmodel= @opindex mcmodel=medlow @item -mcmodel=medlow @@ -34824,8 +34841,10 @@ instruction set support. @item lujiazui ZHAOXIN lujiazui CPU with x86-64, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, -SSE4.2, AVX, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, CX16, -ABM, BMI, BMI2, F16C, FXSR, RDSEED instruction set support. +SSE4.2, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, CX16, +ABM, BMI, BMI2, FXSR, RDSEED instruction set support. While the CPUs +do support AVX and F16C, these aren't enabled by @code{-march=lujiazui} +for performance reasons. @item yongfeng ZHAOXIN yongfeng CPU with x86-64, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, @@ -37761,6 +37780,23 @@ installed. Specifying the language as one of these variants also inhibits output of the object file, as header files have no associated object file. +Header units can be used in much the same way as precompiled headers +(@pxref{Precompiled Headers}), but with fewer restrictions: an +#include that is translated to a header unit import can appear at any +point in the source file, and multiple header units can be used +together. In particular, the @option{-include} strategy works: with +the bits/stdc++.h header used for libstdc++ precompiled headers you +can + +@smallexample +g++ -fmodules-ts -x c++-system-header -c bits/stdc++.h +g++ -fmodules-ts -include bits/stdc++.h mycode.C +@end smallexample + +and any standard library #includes in mycode.C will be skipped, +because the import brought in the whole library. This can be a simple +way to use modules to speed up compilation without any code changes. + The @option{-fmodule-only} option disables generation of the associated object file for compiling a module interface. Only the CMI is generated. This option is implied when using the diff --git a/gcc/doc/match-and-simplify.texi b/gcc/doc/match-and-simplify.texi index 01f19e2f62c..63d5af159f5 100644 --- a/gcc/doc/match-and-simplify.texi +++ b/gcc/doc/match-and-simplify.texi @@ -361,6 +361,22 @@ Usually the types of the generated result expressions are determined from the context, but sometimes like in the above case it is required that you specify them explicitly. +Another modifier for generated expressions is @code{^} which +tells the machinery to try more matches for some special cases. +For example, normally the @code{cond} only allows the gimple +assign when matching. It will also try to match the gimple @code{PHI} +besides gimple assign if appending the @code{^} to the @code{cond}. +Aka @code{cond^}. Consider below example + +@smallexample +(match (unsigned_sat_add @@0 @@1) + (cond^ (ge (plus:c@@2 @@0 @@1) @@0) @@2 integer_minus_onep)) +@end smallexample + +The above matching will generate the predicate function named +@code{gimple_unsigned_sat_add} that accepts both the gimple +assign and gimple @code{PHI}. + Another modifier for generated expressions is @code{!} which tells the machinery to only consider the simplification in case the marked expression simplified to a simple operand. Consider diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 00df8aeb6b4..8a7aa70d605 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1066,10 +1066,6 @@ also define the hook to @code{default_promote_function_mode_always_promote} if you would like to apply the same rules given by @code{PROMOTE_MODE}. @end deftypefn -@deftypefn {Target Hook} machine_mode TARGET_PROMOTE_FUNCTION_MODE_CA (cumulative_args_t, @var{function_arg_info}, @var{const_tree}, int *@var{}, @var{int}) -Like @code{promote_function_mode}, but takes a cumulative_args pointer and a current arg to supply the input. -@end deftypefn - @defmac PARM_BOUNDARY Normal alignment required for function parameters on the stack, in bits. All stack parameters receive at least this much alignment @@ -4475,16 +4471,6 @@ with the specified mode and type. The default hook returns @code{PARM_BOUNDARY} for all arguments. @end deftypefn -@deftypefn {Target Hook} {unsigned int} TARGET_FUNCTION_ARG_BOUNDARY_CA (machine_mode @var{mode}, const_tree @var{type}, cumulative_args_t @var{ca}) -This is the @code{cumulative_args_t}-based version of -@code{TARGET_FUNCTION_ARG_BOUNDARY}. Define this hook if you need more -fine-grained control over argument alignment, e.g. depending on whether -it is a named argument or not, or any other criteria that you choose to -place in the @var{ca} structure. - -The default hook will call @code{TARGET_FUNCTION_ARG_BOUNDARY}. -@end deftypefn - @deftypefn {Target Hook} {unsigned int} TARGET_FUNCTION_ARG_ROUND_BOUNDARY (machine_mode @var{mode}, const_tree @var{type}) Normally, the size of an argument is rounded up to @code{PARM_BOUNDARY}, which is the default value for this hook. You can define this hook to @@ -4492,16 +4478,6 @@ return a different value if an argument size must be rounded to a larger value. @end deftypefn -@deftypefn {Target Hook} {unsigned int} TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA (machine_mode @var{mode}, const_tree @var{type}, cumulative_args_t @var{ca}) -This is the @code{cumulative_args_t}-based version of -@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. Define this hook if you need more -fine-grained control over argument size rounding, e.g. depending on whether -it is a named argument or not, or any other criteria that you choose to -place in the @var{ca} structure. - -The default hook will call @code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. -@end deftypefn - @defmac FUNCTION_ARG_REGNO_P (@var{regno}) A C expression that is nonzero if @var{regno} is the number of a hard register in which function arguments are sometimes passed. This does @@ -5581,6 +5557,13 @@ except the last are treated as named. You need not define this hook if it always returns @code{false}. @end deftypefn +@deftypefn {Target Hook} int TARGET_CALL_OFFSET_RETURN_LABEL (rtx_insn *@var{call_insn}) +While generating call-site debug info for a CALL insn, or a SEQUENCE +insn starting with a CALL, this target hook is invoked to compute the +offset to be added to the debug label emitted after the call to obtain +the return address that should be recorded as the return PC. +@end deftypefn + @deftypefn {Target Hook} void TARGET_START_CALL_ARGS (cumulative_args_t @var{complete_args}) This target hook is invoked while generating RTL for a function call, after the argument values have been computed, and after stack arguments @@ -12733,11 +12716,6 @@ This target hook can be used to generate a target-specific code If selftests are enabled, run any selftests for this target. @end deftypefn -@deftypefn {Target Hook} bool TARGET_UNREACHABLE_SHOULD_TRAP (void) -This hook should return @code{true} if the target wants @code{__builtin_unreachable} to expand to a trap or @code{abort ()}. - The default value is false. -@end deftypefn - @deftypefn {Target Hook} bool TARGET_MEMTAG_CAN_TAG_ADDRESSES () True if the backend architecture naturally supports ignoring some region of pointers. This feature means that @option{-fsanitize=hwaddress} can diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 0ded0f992d4..9e0830758ae 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -949,8 +949,6 @@ applied. @hook TARGET_PROMOTE_FUNCTION_MODE -@hook TARGET_PROMOTE_FUNCTION_MODE_CA - @defmac PARM_BOUNDARY Normal alignment required for function parameters on the stack, in bits. All stack parameters receive at least this much alignment @@ -3443,12 +3441,8 @@ required. @hook TARGET_FUNCTION_ARG_BOUNDARY -@hook TARGET_FUNCTION_ARG_BOUNDARY_CA - @hook TARGET_FUNCTION_ARG_ROUND_BOUNDARY -@hook TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA - @defmac FUNCTION_ARG_REGNO_P (@var{regno}) A C expression that is nonzero if @var{regno} is the number of a hard register in which function arguments are sometimes passed. This does @@ -3893,6 +3887,8 @@ These machine description macros help implement varargs: @hook TARGET_STRICT_ARGUMENT_NAMING +@hook TARGET_CALL_OFFSET_RETURN_LABEL + @hook TARGET_START_CALL_ARGS @hook TARGET_CALL_ARGS @@ -8105,8 +8101,6 @@ maintainer is familiar with. @hook TARGET_RUN_TARGET_SELFTESTS -@hook TARGET_UNREACHABLE_SHOULD_TRAP - @hook TARGET_MEMTAG_CAN_TAG_ADDRESSES @hook TARGET_MEMTAG_TAG_SIZE diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index 5b064ffd78a..f90f7b1cfef 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -3593,7 +3593,7 @@ typedef struct var_loc_list_def var_loc_list; /* Call argument location list. */ struct GTY ((chain_next ("%h.next"))) call_arg_loc_node { - rtx GTY (()) call_arg_loc_note; + rtx_insn * GTY (()) call_insn; const char * GTY (()) label; tree GTY (()) block; bool tail_call_p; @@ -3777,7 +3777,8 @@ static void remove_addr_table_entry (addr_table_entry *); static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx, bool); static inline rtx AT_addr (dw_attr_node *); static void add_AT_symview (dw_die_ref, enum dwarf_attribute, const char *); -static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *); +static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *, + int = 0); static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *); static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *); static void add_AT_range_list (dw_die_ref, enum dwarf_attribute, @@ -5353,14 +5354,17 @@ add_AT_symview (dw_die_ref die, enum dwarf_attribute attr_kind, static inline void add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind, - const char *lbl_id) + const char *lbl_id, int offset) { dw_attr_node attr; attr.dw_attr = attr_kind; attr.dw_attr_val.val_class = dw_val_class_lbl_id; attr.dw_attr_val.val_entry = NULL; - attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); + if (!offset) + attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); + else + attr.dw_attr_val.v.val_lbl_id = xasprintf ("%s%+i", lbl_id, offset); if (dwarf_split_debug_info) attr.dw_attr_val.val_entry = add_addr_table_entry (attr.dw_attr_val.v.val_lbl_id, @@ -19383,7 +19387,7 @@ loc_list_from_tree_1 (tree loc, int want_address, case ROUND_DIV_EXPR: if (TYPE_UNSIGNED (TREE_TYPE (loc))) { - enum machine_mode mode = TYPE_MODE (TREE_TYPE (loc)); + const enum machine_mode mode = TYPE_MODE (TREE_TYPE (loc)); scalar_int_mode int_mode; if ((dwarf_strict && dwarf_version < 5) @@ -19518,6 +19522,15 @@ loc_list_from_tree_1 (tree loc, int want_address, do_comp_binop: if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) { + const enum machine_mode mode + = TYPE_MODE (TREE_TYPE (TREE_OPERAND (loc, 0))); + scalar_int_mode int_mode; + + /* We can use a signed comparison if the sign bit is not set. */ + if (is_a (mode, &int_mode) + && GET_MODE_SIZE (int_mode) < DWARF2_ADDR_SIZE) + goto do_binop; + list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context); list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context); list_ret = loc_list_from_uint_comparison (list_ret, list_ret1, @@ -19544,6 +19557,7 @@ loc_list_from_tree_1 (tree loc, int want_address, add_loc_list (&list_ret, list_ret1); if (list_ret == 0) return 0; + add_loc_descr_to_each (list_ret, new_loc_descr (op, 0, 0)); break; @@ -19668,6 +19682,28 @@ loc_list_from_tree_1 (tree loc, int want_address, if (!ret && !list_ret) return 0; + /* Implement wrap-around arithmetics for small integer types. */ + if ((TREE_CODE (loc) == PLUS_EXPR + || TREE_CODE (loc) == MINUS_EXPR + || TREE_CODE (loc) == MULT_EXPR + || TREE_CODE (loc) == NEGATE_EXPR + || TREE_CODE (loc) == LSHIFT_EXPR) + && INTEGRAL_TYPE_P (TREE_TYPE (loc)) + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (loc))) + { + const enum machine_mode mode = TYPE_MODE (TREE_TYPE (loc)); + scalar_int_mode int_mode; + + if (is_a (mode, &int_mode) + && GET_MODE_SIZE (int_mode) < DWARF2_ADDR_SIZE) + { + const unsigned HOST_WIDE_INT mask + = (HOST_WIDE_INT_1U << GET_MODE_BITSIZE (int_mode)) - 1; + add_loc_descr_to_each (list_ret, uint_loc_descriptor (mask)); + add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_and, 0, 0)); + } + } + if (want_address == 2 && !have_address && (dwarf_version >= 4 || !dwarf_strict)) { @@ -23515,7 +23551,9 @@ gen_call_site_die (tree decl, dw_die_ref subr_die, if (stmt_die == NULL) stmt_die = subr_die; die = new_die (dwarf_TAG (DW_TAG_call_site), stmt_die, NULL_TREE); - add_AT_lbl_id (die, dwarf_AT (DW_AT_call_return_pc), ca_loc->label); + add_AT_lbl_id (die, dwarf_AT (DW_AT_call_return_pc), + ca_loc->label, + targetm.calls.call_offset_return_label (ca_loc->call_insn)); if (ca_loc->tail_call_p) add_AT_flag (die, dwarf_AT (DW_AT_call_tail_call), 1); if (ca_loc->symbol_ref) @@ -24202,11 +24240,14 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) { dw_die_ref die = NULL; rtx tloc = NULL_RTX, tlocc = NULL_RTX; + rtx call_arg_loc_note + = find_reg_note (ca_loc->call_insn, + REG_CALL_ARG_LOCATION, NULL_RTX); rtx arg, next_arg; tree arg_decl = NULL_TREE; - for (arg = (ca_loc->call_arg_loc_note != NULL_RTX - ? XEXP (ca_loc->call_arg_loc_note, 0) + for (arg = (call_arg_loc_note != NULL_RTX + ? XEXP (call_arg_loc_note, 0) : NULL_RTX); arg; arg = next_arg) { @@ -28251,8 +28292,7 @@ create_label: = ggc_cleared_alloc (); rtx_insn *prev = call_insn; - ca_loc->call_arg_loc_note - = find_reg_note (call_insn, REG_CALL_ARG_LOCATION, NULL_RTX); + ca_loc->call_insn = call_insn; ca_loc->next = NULL; ca_loc->label = last_label; gcc_assert (prev diff --git a/gcc/exec-tool.in b/gcc/exec-tool.in index ec1a144e415..7d152e083a7 100644 --- a/gcc/exec-tool.in +++ b/gcc/exec-tool.in @@ -23,8 +23,6 @@ ORIGINAL_AS_FOR_TARGET="@ORIGINAL_AS_FOR_TARGET@" ORIGINAL_LD_FOR_TARGET="@ORIGINAL_LD_FOR_TARGET@" ORIGINAL_LD_BFD_FOR_TARGET="@ORIGINAL_LD_BFD_FOR_TARGET@" ORIGINAL_LD_GOLD_FOR_TARGET="@ORIGINAL_LD_GOLD_FOR_TARGET@" -ORIGINAL_LLD_FOR_TARGET="@ORIGINAL_LLD_FOR_TARGET@" -ORIGINAL_CLASSIC_LD_FOR_TARGET="@ORIGINAL_CLASSIC_LD_FOR_TARGET@" ORIGINAL_PLUGIN_LD_FOR_TARGET="@ORIGINAL_PLUGIN_LD_FOR_TARGET@" ORIGINAL_NM_FOR_TARGET="@ORIGINAL_NM_FOR_TARGET@" ORIGINAL_DSYMUTIL_FOR_TARGET="@ORIGINAL_DSYMUTIL_FOR_TARGET@" @@ -41,41 +39,24 @@ case "$invoked" in dir=gas ;; collect-ld) - # when using a linker plugin, gcc will always pass '-plugin' as the - # first or second option to the linker. - if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then - original=$ORIGINAL_PLUGIN_LD_FOR_TARGET - else - original=$ORIGINAL_LD_FOR_TARGET - fi - # Check -fuse-ld=bfd, -fuse-ld=gold and -fuse-ld=classic - # Remove -fuse-ld=classic from the command line - for arg do - # temporarily, remove the arg. - shift - case $arg in - -fuse-ld=bfd) - original=$ORIGINAL_LD_BFD_FOR_TARGET - ;; - -fuse-ld=gold) - original=$ORIGINAL_LD_GOLD_FOR_TARGET - ;; - -fuse-ld=lld) - original=$ORIGINAL_LLD_FOR_TARGET - # We want to remove this from the command line; by the slightly - # obtuse mechanism of not putting it back. - continue - ;; - -fuse-ld=classic) - original=$ORIGINAL_CLASSIC_LD_FOR_TARGET - # As for lld. - continue - ;; - *) ;; - esac - # if we want to keep the arg, put it back. - set -- "$@" "$arg" - done + # Check -fuse-ld=bfd and -fuse-ld=gold + case " $* " in + *\ -fuse-ld=bfd\ *) + original=$ORIGINAL_LD_BFD_FOR_TARGET + ;; + *\ -fuse-ld=gold\ *) + original=$ORIGINAL_LD_GOLD_FOR_TARGET + ;; + *) + # when using a linker plugin, gcc will always pass '-plugin' as the + # first or second option to the linker. + if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then + original=$ORIGINAL_PLUGIN_LD_FOR_TARGET + else + original=$ORIGINAL_LD_FOR_TARGET + fi + ;; + esac prog=ld-new$exeext if test "$original" = ../gold/ld-new$exeext; then dir=gold diff --git a/gcc/explow.cc b/gcc/explow.cc index ab5e9819117..8e5f6b8e680 100644 --- a/gcc/explow.cc +++ b/gcc/explow.cc @@ -37,7 +37,6 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "except.h" #include "dojump.h" -#include "calls.h" #include "explow.h" #include "expr.h" #include "stringpool.h" @@ -818,16 +817,6 @@ promote_function_mode (const_tree type, machine_mode mode, int *punsignedp, return mode; } } - -machine_mode -promote_function_mode (cumulative_args_t args_so_far, function_arg_info arg, - const_tree funtype, int *punsignedp , int for_return) -{ - return targetm.calls.promote_function_mode_ca (args_so_far, arg, funtype, - punsignedp, for_return); -// return promote_function_mode (arg.type, arg.mode, punsignedp, funtype, for_return); -} - /* Return the mode to use to store a scalar of TYPE and MODE. PUNSIGNEDP points to the signedness of the type and may be adjusted to show what signedness to use on extension operations. */ diff --git a/gcc/explow.h b/gcc/explow.h index 6cc989798be..16aa02cfb68 100644 --- a/gcc/explow.h +++ b/gcc/explow.h @@ -20,8 +20,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_EXPLOW_H #define GCC_EXPLOW_H -#include "calls.h" /* for cummulative args stuff. */ - /* Return a memory reference like MEMREF, but which is known to have a valid address. */ extern rtx validize_mem (rtx); @@ -49,13 +47,8 @@ extern rtx force_not_mem (rtx); /* Return mode and signedness to use when an argument or result in the given mode is promoted. */ -machine_mode promote_function_mode (const_tree, machine_mode, int *, - const_tree, int); - -/* Return mode and signedness to use when an argument or result in the - given mode is promoted. */ -machine_mode promote_function_mode (cumulative_args_t, function_arg_info, - const_tree, int *, int); +extern machine_mode promote_function_mode (const_tree, machine_mode, int *, + const_tree, int); /* Return mode and signedness to use when an object in the given mode is promoted. */ diff --git a/gcc/flag-types.h b/gcc/flag-types.h index 5a2b461fa75..1e497f0bb91 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -396,7 +396,8 @@ enum lto_partition_model { LTO_PARTITION_ONE = 1, LTO_PARTITION_BALANCED = 2, LTO_PARTITION_1TO1 = 3, - LTO_PARTITION_MAX = 4 + LTO_PARTITION_MAX = 4, + LTO_PARTITION_CACHE = 5 }; /* flag_lto_linker_output initialization values. */ diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 7b268964acc..710d697c021 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -177,7 +177,7 @@ minmax_from_comparison (tree_code cmp, tree exp0, tree exp1, tree exp2, tree exp /* a != MIN_RANGE ? a : MIN_RANGE+1 -> MAX_EXPR+1, a> */ if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME) { - value_range r; + int_range_max r; get_range_query (cfun)->range_of_expr (r, exp0); if (r.undefined_p ()) r.set_varying (TREE_TYPE (exp0)); @@ -199,7 +199,7 @@ minmax_from_comparison (tree_code cmp, tree exp0, tree exp1, tree exp2, tree exp /* a != MAX_RANGE ? a : MAX_RANGE-1 -> MIN_EXPR-1, a> */ if (cmp == NE_EXPR && TREE_CODE (exp0) == SSA_NAME) { - value_range r; + int_range_max r; get_range_query (cfun)->range_of_expr (r, exp0); if (r.undefined_p ()) r.set_varying (TREE_TYPE (exp0)); @@ -2246,7 +2246,18 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg if (! overflow) val = real_to_integer (&r, &overflow, TYPE_PRECISION (type)); - t = force_fit_type (type, val, -1, overflow | TREE_OVERFLOW (arg1)); + /* According to IEEE standard, for conversions from floating point to + integer. When a NaN or infinite operand cannot be represented in the + destination format and this cannot otherwise be indicated, the invalid + operation exception shall be signaled. When a numeric operand would + convert to an integer outside the range of the destination format, the + invalid operation exception shall be signaled if this situation cannot + otherwise be indicated. */ + if (!flag_trapping_math || !overflow) + t = force_fit_type (type, val, -1, overflow | TREE_OVERFLOW (arg1)); + else + t = NULL_TREE; + return t; } @@ -15241,7 +15252,6 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_FFS: CASE_CFN_PARITY: CASE_CFN_POPCOUNT: - CASE_CFN_CLZ: CASE_CFN_CLRSB: case CFN_BUILT_IN_BSWAP16: case CFN_BUILT_IN_BSWAP32: @@ -15250,6 +15260,12 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, /* Always true. */ return true; + CASE_CFN_CLZ: + CASE_CFN_CTZ: + if (arg1) + return RECURSE (arg1); + return true; + CASE_CFN_SQRT: CASE_CFN_SQRT_FN: /* sqrt(-0.0) is -0.0. */ @@ -15327,8 +15343,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, non-negative if both operands are non-negative. In the presence of qNaNs, we're non-negative if either operand is non-negative and can't be a qNaN, or if both operands are non-negative. */ - if (tree_expr_maybe_signaling_nan_p (arg0) || - tree_expr_maybe_signaling_nan_p (arg1)) + if (tree_expr_maybe_signaling_nan_p (arg0) + || tree_expr_maybe_signaling_nan_p (arg1)) return RECURSE (arg0) && RECURSE (arg1); return RECURSE (arg0) ? (!tree_expr_maybe_nan_p (arg0) || RECURSE (arg1)) @@ -15427,8 +15443,8 @@ tree_invalid_nonnegative_warnv_p (tree t, bool *strict_overflow_p, int depth) case CALL_EXPR: { - tree arg0 = call_expr_nargs (t) > 0 ? CALL_EXPR_ARG (t, 0) : NULL_TREE; - tree arg1 = call_expr_nargs (t) > 1 ? CALL_EXPR_ARG (t, 1) : NULL_TREE; + tree arg0 = call_expr_nargs (t) > 0 ? CALL_EXPR_ARG (t, 0) : NULL_TREE; + tree arg1 = call_expr_nargs (t) > 1 ? CALL_EXPR_ARG (t, 1) : NULL_TREE; return tree_call_nonnegative_warnv_p (TREE_TYPE (t), get_call_combined_fn (t), diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 4e3dba6337d..4ef3e119f5d 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,87 @@ +2024-06-05 Jakub Jelinek + Frederik Harwath + Sandra Loosemore + + * gfortran.h (enum gfc_statement): Add ST_OMP_UNROLL, + ST_OMP_END_UNROLL, ST_OMP_TILE and ST_OMP_END_TILE. + (struct gfc_omp_clauses): Add sizes_list, partial, full and erroneous + members. + (enum gfc_exec_op): Add EXEC_OMP_UNROLL and EXEC_OMP_TILE. + (gfc_expr_list_len): Declare. + * match.h (gfc_match_omp_tile, gfc_match_omp_unroll): Declare. + * openmp.cc (gfc_get_location): Declare. + (gfc_free_omp_clauses): Free sizes_list. + (match_oacc_expr_list): Rename to ... + (match_omp_oacc_expr_list): ... this. Add is_omp argument and + change diagnostic wording if it is true. + (enum omp_mask2): Add OMP_CLAUSE_{FULL,PARTIAL,SIZES}. + (gfc_match_omp_clauses): Parse full, partial and sizes clauses. + (gfc_match_oacc_wait): Use match_omp_oacc_expr_list instead of + match_oacc_expr_list. + (OMP_UNROLL_CLAUSES, OMP_TILE_CLAUSES): Define. + (gfc_match_omp_tile, gfc_match_omp_unroll): New functions. + (resolve_omp_clauses): Diagnose full vs. partial clause conflict. + Resolve sizes clause arguments. + (find_nested_loop_in_chain): Use switch instead of series of ifs. + Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL. + (gfc_resolve_omp_do_blocks): Set omp_current_do_collapse to + list length of sizes_list if present. + (gfc_resolve_do_iterator): Return for EXEC_OMP_TILE or + EXEC_OMP_UNROLL. + (restructure_intervening_code): Remove spurious ()s around & operands. + (is_outer_iteration_variable): Handle EXEC_OMP_TILE and + EXEC_OMP_UNROLL. + (check_nested_loop_in_chain): Likewise. + (expr_is_invariant): Likewise. + (resolve_omp_do): Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL. Diagnose + tile without sizes clause. Use sizes_list length for count if + non-NULL. Set code->ext.omp_clauses->erroneous on loops where we've + reported diagnostics. Sorry for mixing non-rectangular loops with + generated loops. + (omp_code_to_statement): Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL. + (gfc_resolve_omp_directive): Likewise. + * parse.cc (decode_omp_directive): Parse end tile, end unroll, tile + and unroll. Move nothing entry alphabetically. + (case_exec_markers): Add ST_OMP_TILE and ST_OMP_UNROLL. + (gfc_ascii_statement): Handle ST_OMP_END_TILE, ST_OMP_END_UNROLL, + ST_OMP_TILE and ST_OMP_UNROLL. + (parse_omp_do): Add nested argument. Handle ST_OMP_TILE and + ST_OMP_UNROLL. + (parse_omp_structured_block): Adjust parse_omp_do caller. + (parse_executable): Likewise. Handle ST_OMP_TILE and ST_OMP_UNROLL. + * resolve.cc (gfc_resolve_blocks): Handle EXEC_OMP_TILE and + EXEC_OMP_UNROLL. + (gfc_resolve_code): Likewise. + * st.cc (gfc_free_statement): Likewise. + * trans.cc (trans_code): Likewise. + * trans-openmp.cc (gfc_trans_omp_clauses): Handle full, partial and + sizes clauses. Use tree_cons + nreverse instead of + temporary vector and build_tree_list_vec for tile_list handling. + (gfc_expr_list_len): New function. + (gfc_trans_omp_do): Rename tile to oacc_tile. Handle sizes clause. + Don't assert code->op is EXEC_DO. Handle EXEC_OMP_TILE and + EXEC_OMP_UNROLL. + (gfc_trans_omp_directive): Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL. + * dump-parse-tree.cc (show_omp_clauses): Dump full, partial and + sizes clauses. + (show_omp_node): Handle EXEC_OMP_TILE and EXEC_OMP_UNROLL. + (show_code_node): Likewise. + +2024-06-05 Kewen Lin + + * trans-intrinsic.cc (build_round_expr): Use TYPE_PRECISION of + long_double_type_node to replace LONG_DOUBLE_TYPE_SIZE. + * trans-types.cc (gfc_build_real_type): Use TYPE_PRECISION of + {float,double,long_double}_type_node to replace + {FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE. + +2024-06-04 Harald Anlauf + + PR fortran/83865 + * trans-stmt.cc (gfc_trans_allocate): Restrict special case for + source-expression with zero-length character to rank 0, so that + the array shape is not discarded. + 2024-05-29 Andre Vehreschild PR fortran/90069 diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc index 87a65036a3d..80aa8ef84e7 100644 --- a/gcc/fortran/dump-parse-tree.cc +++ b/gcc/fortran/dump-parse-tree.cc @@ -2119,6 +2119,26 @@ show_omp_clauses (gfc_omp_clauses *omp_clauses) } if (omp_clauses->assume) show_omp_assumes (omp_clauses->assume); + if (omp_clauses->full) + fputs (" FULL", dumpfile); + if (omp_clauses->partial) + { + fputs (" PARTIAL", dumpfile); + if (omp_clauses->partial > 0) + fprintf (dumpfile, "(%d)", omp_clauses->partial); + } + if (omp_clauses->sizes_list) + { + gfc_expr_list *sizes; + fputs (" SIZES(", dumpfile); + for (sizes = omp_clauses->sizes_list; sizes; sizes = sizes->next) + { + show_expr (sizes->expr); + if (sizes->next) + fputs (", ", dumpfile); + } + fputc (')', dumpfile); + } } /* Show a single OpenMP or OpenACC directive node and everything underneath it @@ -2231,6 +2251,8 @@ show_omp_node (int level, gfc_code *c) name = "TEAMS DISTRIBUTE PARALLEL DO SIMD"; break; case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: name = "TEAMS DISTRIBUTE SIMD"; break; case EXEC_OMP_TEAMS_LOOP: name = "TEAMS LOOP"; break; + case EXEC_OMP_TILE: name = "TILE"; break; + case EXEC_OMP_UNROLL: name = "UNROLL"; break; case EXEC_OMP_WORKSHARE: name = "WORKSHARE"; break; default: gcc_unreachable (); @@ -2309,6 +2331,8 @@ show_omp_node (int level, gfc_code *c) case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: case EXEC_OMP_TEAMS_LOOP: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: case EXEC_OMP_WORKSHARE: omp_clauses = c->ext.omp_clauses; break; @@ -3559,6 +3583,8 @@ show_code_node (int level, gfc_code *c) case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: case EXEC_OMP_TEAMS_LOOP: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: case EXEC_OMP_WORKSHARE: show_omp_node (level, c); break; diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index a162744c719..be138d196a2 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -5573,11 +5573,14 @@ bool gfc_is_alloc_class_scalar_function (gfc_expr *expr) { if (expr->expr_type == EXPR_FUNCTION - && expr->value.function.esym - && expr->value.function.esym->result - && expr->value.function.esym->result->ts.type == BT_CLASS - && !CLASS_DATA (expr->value.function.esym->result)->attr.dimension - && CLASS_DATA (expr->value.function.esym->result)->attr.allocatable) + && ((expr->value.function.esym + && expr->value.function.esym->result + && expr->value.function.esym->result->ts.type == BT_CLASS + && !CLASS_DATA (expr->value.function.esym->result)->attr.dimension + && CLASS_DATA (expr->value.function.esym->result)->attr.allocatable) + || (expr->ts.type == BT_CLASS + && CLASS_DATA (expr)->attr.allocatable + && !CLASS_DATA (expr)->attr.dimension))) return true; return false; diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index de1a7cd0935..36ed8eeac2d 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -321,7 +321,9 @@ enum gfc_statement ST_OMP_ALLOCATE, ST_OMP_ALLOCATE_EXEC, ST_OMP_ALLOCATORS, ST_OMP_END_ALLOCATORS, /* Note: gfc_match_omp_nothing returns ST_NONE. */ - ST_OMP_NOTHING, ST_NONE + ST_OMP_NOTHING, ST_NONE, + ST_OMP_UNROLL, ST_OMP_END_UNROLL, + ST_OMP_TILE, ST_OMP_END_TILE }; /* Types of interfaces that we can have. Assignment interfaces are @@ -1577,11 +1579,13 @@ typedef struct gfc_omp_clauses struct gfc_expr *dist_chunk_size; struct gfc_expr *message; struct gfc_omp_assumptions *assume; + struct gfc_expr_list *sizes_list; const char *critical_name; enum gfc_omp_default_sharing default_sharing; enum gfc_omp_atomic_op atomic_op; enum gfc_omp_defaultmap defaultmap[OMP_DEFAULTMAP_CAT_NUM]; int collapse, orderedc; + int partial; unsigned nowait:1, ordered:1, untied:1, mergeable:1, ancestor:1; unsigned inbranch:1, notinbranch:1, nogroup:1; unsigned sched_simd:1, sched_monotonic:1, sched_nonmonotonic:1; @@ -1591,6 +1595,7 @@ typedef struct gfc_omp_clauses unsigned non_rectangular:1, order_concurrent:1; unsigned contains_teams_construct:1, target_first_st_is_teams:1; unsigned contained_in_target_construct:1, indirect:1; + unsigned full:1, erroneous:1; ENUM_BITFIELD (gfc_omp_sched_kind) sched_kind:3; ENUM_BITFIELD (gfc_omp_device_type) device_type:2; ENUM_BITFIELD (gfc_omp_memorder) memorder:3; @@ -3033,6 +3038,7 @@ enum gfc_exec_op EXEC_OMP_TARGET_TEAMS_LOOP, EXEC_OMP_MASKED, EXEC_OMP_PARALLEL_MASKED, EXEC_OMP_PARALLEL_MASKED_TASKLOOP, EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD, EXEC_OMP_MASKED_TASKLOOP, EXEC_OMP_MASKED_TASKLOOP_SIMD, EXEC_OMP_SCOPE, + EXEC_OMP_UNROLL, EXEC_OMP_TILE, EXEC_OMP_ERROR, EXEC_OMP_ALLOCATE, EXEC_OMP_ALLOCATORS }; @@ -3958,6 +3964,9 @@ void gfc_generate_module_code (gfc_namespace *); /* trans-intrinsic.cc */ bool gfc_inline_intrinsic_function_p (gfc_expr *); +/* trans-openmp.cc */ +int gfc_expr_list_len (gfc_expr_list *); + /* bbt.cc */ typedef int (*compare_fn) (void *, void *); void gfc_insert_bbt (void *, void *, compare_fn); diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h index b09921357fd..c2b7d69c37c 100644 --- a/gcc/fortran/match.h +++ b/gcc/fortran/match.h @@ -228,6 +228,8 @@ match gfc_match_omp_teams_distribute_parallel_do_simd (void); match gfc_match_omp_teams_distribute_simd (void); match gfc_match_omp_teams_loop (void); match gfc_match_omp_threadprivate (void); +match gfc_match_omp_tile (void); +match gfc_match_omp_unroll (void); match gfc_match_omp_workshare (void); match gfc_match_omp_end_critical (void); match gfc_match_omp_end_nowait (void); diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 5246647e6f8..9b30a108560 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "bitmap.h" #include "omp-api.h" /* For omp_runtime_api_procname. */ +location_t gfc_get_location (locus *); static gfc_statement omp_code_to_statement (gfc_code *); @@ -195,6 +196,7 @@ gfc_free_omp_clauses (gfc_omp_clauses *c) i == OMP_LIST_USES_ALLOCATORS); gfc_free_expr_list (c->wait_list); gfc_free_expr_list (c->tile_list); + gfc_free_expr_list (c->sizes_list); free (CONST_CAST (char *, c->critical_name)); if (c->assume) { @@ -762,8 +764,8 @@ cleanup: } static match -match_oacc_expr_list (const char *str, gfc_expr_list **list, - bool allow_asterisk) +match_omp_oacc_expr_list (const char *str, gfc_expr_list **list, + bool allow_asterisk, bool is_omp) { gfc_expr_list *head, *tail, *p; locus old_loc; @@ -815,7 +817,10 @@ match_oacc_expr_list (const char *str, gfc_expr_list **list, return MATCH_YES; syntax: - gfc_error ("Syntax error in OpenACC expression list at %C"); + if (is_omp) + gfc_error ("Syntax error in OpenMP expression list at %C"); + else + gfc_error ("Syntax error in OpenACC expression list at %C"); cleanup: gfc_free_expr_list (head); @@ -1098,6 +1103,9 @@ enum omp_mask2 OMP_CLAUSE_ASSUMPTIONS, /* OpenMP 5.1. */ OMP_CLAUSE_USES_ALLOCATORS, /* OpenMP 5.0 */ OMP_CLAUSE_INDIRECT, /* OpenMP 5.1 */ + OMP_CLAUSE_FULL, /* OpenMP 5.1. */ + OMP_CLAUSE_PARTIAL, /* OpenMP 5.1. */ + OMP_CLAUSE_SIZES, /* OpenMP 5.1. */ /* This must come last. */ OMP_MASK2_LAST }; @@ -2682,6 +2690,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, && gfc_match_motion_var_list ("from (", &c->lists[OMP_LIST_FROM], &head) == MATCH_YES) continue; + if ((mask & OMP_CLAUSE_FULL) + && (m = gfc_match_dupl_check (!c->full, "full")) != MATCH_NO) + { + if (m == MATCH_ERROR) + goto error; + c->full = needs_space = true; + continue; + } break; case 'g': if ((mask & OMP_CLAUSE_GANG) @@ -3367,6 +3383,32 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, } break; case 'p': + if (mask & OMP_CLAUSE_PARTIAL) + { + if ((m = gfc_match_dupl_check (!c->partial, "partial")) + != MATCH_NO) + { + int expr; + if (m == MATCH_ERROR) + goto error; + + c->partial = -1; + + gfc_expr *cexpr = NULL; + m = gfc_match (" ( %e )", &cexpr); + if (m == MATCH_NO) + ; + else if (m == MATCH_YES + && !gfc_extract_int (cexpr, &expr, -1) + && expr > 0) + c->partial = expr; + else + gfc_error_now ("PARTIAL clause argument not constant " + "positive integer at %C"); + gfc_free_expr (cexpr); + continue; + } + } if ((mask & OMP_CLAUSE_COPY) && gfc_match ("pcopy ( ") == MATCH_YES && gfc_match_omp_map_clause (&c->lists[OMP_LIST_MAP], @@ -3649,6 +3691,20 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, } continue; } + if ((mask & OMP_CLAUSE_SIZES) + && ((m = gfc_match_dupl_check (!c->sizes_list, "sizes")) + != MATCH_NO)) + { + if (m == MATCH_ERROR) + goto error; + m = match_omp_oacc_expr_list (" (", &c->sizes_list, false, true); + if (m == MATCH_ERROR) + goto error; + if (m == MATCH_YES) + continue; + gfc_error ("Expected %<(%> after %qs at %C", "sizes"); + goto error; + } break; case 't': if ((mask & OMP_CLAUSE_TASK_REDUCTION) @@ -3675,8 +3731,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, } if ((mask & OMP_CLAUSE_TILE) && !c->tile_list - && match_oacc_expr_list ("tile (", &c->tile_list, - true) == MATCH_YES) + && match_omp_oacc_expr_list ("tile (", &c->tile_list, + true, false) == MATCH_YES) continue; if ((mask & OMP_CLAUSE_TO) && (mask & OMP_CLAUSE_LINK)) { @@ -3772,7 +3828,7 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, if ((mask & OMP_CLAUSE_WAIT) && gfc_match ("wait") == MATCH_YES) { - m = match_oacc_expr_list (" (", &c->wait_list, false); + m = match_omp_oacc_expr_list (" (", &c->wait_list, false, false); if (m == MATCH_ERROR) goto error; else if (m == MATCH_NO) @@ -4128,7 +4184,7 @@ gfc_match_oacc_wait (void) bool space = true; match m; - m = match_oacc_expr_list (" (", &wait_list, true); + m = match_omp_oacc_expr_list (" (", &wait_list, true, false); if (m == MATCH_ERROR) return m; else if (m == MATCH_YES) @@ -4528,6 +4584,10 @@ cleanup: (omp_mask (OMP_CLAUSE_AT) | OMP_CLAUSE_MESSAGE | OMP_CLAUSE_SEVERITY) #define OMP_WORKSHARE_CLAUSES \ omp_mask (OMP_CLAUSE_NOWAIT) +#define OMP_UNROLL_CLAUSES \ + (omp_mask (OMP_CLAUSE_FULL) | OMP_CLAUSE_PARTIAL) +#define OMP_TILE_CLAUSES \ + (omp_mask (OMP_CLAUSE_SIZES)) #define OMP_ALLOCATORS_CLAUSES \ omp_mask (OMP_CLAUSE_ALLOCATE) @@ -6793,6 +6853,17 @@ gfc_match_omp_teams_distribute_simd (void) | OMP_SIMD_CLAUSES); } +match +gfc_match_omp_tile (void) +{ + return match_omp (EXEC_OMP_TILE, OMP_TILE_CLAUSES); +} + +match +gfc_match_omp_unroll (void) +{ + return match_omp (EXEC_OMP_UNROLL, OMP_UNROLL_CLAUSES); +} match gfc_match_omp_workshare (void) @@ -9182,6 +9253,9 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, gfc_error ("% clause at %L must not be used together with " "% clause", &omp_clauses->lists[OMP_LIST_REDUCTION]->where); + if (omp_clauses->full && omp_clauses->partial) + gfc_error ("% clause at %C must not be used together with " + "% clause"); if (omp_clauses->async) if (omp_clauses->async_expr) resolve_scalar_int_expr (omp_clauses->async_expr, "ASYNC"); @@ -9233,6 +9307,22 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, gfc_error ("%s must contain at least one MAP clause at %L", p, &code->loc); } + if (omp_clauses->sizes_list) + { + gfc_expr_list *el; + for (el = omp_clauses->sizes_list; el; el = el->next) + { + resolve_scalar_int_expr (el->expr, "SIZES"); + if (el->expr->expr_type != EXPR_CONSTANT) + gfc_error ("SIZES requires constant expression at %L", + &el->expr->where); + else if (el->expr->expr_type == EXPR_CONSTANT + && el->expr->ts.type == BT_INTEGER + && mpz_sgn (el->expr->value.integer) <= 0) + gfc_error ("INTEGER expression of %s clause at %L must be " + "positive", "SIZES", &el->expr->where); + } + } if (!openacc && omp_clauses->detach) { @@ -9913,16 +10003,19 @@ find_nested_loop_in_chain (gfc_code *chain) return NULL; for (code = chain; code; code = code->next) - { - if (code->op == EXEC_DO) + switch (code->op) + { + case EXEC_DO: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: return code; - else if (code->op == EXEC_BLOCK) - { - gfc_code *c = find_nested_loop_in_block (code); - if (c) - return c; - } - } + case EXEC_BLOCK: + if (gfc_code *c = find_nested_loop_in_block (code)) + return c; + break; + default: + break; + } return NULL; } @@ -9950,6 +10043,9 @@ gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns) omp_current_do_collapse = code->ext.omp_clauses->orderedc; else if (code->ext.omp_clauses->collapse) omp_current_do_collapse = code->ext.omp_clauses->collapse; + else if (code->ext.omp_clauses->sizes_list) + omp_current_do_collapse + = gfc_expr_list_len (code->ext.omp_clauses->sizes_list); else omp_current_do_collapse = 1; if (code->ext.omp_clauses->lists[OMP_LIST_REDUCTION_INSCAN]) @@ -10141,6 +10237,8 @@ gfc_resolve_do_iterator (gfc_code *code, gfc_symbol *sym, bool add_clause) if (code == c) return; c = find_nested_loop_in_chain (c->block->next); + if (c && (c->op == EXEC_OMP_TILE || c->op == EXEC_OMP_UNROLL)) + return; } /* An openacc context may represent a data clause. Abort if so. */ @@ -10439,7 +10537,7 @@ restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop, gfc_code *tail = NULL; gfc_code *innermost_loop = NULL; - for (code = *chainp; code; code = code->next, chainp = &((*chainp)->next)) + for (code = *chainp; code; code = code->next, chainp = &(*chainp)->next) { if (code->op == EXEC_DO) { @@ -10452,7 +10550,7 @@ restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop, innermost_loop = code; else innermost_loop - = restructure_intervening_code (&(code->block->next), + = restructure_intervening_code (&code->block->next, code, count - 1); break; } @@ -10467,7 +10565,7 @@ restructure_intervening_code (gfc_code **chainp, gfc_code *outer_loop, code->next = NULL; innermost_loop - = restructure_intervening_code (&(ns->code), outer_loop, + = restructure_intervening_code (&ns->code, outer_loop, count); /* At this point we have already pulled out the nested loop and @@ -10524,6 +10622,11 @@ is_outer_iteration_variable (gfc_code *code, int depth, gfc_symbol *var) { do_code = find_nested_loop_in_chain (do_code->block->next); gcc_assert (do_code); + if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL) + { + --i; + continue; + } gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym; if (var == ivar) return true; @@ -10548,6 +10651,8 @@ check_nested_loop_in_chain (gfc_code *chain, gfc_expr *expr, gfc_symbol *sym, { if (code->op == EXEC_DO) return code; + else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL) + return check_nested_loop_in_chain (code->block->next, expr, sym, bad); else if (code->op == EXEC_BLOCK) { gfc_code *c = check_nested_loop_in_block (code, expr, sym, bad); @@ -10654,6 +10759,11 @@ expr_is_invariant (gfc_code *code, int depth, gfc_expr *expr) { do_code = find_nested_loop_in_chain (do_code->block->next); gcc_assert (do_code); + if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL) + { + --i; + continue; + } gfc_symbol *ivar = do_code->ext.iterator->var->symtree->n.sym; if (gfc_find_sym_in_expr (ivar, expr)) return false; @@ -10728,13 +10838,14 @@ static void resolve_omp_do (gfc_code *code) { gfc_code *do_code, *next; - int list, i, count; + int list, i, count, non_generated_count; gfc_omp_namelist *n; gfc_symbol *dovar; const char *name; bool is_simd = false; bool errorp = false; bool perfect_nesting_errorp = false; + bool imperfect = false; switch (code->op) { @@ -10829,15 +10940,23 @@ resolve_omp_do (gfc_code *code) is_simd = true; break; case EXEC_OMP_TEAMS_LOOP: name = "!$OMP TEAMS LOOP"; break; + case EXEC_OMP_TILE: name = "!$OMP TILE"; break; + case EXEC_OMP_UNROLL: name = "!$OMP UNROLL"; break; default: gcc_unreachable (); } if (code->ext.omp_clauses) resolve_omp_clauses (code, code->ext.omp_clauses, NULL); + if (code->op == EXEC_OMP_TILE && code->ext.omp_clauses->sizes_list == NULL) + gfc_error ("SIZES clause is required on !$OMP TILE construct at %L", + &code->loc); + do_code = code->block->next; if (code->ext.omp_clauses->orderedc) count = code->ext.omp_clauses->orderedc; + else if (code->ext.omp_clauses->sizes_list) + count = gfc_expr_list_len (code->ext.omp_clauses->sizes_list); else { count = code->ext.omp_clauses->collapse; @@ -10845,6 +10964,7 @@ resolve_omp_do (gfc_code *code) count = 1; } + non_generated_count = count; /* While the spec defines the loop nest depth independently of the COLLAPSE clause, in practice the middle end only pays attention to the COLLAPSE depth and treats any further inner loops as the final-loop-body. So @@ -10858,13 +10978,61 @@ resolve_omp_do (gfc_code *code) { gfc_error ("%s cannot be a DO WHILE or DO without loop control " "at %L", name, &do_code->loc); - return; + goto fail; } if (do_code->op == EXEC_DO_CONCURRENT) { gfc_error ("%s cannot be a DO CONCURRENT loop at %L", name, &do_code->loc); - return; + goto fail; + } + if (do_code->op == EXEC_OMP_TILE || do_code->op == EXEC_OMP_UNROLL) + { + if (do_code->op == EXEC_OMP_UNROLL) + { + if (!do_code->ext.omp_clauses->partial) + { + gfc_error ("Generated loop of UNROLL construct at %L " + "without PARTIAL clause does not have " + "canonical form", &do_code->loc); + goto fail; + } + else if (i != count) + { + gfc_error ("UNROLL construct at %L with PARTIAL clause " + "generates just one loop with canonical form " + "but %d loops are needed", + &do_code->loc, count - i + 1); + goto fail; + } + } + else if (do_code->op == EXEC_OMP_TILE) + { + if (do_code->ext.omp_clauses->sizes_list == NULL) + /* This should have been diagnosed earlier already. */ + return; + int l = gfc_expr_list_len (do_code->ext.omp_clauses->sizes_list); + if (count - i + 1 > l) + { + gfc_error ("TILE construct at %L generates %d loops " + "with canonical form but %d loops are needed", + &do_code->loc, l, count - i + 1); + goto fail; + } + } + if (do_code->ext.omp_clauses && do_code->ext.omp_clauses->erroneous) + goto fail; + if (imperfect && !perfect_nesting_errorp) + { + sorry_at (gfc_get_location (&do_code->loc), + "Imperfectly nested loop using generated loops"); + errorp = true; + } + if (non_generated_count == count) + non_generated_count = i - 1; + --i; + do_code = do_code->block->next; + continue; } gcc_assert (do_code->op == EXEC_DO); if (do_code->ext.iterator->var->ts.type != BT_INTEGER) @@ -10966,7 +11134,16 @@ resolve_omp_do (gfc_code *code) errorp = true; } if (start_var || end_var) - code->ext.omp_clauses->non_rectangular = 1; + { + code->ext.omp_clauses->non_rectangular = 1; + if (i > non_generated_count) + { + sorry_at (gfc_get_location (&do_code->loc), + "Non-rectangular loops from generated loops " + "unsupported"); + errorp = true; + } + } /* Only parse loop body into nested loop and intervening code if there are supposed to be more loops in the nest to collapse. */ @@ -10980,7 +11157,7 @@ resolve_omp_do (gfc_code *code) /* Parse error, can't recover from this. */ gfc_error ("not enough DO loops for collapsed %s (level %d) at %L", name, i, &code->loc); - return; + goto fail; } else if (next != do_code->block->next || next->next) /* Imperfectly nested loop found. */ @@ -11002,22 +11179,35 @@ resolve_omp_do (gfc_code *code) name, &code->loc); perfect_nesting_errorp = true; } - /* FIXME: Also diagnose for TILE directives. */ + else if (code->op == EXEC_OMP_TILE) + { + gfc_error ("%s inner loops must be perfectly nested at %L", + name, &code->loc); + perfect_nesting_errorp = true; + } if (perfect_nesting_errorp) errorp = true; } if (diagnose_intervening_code_errors (do_code->block->next, name, next)) errorp = true; + imperfect = true; } do_code = next; } /* Give up now if we found any constraint violations. */ if (errorp) - return; + { + fail: + if (code->ext.omp_clauses) + code->ext.omp_clauses->erroneous = 1; + return; + } - restructure_intervening_code (&(code->block->next), code, count); + if (non_generated_count) + restructure_intervening_code (&code->block->next, code, + non_generated_count); } @@ -11168,6 +11358,10 @@ omp_code_to_statement (gfc_code *code) return ST_OMP_PARALLEL_LOOP; case EXEC_OMP_DEPOBJ: return ST_OMP_DEPOBJ; + case EXEC_OMP_TILE: + return ST_OMP_TILE; + case EXEC_OMP_UNROLL: + return ST_OMP_UNROLL; default: gcc_unreachable (); } @@ -11632,6 +11826,8 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns) case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: case EXEC_OMP_TEAMS_LOOP: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: resolve_omp_do (code); break; case EXEC_OMP_TARGET: diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc index 79c810c86ba..b28c8a94547 100644 --- a/gcc/fortran/parse.cc +++ b/gcc/fortran/parse.cc @@ -1006,14 +1006,22 @@ decode_omp_directive (void) case 'e': matchs ("end assume", gfc_match_omp_eos_error, ST_OMP_END_ASSUME); matchs ("end simd", gfc_match_omp_eos_error, ST_OMP_END_SIMD); + matchs ("end tile", gfc_match_omp_eos_error, ST_OMP_END_TILE); + matchs ("end unroll", gfc_match_omp_eos_error, ST_OMP_END_UNROLL); matcho ("error", gfc_match_omp_error, ST_OMP_ERROR); break; + case 'n': + matcho ("nothing", gfc_match_omp_nothing, ST_NONE); + break; case 's': matchs ("scan", gfc_match_omp_scan, ST_OMP_SCAN); matchs ("simd", gfc_match_omp_simd, ST_OMP_SIMD); break; - case 'n': - matcho ("nothing", gfc_match_omp_nothing, ST_NONE); + case 't': + matchs ("tile", gfc_match_omp_tile, ST_OMP_TILE); + break; + case 'u': + matchs ("unroll", gfc_match_omp_unroll, ST_OMP_UNROLL); break; } @@ -1916,6 +1924,7 @@ next_statement (void) case ST_OMP_LOOP: case ST_OMP_PARALLEL_LOOP: case ST_OMP_TEAMS_LOOP: \ case ST_OMP_TARGET_PARALLEL_LOOP: case ST_OMP_TARGET_TEAMS_LOOP: \ case ST_OMP_ALLOCATE_EXEC: case ST_OMP_ALLOCATORS: case ST_OMP_ASSUME: \ + case ST_OMP_TILE: case ST_OMP_UNROLL: \ case ST_CRITICAL: \ case ST_OACC_PARALLEL_LOOP: case ST_OACC_PARALLEL: case ST_OACC_KERNELS: \ case ST_OACC_DATA: case ST_OACC_HOST_DATA: case ST_OACC_LOOP: \ @@ -2786,6 +2795,12 @@ gfc_ascii_statement (gfc_statement st, bool strip_sentinel) case ST_OMP_END_TEAMS_LOOP: p = "!$OMP END TEAMS LOOP"; break; + case ST_OMP_END_TILE: + p = "!$OMP END TILE"; + break; + case ST_OMP_END_UNROLL: + p = "!$OMP END UNROLL"; + break; case ST_OMP_END_WORKSHARE: p = "!$OMP END WORKSHARE"; break; @@ -2968,6 +2983,12 @@ gfc_ascii_statement (gfc_statement st, bool strip_sentinel) case ST_OMP_THREADPRIVATE: p = "!$OMP THREADPRIVATE"; break; + case ST_OMP_TILE: + p = "!$OMP TILE"; + break; + case ST_OMP_UNROLL: + p = "!$OMP UNROLL"; + break; case ST_OMP_WORKSHARE: p = "!$OMP WORKSHARE"; break; @@ -5441,7 +5462,7 @@ loop: /* Parse the statements of OpenMP do/parallel do. */ static gfc_statement -parse_omp_do (gfc_statement omp_st) +parse_omp_do (gfc_statement omp_st, int nested) { gfc_statement st; gfc_code *cp, *np; @@ -5462,11 +5483,20 @@ parse_omp_do (gfc_statement omp_st) unexpected_eof (); else if (st == ST_DO) break; + else if (st == ST_OMP_UNROLL || st == ST_OMP_TILE) + { + st = parse_omp_do (st, nested + 1); + if (st == ST_IMPLIED_ENDDO) + return st; + goto do_end; + } else unexpected_statement (st); } parse_do_block (); + for (; nested; --nested) + pop_state (); if (gfc_statement_label != NULL && gfc_state_stack->previous != NULL && gfc_state_stack->previous->state == COMP_DO @@ -5487,6 +5517,7 @@ parse_omp_do (gfc_statement omp_st) pop_state (); st = next_statement (); +do_end: gfc_statement omp_end_st = ST_OMP_END_DO; switch (omp_st) { @@ -5570,9 +5601,9 @@ parse_omp_do (gfc_statement omp_st) case ST_OMP_TEAMS_DISTRIBUTE_SIMD: omp_end_st = ST_OMP_END_TEAMS_DISTRIBUTE_SIMD; break; - case ST_OMP_TEAMS_LOOP: - omp_end_st = ST_OMP_END_TEAMS_LOOP; - break; + case ST_OMP_TEAMS_LOOP: omp_end_st = ST_OMP_END_TEAMS_LOOP; break; + case ST_OMP_TILE: omp_end_st = ST_OMP_END_TILE; break; + case ST_OMP_UNROLL: omp_end_st = ST_OMP_END_UNROLL; break; default: gcc_unreachable (); } if (st == omp_end_st) @@ -6073,7 +6104,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) case ST_OMP_PARALLEL_DO: case ST_OMP_PARALLEL_DO_SIMD: - st = parse_omp_do (st); + st = parse_omp_do (st, 0); continue; case ST_OMP_ATOMIC: @@ -6370,7 +6401,9 @@ parse_executable (gfc_statement st) case ST_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case ST_OMP_TEAMS_DISTRIBUTE_SIMD: case ST_OMP_TEAMS_LOOP: - st = parse_omp_do (st); + case ST_OMP_TILE: + case ST_OMP_UNROLL: + st = parse_omp_do (st, 0); if (st == ST_IMPLIED_ENDDO) return st; continue; diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index d7a0856fcca..4f4fafa4217 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -11437,6 +11437,8 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns) case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case EXEC_OMP_TEAMS_LOOP: case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: case EXEC_OMP_WORKSHARE: break; @@ -12604,6 +12606,8 @@ gfc_resolve_code (gfc_code *code, gfc_namespace *ns) case EXEC_OMP_LOOP: case EXEC_OMP_SIMD: case EXEC_OMP_TARGET_SIMD: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: gfc_resolve_omp_do_blocks (code, ns); break; case EXEC_SELECT_TYPE: @@ -13102,6 +13106,8 @@ start: case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: case EXEC_OMP_TEAMS_LOOP: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: case EXEC_OMP_WORKSHARE: gfc_resolve_omp_directive (code, ns); break; diff --git a/gcc/fortran/st.cc b/gcc/fortran/st.cc index 6a605ad91d4..0218d290782 100644 --- a/gcc/fortran/st.cc +++ b/gcc/fortran/st.cc @@ -279,6 +279,8 @@ gfc_free_statement (gfc_code *p) case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: case EXEC_OMP_TEAMS_LOOP: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: case EXEC_OMP_WORKSHARE: gfc_free_omp_clauses (p->ext.omp_clauses); break; diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index eec62c296ff..cc50b961a97 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -1885,6 +1885,16 @@ gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc, gfc_conv_descriptor_data_get (desc)); tmp = gfc_build_array_ref (tmp, offset, NULL); + if (expr->expr_type == EXPR_FUNCTION && expr->ts.type == BT_DERIVED + && expr->ts.u.derived->attr.alloc_comp) + { + if (!VAR_P (se->expr)) + se->expr = gfc_evaluate_now (se->expr, &se->pre); + gfc_add_expr_to_block (&se->finalblock, + gfc_deallocate_alloc_comp_no_caf ( + expr->ts.u.derived, se->expr, expr->rank, true)); + } + if (expr->ts.type == BT_CHARACTER) { int i = gfc_validate_kind (BT_CHARACTER, expr->ts.kind, false); @@ -2147,6 +2157,8 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, *poffset = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, *poffset, gfc_index_one_node); + if (finalblock) + gfc_add_block_to_block (finalblock, &se.finalblock); } else { @@ -2795,6 +2807,7 @@ trans_array_constructor (gfc_ss * ss, locus * where) tree neg_len; char *msg; stmtblock_t finalblock; + bool finalize_required; /* Save the old values for nested checking. */ old_first_len = first_len; @@ -2973,8 +2986,11 @@ trans_array_constructor (gfc_ss * ss, locus * where) TREE_USED (offsetvar) = 0; gfc_init_block (&finalblock); + finalize_required = expr->must_finalize; + if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp) + finalize_required = true; gfc_trans_array_constructor_value (&outer_loop->pre, - expr->must_finalize ? &finalblock : NULL, + finalize_required ? &finalblock : NULL, type, desc, c, &offset, &offsetvar, dynamic); diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 9f6cc8f871e..d6f4d6bfe45 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -8301,7 +8301,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, } /* Finalize the result, if necessary. */ - attr = CLASS_DATA (expr->value.function.esym->result)->attr; + attr = expr->value.function.esym + ? CLASS_DATA (expr->value.function.esym->result)->attr + : CLASS_DATA (expr)->attr; if (!((gfc_is_class_array_function (expr) || gfc_is_alloc_class_scalar_function (expr)) && attr.pointer)) @@ -10085,27 +10087,26 @@ trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le, if (re->expr_type != EXPR_VARIABLE && re->expr_type != EXPR_NULL && rse->expr != NULL_TREE) { - if (re->ts.type == BT_CLASS && !GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr))) - class_expr = gfc_get_class_from_expr (rse->expr); + if (!DECL_P (rse->expr)) + { + if (re->ts.type == BT_CLASS && !GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr))) + class_expr = gfc_get_class_from_expr (rse->expr); - if (rse->loop) - pre = &rse->loop->pre; - else - pre = &rse->pre; + if (rse->loop) + pre = &rse->loop->pre; + else + pre = &rse->pre; - if (class_expr != NULL_TREE && UNLIMITED_POLY (re)) - { - tmp = TREE_OPERAND (rse->expr, 0); - tmp = gfc_create_var (TREE_TYPE (tmp), "rhs"); - gfc_add_modify (&rse->pre, tmp, TREE_OPERAND (rse->expr, 0)); + if (class_expr != NULL_TREE && UNLIMITED_POLY (re)) + tmp = gfc_evaluate_now (TREE_OPERAND (rse->expr, 0), &rse->pre); + else + tmp = gfc_evaluate_now (rse->expr, &rse->pre); + + rse->expr = tmp; } else - { - tmp = gfc_create_var (TREE_TYPE (rse->expr), "rhs"); - gfc_add_modify (&rse->pre, tmp, rse->expr); - } + pre = &rse->pre; - rse->expr = tmp; temp_rhs = true; } diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index 912c1000e18..96839705112 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -395,7 +395,8 @@ build_round_expr (tree arg, tree restype) don't have an appropriate function that converts directly to the integer type (such as kind == 16), just use ROUND, and then convert the result to an integer. We might also need to convert the result afterwards. */ - if (resprec <= INT_TYPE_SIZE && argprec <= LONG_DOUBLE_TYPE_SIZE) + if (resprec <= INT_TYPE_SIZE + && argprec <= TYPE_PRECISION (long_double_type_node)) fn = builtin_decl_for_precision (BUILT_IN_IROUND, argprec); else if (resprec <= LONG_TYPE_SIZE) fn = builtin_decl_for_precision (BUILT_IN_LROUND, argprec); diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index f867e2240bf..df1bf144e23 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -4327,6 +4327,34 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, omp_clauses = gfc_trans_add_clause (c, omp_clauses); } + if (clauses->full) + { + c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FULL); + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + + if (clauses->partial) + { + c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARTIAL); + OMP_CLAUSE_PARTIAL_EXPR (c) + = (clauses->partial > 0 + ? build_int_cst (integer_type_node, clauses->partial) + : NULL_TREE); + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + + if (clauses->sizes_list) + { + tree list = NULL_TREE; + for (gfc_expr_list *el = clauses->sizes_list; el; el = el->next) + list = tree_cons (NULL_TREE, gfc_convert_expr_to_tree (block, el->expr), + list); + + c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIZES); + OMP_CLAUSE_SIZES_LIST (c) = nreverse (list); + omp_clauses = gfc_trans_add_clause (c, omp_clauses); + } + if (clauses->ordered) { c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDERED); @@ -4783,18 +4811,14 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, } if (clauses->tile_list) { - vec *tvec; - gfc_expr_list *el; - - vec_alloc (tvec, 4); - - for (el = clauses->tile_list; el; el = el->next) - vec_safe_push (tvec, gfc_convert_expr_to_tree (block, el->expr)); + tree list = NULL_TREE; + for (gfc_expr_list *el = clauses->tile_list; el; el = el->next) + list = tree_cons (NULL_TREE, gfc_convert_expr_to_tree (block, el->expr), + list); c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TILE); - OMP_CLAUSE_TILE_LIST (c) = build_tree_list_vec (tvec); + OMP_CLAUSE_TILE_LIST (c) = nreverse (list); omp_clauses = gfc_trans_add_clause (c, omp_clauses); - tvec->truncate (0); } if (clauses->vector) { @@ -5718,6 +5742,16 @@ gfc_nonrect_loop_expr (stmtblock_t *pblock, gfc_se *sep, int loop_n, return true; } +int +gfc_expr_list_len (gfc_expr_list *list) +{ + unsigned len = 0; + for (; list; list = list->next) + len++; + + return len; +} + static tree gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, gfc_omp_clauses *do_clauses, tree par_clauses) @@ -5733,18 +5767,19 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, dovar_init *di; unsigned ix; vec *saved_doacross_steps = doacross_steps; - gfc_expr_list *tile = do_clauses ? do_clauses->tile_list : clauses->tile_list; + gfc_expr_list *oacc_tile + = do_clauses ? do_clauses->tile_list : clauses->tile_list; + gfc_expr_list *sizes + = do_clauses ? do_clauses->sizes_list : clauses->sizes_list; gfc_code *orig_code = code; /* Both collapsed and tiled loops are lowered the same way. In OpenACC, those clauses are not compatible, so prioritize the tile clause, if present. */ - if (tile) - { - collapse = 0; - for (gfc_expr_list *el = tile; el; el = el->next) - collapse++; - } + if (oacc_tile) + collapse = gfc_expr_list_len (oacc_tile); + else if (sizes) + collapse = gfc_expr_list_len (sizes); doacross_steps = NULL; if (clauses->orderedc) @@ -5753,7 +5788,6 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, collapse = 1; code = code->block->next; - gcc_assert (code->op == EXEC_DO); init = make_tree_vec (collapse); cond = make_tree_vec (collapse); @@ -5779,6 +5813,17 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, int dovar_found = 0; tree dovar_decl; + if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL) + { + TREE_VEC_ELT (init, i) = NULL_TREE; + TREE_VEC_ELT (cond, i) = NULL_TREE; + TREE_VEC_ELT (incr, i) = NULL_TREE; + TREE_VEC_ELT (incr, i) = NULL_TREE; + if (orig_decls) + TREE_VEC_ELT (orig_decls, i) = NULL_TREE; + continue; + } + gcc_assert (code->op == EXEC_DO); if (clauses) { gfc_omp_namelist *n = NULL; @@ -6092,6 +6137,8 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, if (code1 != scan) tmpcode->next = scan; } + else if (code->op == EXEC_OMP_TILE || code->op == EXEC_OMP_UNROLL) + tmp = gfc_trans_omp_code (code, true); else tmp = gfc_trans_omp_code (code->block->next, true); gfc_add_expr_to_block (&body, tmp); @@ -6112,6 +6159,8 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, case EXEC_OMP_LOOP: stmt = make_node (OMP_LOOP); break; case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break; case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break; + case EXEC_OMP_TILE: stmt = make_node (OMP_TILE); break; + case EXEC_OMP_UNROLL: stmt = make_node (OMP_UNROLL); break; default: gcc_unreachable (); } @@ -8219,6 +8268,8 @@ gfc_trans_omp_directive (gfc_code *code) case EXEC_OMP_LOOP: case EXEC_OMP_SIMD: case EXEC_OMP_TASKLOOP: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses, NULL); case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc index 9b497d6bdc6..93b633e212e 100644 --- a/gcc/fortran/trans-stmt.cc +++ b/gcc/fortran/trans-stmt.cc @@ -6449,8 +6449,9 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate) else gfc_add_block_to_block (&post, &se.post); - /* Special case when string in expr3 is zero. */ + /* Special case when string in expr3 is scalar and has length zero. */ if (code->expr3->ts.type == BT_CHARACTER + && code->expr3->rank == 0 && integer_zerop (se.string_length)) { gfc_init_se (&se, NULL); diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc index 8466c595e06..0ef67723fcd 100644 --- a/gcc/fortran/trans-types.cc +++ b/gcc/fortran/trans-types.cc @@ -873,13 +873,15 @@ gfc_build_real_type (gfc_real_info *info) int mode_precision = info->mode_precision; tree new_type; - if (mode_precision == FLOAT_TYPE_SIZE) + if (mode_precision == TYPE_PRECISION (float_type_node)) info->c_float = 1; - if (mode_precision == DOUBLE_TYPE_SIZE) + if (mode_precision == TYPE_PRECISION (double_type_node)) info->c_double = 1; - if (mode_precision == LONG_DOUBLE_TYPE_SIZE && !info->c_float128) + if (mode_precision == TYPE_PRECISION (long_double_type_node) + && !info->c_float128) info->c_long_double = 1; - if (mode_precision != LONG_DOUBLE_TYPE_SIZE && mode_precision == 128) + if (mode_precision != TYPE_PRECISION (long_double_type_node) + && mode_precision == 128) { /* TODO: see PR101835. */ info->c_float128 = 1; diff --git a/gcc/fortran/trans.cc b/gcc/fortran/trans.cc index badad6ae892..a208afe90ab 100644 --- a/gcc/fortran/trans.cc +++ b/gcc/fortran/trans.cc @@ -2656,6 +2656,8 @@ trans_code (gfc_code * code, tree cond) case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: case EXEC_OMP_TEAMS_LOOP: + case EXEC_OMP_TILE: + case EXEC_OMP_UNROLL: case EXEC_OMP_WORKSHARE: res = gfc_trans_omp_directive (code); break; diff --git a/gcc/function.cc b/gcc/function.cc index 7e5434fd2af..4edd4da1247 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -58,8 +58,8 @@ along with GCC; see the file COPYING3. If not see #include "varasm.h" #include "except.h" #include "dojump.h" -#include "calls.h" #include "explow.h" +#include "calls.h" #include "expr.h" #include "optabs-tree.h" #include "output.h" @@ -2449,10 +2449,7 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm, else if (DECL_CHAIN (parm)) data->arg.named = 1; /* Not the last non-variadic parm. */ else if (targetm.calls.strict_argument_naming (all->args_so_far)) - { - data->arg.named = 1; /* Only variadic ones are unnamed. */ - data->arg.last_named = 1; - } + data->arg.named = 1; /* Only variadic ones are unnamed. */ else data->arg.named = 0; /* Treat as variadic. */ @@ -2494,12 +2491,9 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm, /* Find mode as it is passed by the ABI. */ unsignedp = TYPE_UNSIGNED (data->arg.type); -// data->arg.mode -// = promote_function_mode (data->arg.type, data->arg.mode, &unsignedp, -// TREE_TYPE (current_function_decl), 0); - data->arg.mode = promote_function_mode (all->args_so_far, data->arg, - TREE_TYPE (current_function_decl), - &unsignedp, 0); + data->arg.mode + = promote_function_mode (data->arg.type, data->arg.mode, &unsignedp, + TREE_TYPE (current_function_decl), 0); } /* A subroutine of assign_parms. Invoke setup_incoming_varargs. */ @@ -2512,7 +2506,6 @@ assign_parms_setup_varargs (struct assign_parm_data_all *all, function_arg_info last_named_arg = data->arg; last_named_arg.named = true; - last_named_arg.last_named = true; targetm.calls.setup_incoming_varargs (all->args_so_far, last_named_arg, &varargs_pretend_bytes, no_rtl); @@ -2621,9 +2614,7 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all, locate_and_pad_parm (data->arg.mode, data->arg.type, in_regs, all->reg_parm_stack_space, - entry_parm ? data->partial : 0, - all->args_so_far, - current_function_decl, + entry_parm ? data->partial : 0, current_function_decl, &all->stack_args_size, &data->locate); /* Update parm_stack_boundary if this parameter is passed in the @@ -3930,8 +3921,7 @@ gimplify_parameters (gimple_seq *cleanup) if (data.arg.pass_by_reference) { tree type = TREE_TYPE (data.arg.type); - function_arg_info orig_arg (type, data.arg.named, - data.arg.last_named); + function_arg_info orig_arg (type, data.arg.named); if (reference_callee_copied (&all.args_so_far_v, orig_arg)) { tree local, t; @@ -4034,7 +4024,6 @@ gimplify_parameters (gimple_seq *cleanup) void locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs, int reg_parm_stack_space, int partial, - cumulative_args_t ca, tree fndecl ATTRIBUTE_UNUSED, struct args_size *initial_offset_ptr, struct locate_and_pad_arg_data *locate) @@ -4072,23 +4061,9 @@ locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs, ? arg_size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode))); where_pad = targetm.calls.function_arg_padding (passed_mode, type); - - if (flag_stack_use_cumulative_args) - { - boundary = targetm.calls.function_arg_boundary_ca (passed_mode, - type, - ca); - round_boundary = targetm.calls.function_arg_round_boundary_ca - (passed_mode, type, ca); - } - else - { - boundary = targetm.calls.function_arg_boundary (passed_mode, - type); - round_boundary = targetm.calls.function_arg_round_boundary - (passed_mode, type); - } - + boundary = targetm.calls.function_arg_boundary (passed_mode, type); + round_boundary = targetm.calls.function_arg_round_boundary (passed_mode, + type); locate->where_pad = where_pad; /* Alignment can't exceed MAX_SUPPORTED_STACK_ALIGNMENT. */ diff --git a/gcc/function.h b/gcc/function.h index 520fde7694c..c0ba6cc1531 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -20,7 +20,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_FUNCTION_H #define GCC_FUNCTION_H -#include "cumulative-args.h" /* Stack of pending (incomplete) sequences saved by `start_sequence'. Each element describes one pending sequence. @@ -681,7 +680,6 @@ extern bool aggregate_value_p (const_tree, const_tree); extern bool use_register_for_decl (const_tree); extern gimple_seq gimplify_parameters (gimple_seq *); extern void locate_and_pad_parm (machine_mode, tree, int, int, int, - cumulative_args_t, tree, struct args_size *, struct locate_and_pad_arg_data *); extern void generate_setjmp_warnings (void); diff --git a/gcc/gcc.cc b/gcc/gcc.cc index 830a4700a87..d80b604a48d 100644 --- a/gcc/gcc.cc +++ b/gcc/gcc.cc @@ -4354,7 +4354,8 @@ driver_handle_option (struct gcc_options *opts, { const char *basename = (opts->x_dump_base_name ? opts->x_dump_base_name : opts->x_main_input_basename); - diagnostic_output_format_init (dc, basename, + diagnostic_output_format_init (dc, + opts->x_main_input_filename, basename, (enum diagnostics_output_format)value, opts->x_flag_diagnostics_json_formatting); break; diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc index f1e0e7abe0c..a56bd90cb2c 100644 --- a/gcc/genmatch.cc +++ b/gcc/genmatch.cc @@ -848,12 +848,13 @@ public: : operand (OP_EXPR, loc), operation (operation_), ops (vNULL), expr_type (NULL), is_commutative (is_commutative_), is_generic (false), force_single_use (false), force_leaf (false), - opt_grp (0) {} + match_phi (false), opt_grp (0) {} expr (expr *e) : operand (OP_EXPR, e->location), operation (e->operation), ops (vNULL), expr_type (e->expr_type), is_commutative (e->is_commutative), is_generic (e->is_generic), force_single_use (e->force_single_use), - force_leaf (e->force_leaf), opt_grp (e->opt_grp) {} + force_leaf (e->force_leaf), match_phi (e->match_phi), + opt_grp (e->opt_grp) {} void append_op (operand *op) { ops.safe_push (op); } /* The operator and its operands. */ id_base *operation; @@ -871,6 +872,8 @@ public: /* Whether in the result expression this should be a leaf node with any children simplified down to simple operands. */ bool force_leaf; + /* Whether the COND_EXPR is matching PHI gimple, default false. */ + bool match_phi; /* If non-zero, the group for optional handling. */ unsigned char opt_grp; void gen_transform (FILE *f, int, const char *, bool, int, @@ -1819,6 +1822,7 @@ public: char *get_name (char *); void gen_opname (char *, unsigned); + void gen_phi_on_cond (FILE *, int, int); }; /* Leaf node of the decision tree, used for DT_SIMPLIFY. */ @@ -1898,7 +1902,8 @@ cmp_operand (operand *o1, operand *o2) expr *e1 = static_cast(o1); expr *e2 = static_cast(o2); if (e1->operation != e2->operation - || e1->is_generic != e2->is_generic) + || e1->is_generic != e2->is_generic + || e1->match_phi != e2->match_phi) return false; if (e1->operation->kind == id_base::FN /* For function calls also compare number of arguments. */ @@ -3251,6 +3256,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth, depth); indent += 4; fprintf_indent (f, indent, "{\n"); + bool cond_expr_p = false; for (unsigned i = 0; i < exprs_len; ++i) { expr *e = as_a (gimple_exprs[i]->op); @@ -3262,6 +3268,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth, else { id_base *op = e->operation; + cond_expr_p |= (*op == COND_EXPR && e->match_phi); if (*op == CONVERT_EXPR || *op == NOP_EXPR) fprintf_indent (f, indent, "CASE_CONVERT:\n"); else @@ -3275,6 +3282,27 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth, fprintf_indent (f, indent, "default:;\n"); fprintf_indent (f, indent, "}\n"); indent -= 4; + + if (cond_expr_p) + { + fprintf_indent (f, indent, + "else if (gphi *_a%d = dyn_cast (_d%d))\n", + depth, depth); + indent += 2; + fprintf_indent (f, indent, "{\n"); + indent += 2; + + for (unsigned i = 0; i < exprs_len; i++) + { + expr *e = as_a (gimple_exprs[i]->op); + if (*e->operation == COND_EXPR && e->match_phi) + gimple_exprs[i]->gen_phi_on_cond (f, indent, depth); + } + + indent -= 2; + fprintf_indent (f, indent, "}\n"); + indent -= 2; + } } if (fns_len) @@ -3483,6 +3511,86 @@ dt_operand::gen (FILE *f, int indent, bool gimple, int depth) } } +/* Generate matching code for the phi when meet COND_EXPR. */ + +void +dt_operand::gen_phi_on_cond (FILE *f, int indent, int depth) +{ + fprintf_indent (f, indent, + "basic_block _b%d = gimple_bb (_a%d);\n", depth, depth); + + fprintf_indent (f, indent, "if (gimple_phi_num_args (_a%d) == 2)\n", depth); + + indent += 2; + fprintf_indent (f, indent, "{\n"); + indent += 2; + + fprintf_indent (f, indent, + "basic_block _pb_0_%d = EDGE_PRED (_b%d, 0)->src;\n", depth, depth); + fprintf_indent (f, indent, + "basic_block _pb_1_%d = EDGE_PRED (_b%d, 1)->src;\n", depth, depth); + fprintf_indent (f, indent, + "basic_block _db_%d = safe_dyn_cast (*gsi_last_bb (_pb_0_%d)) ? " + "_pb_0_%d : _pb_1_%d;\n", depth, depth, depth, depth); + fprintf_indent (f, indent, + "basic_block _other_db_%d = safe_dyn_cast " + "(*gsi_last_bb (_pb_0_%d)) ? _pb_1_%d : _pb_0_%d;\n", + depth, depth, depth, depth); + + fprintf_indent (f, indent, + "gcond *_ct_%d = safe_dyn_cast (*gsi_last_bb (_db_%d));\n", + depth, depth); + fprintf_indent (f, indent, "if (_ct_%d" + " && EDGE_COUNT (_other_db_%d->preds) == 1\n", depth, depth); + fprintf_indent (f, indent, + " && EDGE_COUNT (_other_db_%d->succs) == 1\n", depth); + fprintf_indent (f, indent, + " && EDGE_PRED (_other_db_%d, 0)->src == _db_%d)\n", depth, depth); + + indent += 2; + fprintf_indent (f, indent, "{\n"); + indent += 2; + + fprintf_indent (f, indent, + "tree _cond_lhs_%d = gimple_cond_lhs (_ct_%d);\n", depth, depth); + fprintf_indent (f, indent, + "tree _cond_rhs_%d = gimple_cond_rhs (_ct_%d);\n", depth, depth); + + char opname_0[20]; + char opname_1[20]; + char opname_2[20]; + gen_opname (opname_0, 0); + + fprintf_indent (f, indent, + "tree %s = build2 (gimple_cond_code (_ct_%d), " + "boolean_type_node, _cond_lhs_%d, _cond_rhs_%d);\n", + opname_0, depth, depth, depth); + + fprintf_indent (f, indent, + "bool _arg_0_is_true_%d = gimple_phi_arg_edge (_a%d, 0)->flags" + " & EDGE_TRUE_VALUE;\n", depth, depth); + + gen_opname (opname_1, 1); + fprintf_indent (f, indent, + "tree %s = gimple_phi_arg_def (_a%d, _arg_0_is_true_%d ? 0 : 1);\n", + opname_1, depth, depth); + + gen_opname (opname_2, 2); + fprintf_indent (f, indent, + "tree %s = gimple_phi_arg_def (_a%d, _arg_0_is_true_%d ? 1 : 0);\n", + opname_2, depth, depth); + + gen_kids (f, indent, true, depth); + + indent -= 2; + fprintf_indent (f, indent, "}\n"); + indent -= 2; + + indent -= 2; + fprintf_indent (f, indent, "}\n"); + indent -= 2; +} + /* Emit a logging call to the debug file to the file F, with the INDENT from either the RESULT location or the S's match location if RESULT is null. */ static void @@ -4600,6 +4708,18 @@ parser::parse_expr () e->force_leaf = true; } + if (token->type == CPP_XOR && !(token->flags & PREV_WHITE)) + { + if (!parsing_match_operand) + fatal_at (token, "modifier '^' is only valid in a match expression"); + + if (!(*e->operation == COND_EXPR)) + fatal_at (token, "modifier '^' can only act on operation COND_EXPR"); + + eat_token (CPP_XOR); + e->match_phi = true; + } + if (token->type == CPP_COLON && !(token->flags & PREV_WHITE)) { diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc index 008071cd546..2fa3d18d295 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -262,7 +262,7 @@ static bool check_out_of_bounds_and_warn (location_t location, tree ref, tree low_sub_org, tree low_sub, tree up_sub, tree up_bound, tree up_bound_p1, - const value_range *vr, + const irange *vr, bool ignore_off_by_one, bool for_array_bound, bool *out_of_bound) { @@ -373,7 +373,7 @@ array_bounds_checker::check_array_ref (location_t location, tree ref, tree up_sub = low_sub_org; tree low_sub = low_sub_org; - value_range vr; + int_range_max vr; if (TREE_CODE (low_sub_org) == SSA_NAME) { get_value_range (vr, low_sub_org, stmt); diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index d2a0f6ddf19..7c534d56bf1 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -874,8 +874,8 @@ size_must_be_zero_p (tree size) can be stored in ssize_t, the signed counterpart of size_t. */ wide_int ssize_max = wi::lshift (wi::one (prec), prec - 1) - 1; wide_int zero = wi::zero (TYPE_PRECISION (type)); - value_range valid_range (type, zero, ssize_max); - value_range vr; + int_range_max valid_range (type, zero, ssize_max); + int_range_max vr; get_range_query (cfun)->range_of_expr (vr, size); if (vr.undefined_p ()) @@ -9334,10 +9334,10 @@ static bool gimple_call_nonnegative_warnv_p (gimple *stmt, bool *strict_overflow_p, int depth) { - tree arg0 = gimple_call_num_args (stmt) > 0 ? - gimple_call_arg (stmt, 0) : NULL_TREE; - tree arg1 = gimple_call_num_args (stmt) > 1 ? - gimple_call_arg (stmt, 1) : NULL_TREE; + tree arg0 + = gimple_call_num_args (stmt) > 0 ? gimple_call_arg (stmt, 0) : NULL_TREE; + tree arg1 + = gimple_call_num_args (stmt) > 1 ? gimple_call_arg (stmt, 1) : NULL_TREE; tree lhs = gimple_call_lhs (stmt); return (lhs && tree_call_nonnegative_warnv_p (TREE_TYPE (lhs), diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc index 7e8b6e3c51a..56e5f826a8d 100644 --- a/gcc/gimple-lower-bitint.cc +++ b/gcc/gimple-lower-bitint.cc @@ -4286,11 +4286,7 @@ bitint_large_huge::lower_addsub_overflow (tree obj, gimple *stmt) bool single_comparison = (startlimb + 2 >= fin || (startlimb & 1) != (i & 1)); if (!single_comparison) - { - cmp_code = GE_EXPR; - if (!check_zero && (start % limb_prec) == 0) - single_comparison = true; - } + cmp_code = GE_EXPR; else if ((startlimb & 1) == (i & 1)) cmp_code = EQ_EXPR; else diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc index 8c28c76cf0e..01688b8581b 100644 --- a/gcc/gimple-predicate-analysis.cc +++ b/gcc/gimple-predicate-analysis.cc @@ -300,7 +300,7 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def, flag_var >= [min, max] -> flag_var > [min-1, max] if no overflow/wrap. */ tree type = TREE_TYPE (cond_lhs); - value_range r; + int_range_max r; if (!INTEGRAL_TYPE_P (type) || !get_range_query (cfun)->range_of_expr (r, cond_rhs) || r.undefined_p () diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc index aec3f39ec0e..1b9a84708b9 100644 --- a/gcc/gimple-range-op.cc +++ b/gcc/gimple-range-op.cc @@ -941,8 +941,10 @@ cfn_clz::fold_range (irange &r, tree type, const irange &lh, int maxi = prec - 1; if (m_gimple_call_internal_p) { - // Only handle the single common value. - if (rh.lower_bound () == prec) + // Handle only the two common values. + if (rh.lower_bound () == -1) + mini = -1; + else if (rh.lower_bound () == prec) maxi = prec; else // Magic value to give up, unless we can prove arg is non-zero. @@ -953,7 +955,7 @@ cfn_clz::fold_range (irange &r, tree type, const irange &lh, if (wi::gt_p (lh.lower_bound (), 0, TYPE_SIGN (lh.type ()))) { maxi = prec - 1 - wi::floor_log2 (lh.lower_bound ()); - if (mini == -2) + if (mini < 0) mini = 0; } else if (!range_includes_zero_p (lh)) @@ -969,11 +971,11 @@ cfn_clz::fold_range (irange &r, tree type, const irange &lh, if (max == 0) { // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec, - // return [prec, prec], otherwise ignore the range. - if (maxi == prec) - mini = prec; + // return [prec, prec] or [-1, -1], otherwise ignore the range. + if (maxi == prec || mini == -1) + mini = maxi; } - else + else if (mini >= 0) mini = newmini; if (mini == -2) diff --git a/gcc/gimple-ssa-sprintf.cc b/gcc/gimple-ssa-sprintf.cc index 3b19f4d3f35..025b0fbff6f 100644 --- a/gcc/gimple-ssa-sprintf.cc +++ b/gcc/gimple-ssa-sprintf.cc @@ -1079,7 +1079,7 @@ get_int_range (tree arg, gimple *stmt, && TYPE_PRECISION (argtype) <= TYPE_PRECISION (type)) { /* Try to determine the range of values of the integer argument. */ - value_range vr; + int_range_max vr; query->range_of_expr (vr, arg, stmt); if (!vr.undefined_p () && !vr.varying_p ()) @@ -1395,7 +1395,7 @@ format_integer (const directive &dir, tree arg, pointer_query &ptr_qry) { /* Try to determine the range of values of the integer argument (range information is not available for pointers). */ - value_range vr; + int_range_max vr; ptr_qry.rvals->range_of_expr (vr, arg, dir.info->callstmt); if (!vr.varying_p () && !vr.undefined_p ()) @@ -4260,7 +4260,7 @@ try_substitute_return_value (gimple_stmt_iterator *gsi, wide_int min = wi::shwi (retval[0], prec); wide_int max = wi::shwi (retval[1], prec); - value_range r (TREE_TYPE (lhs), min, max); + int_range_max r (TREE_TYPE (lhs), min, max); set_range_info (lhs, r); setrange = true; @@ -4629,7 +4629,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry) /* Try to determine the range of values of the argument and use the greater of the two at level 1 and the smaller of them at level 2. */ - value_range vr; + int_range_max vr; ptr_qry.rvals->range_of_expr (vr, size, info.callstmt); if (!vr.undefined_p ()) diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc index a552ce8dcdf..d71f1331c85 100644 --- a/gcc/gimple-ssa-warn-restrict.cc +++ b/gcc/gimple-ssa-warn-restrict.cc @@ -352,7 +352,7 @@ builtin_memref::extend_offset_range (tree offset) as signed. */ wide_int min, max; value_range_kind rng = VR_VARYING; - value_range vr; + int_range_max vr; if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt)) { tree vr_min, vr_max; diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index b0ed58ed0f9..622c51d5c3f 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -6304,6 +6304,8 @@ is_gimple_stmt (tree t) case OMP_SIMD: case OMP_DISTRIBUTE: case OMP_LOOP: + case OMP_TILE: + case OMP_UNROLL: case OACC_LOOP: case OMP_SCAN: case OMP_SCOPE: @@ -15027,7 +15029,10 @@ gimplify_omp_taskloop_expr (tree type, tree *tp, gimple_seq *pre_p, if (*tp == NULL || is_gimple_constant (*tp)) return; - *tp = get_initialized_tmp_var (*tp, pre_p, NULL, false); + if (TREE_CODE (*tp) == SAVE_EXPR) + gimplify_save_expr (tp, pre_p, NULL); + else + *tp = get_initialized_tmp_var (*tp, pre_p, NULL, false); /* Reference to pointer conversion is considered useless, but is significant for firstprivate clause. Force it here. */ @@ -15070,6 +15075,141 @@ find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *) return NULL_TREE; } +/* Gimplify standalone loop transforming directive which has the + transformations applied already. So, all that is needed is gimplify + the remaining loops as normal loops. */ + +static enum gimplify_status +gimplify_omp_loop_xform (tree *expr_p, gimple_seq *pre_p) +{ + tree for_stmt = *expr_p; + + if (OMP_FOR_PRE_BODY (for_stmt)) + gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), pre_p); + + gimple_seq pre_body = NULL, post_body = NULL; + for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++) + { + if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i) == NULL_TREE) + continue; + tree iters = NULL_TREE; + if (i == 0 + && TREE_CODE (for_stmt) == OMP_UNROLL + && !omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_PARTIAL)) + { + if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_FULL)) + iters = omp_loop_number_of_iterations (for_stmt, 0, NULL); + else + iters = build_int_cst (integer_type_node, 8); + } + tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i); + gcc_assert (TREE_CODE (t) == MODIFY_EXPR); + tree decl = TREE_OPERAND (t, 0); + gcc_assert (DECL_P (decl)); + gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl)) + || POINTER_TYPE_P (TREE_TYPE (decl))); + if (DECL_ARTIFICIAL (decl) + && TREE_PRIVATE (t) + && gimplify_omp_ctxp + && gimplify_omp_ctxp->region_type != ORT_NONE) + { + struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; + do + { + splay_tree_node n + = splay_tree_lookup (ctx->variables, (splay_tree_key) decl); + if (n != NULL) + break; + else if (ctx->region_type != ORT_WORKSHARE + && ctx->region_type != ORT_TASKGROUP + && ctx->region_type != ORT_SIMD + && ctx->region_type != ORT_ACC + && !(ctx->region_type & ORT_TARGET_DATA)) + { + omp_add_variable (ctx, decl, GOVD_PRIVATE); + break; + } + ctx = ctx->outer_context; + } + while (ctx); + } + if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC) + { + gcc_assert (seen_error ()); + continue; + } + gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val, + fb_rvalue); + gimplify_and_add (t, &pre_body); + t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i); + gcc_assert (TREE_OPERAND (t, 0) == decl); + if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC) + { + gcc_assert (seen_error ()); + continue; + } + gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val, + fb_rvalue); + tree l1 = create_artificial_label (UNKNOWN_LOCATION); + tree l2 = create_artificial_label (UNKNOWN_LOCATION); + tree l3 = create_artificial_label (UNKNOWN_LOCATION); + gimplify_seq_add_stmt (&pre_body, gimple_build_goto (l2)); + gimplify_seq_add_stmt (&pre_body, gimple_build_label (l1)); + gimple_seq this_post_body = NULL; + t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i); + if (TREE_CODE (t) == MODIFY_EXPR) + { + t = TREE_OPERAND (t, 1); + if (TREE_CODE (t) == PLUS_EXPR + && TREE_OPERAND (t, 1) == decl) + { + TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0); + TREE_OPERAND (t, 0) = decl; + } + gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val, + fb_rvalue); + } + gimplify_and_add (TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i), + &this_post_body); + gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l2)); + t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i); + gcond *cond = NULL; + tree d = decl; + gimplify_expr (&d, &this_post_body, NULL, is_gimple_val, fb_rvalue); + if (iters && tree_fits_uhwi_p (iters)) + { + unsigned HOST_WIDE_INT niters = tree_to_uhwi (iters); + if ((unsigned HOST_WIDE_INT) (int) niters == niters + && (int) niters > 0) + { + t = build2 (TREE_CODE (t), boolean_type_node, d, + TREE_OPERAND (t, 1)); + t = build3 (ANNOTATE_EXPR, TREE_TYPE (t), t, + build_int_cst (integer_type_node, + annot_expr_unroll_kind), + build_int_cst (integer_type_node, niters)); + gimplify_expr (&t, &this_post_body, NULL, is_gimple_val, + fb_rvalue); + cond = gimple_build_cond (NE_EXPR, t, boolean_false_node, + l1, l3); + } + } + if (cond == NULL) + cond = gimple_build_cond (TREE_CODE (t), d, TREE_OPERAND (t, 1), + l1, l3); + gimplify_seq_add_stmt (&this_post_body, cond); + gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l3)); + gimplify_seq_add_seq (&this_post_body, post_body); + post_body = this_post_body; + } + gimplify_seq_add_seq (pre_p, pre_body); + gimplify_and_add (OMP_FOR_BODY (for_stmt), pre_p); + gimplify_seq_add_seq (pre_p, post_body); + + *expr_p = NULL_TREE; + return GS_ALL_DONE; +} + /* Gimplify the gross structure of an OMP_FOR statement. */ static enum gimplify_status @@ -15089,7 +15229,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) bool loop_p = (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_BIND) != NULL_TREE); - if (OMP_FOR_INIT (for_stmt) == NULL_TREE) + while (OMP_FOR_INIT (for_stmt) == NULL_TREE) { tree *data[4] = { NULL, NULL, NULL, NULL }; gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP); @@ -15101,6 +15241,15 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) *expr_p = NULL_TREE; return GS_ERROR; } + gcc_assert (inner_for_stmt == *data[3]); + omp_maybe_apply_loop_xforms (data[3], + data[2] + ? OMP_FOR_CLAUSES (*data[2]) + : TREE_CODE (for_stmt) == OMP_FOR + ? OMP_FOR_CLAUSES (for_stmt) + : NULL_TREE); + if (inner_for_stmt != *data[3]) + continue; if (data[2] && OMP_FOR_PRE_BODY (*data[2])) { append_to_statement_list_force (OMP_FOR_PRE_BODY (*data[2]), @@ -15254,6 +15403,13 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) OMP_PARALLEL_CLAUSES (*data[1]) = c; } } + break; + } + if (OMP_FOR_INIT (for_stmt) != NULL_TREE) + { + omp_maybe_apply_loop_xforms (expr_p, NULL_TREE); + if (*expr_p != for_stmt) + return GS_OK; } switch (TREE_CODE (for_stmt)) @@ -15305,6 +15461,10 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) case OMP_SIMD: ort = ORT_SIMD; break; + case OMP_TILE: + case OMP_UNROLL: + gcc_assert (inner_for_stmt == NULL_TREE); + return gimplify_omp_loop_xform (expr_p, pre_p); default: gcc_unreachable (); } @@ -16330,6 +16490,10 @@ gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p) enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD; int i; + omp_maybe_apply_loop_xforms (expr_p, NULL_TREE); + if (*expr_p != for_stmt) + return GS_OK; + /* If order is not present, the behavior is as if order(concurrent) appeared. */ tree order = omp_find_clause (clauses, OMP_CLAUSE_ORDER); @@ -18397,6 +18561,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case OMP_FOR: case OMP_DISTRIBUTE: case OMP_TASKLOOP: + case OMP_TILE: + case OMP_UNROLL: case OACC_LOOP: ret = gimplify_omp_for (expr_p, pre_p); break; diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h index be884e96336..349213108ce 100644 --- a/gcc/ginclude/stddef.h +++ b/gcc/ginclude/stddef.h @@ -428,8 +428,9 @@ typedef struct { /* _Float128 is defined as a basic type, so max_align_t must be sufficiently aligned for it. This code must work in C++, so we use __float128 here; that is only available on some - architectures. */ -#if defined(__i386__) || (__APPLE__ && __aarch64__) + architectures, but only on i386 is extra alignment needed for + __float128. */ +#ifdef __i386__ __float128 __max_align_f128 __attribute__((__aligned__(__alignof(__float128)))); #endif } max_align_t; diff --git a/gcc/go/gospec.cc b/gcc/go/gospec.cc index b866d47a942..a3da23dfa3a 100644 --- a/gcc/go/gospec.cc +++ b/gcc/go/gospec.cc @@ -443,8 +443,11 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, using the GNU linker, the Solaris linker needs an option to not warn about this. Everything works without this option, but you get unsightly warnings at link time. */ - generate_option (OPT_Wl_, "-t", 1, CL_DRIVER, &new_decoded_options[j]); - j++; + if (library > 0) + { + generate_option (OPT_Wl_, "-t", 1, CL_DRIVER, &new_decoded_options[j]); + j++; + } #endif *in_decoded_options_count = j; diff --git a/gcc/graphite-sese-to-poly.cc b/gcc/graphite-sese-to-poly.cc index 4f614a3ba82..5ce898505a3 100644 --- a/gcc/graphite-sese-to-poly.cc +++ b/gcc/graphite-sese-to-poly.cc @@ -420,7 +420,7 @@ static void add_param_constraints (scop_p scop, graphite_dim_t p, tree parameter) { tree type = TREE_TYPE (parameter); - value_range r; + int_range_max r; wide_int min, max; gcc_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)); diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 0d27f17b283..4948b48bde8 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -893,7 +893,7 @@ get_min_precision (tree arg, signop sign) } if (TREE_CODE (arg) != SSA_NAME) return prec + (orig_sign != sign); - value_range r; + int_range_max r; while (!get_global_range_query ()->range_of_expr (r, arg) || r.varying_p () || r.undefined_p ()) diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 8de1fa882e9..a8c83437ada 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -276,6 +276,7 @@ DEF_INTERNAL_SIGNED_OPTAB_FN (MULHRS, ECF_CONST | ECF_NOTHROW, first, smulhrs, umulhrs, binary) DEF_INTERNAL_SIGNED_OPTAB_FN (SAT_ADD, ECF_CONST, first, ssadd, usadd, binary) +DEF_INTERNAL_SIGNED_OPTAB_FN (SAT_SUB, ECF_CONST, first, sssub, ussub, binary) DEF_INTERNAL_COND_FN (ADD, ECF_CONST, add, binary) DEF_INTERNAL_COND_FN (SUB, ECF_CONST, sub, binary) diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 58d282046e8..74e847b2dec 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -21,9 +21,6 @@ along with GCC; see the file COPYING3. If not see #define LIBGCCJIT_H #include -#ifdef __APPLE__ -# include /* For ssize_t. */ -#endif #ifdef __cplusplus extern "C" { diff --git a/gcc/lto-opts.cc b/gcc/lto-opts.cc index b3d19f8b361..a3a1d110329 100644 --- a/gcc/lto-opts.cc +++ b/gcc/lto-opts.cc @@ -152,6 +152,7 @@ lto_write_options (void) case OPT_fprofile_prefix_map_: case OPT_fcanon_prefix_map: case OPT_fwhole_program: + case OPT_fltrans_output_list_: continue; default: diff --git a/gcc/lto-streamer.cc b/gcc/lto-streamer.cc index 8032bbf7108..40ca6b2da1b 100644 --- a/gcc/lto-streamer.cc +++ b/gcc/lto-streamer.cc @@ -132,11 +132,18 @@ lto_get_section_name (int section_type, const char *name, doesn't confuse the reader with merged sections. For options don't add a ID, the option reader cannot deal with them - and merging should be ok here. */ - if (section_type == LTO_section_opts) + and merging should be ok here. + + LTRANS files (output of wpa, input and output of ltrans) are handled + directly inside of linker/lto-wrapper, so name uniqueness for external + tools is not needed. + Randomness would inhibit incremental LTO. */ + if (section_type == LTO_section_opts || flag_ltrans) strcpy (post, ""); else if (f != NULL) sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, f->id); + else if (flag_wpa) + strcpy (post, ""); else sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, get_random_seed (false)); char *res = concat (section_name_prefix, sep, add, post, NULL); diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index dd9310eac7c..89b9fceb276 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,7 @@ +2024-06-06 Michal Jires + + * lto-common.cc (lto_section_with_id): Dont load suffix during LTRANS. + 2024-02-21 Martin Jambor PR ipa/113476 diff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc index 2ce94cc3282..34aa63b179c 100644 --- a/gcc/lto/lto-common.cc +++ b/gcc/lto/lto-common.cc @@ -2176,6 +2176,13 @@ lto_section_with_id (const char *name, unsigned HOST_WIDE_INT *id) if (strncmp (name, section_name_prefix, strlen (section_name_prefix))) return 0; + + if (flag_ltrans) + { + *id = 0; + return 1; + } + s = strrchr (name, '.'); if (!s) return 0; diff --git a/gcc/lto/lto-partition.cc b/gcc/lto/lto-partition.cc index 19f91e5d660..2238650fa0e 100644 --- a/gcc/lto/lto-partition.cc +++ b/gcc/lto/lto-partition.cc @@ -18,6 +18,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_VECTOR #include "system.h" #include "coretypes.h" #include "target.h" @@ -37,6 +38,8 @@ along with GCC; see the file COPYING3. If not see #include "ipa-fnsummary.h" #include "lto-partition.h" +#include + vec ltrans_partitions; static void add_symbol_to_partition (ltrans_partition part, symtab_node *node); @@ -60,20 +63,41 @@ cmp_partitions_order (const void *a, const void *b) return orderb - ordera; } -/* Create new partition with name NAME. */ - +/* Create new partition with name NAME. + Does not push into ltrans_partitions. */ static ltrans_partition -new_partition (const char *name) +new_partition_no_push (const char *name) { ltrans_partition part = XCNEW (struct ltrans_partition_def); part->encoder = lto_symtab_encoder_new (false); part->name = name; part->insns = 0; part->symbols = 0; + return part; +} + +/* Create new partition with name NAME. */ + +static ltrans_partition +new_partition (const char *name) +{ + ltrans_partition part = new_partition_no_push (name); ltrans_partitions.safe_push (part); return part; } +/* Free memory used by ltrans partition. + Encoder can be kept to be freed after streaming. */ +static void +free_ltrans_partition (ltrans_partition part, bool delete_encoder) +{ + if (part->initializers_visited) + delete part->initializers_visited; + if (delete_encoder) + lto_symtab_encoder_delete (part->encoder); + free (part); +} + /* Free memory used by ltrans datastructures. */ void @@ -82,12 +106,7 @@ free_ltrans_partitions (void) unsigned int idx; ltrans_partition part; for (idx = 0; ltrans_partitions.iterate (idx, &part); idx++) - { - if (part->initializers_visited) - delete part->initializers_visited; - /* Symtab encoder is freed after streaming. */ - free (part); - } + free_ltrans_partition (part, false); ltrans_partitions.release (); } @@ -428,6 +447,574 @@ account_reference_p (symtab_node *n1, symtab_node *n2) return true; } +/* Joins two partitions into one. + NULL partitions are equivalent to empty partition. + If both partition are non-null, symbols from FROM are added into INTO. */ +static ltrans_partition +join_partitions (ltrans_partition into, ltrans_partition from) +{ + if (!into) + return from; + if (!from) + return into; + + lto_symtab_encoder_iterator lsei; + lto_symtab_encoder_t encoder = from->encoder; + + /* If aux is non zero, it will not be added to the new partition. Since + adding symbols is recursive, it is safer to reduce aux of all symbols + before adding any symbols to other partition. */ + for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) + { + symtab_node *node = lsei_node (lsei); + node->aux = (void *)((size_t)node->aux - 1); + } + + for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) + { + symtab_node *node = lsei_node (lsei); + + if (symbol_partitioned_p (node)) + continue; + + add_symbol_to_partition (into, node); + } + + free_ltrans_partition (from, true); + + return into; +} + +/* Takes symbols from given partitions and splits them into N partitions where + each partitions contains one symbol and its requirements. */ +static std::vector +split_partition_into_nodes (ltrans_partition part) +{ + std::vector partitions; + + lto_symtab_encoder_iterator lsei; + lto_symtab_encoder_t encoder = part->encoder; + + for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) + { + symtab_node *node = lsei_node (lsei); + node->aux = (void *)((size_t)node->aux - 1); + } + + for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) + { + symtab_node *node = lsei_node (lsei); + + if (node->get_partitioning_class () != SYMBOL_PARTITION + || symbol_partitioned_p (node)) + continue; + + ltrans_partition new_part = new_partition_no_push (part->name); + add_symbol_to_partition (new_part, node); + partitions.push_back (new_part); + } + + return partitions; +} + +/* Returns whether partition contains symbols that cannot be reordered. */ +static bool +is_partition_reorder (ltrans_partition part) +{ + lto_symtab_encoder_iterator lsei; + lto_symtab_encoder_t encoder = part->encoder; + + for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) + { + symtab_node *node = lsei_node (lsei); + if (node->no_reorder) + return false; + } + return true; +} + +/* Represents groups of symbols, that should be partitioned into n_partitions + partitions. */ +class partition_set +{ +public: + /* Metadata to easily pass copy to new partition_set. */ + class metadata + { + public: + /* Partitions can be reordered. */ + bool reorder; + /* Partitions can be split into individual symbols. */ + bool splitable; + + metadata (bool reorder, bool splitable): + reorder (reorder), splitable (splitable) + {} + }; + metadata data; + + /* Symbol groups. Use push (g) to insert symbols. */ + std::vector sym_groups; + /* Number of partitions these symbols should be partitioned into. */ + size_t n_partitions; + /* Total number of instructions of all symbols. */ + int64_t insns; + + /* Constructor. Symbols and n_partitions can be added later. */ + partition_set (metadata data, std::vector sym_groups = {}, + size_t n_partitions = 0) + : data (data), sym_groups (std::move (sym_groups)), + n_partitions (n_partitions), insns (0) + { + for (ltrans_partition g: this->sym_groups) + insns += g->insns; + } + + /* Adds symbol group and updates total insns. */ + void + push (ltrans_partition g) + { + sym_groups.push_back (g); + insns += g->insns; + } + + /* Returns whether any symbols group is contained. */ + bool + empty () + { + return sym_groups.empty (); + } +}; + +/* Distributes total n_partitions among partition_sets. + Aims to be as fair as possible. */ +static void +distribute_n_partitions (std::vector& ps, size_t n_partitions) +{ + gcc_assert (ps.size ()); + gcc_assert (ps.size () <= n_partitions); + + int64_t total_size = 0; + + for (partition_set& p: ps) + { + total_size += p.insns; + p.n_partitions = 0; + } + + if (total_size <= 0) + total_size = 1; + + size_t n_partitions_allocated = 0; + + /* First we allocate largest amount of partitions so that target_sizes are + larger than target size of total (insns/total_size). + All partition_set must have n_partitions at least one. */ + for (partition_set& p: ps) + { + p.n_partitions = n_partitions * p.insns / total_size; + if (p.n_partitions == 0 && p.sym_groups.size ()) + p.n_partitions = 1; + if (!p.data.splitable) + p.n_partitions = std::min (p.n_partitions, p.sym_groups.size ()); + + n_partitions_allocated += p.n_partitions; + } + + /* Rare special case, with a lot of initially 0 sized splits. */ + while (n_partitions_allocated > n_partitions) + { + size_t idx = 0; + int64_t min = std::numeric_limits::max (); + + for (size_t i = 0; i < ps.size (); ++i) + { + if (ps[i].n_partitions <= 1) + continue; + + int64_t target_size = ps[i].insns / ps[i].n_partitions; + if (min > target_size) + { + min = target_size; + idx = i; + } + } + + ps[idx].n_partitions--; + n_partitions_allocated--; + } + + /* Typical case where with any increase of n_partitions target size will cross + total target size. We optimize for minimal: + (old_target_size - total_target_size) + - (total_target_size - new_target_size). */ + while (n_partitions_allocated < n_partitions) + { + size_t idx = 0; + int64_t max = 0; + + for (size_t i = 0; i < ps.size (); ++i) + { + if (ps[i].sym_groups.size () <= 1 && !ps[i].data.splitable) + continue; + + int64_t target_size = ps[i].insns / ps[i].n_partitions; + int64_t new_target_size = ps[i].insns / (ps[i].n_partitions + 1); + + int64_t positive_change = target_size + new_target_size; + + if (max < positive_change) + { + max = positive_change; + idx = i; + } + } + + ps[idx].n_partitions++; + n_partitions_allocated++; + } +} + +/* Splits off symbol groups that are larger than target size. + n_partitions are then distributed between individual + split off symbol groups, and everything else as a whole. + + Split off symbol groups with n_partitions > 1, are + then split into individual symbols. + + Order is not conserved. This pass is ignored if reorder is not allowed. */ +static std::vector +partition_over_target_split (partition_set& p) +{ + gcc_assert (p.n_partitions >= 1); + + std::vector all; + partition_set small (p.data); + + int64_t target_size = p.insns / p.n_partitions; + + for (ltrans_partition g: p.sym_groups) + { + if (g->insns > target_size + && (p.data.reorder || is_partition_reorder (g))) + all.push_back (partition_set (p.data, {g})); + else + small.push (g); + } + + if (all.empty ()) + return {}; + + if (small.sym_groups.size ()) + { + /* Handles special case where n_partitions might be smaller than + all.size (). Which can happen as result of interger division or with + 0 sized partition_sets. Then also prevents too small symbol group. + This should also be a special case; more common one, + but with no correctness problems. */ + if (all.size () && ( + small.insns < (int64_t) p.n_partitions + || small.insns < target_size * 0.6 + || small.insns < param_min_partition_size)) + { + size_t idx = 0; + int64_t min_insns = std::numeric_limits::max (); + for (size_t i = 0; i < all.size (); ++i) + { + if (all[i].insns < min_insns) + { + min_insns = all[i].insns; + idx = i; + } + } + + gcc_assert (all[idx].sym_groups.size () == 1); + + ltrans_partition& into = all[idx].sym_groups[0]; + for (ltrans_partition g: small.sym_groups) + into = join_partitions (into, g); + + all[idx].insns = into->insns; + } + else + { + gcc_assert (all.size () < p.n_partitions); + all.push_back (std::move (small)); + } + } + + distribute_n_partitions (all, p.n_partitions); + + for (partition_set& p: all) + { + gcc_assert (p.sym_groups.size ()); + + /* Handles large symbol groups (large files) that will be + further divided. */ + if (p.sym_groups.size () == 1 && p.n_partitions > 1) + { + p.sym_groups = split_partition_into_nodes (p.sym_groups[0]); + p.data.reorder = false; + p.data.splitable = false; + } + } + + return all; +} + +/* Splits partition_set into two partition_sets with + equal or off by one n_partitions. + Order is conserved. */ +static std::vector +partition_binary_split (partition_set& p) +{ + gcc_assert (p.n_partitions > 1); + + if (p.sym_groups.size () < 2) + return {}; + + int64_t target_size = p.insns / p.n_partitions; + + + std::vector result (2, partition_set (p.data)); + partition_set& first = result[0]; + partition_set& second = result[1]; + + first.n_partitions = p.n_partitions/2; + second.n_partitions = p.n_partitions - first.n_partitions; + + int64_t first_target_size = first.n_partitions * target_size; + + int64_t insns = 0; + for (ltrans_partition g: p.sym_groups) + { + /* We want at least one symbol in first partition. */ + if (first.empty ()) + first.push (g); + else if (insns < first_target_size) + { + if (insns + g->insns < first_target_size) + first.push (g); + else + { + /* Target splitting point is in this symbol group. */ + int64_t diff_first = first_target_size - insns; + int64_t diff_second = (insns + g->insns) - first_target_size; + + if (diff_first * second.n_partitions + > diff_second * first.n_partitions) + first.push (g); + else + second.push (g); + } + } + else + second.push (g); + + insns += g->insns; + } + + return result; +} + +/* Split partition_set into 'into' partition_sets with equal or off by one + number of symbol groups. Sizes of symbol groups are ignored for deciding + where to split. n_partitions is then distributed among new partition_sets + based on their sizes. + Order in conserved. */ +static std::vector +partition_fixed_split (partition_set& p, size_t into) +{ + gcc_assert (into < p.n_partitions); + + std::vector result; + + for (size_t i = 0; i < into; ++i) + { + size_t begin = i * p.sym_groups.size () / into; + size_t end = (i + 1) * p.sym_groups.size () / into; + + auto it = p.sym_groups.begin (); + result.push_back (partition_set (p.data, {it + begin, it + end})); + } + + distribute_n_partitions (result, p.n_partitions); + + return result; +} + + +/* Base implementation to inherit from for all Partitioners. */ +class partitioner_base { +public: + /* Partitions sym_groups into n_partitions partitions inserted into + ltrans_partitions. */ + void + apply (std::vector& sym_groups, int n_partitions) + { + partition_set p (partition_set::metadata (true, true), + std::move (sym_groups), n_partitions); + split (p, 0); + } + +protected: + partitioner_base (int64_t min_partition_size, int64_t max_partition_size): + min_partition_size (min_partition_size), + max_partition_size (max_partition_size) + { + gcc_assert (min_partition_size != 0); + gcc_assert (max_partition_size != 0); + } + virtual ~partitioner_base () + {} + + /* Joins all symbol groups into one finalized partition. */ + void + finalize (partition_set& p) + { + ltrans_partition joined = NULL; + + for (ltrans_partition g: p.sym_groups) + joined = join_partitions (joined, g); + + if (joined) + ltrans_partitions.safe_push (joined); + } + + /* Splits all partition_sets. */ + void + split_list (std::vector& ps, uintptr_t state) + { + for (partition_set& p: ps) + split (p, state); + } + + /* Handles common cases: + too large or small n_partitions, or n_partitions = 1. + And then calls split_state. */ + void + split (partition_set& p, uintptr_t state) + { + size_t min_partitions = p.insns / max_partition_size + 1; + size_t max_partitions = p.insns / min_partition_size; + if (!p.data.splitable) + max_partitions = std::min (max_partitions, p.sym_groups.size ()); + + p.n_partitions = std::max (p.n_partitions, min_partitions); + p.n_partitions = std::min (p.n_partitions, max_partitions); + + if (p.n_partitions <= 1) + return finalize (p); + + split_state (p, state); + } + + /* State machine for specific partitioner implementation. */ + virtual void + split_state (partition_set& p, uintptr_t state) = 0; + + int64_t min_partition_size, max_partition_size; +}; + + +/* Partitioner combining fixed, over_target, and binary partitionings. */ +class partitioner_default: public partitioner_base +{ +public: + partitioner_default (int64_t min_partition_size, int64_t max_partition_size): + partitioner_base (min_partition_size, max_partition_size) + {} + +private: + virtual void + split_state (partition_set& p, uintptr_t state) + { + const uintptr_t FIXED = 0; + const uintptr_t OVER_TARGET = 1; + const uintptr_t BINARY = 2; + + std::vector ps; + + switch (state) + { + case FIXED: + if (p.n_partitions > 64 && p.sym_groups.size () >= 4) + { + ps = partition_fixed_split (p, 4); + split_list (ps, OVER_TARGET); + break; + } + + /* FALLTHROUGH */ + case OVER_TARGET: + ps = partition_over_target_split (p); + if (!ps.empty ()) + { + split_list (ps, BINARY); + break; + } + + /* FALLTHROUGH */ + case BINARY: + ps = partition_binary_split (p); + if (!ps.empty ()) + { + split_list (ps, OVER_TARGET); + break; + } + + /* FALLTHROUGH */ + default: + finalize (p); + } + } +}; + +/* Group cgraph nodes into equally-sized partitions. + It tries to keep symbols from single source file together to minimize + propagation of divergence. + + It starts with symbols already grouped by source files. If reasonably + possible it only either combines several files into one final partition, + or, if a file is large, split the file into several final partitions. + + Intermediate representation is partition_set which contains set of + groups of symbols (each group corresponding to original source file) and + number of final partitions this partition_set should split into. + + First partition_fixed_split splits partition_set into constant number of + partition_sets with equal number of symbols groups. If for example there + are 39 source files, the resulting partition_sets will contain 10, 10, + 10, and 9 source files. This splitting intentionally ignores estimated + instruction counts to minimize propagation of divergence. + + Second partition_over_target_split separates too large files and splits + them into individual symbols to be combined back into several smaller + files in next step. + + Third partition_binary_split splits partition_set into two halves until + it should be split into only one final partition, at which point the + remaining symbols are joined into one final partition. +*/ + +void +lto_cache_map (int n_lto_partitions, int max_partition_size) +{ + lto_1_to_1_map (); + + std::vector partitions; + for (unsigned i = 0; i < ltrans_partitions.length (); ++i) + { + ltrans_partition part = ltrans_partitions[i]; + partitions.push_back (part); + } + ltrans_partitions.truncate (0); + + partitioner_default partitioner = partitioner_default + (param_min_partition_size, max_partition_size); + + partitioner.apply (partitions, n_lto_partitions); +} /* Group cgraph nodes into equally-sized partitions. diff --git a/gcc/lto/lto-partition.h b/gcc/lto/lto-partition.h index 8ac7c367577..c139dee0e0d 100644 --- a/gcc/lto/lto-partition.h +++ b/gcc/lto/lto-partition.h @@ -35,6 +35,7 @@ extern vec ltrans_partitions; void lto_1_to_1_map (void); void lto_max_map (void); +void lto_cache_map (int, int); void lto_balanced_map (int, int); void lto_promote_cross_file_statics (void); void free_ltrans_partitions (void); diff --git a/gcc/lto/lto.cc b/gcc/lto/lto.cc index 91aa2fbddb4..58ff0c45f57 100644 --- a/gcc/lto/lto.cc +++ b/gcc/lto/lto.cc @@ -554,6 +554,8 @@ do_whole_program_analysis (void) else if (flag_lto_partition == LTO_PARTITION_BALANCED) lto_balanced_map (param_lto_partitions, param_max_partition_size); + else if (flag_lto_partition == LTO_PARTITION_CACHE) + lto_cache_map (param_lto_partitions, param_max_partition_size); else gcc_unreachable (); diff --git a/gcc/m2/ChangeLog b/gcc/m2/ChangeLog index 80523f0eb25..73f4efa0e49 100644 --- a/gcc/m2/ChangeLog +++ b/gcc/m2/ChangeLog @@ -1,3 +1,13 @@ +2024-06-06 Gaius Mulley + Kewen.Lin + + * gm2-gcc/m2type.cc (build_m2_short_real_node): Rewrite + to use the default float_type_node. + (build_m2_real_node): Rewrite to use the default + double_type_node. + (build_m2_long_real_node): Rewrite to use the default + long_double_type_node or float128_type_node. + 2024-05-21 Gaius Mulley * Make-lang.in (MC_EXTENDED_OPAQUE): New definition. diff --git a/gcc/m2/gm2-gcc/m2type.cc b/gcc/m2/gm2-gcc/m2type.cc index 571923c08ef..5773a5cbd19 100644 --- a/gcc/m2/gm2-gcc/m2type.cc +++ b/gcc/m2/gm2-gcc/m2type.cc @@ -1415,45 +1415,29 @@ build_m2_char_node (void) static tree build_m2_short_real_node (void) { - tree c; - - /* Define `REAL'. */ - - c = make_node (REAL_TYPE); - TYPE_PRECISION (c) = FLOAT_TYPE_SIZE; - layout_type (c); - return c; + /* Define `SHORTREAL'. */ + ASSERT_CONDITION (TYPE_PRECISION (float_type_node) == FLOAT_TYPE_SIZE); + return float_type_node; } static tree build_m2_real_node (void) { - tree c; - /* Define `REAL'. */ - - c = make_node (REAL_TYPE); - TYPE_PRECISION (c) = DOUBLE_TYPE_SIZE; - layout_type (c); - return c; + ASSERT_CONDITION (TYPE_PRECISION (double_type_node) == DOUBLE_TYPE_SIZE); + return double_type_node; } static tree build_m2_long_real_node (void) { tree longreal; - + /* Define `LONGREAL'. */ - if (M2Options_GetIBMLongDouble ()) - { - longreal = make_node (REAL_TYPE); - TYPE_PRECISION (longreal) = LONG_DOUBLE_TYPE_SIZE; - } - else if (M2Options_GetIEEELongDouble ()) + if (M2Options_GetIEEELongDouble ()) longreal = float128_type_node; else longreal = long_double_type_node; - layout_type (longreal); return longreal; } diff --git a/gcc/match.pd b/gcc/match.pd index 480e36bbbaf..5cfe81e80b3 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -633,7 +633,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) if (TYPE_OVERFLOW_UNDEFINED (type)) { #if GIMPLE - value_range vr0; + int_range_max vr0; if (ovf1 == wi::OVF_NONE && ovf2 == wi::OVF_NONE && get_global_range_query ()->range_of_expr (vr0, @4) && !vr0.varying_p () && !vr0.undefined_p ()) @@ -674,7 +674,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) if (TYPE_OVERFLOW_UNDEFINED (type)) { #if GIMPLE - value_range vr0; + int_range_max vr0; if (ovf1 == wi::OVF_NONE && ovf2 == wi::OVF_NONE && get_global_range_query ()->range_of_expr (vr0, @0) && !vr0.varying_p () && !vr0.undefined_p ()) @@ -957,7 +957,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (TYPE_OVERFLOW_UNDEFINED (type) && !TYPE_OVERFLOW_SANITIZED (type)) @0 #if GIMPLE - (with {value_range vr0, vr1;} + (with {int_range_max vr0, vr1;} (if (INTEGRAL_TYPE_P (type) && get_range_query (cfun)->range_of_expr (vr0, @0) && get_range_query (cfun)->range_of_expr (vr1, @1) @@ -973,7 +973,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && wi::multiple_of_p (wi::to_widest (@1), wi::to_widest (@2), SIGNED)) (if (TYPE_OVERFLOW_UNDEFINED (type) && !TYPE_OVERFLOW_SANITIZED (type)) (mult @0 (div! @1 @2)) - (with {value_range vr0, vr1;} + (with {int_range_max vr0, vr1;} (if (get_range_query (cfun)->range_of_expr (vr0, @0) && get_range_query (cfun)->range_of_expr (vr1, @1) && range_op_handler (MULT_EXPR).overflow_free_p (vr0, vr1)) @@ -988,7 +988,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (TYPE_OVERFLOW_UNDEFINED (type) && !TYPE_OVERFLOW_SANITIZED (type)) (div @1 @2) #if GIMPLE - (with {value_range vr0, vr1, vr2;} + (with {int_range_max vr0, vr1, vr2;} (if (get_range_query (cfun)->range_of_expr (vr0, @0) && get_range_query (cfun)->range_of_expr (vr1, @1) && get_range_query (cfun)->range_of_expr (vr2, @2) @@ -1003,7 +1003,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* Simplify (X + M*N) / N -> X / N + M. */ (simplify (div (plus:c@4 @0 (mult:c@3 @1 @2)) @2) - (with {value_range vr0, vr1, vr2, vr3, vr4;} + (with {int_range_max vr0, vr1, vr2, vr3, vr4;} (if (INTEGRAL_TYPE_P (type) && get_range_query (cfun)->range_of_expr (vr1, @1) && get_range_query (cfun)->range_of_expr (vr2, @2) @@ -1024,7 +1024,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* Simplify (X - M*N) / N -> X / N - M. */ (simplify (div (minus@4 @0 (mult:c@3 @1 @2)) @2) - (with {value_range vr0, vr1, vr2, vr3, vr4;} + (with {int_range_max vr0, vr1, vr2, vr3, vr4;} (if (INTEGRAL_TYPE_P (type) && get_range_query (cfun)->range_of_expr (vr1, @1) && get_range_query (cfun)->range_of_expr (vr2, @2) @@ -1057,7 +1057,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) : wi::div_trunc (v, n, TYPE_SIGN (type))) #define exact_mod(v) (shift ? wi::ctz (v) >= n.to_shwi () \ : wi::multiple_of_p (v, n, TYPE_SIGN (type))) - value_range vr0, vr1, vr3; + int_range_max vr0, vr1, vr3; } (if (INTEGRAL_TYPE_P (type) && get_range_query (cfun)->range_of_expr (vr0, @0)) @@ -2867,7 +2867,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) { constant_boolean_node (cmp == NE_EXPR, type); }))) /* ((X inner_op C0) outer_op C1) - With X being a tree where value_range has reasoned certain bits to always be + With X being a tree where range has reasoned certain bits to always be zero throughout its computed value range, inner_op = {|,^}, outer_op = {|,^} and inner_op != outer_op where zero_mask has 1's for all bits that are sure to be 0 in @@ -3056,31 +3056,48 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && wi::eq_p (wi::to_wide (int_cst), wi::max_value (itype)))))) /* Unsigned Saturation Add */ +/* SAT_ADD = usadd_left_part_1 | usadd_right_part_1, aka: + SAT_ADD = (X + Y) | -((X + Y) < X) */ (match (usadd_left_part_1 @0 @1) (plus:c @0 @1) (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) && types_match (type, @0, @1)))) +/* SAT_ADD = usadd_left_part_2 | usadd_right_part_2, aka: + SAT_ADD = REALPART_EXPR <.ADD_OVERFLOW> | (IMAGPART_EXPR <.ADD_OVERFLOW> != 0) */ (match (usadd_left_part_2 @0 @1) (realpart (IFN_ADD_OVERFLOW:c @0 @1)) (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) && types_match (type, @0, @1)))) +/* SAT_ADD = usadd_left_part_1 | usadd_right_part_1, aka: + SAT_ADD = (X + Y) | -((type)(X + Y) < X) */ (match (usadd_right_part_1 @0 @1) (negate (convert (lt (plus:c @0 @1) @0))) (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) && types_match (type, @0, @1)))) +/* SAT_ADD = usadd_left_part_1 | usadd_right_part_1, aka: + SAT_ADD = (X + Y) | -(X > (X + Y)) */ (match (usadd_right_part_1 @0 @1) (negate (convert (gt @0 (plus:c @0 @1)))) (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) && types_match (type, @0, @1)))) +/* SAT_ADD = usadd_left_part_2 | usadd_right_part_2, aka: + SAT_ADD = REALPART_EXPR <.ADD_OVERFLOW> | (IMAGPART_EXPR <.ADD_OVERFLOW> != 0) */ (match (usadd_right_part_2 @0 @1) (negate (convert (ne (imagpart (IFN_ADD_OVERFLOW:c @0 @1)) integer_zerop))) (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) && types_match (type, @0, @1)))) +/* SAT_ADD = usadd_left_part_2 | usadd_right_part_2, aka: + SAT_ADD = REALPART_EXPR <.ADD_OVERFLOW> | -IMAGPART_EXPR <.ADD_OVERFLOW> */ +(match (usadd_right_part_2 @0 @1) + (negate (imagpart (IFN_ADD_OVERFLOW:c @0 @1))) + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) + && types_match (type, @0, @1)))) + /* We cannot merge or overload usadd_left_part_1 and usadd_left_part_2 because the sub part of left_part_2 cannot work with right_part_1. For example, left_part_2 pattern focus one .ADD_OVERFLOW but the @@ -3092,10 +3109,62 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (match (unsigned_integer_sat_add @0 @1) (bit_ior:c (usadd_left_part_1 @0 @1) (usadd_right_part_1 @0 @1))) -/* Unsigned saturation add, case 2 (branchless with .ADD_OVERFLOW). */ +/* Unsigned saturation add, case 2 (branchless with .ADD_OVERFLOW): + SAT_ADD = REALPART_EXPR <.ADD_OVERFLOW> | -IMAGPART_EXPR <.ADD_OVERFLOW> or + SAT_ADD = REALPART_EXPR <.ADD_OVERFLOW> | (IMAGPART_EXPR <.ADD_OVERFLOW> != 0) */ (match (unsigned_integer_sat_add @0 @1) (bit_ior:c (usadd_left_part_2 @0 @1) (usadd_right_part_2 @0 @1))) +/* Unsigned saturation add, case 3 (branch with ge): + SAT_U_ADD = (X + Y) >= x ? (X + Y) : -1. */ +(match (unsigned_integer_sat_add @0 @1) + (cond^ (ge (usadd_left_part_1@2 @0 @1) @0) @2 integer_minus_onep)) + +/* Unsigned saturation add, case 4 (branch with lt): + SAT_U_ADD = (X + Y) < x ? -1 : (X + Y). */ +(match (unsigned_integer_sat_add @0 @1) + (cond^ (lt (usadd_left_part_1@2 @0 @1) @0) integer_minus_onep @2)) + +/* Unsigned saturation add, case 5 (branch with eq .ADD_OVERFLOW): + SAT_U_ADD = REALPART_EXPR <.ADD_OVERFLOW> == 0 ? .ADD_OVERFLOW : -1. */ +(match (unsigned_integer_sat_add @0 @1) + (cond^ (eq (imagpart (IFN_ADD_OVERFLOW:c @0 @1)) integer_zerop) + (usadd_left_part_2 @0 @1) integer_minus_onep)) + +/* Unsigned saturation add, case 6 (branch with ne .ADD_OVERFLOW): + SAT_U_ADD = REALPART_EXPR <.ADD_OVERFLOW> != 0 ? -1 : .ADD_OVERFLOW. */ +(match (unsigned_integer_sat_add @0 @1) + (cond^ (ne (imagpart (IFN_ADD_OVERFLOW:c @0 @1)) integer_zerop) + integer_minus_onep (usadd_left_part_2 @0 @1))) + +/* Unsigned saturation sub, case 1 (branch with gt): + SAT_U_SUB = X > Y ? X - Y : 0 */ +(match (unsigned_integer_sat_sub @0 @1) + (cond (gt @0 @1) (minus @0 @1) integer_zerop) + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) + && types_match (type, @0, @1)))) + +/* Unsigned saturation sub, case 2 (branch with ge): + SAT_U_SUB = X >= Y ? X - Y : 0. */ +(match (unsigned_integer_sat_sub @0 @1) + (cond (ge @0 @1) (minus @0 @1) integer_zerop) + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) + && types_match (type, @0, @1)))) + +/* Unsigned saturation sub, case 3 (branchless with gt): + SAT_U_SUB = (X - Y) * (X > Y). */ +(match (unsigned_integer_sat_sub @0 @1) + (mult:c (minus @0 @1) (convert (gt @0 @1))) + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) + && types_match (type, @0, @1)))) + +/* Unsigned saturation sub, case 4 (branchless with ge): + SAT_U_SUB = (X - Y) * (X >= Y). */ +(match (unsigned_integer_sat_sub @0 @1) + (mult:c (minus @0 @1) (convert (ge @0 @1))) + (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) + && types_match (type, @0, @1)))) + /* x > y && x != XXX_MIN --> x > y x > y && x == XXX_MIN --> false . */ (for eqne (eq ne) @@ -3674,7 +3743,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) = wide_int::from (wi::to_wide (@1), TYPE_PRECISION (inner_type), TYPE_SIGN (inner_type)); - value_range vr; + int_range_max vr; if (get_global_range_query ()->range_of_expr (vr, @0) && !vr.varying_p () && !vr.undefined_p ()) { @@ -5520,7 +5589,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && (wi::to_widest (@2) + 1 == wi::to_widest (@3) || wi::to_widest (@2) == wi::to_widest (@3) + 1)) (with { - value_range r; + int_range_max r; get_range_query (cfun)->range_of_expr (r, @0); if (r.undefined_p ()) r.set_varying (TREE_TYPE (@0)); diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index 2c095200d5b..0b61335dba4 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -144,7 +144,11 @@ omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2, case LE_EXPR: if (POINTER_TYPE_P (TREE_TYPE (*n2))) - *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1); + { + tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v))); + gcc_assert (TREE_CODE (unit) == INTEGER_CST); + *n2 = fold_build_pointer_plus_loc (loc, *n2, unit); + } else *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2, build_int_cst (TREE_TYPE (*n2), 1)); @@ -152,7 +156,14 @@ omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2, break; case GE_EXPR: if (POINTER_TYPE_P (TREE_TYPE (*n2))) - *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1); + { + tree unit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (v))); + gcc_assert (TREE_CODE (unit) == INTEGER_CST); + unit = convert_to_ptrofftype_loc (loc, unit); + unit = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (unit), + unit); + *n2 = fold_build_pointer_plus_loc (loc, *n2, unit); + } else *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2, build_int_cst (TREE_TYPE (*n2), 1)); @@ -3789,5 +3800,480 @@ debug_omp_tokenized_addr (vec &addr_tokens, fputs ("\n", stderr); } +/* Return number of iterations of loop I in FOR_STMT. If PSTEP is non-NULL, + *PSTEP will be the loop step. */ + +tree +omp_loop_number_of_iterations (tree for_stmt, int i, tree *pstep) +{ + tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i); + gcc_assert (TREE_CODE (t) == MODIFY_EXPR); + tree decl = TREE_OPERAND (t, 0); + tree n1 = TREE_OPERAND (t, 1); + tree type = TREE_TYPE (decl); + tree cond = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i); + gcc_assert (COMPARISON_CLASS_P (cond)); + gcc_assert (TREE_OPERAND (cond, 0) == decl); + tree_code cond_code = TREE_CODE (cond); + tree n2 = TREE_OPERAND (cond, 1); + t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i); + tree step = NULL_TREE; + switch (TREE_CODE (t)) + { + case PREINCREMENT_EXPR: + case POSTINCREMENT_EXPR: + gcc_assert (!POINTER_TYPE_P (type)); + gcc_assert (TREE_OPERAND (t, 0) == decl); + step = build_int_cst (type, 1); + break; + case PREDECREMENT_EXPR: + case POSTDECREMENT_EXPR: + gcc_assert (!POINTER_TYPE_P (type)); + gcc_assert (TREE_OPERAND (t, 0) == decl); + step = build_int_cst (type, -1); + break; + case MODIFY_EXPR: + gcc_assert (TREE_OPERAND (t, 0) == decl); + t = TREE_OPERAND (t, 1); + switch (TREE_CODE (t)) + { + case PLUS_EXPR: + if (TREE_OPERAND (t, 1) == decl) + { + TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0); + TREE_OPERAND (t, 0) = decl; + } + /* FALLTHRU */ + case POINTER_PLUS_EXPR: + case MINUS_EXPR: + step = omp_get_for_step_from_incr (EXPR_LOCATION (t), t); + break; + default: + gcc_unreachable (); + } + break; + default: + gcc_unreachable (); + } + omp_adjust_for_condition (EXPR_LOCATION (for_stmt), &cond_code, &n2, + decl, step); + if (pstep) + *pstep = step; + if (INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) < TYPE_PRECISION (long_long_integer_type_node)) + { + n1 = fold_convert (long_long_integer_type_node, n1); + n2 = fold_convert (long_long_integer_type_node, n2); + step = fold_convert (long_long_integer_type_node, step); + } + if (cond_code == LT_EXPR + || POINTER_TYPE_P (type) + || !TYPE_UNSIGNED (TREE_TYPE (n1))) + { + if (POINTER_TYPE_P (type)) + t = fold_build2 (POINTER_DIFF_EXPR, ssizetype, n2, n1); + else + t = fold_build2 (MINUS_EXPR, TREE_TYPE (n1), n2, n1); + t = fold_build2 (CEIL_DIV_EXPR, TREE_TYPE (t), t, step); + } + else + { + t = fold_build2 (MINUS_EXPR, type, n1, n2); + t = fold_build2 (CEIL_DIV_EXPR, type, t, + fold_build1 (NEGATE_EXPR, type, step)); + } + return t; +} + +/* Tile transformation: + Original loop: + + #pragma omp tile sizes(16, 32) + for (i = 0; i < k; ++i) + for (j = 0; j < 128; j += 2) + { + baz (i, j); + } + + Transformed loop: + #pragma omp tile sizes(16, 32) + for (i.0 = 0; i.0 < k; i.0 += 16) + for (j.0 = 0; j.0 < 128; j.0 += 64) + { + i = i.0; + i.1 = MIN_EXPR ; + goto ; + :; + j = j.0; + j.1 = j.0 + 32; + goto ; + :; + { + baz (i, j); + } + j += 2; + :; + if (j < j.1) goto ; else goto ; + :; + ++i; + :; + if (i < i.1) goto ; else goto ; + :; + } + + where the grid loops have canonical form, but the inner + loops don't and so are immediately lowered. */ + +static void +omp_apply_tile (tree for_stmt, tree sizes, int size) +{ + tree pre_body = NULL_TREE, post_body = NULL_TREE; + tree orig_sizes = sizes; + if (OMP_FOR_NON_RECTANGULAR (for_stmt)) + { + error_at (EXPR_LOCATION (for_stmt), "non-rectangular %"); + return; + } + for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++) + { + if (orig_sizes) + { + size = tree_to_uhwi (TREE_VALUE (sizes)); + sizes = TREE_CHAIN (sizes); + } + if (size == 1) + continue; + if (OMP_FOR_ORIG_DECLS (for_stmt) == NULL_TREE) + { + OMP_FOR_ORIG_DECLS (for_stmt) + = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))); + for (int j = 0; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++) + { + gcc_assert (TREE_CODE (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j)) + == MODIFY_EXPR); + TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), j) + = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j), 0); + } + } + tree step; + tree iters = omp_loop_number_of_iterations (for_stmt, i, &step); + tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i); + tree decl = TREE_OPERAND (t, 0); + tree type = TREE_TYPE (decl); + tree griddecl = create_tmp_var_raw (type); + DECL_CONTEXT (griddecl) = current_function_decl; + t = build1 (DECL_EXPR, void_type_node, griddecl); + append_to_statement_list (t, &OMP_FOR_PRE_BODY (for_stmt)); + TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i), 0) = griddecl; + TREE_PRIVATE (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i)) = 1; + tree cond = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i); + TREE_OPERAND (cond, 0) = griddecl; + tree ub = save_expr (TREE_OPERAND (cond, 1)); + TREE_OPERAND (cond, 1) = ub; + t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i); + if (TREE_CODE (cond) == NE_EXPR) + { + tree_code cond_code = TREE_CODE (cond); + omp_adjust_for_condition (EXPR_LOCATION (for_stmt), &cond_code, + &ub, griddecl, step); + TREE_SET_CODE (cond, cond_code); + } + step = save_expr (step); + tree gridstep = fold_build2 (MULT_EXPR, TREE_TYPE (step), + step, build_int_cst (TREE_TYPE (step), + size)); + if (POINTER_TYPE_P (type)) + t = build2 (POINTER_PLUS_EXPR, type, griddecl, + fold_convert (sizetype, gridstep)); + else + t = build2 (PLUS_EXPR, type, griddecl, gridstep); + t = build2 (MODIFY_EXPR, type, griddecl, t); + TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t; + t = build2 (MODIFY_EXPR, type, decl, griddecl); + append_to_statement_list (t, &pre_body); + if (POINTER_TYPE_P (type)) + t = build2 (POINTER_PLUS_EXPR, type, griddecl, + fold_convert (sizetype, gridstep)); + else + t = build2 (PLUS_EXPR, type, griddecl, gridstep); + bool minmax_needed = true; + if (TREE_CODE (iters) == INTEGER_CST) + { + wide_int witers = wi::to_wide (iters); + wide_int wsize = wide_int::from (size, witers.get_precision (), + TYPE_SIGN (TREE_TYPE (iters))); + if (wi::multiple_of_p (witers, wsize, TYPE_SIGN (TREE_TYPE (iters)))) + minmax_needed = false; + } + if (minmax_needed) + switch (TREE_CODE (cond)) + { + case LE_EXPR: + if (POINTER_TYPE_P (type)) + t = build2 (MIN_EXPR, type, t, + build2 (POINTER_PLUS_EXPR, type, ub, size_int (1))); + else + t = build2 (MIN_EXPR, type, t, + build2 (PLUS_EXPR, type, ub, build_one_cst (type))); + break; + case LT_EXPR: + t = build2 (MIN_EXPR, type, t, ub); + break; + case GE_EXPR: + if (POINTER_TYPE_P (type)) + t = build2 (MAX_EXPR, type, t, + build2 (POINTER_PLUS_EXPR, type, ub, size_int (-1))); + else + t = build2 (MAX_EXPR, type, t, + build2 (PLUS_EXPR, type, ub, + build_minus_one_cst (type))); + break; + case GT_EXPR: + t = build2 (MAX_EXPR, type, t, ub); + break; + default: + gcc_unreachable (); + } + tree end = create_tmp_var_raw (type); + DECL_CONTEXT (end) = current_function_decl; + end = build4 (TARGET_EXPR, type, end, t, NULL_TREE, NULL_TREE); + TREE_SIDE_EFFECTS (end) = 1; + append_to_statement_list (end, &pre_body); + tree lab1 = create_artificial_label (UNKNOWN_LOCATION); + tree lab2 = create_artificial_label (UNKNOWN_LOCATION); + t = build1 (GOTO_EXPR, void_type_node, lab2); + append_to_statement_list (t, &pre_body); + t = build1 (LABEL_EXPR, void_type_node, lab1); + append_to_statement_list (t, &pre_body); + tree this_post_body = NULL_TREE; + if (POINTER_TYPE_P (type)) + t = build2 (POINTER_PLUS_EXPR, type, decl, + fold_convert (sizetype, step)); + else + t = build2 (PLUS_EXPR, type, decl, step); + t = build2 (MODIFY_EXPR, type, decl, t); + append_to_statement_list (t, &this_post_body); + t = build1 (LABEL_EXPR, void_type_node, lab2); + append_to_statement_list (t, &this_post_body); + t = build2 ((TREE_CODE (cond) == LT_EXPR || TREE_CODE (cond) == LE_EXPR) + ? LT_EXPR : GT_EXPR, boolean_type_node, decl, end); + if (orig_sizes == NULL_TREE) + { + gcc_assert (i == 0); + t = build3 (ANNOTATE_EXPR, TREE_TYPE (t), t, + build_int_cst (integer_type_node, + annot_expr_unroll_kind), + build_int_cst (integer_type_node, size)); + } + t = build3 (COND_EXPR, void_type_node, t, + build1 (GOTO_EXPR, void_type_node, lab1), NULL_TREE); + append_to_statement_list (t, &this_post_body); + append_to_statement_list (post_body, &this_post_body); + post_body = this_post_body; + } + if (pre_body || post_body) + { + append_to_statement_list (OMP_FOR_BODY (for_stmt), &pre_body); + append_to_statement_list (post_body, &pre_body); + OMP_FOR_BODY (for_stmt) = pre_body; + } +} + +/* Callback for walk_tree to find nested loop transforming construct. */ + +static tree +find_nested_loop_xform (tree *tp, int *walk_subtrees, void *data) +{ + tree **pdata = (tree **) data; + *walk_subtrees = 0; + switch (TREE_CODE (*tp)) + { + case OMP_TILE: + case OMP_UNROLL: + pdata[1] = tp; + return *tp; + case BIND_EXPR: + if (BIND_EXPR_VARS (*tp) + || (BIND_EXPR_BLOCK (*tp) + && BLOCK_VARS (BIND_EXPR_BLOCK (*tp)))) + pdata[0] = tp; + *walk_subtrees = 1; + break; + case STATEMENT_LIST: + if (!tsi_one_before_end_p (tsi_start (*tp))) + pdata[0] = tp; + *walk_subtrees = 1; + break; + case TRY_FINALLY_EXPR: + pdata[0] = tp; + *walk_subtrees = 1; + break; + default: + break; + } + return NULL; +} + +/* Main entry point for performing OpenMP loop transformations. */ + +void +omp_maybe_apply_loop_xforms (tree *expr_p, tree for_clauses) +{ + tree for_stmt = *expr_p; + + switch (TREE_CODE (for_stmt)) + { + case OMP_TILE: + case OMP_UNROLL: + if (OMP_LOOPXFORM_LOWERED (for_stmt)) + return; + break; + default: + break; + } + + tree *inner_expr_p = expr_p; + tree inner_for_stmt = for_stmt; + for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++) + { + /* If some loop nest needs one or more loops in canonical form + from nested loop transforming constructs, first perform the + loop transformation on the nested construct and then move over + the corresponding loops in canonical form from the inner construct + to the outer one. */ + if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i) == NULL_TREE) + { + if (inner_for_stmt == for_stmt + && omp_find_clause (for_clauses ? for_clauses + : OMP_FOR_CLAUSES (for_stmt), + OMP_CLAUSE_ORDERED)) + { + error_at (EXPR_LOCATION (for_stmt), + "% clause used with generated loops"); + *expr_p = void_node; + return; + } + tree *data[2] = { NULL, NULL }; + walk_tree (&OMP_FOR_BODY (inner_for_stmt), + find_nested_loop_xform, &data, NULL); + gcc_assert (data[1]); + if (data[0]) + { + /* If there is a BIND_EXPR declaring some vars, or statement + list with more than one stmt etc., move the intervening + code around the outermost loop. */ + tree t = *inner_expr_p; + *inner_expr_p = OMP_FOR_BODY (inner_for_stmt); + OMP_FOR_BODY (inner_for_stmt) = *data[1]; + *data[1] = t; + inner_expr_p = data[1]; + data[1] = &OMP_FOR_BODY (inner_for_stmt); + } + inner_for_stmt = *data[1]; + + omp_maybe_apply_loop_xforms (data[1], NULL_TREE); + if (*data[1] != inner_for_stmt) + { + tree *data2[2] = { NULL, NULL }; + walk_tree (data[1], find_nested_loop_xform, &data2, NULL); + gcc_assert (data2[1] + && *data2[1] == inner_for_stmt + && data2[0]); + tree t = *inner_expr_p; + *inner_expr_p = *data[1]; + *data[1] = *data2[1]; + *data2[1] = t; + inner_expr_p = data2[1]; + } + tree clauses = OMP_FOR_CLAUSES (inner_for_stmt); + gcc_checking_assert (TREE_CODE (inner_for_stmt) != OMP_UNROLL + || omp_find_clause (clauses, + OMP_CLAUSE_PARTIAL)); + append_to_statement_list (OMP_FOR_PRE_BODY (inner_for_stmt), + &OMP_FOR_PRE_BODY (for_stmt)); + OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE; + if (OMP_FOR_ORIG_DECLS (for_stmt) == NULL_TREE + && OMP_FOR_ORIG_DECLS (inner_for_stmt) != NULL_TREE) + { + OMP_FOR_ORIG_DECLS (for_stmt) + = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))); + for (int j = 0; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); + j++) + { + if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j) == NULL_TREE) + continue; + gcc_assert (TREE_CODE (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), + j)) == MODIFY_EXPR); + TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), j) + = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j), + 0); + } + } + for (int j = 0; j < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); + ++j) + { + if (i + j == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))) + break; + if (OMP_FOR_ORIG_DECLS (for_stmt)) + { + if (OMP_FOR_ORIG_DECLS (inner_for_stmt)) + { + TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i + j) + = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), + j); + TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), j) + = NULL_TREE; + } + else + { + tree t = TREE_VEC_ELT (OMP_FOR_INIT (inner_for_stmt), j); + gcc_assert (TREE_CODE (t) == MODIFY_EXPR); + TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i + j) + = TREE_OPERAND (t, 0); + } + } + TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i + j) + = TREE_VEC_ELT (OMP_FOR_INIT (inner_for_stmt), j); + TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i + j) + = TREE_VEC_ELT (OMP_FOR_COND (inner_for_stmt), j); + TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i + j) + = TREE_VEC_ELT (OMP_FOR_INCR (inner_for_stmt), j); + TREE_VEC_ELT (OMP_FOR_INIT (inner_for_stmt), j) = NULL_TREE; + TREE_VEC_ELT (OMP_FOR_COND (inner_for_stmt), j) = NULL_TREE; + TREE_VEC_ELT (OMP_FOR_INCR (inner_for_stmt), j) = NULL_TREE; + } + } + } + + switch (TREE_CODE (for_stmt)) + { + case OMP_TILE: + tree sizes; + sizes = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_SIZES); + omp_apply_tile (for_stmt, OMP_CLAUSE_SIZES_LIST (sizes), 0); + OMP_LOOPXFORM_LOWERED (for_stmt) = 1; + break; + case OMP_UNROLL: + tree partial; + partial = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), + OMP_CLAUSE_PARTIAL); + if (partial) + omp_apply_tile (for_stmt, NULL_TREE, + OMP_CLAUSE_PARTIAL_EXPR (partial) + ? tree_to_shwi (OMP_CLAUSE_PARTIAL_EXPR (partial)) + : 8); + else if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_FULL)) + { + tree iters = omp_loop_number_of_iterations (for_stmt, 0, NULL); + if (TREE_CODE (iters) != INTEGER_CST) + error_at (EXPR_LOCATION (for_stmt), + "non-constant iteration count of % loop"); + } + OMP_LOOPXFORM_LOWERED (for_stmt) = 1; + break; + default: + break; + } +} #include "gt-omp-general.h" diff --git a/gcc/omp-general.h b/gcc/omp-general.h index b7d85a768ce..37f0548befd 100644 --- a/gcc/omp-general.h +++ b/gcc/omp-general.h @@ -283,4 +283,7 @@ typedef omp_addr_tokenizer::omp_addr_token omp_addr_token; extern bool omp_parse_expr (vec &, tree); +extern tree omp_loop_number_of_iterations (tree, int, tree * = NULL); +extern void omp_maybe_apply_loop_xforms (tree *, tree); + #endif /* GCC_OMP_GENERAL_H */ diff --git a/gcc/optabs.def b/gcc/optabs.def index 3f2cb46aff8..bc2611abdc2 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -118,8 +118,8 @@ OPTAB_NX(sub_optab, "sub$F$a3") OPTAB_NX(sub_optab, "sub$Q$a3") OPTAB_VL(subv_optab, "subv$I$a3", MINUS, "sub", '3', gen_intv_fp_libfunc) OPTAB_VX(subv_optab, "sub$F$a3") -OPTAB_NL(sssub_optab, "sssub$Q$a3", SS_MINUS, "sssub", '3', gen_signed_fixed_libfunc) -OPTAB_NL(ussub_optab, "ussub$Q$a3", US_MINUS, "ussub", '3', gen_unsigned_fixed_libfunc) +OPTAB_NL(sssub_optab, "sssub$a3", SS_MINUS, "sssub", '3', gen_signed_fixed_libfunc) +OPTAB_NL(ussub_optab, "ussub$a3", US_MINUS, "ussub", '3', gen_unsigned_fixed_libfunc) OPTAB_NL(smul_optab, "mul$Q$a3", MULT, "mul", '3', gen_int_fp_fixed_libfunc) OPTAB_NX(smul_optab, "mul$P$a3") OPTAB_NX(smul_optab, "mul$F$a3") diff --git a/gcc/opts.cc b/gcc/opts.cc index 4954984148d..1b1b46455af 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -2961,7 +2961,8 @@ common_handle_option (struct gcc_options *opts, { const char *basename = (opts->x_dump_base_name ? opts->x_dump_base_name : opts->x_main_input_basename); - diagnostic_output_format_init (dc, basename, + diagnostic_output_format_init (dc, + opts->x_main_input_filename, basename, (enum diagnostics_output_format)value, opts->x_flag_diagnostics_json_formatting); break; @@ -3305,7 +3306,6 @@ common_handle_option (struct gcc_options *opts, break; case OPT_fuse_ld_bfd: - case OPT_fuse_ld_classic: case OPT_fuse_ld_gold: case OPT_fuse_ld_lld: case OPT_fuse_ld_mold: diff --git a/gcc/pair-fusion.cc b/gcc/pair-fusion.cc index 9f897ac04e2..26b2284ed37 100644 --- a/gcc/pair-fusion.cc +++ b/gcc/pair-fusion.cc @@ -426,7 +426,7 @@ pair_fusion_bb_info::track_access (insn_info *insn, bool load_p, rtx mem) return; // Ignore writeback accesses if the hook says to do so. - if (!m_pass->should_handle_writeback (writeback::EXISTING) + if (!m_pass->should_handle_writeback (writeback_type::EXISTING) && GET_RTX_CLASS (GET_CODE (XEXP (mem, 0))) == RTX_AUTOINC) return; @@ -1787,7 +1787,7 @@ pair_fusion_bb_info::fuse_pair (bool load_p, // update of the base register and try and fold it in to make this into a // writeback pair. insn_info *trailing_add = nullptr; - if (m_pass->should_handle_writeback (writeback::ALL) + if (m_pass->should_handle_writeback (writeback_type::ALL) && !writeback_effect && (!load_p || (!refers_to_regno_p (base_regno, base_regno + 1, XEXP (pats[0], 0), nullptr) @@ -2996,7 +2996,7 @@ void pair_fusion::process_block (bb_info *bb) rtx pat = PATTERN (rti); bool load_p; if (reload_completed - && should_handle_writeback (writeback::ALL) + && should_handle_writeback (writeback_type::ALL) && pair_mem_insn_p (rti, load_p)) try_promote_writeback (insn, load_p); diff --git a/gcc/pair-fusion.h b/gcc/pair-fusion.h index 2a38dc8f743..45e4edceecb 100644 --- a/gcc/pair-fusion.h +++ b/gcc/pair-fusion.h @@ -75,7 +75,7 @@ struct alias_walker; // When querying should_handle_writeback, this enum is used to // qualify which opportunities we are asking about. -enum class writeback { +enum class writeback_type { // Only those writeback opportunities that arise from existing // auto-increment accesses. EXISTING, @@ -123,7 +123,7 @@ struct pair_fusion { // Return true if we should try to handle writeback opportunities. // WHICH determines the kinds of writeback opportunities the caller // is asking about. - virtual bool should_handle_writeback (enum writeback which) = 0; + virtual bool should_handle_writeback (writeback_type which) = 0; // Given BASE_MEM, the mem from the lower candidate access for a pair, // and LOAD_P (true if the access is a load), check if we should proceed diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index ccf9d823870..c8ab0571e57 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -316,7 +316,7 @@ get_size_range (range_query *query, tree exp, gimple *stmt, tree range[2], if (integral) { - value_range vr; + int_range_max vr; tree tmin, tmax; query->range_of_expr (vr, exp, stmt); diff --git a/gcc/range-op.cc b/gcc/range-op.cc index d188d1a1b63..c576f688221 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -570,9 +570,9 @@ get_shift_range (irange &r, tree type, const irange &op) return false; // Build valid range and intersect it with the shift range. - r = value_range (op.type (), - wi::shwi (0, TYPE_PRECISION (op.type ())), - wi::shwi (TYPE_PRECISION (type) - 1, TYPE_PRECISION (op.type ()))); + r.set (op.type (), + wi::shwi (0, TYPE_PRECISION (op.type ())), + wi::shwi (TYPE_PRECISION (type) - 1, TYPE_PRECISION (op.type ()))); r.intersect (op); // If there are no valid ranges in the shift range, returned false. @@ -4055,13 +4055,13 @@ operator_trunc_mod::op1_range (irange &r, tree type, // (a % b) >= x && x > 0 , then a >= x. if (wi::gt_p (lhs.lower_bound (), 0, sign)) { - r = value_range (type, lhs.lower_bound (), wi::max_value (prec, sign)); + r.set (type, lhs.lower_bound (), wi::max_value (prec, sign)); return true; } // (a % b) <= x && x < 0 , then a <= x. if (wi::lt_p (lhs.upper_bound (), 0, sign)) { - r = value_range (type, wi::min_value (prec, sign), lhs.upper_bound ()); + r.set (type, wi::min_value (prec, sign), lhs.upper_bound ()); return true; } return false; @@ -4083,12 +4083,11 @@ operator_trunc_mod::op2_range (irange &r, tree type, if (wi::gt_p (lhs.lower_bound (), 0, sign)) { if (sign == SIGNED) - r = value_range (type, wi::neg (lhs.lower_bound ()), - lhs.lower_bound (), VR_ANTI_RANGE); + r.set (type, wi::neg (lhs.lower_bound ()), + lhs.lower_bound (), VR_ANTI_RANGE); else if (wi::lt_p (lhs.lower_bound (), wi::max_value (prec, sign), sign)) - r = value_range (type, lhs.lower_bound () + 1, - wi::max_value (prec, sign)); + r.set (type, lhs.lower_bound () + 1, wi::max_value (prec, sign)); else return false; return true; @@ -4097,8 +4096,8 @@ operator_trunc_mod::op2_range (irange &r, tree type, if (wi::lt_p (lhs.upper_bound (), 0, sign)) { if (wi::gt_p (lhs.upper_bound (), wi::min_value (prec, sign), sign)) - r = value_range (type, lhs.upper_bound (), - wi::neg (lhs.upper_bound ()), VR_ANTI_RANGE); + r.set (type, lhs.upper_bound (), + wi::neg (lhs.upper_bound ()), VR_ANTI_RANGE); else return false; return true; diff --git a/gcc/range.cc b/gcc/range.cc index b362e0f12e0..5ee0edc54f6 100644 --- a/gcc/range.cc +++ b/gcc/range.cc @@ -29,23 +29,23 @@ along with GCC; see the file COPYING3. If not see #include "ssa.h" #include "range.h" -value_range +int_range<2> range_positives (tree type) { unsigned prec = TYPE_PRECISION (type); signop sign = TYPE_SIGN (type); - return value_range (type, wi::zero (prec), wi::max_value (prec, sign)); + return int_range<2> (type, wi::zero (prec), wi::max_value (prec, sign)); } -value_range +int_range<2> range_negatives (tree type) { unsigned prec = TYPE_PRECISION (type); signop sign = TYPE_SIGN (type); - value_range r; + int_range<2> r; if (sign == UNSIGNED) r.set_undefined (); else - r = value_range (type, wi::min_value (prec, sign), wi::minus_one (prec)); + r.set (type, wi::min_value (prec, sign), wi::minus_one (prec)); return r; } diff --git a/gcc/range.h b/gcc/range.h index eccb9490e4d..e98dc2390a6 100644 --- a/gcc/range.h +++ b/gcc/range.h @@ -21,8 +21,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_RANGE_H #define GCC_RANGE_H -value_range range_positives (tree type); -value_range range_negatives (tree type); +int_range<2> range_positives (tree type); +int_range<2> range_negatives (tree type); // Return an irange instance that is a boolean TRUE. diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index 5caf1dfd957..9bc3ef9ad9f 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -2256,14 +2256,25 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode, switch (code) { case FIX: + /* According to IEEE standard, for conversions from floating point to + integer. When a NaN or infinite operand cannot be represented in + the destination format and this cannot otherwise be indicated, the + invalid operation exception shall be signaled. When a numeric + operand would convert to an integer outside the range of the + destination format, the invalid operation exception shall be + signaled if this situation cannot otherwise be indicated. */ if (REAL_VALUE_ISNAN (*x)) - return const0_rtx; + return flag_trapping_math ? NULL_RTX : const0_rtx; + + if (REAL_VALUE_ISINF (*x) && flag_trapping_math) + return NULL_RTX; /* Test against the signed upper bound. */ wmax = wi::max_value (width, SIGNED); real_from_integer (&t, VOIDmode, wmax, SIGNED); if (real_less (&t, x)) - return immed_wide_int_const (wmax, mode); + return (flag_trapping_math + ? NULL_RTX : immed_wide_int_const (wmax, mode)); /* Test against the signed lower bound. */ wmin = wi::min_value (width, SIGNED); @@ -2276,13 +2287,17 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode, case UNSIGNED_FIX: if (REAL_VALUE_ISNAN (*x) || REAL_VALUE_NEGATIVE (*x)) - return const0_rtx; + return flag_trapping_math ? NULL_RTX : const0_rtx; + + if (REAL_VALUE_ISINF (*x) && flag_trapping_math) + return NULL_RTX; /* Test against the unsigned upper bound. */ wmax = wi::max_value (width, UNSIGNED); real_from_integer (&t, VOIDmode, wmax, UNSIGNED); if (real_less (&t, x)) - return immed_wide_int_const (wmax, mode); + return (flag_trapping_math + ? NULL_RTX : immed_wide_int_const (wmax, mode)); return immed_wide_int_const (real_to_integer (x, &fail, width), mode); @@ -4050,6 +4065,31 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, return tem; } + /* (and:v4si + (ashiftrt:v4si A 16) + (const_vector: 0xffff x4)) + is just (lshiftrt:v4si A 16). */ + if (VECTOR_MODE_P (mode) && GET_CODE (op0) == ASHIFTRT + && (CONST_INT_P (XEXP (op0, 1)) + || (GET_CODE (XEXP (op0, 1)) == CONST_VECTOR + && CONST_VECTOR_DUPLICATE_P (XEXP (op0, 1)))) + && GET_CODE (op1) == CONST_VECTOR + && CONST_VECTOR_DUPLICATE_P (op1)) + { + unsigned HOST_WIDE_INT shift_count + = (CONST_INT_P (XEXP (op0, 1)) + ? UINTVAL (XEXP (op0, 1)) + : UINTVAL (XVECEXP (XEXP (op0, 1), 0, 0))); + unsigned HOST_WIDE_INT inner_prec + = GET_MODE_PRECISION (GET_MODE_INNER (mode)); + + /* Avoid UD shift count. */ + if (shift_count < inner_prec + && (UINTVAL (XVECEXP (op1, 0, 0)) + == (HOST_WIDE_INT_1U << (inner_prec - shift_count)) - 1)) + return simplify_gen_binary (LSHIFTRT, mode, XEXP (op0, 0), XEXP (op0, 1)); + } + tem = simplify_byte_swapping_operation (code, mode, op0, op1); if (tem) return tem; diff --git a/gcc/target.def b/gcc/target.def index 20561fc8060..70070caebc7 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4680,13 +4680,6 @@ if you would like to apply the same rules given by @code{PROMOTE_MODE}.", const_tree funtype, int for_return), default_promote_function_mode) -DEFHOOK -(promote_function_mode_ca, - "Like @code{promote_function_mode}, but takes a cumulative_args pointer \ - and a current arg to supply the input.", - machine_mode, (cumulative_args_t, function_arg_info, const_tree, int *, int), - default_promote_function_mode_ca) - DEFHOOK (promote_prototypes, "This target hook returns @code{true} if an argument declared in a\n\ @@ -4897,6 +4890,15 @@ Most ports do not need to implement anything for this hook.", void, (cumulative_args_t complete_args), hook_void_CUMULATIVE_ARGS) +DEFHOOK +(call_offset_return_label, + "While generating call-site debug info for a CALL insn, or a SEQUENCE\n\ +insn starting with a CALL, this target hook is invoked to compute the\n\ +offset to be added to the debug label emitted after the call to obtain\n\ +the return address that should be recorded as the return PC.", + int, (rtx_insn *call_insn), + hook_int_rtx_insn_0) + DEFHOOK (push_argument, "This target hook returns @code{true} if push instructions will be\n\ @@ -5140,18 +5142,6 @@ with the specified mode and type. The default hook returns\n\ unsigned int, (machine_mode mode, const_tree type), default_function_arg_boundary) -DEFHOOK -(function_arg_boundary_ca, - "This is the @code{cumulative_args_t}-based version of\n\ -@code{TARGET_FUNCTION_ARG_BOUNDARY}. Define this hook if you need more\n\ -fine-grained control over argument alignment, e.g. depending on whether\n\ -it is a named argument or not, or any other criteria that you choose to\n\ -place in the @var{ca} structure.\n\ -\n\ -The default hook will call @code{TARGET_FUNCTION_ARG_BOUNDARY}.", - unsigned int, (machine_mode mode, const_tree type, cumulative_args_t ca), - default_function_arg_boundary_ca) - DEFHOOK (function_arg_round_boundary, "Normally, the size of an argument is rounded up to @code{PARM_BOUNDARY},\n\ @@ -5161,18 +5151,6 @@ value.", unsigned int, (machine_mode mode, const_tree type), default_function_arg_round_boundary) -DEFHOOK -(function_arg_round_boundary_ca, - "This is the @code{cumulative_args_t}-based version of\n\ -@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. Define this hook if you need more\n\ -fine-grained control over argument size rounding, e.g. depending on whether\n\ -it is a named argument or not, or any other criteria that you choose to\n\ -place in the @var{ca} structure.\n\ -\n\ -The default hook will call @code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}.", - unsigned int, (machine_mode mode, const_tree type, cumulative_args_t ca), - default_function_arg_round_boundary_ca) - /* Return the diagnostic message string if function without a prototype is not allowed for this 'val' argument; NULL otherwise. */ DEFHOOK @@ -7420,16 +7398,6 @@ DEFHOOKPOD libatomic. The default value is false.", bool, false) -/* This value represents whether __builtin_unreachable should be expanded - as a trap instruction (or an abort() if the trap is not available). */ -DEFHOOK -(unreachable_should_trap, - "This hook should return @code{true} if the target wants \ - @code{__builtin_unreachable} to expand to a trap or @code{abort ()}.\n\ - The default value is false.", - bool, (void), - hook_bool_void_false) - /* Close the 'struct gcc_target' definition. */ HOOK_VECTOR_END (C90_EMPTY_HACK) diff --git a/gcc/target.h b/gcc/target.h index b51630a9782..c1f99b97b86 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -51,8 +51,22 @@ #include "insn-codes.h" #include "tm.h" #include "hard-reg-set.h" -#include "tree-core.h" -#include "cumulative-args.h" + +#if CHECKING_P + +struct cumulative_args_t { void *magic; void *p; }; + +#else /* !CHECKING_P */ + +/* When using a GCC build compiler, we could use + __attribute__((transparent_union)) to get cumulative_args_t function + arguments passed like scalars where the ABI would mandate a less + efficient way of argument passing otherwise. However, that would come + at the cost of less type-safe !CHECKING_P compilation. */ + +union cumulative_args_t { void *p; }; + +#endif /* !CHECKING_P */ /* Target properties of _BitInt(N) type. _BitInt(N) is to be represented as series of abi_limb_mode CEIL (N, GET_MODE_PRECISION (abi_limb_mode)) diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc index a529998f618..fb339bf75dd 100644 --- a/gcc/targhooks.cc +++ b/gcc/targhooks.cc @@ -161,15 +161,6 @@ default_promote_function_mode_always_promote (const_tree type, return promote_mode (type, mode, punsignedp); } -machine_mode -default_promote_function_mode_ca (cumulative_args_t, function_arg_info arg, - const_tree funtype, int *punsignedp, - int for_return) -{ - return promote_function_mode (arg.type, arg.mode, punsignedp, - funtype, for_return); -} - machine_mode default_cc_modes_compatible (machine_mode m1, machine_mode m2) { @@ -885,14 +876,6 @@ default_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED, return PARM_BOUNDARY; } -unsigned int -default_function_arg_boundary_ca (machine_mode mode ATTRIBUTE_UNUSED, - const_tree type ATTRIBUTE_UNUSED, - cumulative_args_t ca ATTRIBUTE_UNUSED) -{ - return default_function_arg_boundary (mode, type); -} - unsigned int default_function_arg_round_boundary (machine_mode mode ATTRIBUTE_UNUSED, const_tree type ATTRIBUTE_UNUSED) @@ -900,14 +883,6 @@ default_function_arg_round_boundary (machine_mode mode ATTRIBUTE_UNUSED, return PARM_BOUNDARY; } -unsigned int -default_function_arg_round_boundary_ca (machine_mode mode ATTRIBUTE_UNUSED, - const_tree type ATTRIBUTE_UNUSED, - cumulative_args_t ca ATTRIBUTE_UNUSED) -{ - return default_function_arg_round_boundary (mode, type); -} - void hook_void_bitmap (bitmap regs ATTRIBUTE_UNUSED) { diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 392fd0d315e..85f3817c176 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -34,9 +34,6 @@ extern machine_mode default_promote_function_mode (const_tree, machine_mode, extern machine_mode default_promote_function_mode_always_promote (const_tree, machine_mode, int *, const_tree, int); -extern machine_mode default_promote_function_mode_ca - (cumulative_args_t, function_arg_info, const_tree, int *, int); - extern machine_mode default_cc_modes_compatible (machine_mode, machine_mode); @@ -163,12 +160,6 @@ extern unsigned int default_function_arg_boundary (machine_mode, const_tree); extern unsigned int default_function_arg_round_boundary (machine_mode, const_tree); -extern unsigned int default_function_arg_boundary_ca (machine_mode, - const_tree, - cumulative_args_t ca); -extern unsigned int default_function_arg_round_boundary_ca (machine_mode, - const_tree, - cumulative_args_t ca); extern bool hook_bool_const_rtx_commutative_p (const_rtx, int); extern rtx default_function_value (const_tree, const_tree, bool); extern HARD_REG_SET default_zero_call_used_regs (HARD_REG_SET); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 43621e0a9b8..f2569929416 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,455 @@ +2024-06-06 Jakub Jelinek + + PR c/114493 + * gcc.dg/pr114493-1.c: New test. + * gcc.dg/pr114493-2.c: New test. + +2024-06-06 Pengxuan Zheng + + PR target/113880 + PR target/113869 + * gcc.target/aarch64/extend-vec.c: New test. + +2024-06-06 Uros Bizjak + + PR middle-end/112600 + * gcc.target/i386/pr112600-2a.c: New test. + * gcc.target/i386/pr112600-2b.c: New test. + +2024-06-06 Richard Ball + + * gcc.target/arm/thumb2-switchstatement.c: New test. + +2024-06-06 Thomas Schwinge + + * gcc.target/nvptx/nvptx.exp + (check_effective_target_default_ptx_isa_version_at_least_6_0): + New. + * gcc.target/nvptx/uniform-simt-2.c: Adjust. + * gcc.target/nvptx/uniform-simt-5.c: New. + +2024-06-06 Hongyu Wang + + * gcc.target/i386/apx-ccmp-1.c: Add test for fp compare. + * gcc.target/i386/apx-ccmp-2.c: Likewise. + +2024-06-06 Hongyu Wang + + * gcc.target/i386/apx-ccmp-1.c: New compile test. + * gcc.target/i386/apx-ccmp-2.c: New runtime test. + +2024-06-06 Hongyu Wang + + PR target/115341 + * lib/target-supports.exp (check_effective_target_apxf): + Check for all apx sub-features. + +2024-06-06 liuhongt + + PR target/115365 + * gcc.dg/pr100927.c: Don't scan fix:SI from the note. + +2024-06-06 liuhongt + + * gcc.target/i386/pr114428.c: New test. + +2024-06-06 liuhongt + + * gcc.target/i386/pr114428-1.c: New test. + +2024-06-05 Robin Dapp + + * lib/target-supports.exp: Add + check_effective_target_riscv_v_misalign_ok. + * gcc.dg/vect/costmodel/riscv/rvv/dynamic-lmul2-7.c: Add + -mno-vector-strict-align. + * gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-10.c: Ditto. + * gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-11.c: Ditto. + * gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-12.c: Ditto. + * gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-8.c: Ditto. + * gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-9.c: Ditto. + * gcc.target/riscv/rvv/autovec/vls/misalign-1.c: Ditto. + +2024-06-05 Tamar Christina + + * gcc.target/aarch64/sve/pred_clobber_1.c: New test. + * gcc.target/aarch64/sve/pred_clobber_2.c: New test. + * gcc.target/aarch64/sve/pred_clobber_3.c: New test. + * gcc.target/aarch64/sve/pred_clobber_4.c: New test. + +2024-06-05 Jakub Jelinek + Frederik Harwath + Sandra Loosemore + + * c-c++-common/gomp/attrs-tile-1.c: New test. + * c-c++-common/gomp/attrs-tile-2.c: New test. + * c-c++-common/gomp/attrs-tile-3.c: New test. + * c-c++-common/gomp/attrs-tile-4.c: New test. + * c-c++-common/gomp/attrs-tile-5.c: New test. + * c-c++-common/gomp/attrs-tile-6.c: New test. + * c-c++-common/gomp/attrs-unroll-1.c: New test. + * c-c++-common/gomp/attrs-unroll-2.c: New test. + * c-c++-common/gomp/attrs-unroll-3.c: New test. + * c-c++-common/gomp/attrs-unroll-inner-1.c: New test. + * c-c++-common/gomp/attrs-unroll-inner-2.c: New test. + * c-c++-common/gomp/attrs-unroll-inner-3.c: New test. + * c-c++-common/gomp/attrs-unroll-inner-4.c: New test. + * c-c++-common/gomp/attrs-unroll-inner-5.c: New test. + * c-c++-common/gomp/imperfect-attributes.c: Adjust expected + diagnostics. + * c-c++-common/gomp/imperfect-loop-nest.c: New test. + * c-c++-common/gomp/ordered-5.c: New test. + * c-c++-common/gomp/scan-7.c: New test. + * c-c++-common/gomp/tile-1.c: New test. + * c-c++-common/gomp/tile-2.c: New test. + * c-c++-common/gomp/tile-3.c: New test. + * c-c++-common/gomp/tile-4.c: New test. + * c-c++-common/gomp/tile-5.c: New test. + * c-c++-common/gomp/tile-6.c: New test. + * c-c++-common/gomp/tile-7.c: New test. + * c-c++-common/gomp/tile-8.c: New test. + * c-c++-common/gomp/tile-9.c: New test. + * c-c++-common/gomp/tile-10.c: New test. + * c-c++-common/gomp/tile-11.c: New test. + * c-c++-common/gomp/tile-12.c: New test. + * c-c++-common/gomp/tile-13.c: New test. + * c-c++-common/gomp/tile-14.c: New test. + * c-c++-common/gomp/tile-15.c: New test. + * c-c++-common/gomp/unroll-1.c: New test. + * c-c++-common/gomp/unroll-2.c: New test. + * c-c++-common/gomp/unroll-3.c: New test. + * c-c++-common/gomp/unroll-4.c: New test. + * c-c++-common/gomp/unroll-5.c: New test. + * c-c++-common/gomp/unroll-6.c: New test. + * c-c++-common/gomp/unroll-7.c: New test. + * c-c++-common/gomp/unroll-8.c: New test. + * c-c++-common/gomp/unroll-9.c: New test. + * c-c++-common/gomp/unroll-inner-1.c: New test. + * c-c++-common/gomp/unroll-inner-2.c: New test. + * c-c++-common/gomp/unroll-inner-3.c: New test. + * c-c++-common/gomp/unroll-non-rect-1.c: New test. + * c-c++-common/gomp/unroll-non-rect-2.c: New test. + * c-c++-common/gomp/unroll-non-rect-3.c: New test. + * c-c++-common/gomp/unroll-simd-1.c: New test. + * gcc.dg/gomp/attrs-4.c: Adjust expected diagnostics. + * gcc.dg/gomp/for-1.c: Likewise. + * gcc.dg/gomp/for-11.c: Likewise. + * g++.dg/gomp/attrs-4.C: Likewise. + * g++.dg/gomp/for-1.C: Likewise. + * g++.dg/gomp/pr94512.C: Likewise. + * g++.dg/gomp/tile-1.C: New test. + * g++.dg/gomp/tile-2.C: New test. + * g++.dg/gomp/unroll-1.C: New test. + * g++.dg/gomp/unroll-2.C: New test. + * g++.dg/gomp/unroll-3.C: New test. + * gfortran.dg/gomp/inner-loops-1.f90: New test. + * gfortran.dg/gomp/inner-loops-2.f90: New test. + * gfortran.dg/gomp/pure-1.f90: Add tests for !$omp unroll + and !$omp tile. + * gfortran.dg/gomp/pure-2.f90: Remove those tests from here. + * gfortran.dg/gomp/scan-9.f90: New test. + * gfortran.dg/gomp/tile-1.f90: New test. + * gfortran.dg/gomp/tile-2.f90: New test. + * gfortran.dg/gomp/tile-3.f90: New test. + * gfortran.dg/gomp/tile-4.f90: New test. + * gfortran.dg/gomp/tile-5.f90: New test. + * gfortran.dg/gomp/tile-6.f90: New test. + * gfortran.dg/gomp/tile-7.f90: New test. + * gfortran.dg/gomp/tile-8.f90: New test. + * gfortran.dg/gomp/tile-9.f90: New test. + * gfortran.dg/gomp/tile-10.f90: New test. + * gfortran.dg/gomp/tile-imperfect-nest-1.f90: New test. + * gfortran.dg/gomp/tile-imperfect-nest-2.f90: New test. + * gfortran.dg/gomp/tile-inner-loops-1.f90: New test. + * gfortran.dg/gomp/tile-inner-loops-2.f90: New test. + * gfortran.dg/gomp/tile-inner-loops-3.f90: New test. + * gfortran.dg/gomp/tile-inner-loops-4.f90: New test. + * gfortran.dg/gomp/tile-inner-loops-5.f90: New test. + * gfortran.dg/gomp/tile-inner-loops-6.f90: New test. + * gfortran.dg/gomp/tile-inner-loops-7.f90: New test. + * gfortran.dg/gomp/tile-inner-loops-8.f90: New test. + * gfortran.dg/gomp/tile-non-rectangular-1.f90: New test. + * gfortran.dg/gomp/tile-non-rectangular-2.f90: New test. + * gfortran.dg/gomp/tile-non-rectangular-3.f90: New test. + * gfortran.dg/gomp/tile-unroll-1.f90: New test. + * gfortran.dg/gomp/tile-unroll-2.f90: New test. + * gfortran.dg/gomp/unroll-1.f90: New test. + * gfortran.dg/gomp/unroll-2.f90: New test. + * gfortran.dg/gomp/unroll-3.f90: New test. + * gfortran.dg/gomp/unroll-4.f90: New test. + * gfortran.dg/gomp/unroll-5.f90: New test. + * gfortran.dg/gomp/unroll-6.f90: New test. + * gfortran.dg/gomp/unroll-7.f90: New test. + * gfortran.dg/gomp/unroll-8.f90: New test. + * gfortran.dg/gomp/unroll-9.f90: New test. + * gfortran.dg/gomp/unroll-10.f90: New test. + * gfortran.dg/gomp/unroll-11.f90: New test. + * gfortran.dg/gomp/unroll-12.f90: New test. + * gfortran.dg/gomp/unroll-13.f90: New test. + * gfortran.dg/gomp/unroll-inner-loop-1.f90: New test. + * gfortran.dg/gomp/unroll-inner-loop-2.f90: New test. + * gfortran.dg/gomp/unroll-no-clause-1.f90: New test. + * gfortran.dg/gomp/unroll-non-rect-1.f90: New test. + * gfortran.dg/gomp/unroll-non-rect-2.f90: New test. + * gfortran.dg/gomp/unroll-simd-1.f90: New test. + * gfortran.dg/gomp/unroll-simd-2.f90: New test. + * gfortran.dg/gomp/unroll-simd-3.f90: New test. + * gfortran.dg/gomp/unroll-tile-1.f90: New test. + * gfortran.dg/gomp/unroll-tile-2.f90: New test. + * gfortran.dg/gomp/unroll-tile-inner-1.f90: New test. + +2024-06-05 Wilco Dijkstra + + * lib/scanasm.exp (configure_check-function-bodies): Allow single-char + function names. + +2024-06-05 Thomas Schwinge + + * c-c++-common/initpri1_part_c1.c: Consider 'CDTOR_LINKAGE'. + * c-c++-common/initpri1_part_c2.c: Likewise. + * c-c++-common/initpri1_part_c3.c: Likewise. + * c-c++-common/initpri1_part_cd4.c: Likewise. + * c-c++-common/initpri1_part_d1.c: Likewise. + * c-c++-common/initpri1_part_d2.c: Likewise. + * c-c++-common/initpri1_part_d3.c: Likewise. + * c-c++-common/initpri1.c: Specify it. + * c-c++-common/initpri1-lto.c: Likewise. + * c-c++-common/initpri1-split.c: Likewise. + * c-c++-common/initpri1-static.c: New. + * c-c++-common/initpri1-lto-static.c: Likewise. + * c-c++-common/initpri1-split-static.c: Likewise. + +2024-06-05 Thomas Schwinge + + * c-c++-common/initpri1.c: Split into... + * c-c++-common/initpri1_part_c1.c: ... this, and... + * c-c++-common/initpri1_part_c2.c: ... this, and... + * c-c++-common/initpri1_part_c3.c: ... this, and... + * c-c++-common/initpri1_part_cd4.c: ... this, and... + * c-c++-common/initpri1_part_d1.c: ... this, and... + * c-c++-common/initpri1_part_d2.c: ... this, and... + * c-c++-common/initpri1_part_d3.c: ... this, and... + * c-c++-common/initpri1_part_main.c: ... this part. + * c-c++-common/initpri1-split.c: New. + +2024-06-05 Thomas Schwinge + + * gcc.dg/initpri1-lto.c: Integrate this... + * c-c++-common/initpri1-lto.c: ... here. + +2024-06-05 Thomas Schwinge + + * gcc.dg/initpri1.c: Integrate this... + * g++.dg/special/initpri1.C: ..., and this... + * c-c++-common/initpri1.c: ... here. + * gcc.dg/initpri1-lto.c: Adjust. + * gcc.dg/initpri2.c: Integrate this... + * g++.dg/special/initpri2.C: ..., and this... + * c-c++-common/initpri2.c: ... here. + +2024-06-05 Thomas Schwinge + + PR lto/46083 + * gcc.dg/initpri3.c: Remove. + * gcc.dg/initpri1-lto.c: New. + +2024-06-05 liuhongt + + * gcc.dg/pr100927.c: New test. + * c-c++-common/Wconversion-1.c: Add -fno-trapping-math. + * c-c++-common/dfp/convert-int-saturate.c: Ditto. + * g++.dg/ubsan/pr63956.C: Ditto. + * g++.dg/warn/Wconversion-real-integer.C: Ditto. + * gcc.c-torture/execute/20031003-1.c: Ditto. + * gcc.dg/Wconversion-complex-c99.c: Ditto. + * gcc.dg/Wconversion-real-integer.c: Ditto. + * gcc.dg/c90-const-expr-11.c: Ditto. + * gcc.dg/overflow-warn-8.c: Ditto. + +2024-06-05 Xiao Zeng + + * gcc.target/riscv/zfbfmin-bf16_arithmetic.c: New test. + * gcc.target/riscv/zfbfmin-bf16_comparison.c: New test. + * gcc.target/riscv/zfbfmin-bf16_float_libcall_convert.c: New test. + * gcc.target/riscv/zfbfmin-bf16_integer_libcall_convert.c: New test. + +2024-06-04 Simon Martin + + PR c++/103388 + * g++.dg/parse/crash73.C: New test. + +2024-06-04 Harald Anlauf + + PR fortran/83865 + * gfortran.dg/allocate_with_source_32.f90: New test. + +2024-06-04 Simon Martin + + PR c++/111106 + * g++.dg/cpp2a/consteval37.C: New test. + +2024-06-04 Jakub Jelinek + + PR tree-optimization/115337 + * gcc.dg/bitint-106.c: New test. + +2024-06-04 Rainer Orth + + * gcc.target/i386/avx10_1-25.c: Require ifunc support. + * gcc.target/i386/avx10_1-26.c: Likewise. + +2024-06-04 Jakub Jelinek + + PR middle-end/108789 + * gcc.c-torture/execute/pr108789.c: New test. + +2024-06-04 Richard Biener + + * gcc.dg/vect/slp-24.c: Expect another SLP instance for the + reduction. + * gcc.dg/vect/slp-24-big-array.c: Likewise. + * gcc.dg/vect/slp-reduc-6.c: Remove scan for zero SLP instances. + +2024-06-04 Rainer Orth + + PR analyzer/107750 + * gcc.dg/analyzer/fd-accept.c: Skip on *-*-solaris2*. + * gcc.dg/analyzer/fd-access-mode-target-headers.c: Likewise. + * gcc.dg/analyzer/fd-connect.c: Likewise. + * gcc.dg/analyzer/fd-datagram-socket.c: Likewise. + * gcc.dg/analyzer/fd-listen.c: Likewise. + * gcc.dg/analyzer/fd-socket-misuse.c: Likewise. + * gcc.dg/analyzer/fd-stream-socket-active-open.c: Likewise. + * gcc.dg/analyzer/fd-stream-socket-passive-open.c: Likewise. + * gcc.dg/analyzer/fd-stream-socket.c: Likewise. + +2024-06-04 liuhongt + + PR target/115299 + * gcc.target/i386/pr86722.c: Also scan for blendvpd. + +2024-06-03 Jakub Jelinek + + PR c++/115012 + * g++.dg/cpp0x/variadic185.C: New test. + +2024-06-03 David Malcolm + + * c-c++-common/analyzer/sarif-path-role.c: New test. + * c-c++-common/analyzer/sarif-path-role.h: New header for above + test. + * c-c++-common/diagnostic-format-sarif-file-1.c: Verify the + artifact's "role" property. + * c-c++-common/diagnostic-format-sarif-file-header-role.c: New + test. + * c-c++-common/diagnostic-format-sarif-file-header-role.h: New + header for above test. + * c-c++-common/diagnostic-format-sarif-file-no-results.c: New + test. + +2024-06-03 Uros Bizjak + + PR target/115321 + * gcc.target/i386/pr115321.c: New test. + +2024-06-03 Richard Biener + + PR testsuite/115304 + * gcc.dg/vect/slp-gap-1.c: Require vect_unpack and vect_perm. + +2024-06-03 Rainer Orth + + PR tree-optimization/115303 + * gcc.dg/vect/pr112325.c: Require vect_shift. + +2024-06-03 Richard Biener + + * gcc.dg/vect/no-scevccp-outer-7.c: Adjust scanning for + succeeded analysis not interrupted by failure. + * gcc.dg/vect/no-scevccp-vect-iv-3.c: Likewise. + * gcc.dg/vect/vect-cond-reduc-4.c: Likewise. + * gcc.dg/vect/vect-live-2.c: Likewise. + * gcc.dg/vect/vect-outer-4c-big-array.c: Likewise. + * gcc.dg/vect/vect-reduc-dot-s16a.c: Likewise. + * gcc.dg/vect/vect-reduc-dot-s8a.c: Likewise. + * gcc.dg/vect/vect-reduc-dot-s8b.c: Likewise. + * gcc.dg/vect/vect-reduc-dot-u16a.c: Likewise. + * gcc.dg/vect/vect-reduc-dot-u16b.c: Likewise. + * gcc.dg/vect/vect-reduc-dot-u8a.c: Likewise. + * gcc.dg/vect/vect-reduc-dot-u8b.c: Likewise. + * gcc.dg/vect/vect-reduc-pattern-1a.c: Likewise. + * gcc.dg/vect/vect-reduc-pattern-1b-big-array.c: Likewise. + * gcc.dg/vect/vect-reduc-pattern-1c-big-array.c: Likewise. + * gcc.dg/vect/vect-reduc-pattern-2a.c: Likewise. + * gcc.dg/vect/vect-reduc-pattern-2b-big-array.c: Likewise. + * gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c: Likewise. + +2024-06-03 liuhongt + + * gcc.target/i386/pr115299.c: New test. + * gcc.target/i386/pr86722.c: Adjust testcase. + +2024-06-03 Haochen Jiang + + * gcc.target/i386/avx10_1-25.c: New test. + * gcc.target/i386/avx10_1-26.c: Ditto. + +2024-06-03 Lingling Kong + + * gcc.target/i386/apx-nf.c: Add test. + +2024-06-03 Lingling Kong + + * gcc.target/i386/apx-nf.c: New test. + +2024-06-03 Lingling Kong + Hongyu Wong + + * gcc.target/i386/apx-ndd.c: Fixed test. + +2024-06-03 Hu, Lin1 + + PR target/113609 + * gcc.target/i386/pr113609-1.c: New test. + * gcc.target/i386/pr113609-2.c: Ditto. + +2024-06-02 Simon Martin + + PR c++/109958 + * g++.dg/overload/using6.C: New test. + +2024-06-01 David Malcolm + + PR analyzer/106203 + * c-c++-common/analyzer/allocation-size-1.c (test_9): Remove + xfail. + * c-c++-common/analyzer/allocation-size-2.c (test_8): Likewise. + * gcc.dg/analyzer/allocation-size-multiline-4.c: New test. + * gcc.dg/plugin/analyzer_cpython_plugin.c + (refcnt_stmt_finder::update_event_loc_info): New. + +2024-06-01 Georg-Johann Lay + + PR target/115317 + * gcc.target/avr/torture/pr115317-isinf.c: New test. + +2024-06-01 Georg-Johann Lay + + PR tree-optimization/115307 + * gcc.target/avr/torture/pr115307-isinf.c: New test. + +2024-06-01 Jeff Law + + * gcc.target/riscv/synthesis-10.c: New test. + +2024-06-01 Nathaniel Shead + + PR c++/114867 + * g++.dg/modules/using-17_a.C: New test. + * g++.dg/modules/using-17_b.C: New test. + * g++.dg/modules/using-18_a.C: New test. + * g++.dg/modules/using-18_b.C: New test. + 2024-05-31 Robin Dapp * gcc.target/riscv/rvv/autovec/unop/popcount-1.c: Adjust check diff --git a/gcc/testsuite/c-c++-common/Wconversion-1.c b/gcc/testsuite/c-c++-common/Wconversion-1.c index 81f9498d07c..9d874d19548 100644 --- a/gcc/testsuite/c-c++-common/Wconversion-1.c +++ b/gcc/testsuite/c-c++-common/Wconversion-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Wconversion" } */ +/* { dg-options "-Wconversion -fno-trapping-math" } */ typedef char T; diff --git a/gcc/testsuite/c-c++-common/analyzer/allocation-size-1.c b/gcc/testsuite/c-c++-common/analyzer/allocation-size-1.c index 05efc4f8028..5b4e7392782 100644 --- a/gcc/testsuite/c-c++-common/analyzer/allocation-size-1.c +++ b/gcc/testsuite/c-c++-common/analyzer/allocation-size-1.c @@ -103,13 +103,7 @@ void test_8 (void) void test_9 (void) { - /* FIXME: At the moment, region_model::set_value (lhs, ) - is called at the src_node of the return edge. This edge has no stmts - associated with it, leading to a rejection of the warning inside - impl_region_model_context::warn. To ensure that the indentation - in the diagnostic is right, the warning has to be emitted on an EN - that is after the return edge. */ - int32_t *buf = (int32_t *) create_buffer(42); /* { dg-warning "" "" { xfail *-*-* } } */ + int32_t *buf = (int32_t *) create_buffer(42); /* { dg-warning "allocated buffer size is not a multiple of the pointee's size" } */ free (buf); } diff --git a/gcc/testsuite/c-c++-common/analyzer/allocation-size-2.c b/gcc/testsuite/c-c++-common/analyzer/allocation-size-2.c index ff4cb563469..a9f92cf2d02 100644 --- a/gcc/testsuite/c-c++-common/analyzer/allocation-size-2.c +++ b/gcc/testsuite/c-c++-common/analyzer/allocation-size-2.c @@ -86,13 +86,7 @@ void test_7(int32_t n) void test_8(int32_t n) { - /* FIXME: At the moment, region_model::set_value (lhs, ) - is called at the src_node of the return edge. This edge has no stmts - associated with it, leading to a rejection of the warning inside - impl_region_model_context::warn. To ensure that the indentation - in the diagnostic is right, the warning has to be emitted on an EN - that is after the return edge. */ - int32_t *buf = (int32_t *)create_buffer(n * sizeof(int16_t)); /* { dg-warning "" "" { xfail *-*-* } } */ + int32_t *buf = (int32_t *)create_buffer(n * sizeof(int16_t)); /* { dg-warning "allocated buffer size is not a multiple of the pointee's size" } */ free (buf); } diff --git a/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-pr110387.c b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-pr110387.c index a046659c83e..b4454805eb5 100644 --- a/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-pr110387.c +++ b/gcc/testsuite/c-c++-common/analyzer/out-of-bounds-pr110387.c @@ -12,8 +12,8 @@ _S_copy (long __n) void _M_construct () { - x = &c - &b; + x = &c - &b; /* { dg-warning "undefined behavior when subtracting pointers" } */ unsigned long __dnew = x; if (__dnew > 1) - _S_copy (&c - &b); + _S_copy (&c - &b); /* { dg-warning "undefined behavior when subtracting pointers" } */ } diff --git a/gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-1.c b/gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-1.c new file mode 100644 index 00000000000..73684c115fc --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-1.c @@ -0,0 +1,46 @@ +#include + +ptrdiff_t +test_invalid_sub_addrs_of_locals (void) +{ + int a; /* { dg-message "underlying object for left-hand side of subtraction created here" } */ + int b; /* { dg-message "underlying object for right-hand side of subtraction created here" } */ + return &a - &b; /* { dg-warning "undefined behavior when subtracting pointers \\\[CWE-469\\\] \\\[-Wanalyzer-undefined-behavior-ptrdiff\\\]" } */ + /* { dg-message "subtraction of pointers has undefined behavior if they do not point into the same array object" "final event" { target *-*-* } .-1 } */ +} + +ptrdiff_t +test_valid_sub_addrs_within_array (void) +{ + int a[10]; + return &a[7] - &a[3]; +} + +ptrdiff_t +test_invalid_sub_addrs_within_arrays (void) +{ + int a[10]; /* { dg-message "left-hand side" } */ + int b[10]; /* { dg-message "right-hand side" } */ + return &a[7] - &b[3]; /* { dg-warning "undefined behavior when subtracting pointers" } */ +} + + +ptrdiff_t +test_invalid_sub_addrs_between_heap_allocs (size_t n) +{ + char *p = (char *)__builtin_malloc (n); /* { dg-message "left-hand side" } */ + char *q = (char *)__builtin_malloc (n); /* { dg-message "right-hand side" } */ + ptrdiff_t d = p - q; /* { dg-warning "undefined behavior when subtracting pointers" } */ + __builtin_free (p); + __builtin_free (q); + return d; +} + +int arr[42]; /* { dg-message "right-hand side" } */ +int sentinel; /* { dg-message "left-hand side" } */ + +ptrdiff_t +test_invalid_calc_of_array_size (void) +{ + return &sentinel - arr; /* { dg-warning "undefined behavior when subtracting pointers" } */ +} diff --git a/gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-CWE-469-example.c b/gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-CWE-469-example.c new file mode 100644 index 00000000000..7f8bd342acb --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/ptr-subtraction-CWE-469-example.c @@ -0,0 +1,81 @@ +/* Example heavily adapted from https://cwe.mitre.org/data/definitions/469.html + which states "Copyright © 2006–2024, The MITRE Corporation. CWE, CWSS, CWRAF, and the CWE logo are trademarks of The MITRE Corporation." + and which has this on: + https://cwe.mitre.org/about/termsofuse.html + + Terms of Use + + CWE™ is free to use by any organization or individual for any research, development, and/or commercial purposes, per these CWE Terms of Use. Accordingly, The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE is a trademark of The MITRE Corporation. Please contact cwe@mitre.org if you require further clarification on this issue. + + DISCLAIMERS + + By accessing information through this site you (as “the user”) hereby agrees the site and the information is provided on an “as is” basis only without warranty of any kind, express or implied, including but not limited to implied warranties of merchantability, availability, accuracy, noninfringement, or fitness for a particular purpose. Use of this site and the information is at the user’s own risk. The user shall comply with all applicable laws, rules, and regulations, and the data source’s restrictions, when using the site. + + By contributing information to this site you (as “the contributor”) hereby represents and warrants the contributor has obtained all necessary permissions from copyright holders and other third parties to allow the contributor to contribute, and this site to host and display, the information and any such contribution, hosting, and displaying will not violate any law, rule, or regulation. Additionally, the contributor hereby grants all users of such information a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute such information and all derivative works. + + The MITRE Corporation expressly disclaims any liability for any damages arising from the contributor’s contribution of such information, the user’s use of the site or such information, and The MITRE Corporation’s hosting the tool and displaying the information. The foregoing disclaimer specifically includes but is not limited to general, consequential, indirect, incidental, exemplary, or special or punitive damages (including but not limited to loss of income, program interruption, loss of information, or other pecuniary loss) arising out of use of this information, no matter the cause of action, even if The MITRE Corporation has been advised of the possibility of such damages. */ + +/* We need this for the issue to be found, or the loop analysis + is too simplistic. */ +/* { dg-additional-options "-fno-analyzer-state-merge" } */ +/* { dg-additional-options "-Wno-analyzer-too-complex" } */ +/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */ + +#include + +struct node { + int data; + struct node* next; +}; + +/* The example fails to initialize "tail" for the head == NULL case. */ + +int example_1_with_uninit (struct node* head) { + struct node* current = head; + struct node* tail; + while (current != NULL) { + tail = current; + current = current->next; + } + return tail - head; /* { dg-warning "use of uninitialized value 'tail'" } */ +} + +int example_1_bad (struct node* head) { + struct node* current = head; + struct node* tail = head; /* initialization added */ + while (current != NULL) { + tail = current; + current = current->next; + } + return tail - head; /* { dg-warning "undefined behavior when subtracting pointers" } */ +} + +int example_1_good (struct node* head) { + struct node* current = head; + int count = 0; + while (current != NULL) { + count++; + current = current->next; + } + return count; +} + +/* We need to add usage of the function to detect the issue. */ + +int usage_of_example_1_bad (void) +{ + struct node p; /* { dg-message "right-hand side" } */ + struct node q; /* { dg-message "left-hand side" } */ + p.next = &q; + q.next = NULL; + return example_1_bad (&p); +} + +int usage_of_example_1_good (void) +{ + struct node p; + struct node q; + p.next = &q; + q.next = NULL; + return example_1_good (&p); +} diff --git a/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.c b/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.c new file mode 100644 index 00000000000..d0f6cefcf4d --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-additional-options " -fno-diagnostics-json-formatting -fdiagnostics-format=sarif-file" } */ + +#include + +void test_1 (void) +{ + void *ptr = malloc (1024); +#include "sarif-path-role.h" + free (ptr); +} + +/* Verify SARIF output. + + { dg-final { verify-sarif-file } } + + Verify that the artifact for the header has this role, given + that it's only referenced by an execution path event. + + { dg-final { scan-sarif-file "\"roles\": \\\[\"tracedFile\"\\\]" } } +*/ diff --git a/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.h b/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.h new file mode 100644 index 00000000000..fe620f9b82a --- /dev/null +++ b/gcc/testsuite/c-c++-common/analyzer/sarif-path-role.h @@ -0,0 +1,2 @@ +/* Generate an execution path event within a header. */ +free (ptr); diff --git a/gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c b/gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c index 2d01f99468b..6b362c2aa95 100644 --- a/gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c +++ b/gcc/testsuite/c-c++-common/dfp/convert-int-saturate.c @@ -2,6 +2,7 @@ C99 6.3.1.4(1a) New. Test integer saturation. */ +/* { dg-options "-fno-trapping-math" } */ #ifndef __STDC_WANT_DEC_FP__ #define __STDC_WANT_DEC_FP__ 1 #endif diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c index f0dcaa705ca..50375465483 100644 --- a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c +++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-1.c @@ -20,6 +20,11 @@ { dg-final { scan-sarif-file "\"contents\": " } } { dg-final { scan-sarif-file "\"text\": " } } + + Verify that this file's "role" is "analysisTarget", as per + "NOTE 3" in SARIF v2.1.0 section 3.24.6. + { dg-final { scan-sarif-file "\"roles\": \\\[\"analysisTarget\"\\\]" } } + { dg-final { scan-sarif-file "\"tool\": " } } { dg-final { scan-sarif-file "\"driver\": " } } { dg-final { scan-sarif-file "\"name\": \"GNU C" } } diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.c b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.c new file mode 100644 index 00000000000..bfbbe4c2946 --- /dev/null +++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-fdiagnostics-format=sarif-file" } */ + +/* Generate a warning in a header file. */ +#include "diagnostic-format-sarif-file-header-role.h" + +/* Verify that some JSON was written to a file with the expected name. */ +/* { dg-final { verify-sarif-file } } */ + +/* Verify that the header file's "role" is "resultFile", as per "NOTE 3" + in SARIF v2.1.0 section 3.24.6. */ +/* { dg-final { scan-sarif-file "\"roles\": \\\[\"resultFile\"\\\]" } } */ diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.h b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.h new file mode 100644 index 00000000000..0111cd2fe7c --- /dev/null +++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-header-role.h @@ -0,0 +1 @@ +#warning this is a warning from a header file diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-no-results.c b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-no-results.c new file mode 100644 index 00000000000..9540c3335aa --- /dev/null +++ b/gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-no-results.c @@ -0,0 +1,44 @@ +/* Verify behavior of SARIF output for the "no diagnostics" case. */ + +/* { dg-do compile } */ +/* { dg-options "-fdiagnostics-format=sarif-file" } */ + +int non_empty; + +/* Verify that some JSON was written to a file with the expected name. */ +/* { dg-final { verify-sarif-file } } */ + +/* We expect various properties. + The indentation here reflects the expected hierarchy, though these tests + don't check for that, merely the string fragments we expect. + { dg-final { scan-sarif-file "\"version\": \"2.1.0\"" } } + { dg-final { scan-sarif-file "\"runs\": \\\[" } } + { dg-final { scan-sarif-file "\"artifacts\": \\\[" } } + { dg-final { scan-sarif-file "\"location\": " } } + { dg-final { scan-sarif-file "\"uri\": " } } + + { dg-final { scan-sarif-file "\"sourceLanguage\": \"c\"" { target c } } } + { dg-final { scan-sarif-file "\"sourceLanguage\": \"cplusplus\"" { target c++ } } } + + We expect the contents of the file to *not* be quoted if + there are no results. + { dg-final { scan-sarif-file-not "\"contents\": " } } + { dg-final { scan-sarif-file-not "\"text\": " } } + + Verify that this file's "role" is "analysisTarget", as per + "NOTE 3" in SARIF v2.1.0 section 3.24.6. + { dg-final { scan-sarif-file "\"roles\": \\\[\"analysisTarget\"\\\]" } } + + { dg-final { scan-sarif-file "\"tool\": " } } + { dg-final { scan-sarif-file "\"driver\": " } } + { dg-final { scan-sarif-file "\"name\": \"GNU C" } } + { dg-final { scan-sarif-file "\"fullName\": \"GNU C" } } + { dg-final { scan-sarif-file "\"informationUri\": \"" } } + + { dg-final { scan-sarif-file "\"invocations\": \\\[" } } + { dg-final { scan-sarif-file "\"toolExecutionNotifications\": \\\[\\\]" } } + { dg-final { scan-sarif-file "\"executionSuccessful\": true" } } + + We expect an empty list for "results" + { dg-final { scan-sarif-file "\"results\": \\\[\\\]" } } */ + diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-1.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-1.c new file mode 100644 index 00000000000..e9c9bd3e13a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-1.c @@ -0,0 +1,57 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::directive (tile sizes(1))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (unroll partial), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::directive (tile sizes(1))]] + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + [[omp::directive (tile sizes(1))]] + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-2.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-2.c new file mode 100644 index 00000000000..d6d04996587 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-2.c @@ -0,0 +1,70 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll partial), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-3.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-3.c new file mode 100644 index 00000000000..32348ec4e33 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-3.c @@ -0,0 +1,47 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (for collapse(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(1)), + directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (for collapse(1)), + directive (tile sizes(1)), + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-4.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-4.c new file mode 100644 index 00000000000..6645c792b10 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-4.c @@ -0,0 +1,106 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::directive (tile sizes(0))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(-1))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes())]] /* { dg-error "expected expression before" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + dummy (i); + + [[omp::directive (tile sizes)]] /* { dg-error "expected '\\\(' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(1) sizes(1))]] /* { dg-error "expected end of line before 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile, sizes(1), sizes(1))]] /* { dg-error "expected end of line before ','" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (unroll partia), /* { dg-error "expected an OpenMP clause before 'partia'" } */ + directive (tile sizes(1)))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (unroll))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(1)), + directive (unroll full))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(8,8)), + directive (unroll partial), /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (tile sizes(8,8)), + directive (unroll partial))]] /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] /* { dg-error "non-rectangular 'tile'" } */ + for (int i = 0; i < 100; ++i) + for (int j = i; j < 100; ++j) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] /* { dg-error "non-rectangular 'tile'" } */ + for (int i = 0; i < 100; ++i) + for (int j = 2; j < i; ++j) + dummy (i); + + [[omp::directive (tile sizes(1, 2, 3))]] + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::directive (tile sizes(1, 2))]] + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + [[omp::directive (tile sizes(1, 2))]] + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + int s; + [[omp::directive (tile sizes(s))]] /* { dg-error "'sizes' argument needs positive integral constant" "" { target { ! c++98_only } } } */ + /* { dg-error "the value of 's' is not usable in a constant expression" "" { target { c++ && { ! c++98_only } } } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::directive (tile sizes(42.0))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-5.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-5.c new file mode 100644 index 00000000000..d9b2dd98a2c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-5.c @@ -0,0 +1,113 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (parallel for), + directive (tile sizes(0)))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(-1)))]] /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), /* { dg-error "expected primary-expression before" "" { target c++ } .+1 } */ + directive (tile sizes()))]] /* { dg-error "expected expression before" "" { target c } } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), /* { dg-error "expected primary-expression before" "" { target c++ } .+1 } */ + directive (tile sizes(,)))]] /* { dg-error "expected expression before" "" { target c } } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes))]] /* { dg-error "expected '\\\(' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1) sizes(1)))]] /* { dg-error "expected end of line before 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll partia), /* { dg-error "expected an OpenMP clause before 'partia'" } */ + directive (tile sizes(1)))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1)), + directive (unroll full))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(8,8)), + directive (unroll partial), /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + directive (tile sizes(1)))]] + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(8,8)), + directive (unroll partial))]] /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = i; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = 2; j < i; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + [[omp::sequence (directive (parallel for), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-tile-6.c b/gcc/testsuite/c-c++-common/gomp/attrs-tile-6.c new file mode 100644 index 00000000000..7ac40fb99f0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-tile-6.c @@ -0,0 +1,72 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (for), + directive (tile sizes(1, 2)))]] /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = i; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for), + directive (tile sizes(1, 2)))]] /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = 0; j < i; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(3)), + directive (tile sizes(1, 2)))]] /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(5, 6)), + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + dummy (i); + + [[omp::sequence (directive (for collapse(2)), + directive (tile sizes(1, 2)), + directive (tile sizes(1)))]] /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(3)), + directive (tile sizes(1, 2)), /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + directive (tile sizes(1, 2)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + [[omp::sequence (directive (for collapse(3)), + directive (tile sizes(5, 6)), /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + directive (tile sizes(1, 2, 3)))]] + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-1.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-1.c new file mode 100644 index 00000000000..be3340a3583 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-1.c @@ -0,0 +1,135 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test1 (void) +{ + [[omp::directive (unroll partial)]] + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test2 (void) +{ + [[omp::directive (unroll partial(10))]] + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test3 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test4 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 0; i > 100; ++i) + dummy (i); +} + +void +test5 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 1; i <= 100; ++i) + dummy (i); +} + +void +test6 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 200; i >= 100; i--) + dummy (i); +} + +void +test7 (void) +{ + [[omp::directive (unroll full)]] + for (int i = -100; i > 100; ++i) + dummy (i); +} + +void +test8 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 100; i > -200; --i) + dummy (i); +} + +void +test9 (void) +{ + [[omp::directive (unroll full)]] + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test10 (void) +{ + [[omp::directive (unroll full)]] + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test12 (void) +{ + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test13 (void) +{ + for (int i = 0; i < 100; ++i) + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test14 (void) +{ + [[omp::directive (for)]] + for (int i = 0; i < 100; ++i) + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test15 (void) +{ + [[omp::directive (for)]] + for (int i = 0; i < 100; ++i) + { + dummy (i); + + [[omp::sequence (directive (unroll full), + directive (unroll partial), + directive (unroll partial))]] + for (int j = -300; j != 100; ++j) + dummy (j); + + dummy (i); + } + } diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-2.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-2.c new file mode 100644 index 00000000000..89170bc76dc --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-2.c @@ -0,0 +1,81 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ +/* { dg-prune-output "error: invalid controlling predicate" } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::sequence (directive (unroll partial), + directive (unroll full))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll full), /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + directive (unroll partial))]] + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll full), + directive (unroll full))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll partial partial))]] /* { dg-error "too many 'partial' clauses" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::directive (unroll full full)]] /* { dg-error "too many 'full' clauses" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (unroll partial), + directive (unroll))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll))]] /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + int i; + + [[omp::sequence (directive (for), /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + directive (unroll foo))]] /* { dg-error "expected an OpenMP clause before 'foo'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::directive (unroll partial(i))]] + /* { dg-error "the value of 'i' is not usable in a constant expression" "" { target c++ } .-1 } */ + /* { dg-error "'partial' argument needs positive constant integer expression" "" { target *-*-* } .-2 } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::directive (unroll parti)]] /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll partial(1)), /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + directive (unroll parti))]] /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + [[omp::sequence (directive (for), + directive (unroll partial(1)), /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + directive (unroll parti))]] /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + int sum = 0; + [[omp::sequence (directive (parallel for reduction(+ : sum) collapse(2)), + directive (unroll partial(1)))]] /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 3; i < 10; ++i) + for (int j = -2; j < 7; ++j) + sum++; +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-3.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-3.c new file mode 100644 index 00000000000..35dbf4fc159 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ +/* { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple -fdump-tree-cunroll" } */ + +extern void dummy (int); + +void +test1 (void) +{ + [[omp::directive (unroll full)]] + for (int i = 0; i < 10; i++) + dummy (i); +} + +/* Loop should be removed with 10 copies of the body remaining */ +/* { dg-final { scan-tree-dump-times "dummy" 10 "cunroll" } } */ +/* { dg-final { scan-tree-dump "#pragma omp unroll" "original" } } */ +/* { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-1.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-1.c new file mode 100644 index 00000000000..5cec7805555 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (unroll, partial)]] + for (int j = 0; j != 100; ++j) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-2.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-2.c new file mode 100644 index 00000000000..680fca4722a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + [[omp::directive (tile sizes (2))]] + for (int j = 0; j != 100; ++j) + dummy (i); + + [[omp::directive (target parallel for, collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (tile, sizes(2, 3))]] + for (int j = 0; j != 100; ++j) + for (int k = 0; k != 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-3.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-3.c new file mode 100644 index 00000000000..f91d4dd50c6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +/* Test that omp::sequence is handled properly in a loop nest, but that + invalid attribute specifiers are rejected. */ + +extern void dummy (int); + +void +test1 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::sequence (directive (unroll, partial))]] + for (int j = 0; j != 100; ++j) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-4.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-4.c new file mode 100644 index 00000000000..c08985f48e0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-4.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +extern void dummy (int); + +void +test (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (tile sizes(2, 3))]] + for (int j = 0; j != 100; ++j) /* { dg-error "not enough nested loops" } */ + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-5.c b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-5.c new file mode 100644 index 00000000000..04614f88270 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/attrs-unroll-inner-5.c @@ -0,0 +1,61 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-additional-options "-std=c23" { target c } } */ + +/* Test that omp::sequence is handled properly in a loop nest, but that + invalid attribute specifiers are rejected. */ + +extern void dummy (int); + +void +test2 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (masked)]] /* { dg-error "expected 'for' loop or OpenMP loop transformation construct" } */ + for (int j = 0; j != 100; ++j) /* { dg-error "loop not permitted" } */ + dummy (i); +} + +void +test3 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (unroll, partial)]] /* { dg-error "attributes on the same statement" } */ + [[omp::directive (masked)]] + for (int j = 0; j != 100; ++j) + dummy (i); +} + +void +test4 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::sequence (directive (unroll, partial), + directive (masked))]] /* { dg-error "loop nest expected" } */ + for (int j = 0; j != 100; ++j) + dummy (i); /* { dg-error "declared" } */ +} + +void +test5 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::sequence (directive (masked), /* { dg-error "expected 'for' loop or OpenMP loop transformation construct" } */ + directive (unroll, partial))]] + for (int j = 0; j != 100; ++j) + dummy (i); +} + +void +test6 (void) +{ + [[omp::directive (target parallel for collapse(2))]] + for (int i = -300; i != 100; ++i) + [[omp::directive (unroll, partial), /* { dg-error "attributes on the same statement" } */ + omp::directive (masked)]] + for (int j = 0; j != 100; ++j) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c b/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c index 776295ce22a..3c35e7c54b6 100644 --- a/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c @@ -1,17 +1,20 @@ /* { dg-do compile { target { c || c++11 } } } */ /* Check that a nested FOR loop with standard c/c++ attributes on it - is treated as intervening code, since it doesn't match the grammar - for canonical loop nest form. */ + (not the C++ attribute syntax for OpenMP directives) + gives an error. */ extern void do_something (void); + +/* This one should be OK, an empty attribute list is ignored in both C + and C++. */ void imperfect1 (int x, int y) { #pragma omp for collapse (2) - for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + for (int i = 0; i < x; i++) { - [[]] for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + [[]] for (int j = 0; j < y; j++) do_something (); } } @@ -19,16 +22,15 @@ void imperfect1 (int x, int y) void perfect1 (int x, int y) { #pragma omp for ordered (2) - for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ - /* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */ + for (int i = 0; i < x; i++) { - [[]] for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + [[]] for (int j = 0; j < y; j++) do_something (); } } /* Similar, but put the attributes on a block wrapping the nested loop - instead. */ + instead. This is not allowed by the grammar. */ void imperfect2 (int x, int y) { diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-loop-nest.c b/gcc/testsuite/c-c++-common/gomp/imperfect-loop-nest.c new file mode 100644 index 00000000000..e03350b878a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-loop-nest.c @@ -0,0 +1,12 @@ +void +test (void) +{ +#pragma omp tile sizes (2,4,6) + for (unsigned i = 0; i < 10; i++) /* { dg-error "inner loops must be perfectly nested" } */ + for (unsigned j = 0; j < 10; j++) + { + float intervening_decl = 0; +#pragma omp unroll partial(2) + for (unsigned k = 0; k < 10; k++); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/ordered-5.c b/gcc/testsuite/c-c++-common/gomp/ordered-5.c new file mode 100644 index 00000000000..ee798f4dd1b --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/ordered-5.c @@ -0,0 +1,140 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +void +foo (void) +{ + int i; + #pragma omp for ordered /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp tile sizes (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered + ; + } + #pragma omp for ordered /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp tile sizes (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered threads + ; + } + #pragma omp for simd ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered threads, simd + ; + } + #pragma omp for simd ordered(1) /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp for simd ordered(1) /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:omp_cur_iteration) + } + #pragma omp parallel for ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp parallel for ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp tile sizes (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:) + } + #pragma omp for ordered(1) /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp tile sizes (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp for ordered(1) /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp tile sizes (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:omp_cur_iteration) + } +} + +void +bar (void) +{ + int i; + #pragma omp for ordered /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp unroll partial (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered + ; + } + #pragma omp for ordered /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp unroll partial (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered threads + ; + } + #pragma omp for simd ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered threads, simd + ; + } + #pragma omp for simd ordered(1) /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp for simd ordered(1) /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:omp_cur_iteration) + } + #pragma omp parallel for ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp parallel for ordered /* { dg-error "'ordered' clause used with generated loops" "" { target c } } */ + #pragma omp unroll partial (2) /* { dg-error "'ordered' clause used with generated loops" "" { target c++ } } */ + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:) + } + #pragma omp for ordered(1) /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp unroll partial (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) + } + #pragma omp for ordered(1) /* { dg-error "'ordered' clause used with generated loops" } */ + #pragma omp unroll partial (2) + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:omp_cur_iteration) + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/scan-7.c b/gcc/testsuite/c-c++-common/gomp/scan-7.c new file mode 100644 index 00000000000..412c98d5ee0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/scan-7.c @@ -0,0 +1,55 @@ +int a; + +void +foo (int *c, int *d) +{ + #pragma omp for reduction (inscan, +: a) /* { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + #pragma omp tile sizes (2) + for (int i = 0; i < 64; ++i) + { + a = a + c[i]; + #pragma omp scan inclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ + d[i] = a; + } +} + +void +bar (int **c, int **d) +{ + #pragma omp for collapse (2) reduction (inscan, +: a) /* { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + for (int i = 0; i < 64; ++i) + #pragma omp tile sizes (3) + for (int j = 0; j < 64; ++j) + { + d[i][j] = a; + #pragma omp scan exclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ + a = a + c[i][j]; + } +} + +void +baz (int *c, int *d) +{ + #pragma omp for reduction (inscan, +: a) /* { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + #pragma omp unroll partial (2) + for (int i = 0; i < 64; ++i) + { + d[i] = a; + #pragma omp scan exclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ + a = a + c[i]; + } +} + +void +qux (int **c, int **d) +{ + #pragma omp for collapse (2) reduction (inscan, +: a) /* { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + for (int i = 0; i < 64; ++i) + #pragma omp unroll partial (3) + for (int j = 0; j < 64; ++j) + { + a = a + c[i][j]; + #pragma omp scan inclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ + d[i][j] = a; + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-1.c b/gcc/testsuite/c-c++-common/gomp/tile-1.c new file mode 100644 index 00000000000..12d733183fa --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-1.c @@ -0,0 +1,54 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(5, 6) + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp unroll partial + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-10.c b/gcc/testsuite/c-c++-common/gomp/tile-10.c new file mode 100644 index 00000000000..3d1c5a950a0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-10.c @@ -0,0 +1,90 @@ +void +test1 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) /* { dg-error "the same loop iteration variables 'i' used in multiple associated loops" "" { target c } } */ + for (i = 0; i < 1024; ++i) /* { dg-error "the same loop iteration variables 'i' used in multiple associated loops" "" { target c++ } } */ + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (i = 0; i < 1024; ++i) + ; +} + +void +test2 (void) +{ + long long i; + int j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) /* { dg-error "outer iteration variable 'i' used in initializer expression has type other than 'int'" "" { target c } } */ + for (i = 0; i < 1024; ++i) /* { dg-error "outer iteration variable 'i' used in initializer expression has type other than 'int'" "" { target c++ } } */ + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = i; l < 1024; ++l) + ; +} + +void +test3 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) + for (i = 0; i < 1024; ++i) + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = 0; l < 7 * i * i; ++l) /* { dg-error "condition expression refers to iteration variable 'i'" } */ + ; +} + +void +test4 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) + for (i = 0; i < 1024; ++i) + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = i * i; l < 1024; ++l) /* { dg-error "initializer expression refers to iteration variable 'i'" } */ + ; +} + +void +test5 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) + for (i = 0; i < 1024; ++i) + #pragma omp tile sizes (2, 2, 2) /* { dg-error "increment expression refers to iteration variable 'j'" "" { target c } } */ + for (j = 0; j < 1024; ++j) /* { dg-error "increment expression refers to iteration variable 'j'" "" { target c++ } } */ + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = 0; l < 1024; l += j) + ; +} + +void +test6 (void) +{ + int i, j, k, l; + #pragma omp for collapse(4) private (i, j, k, l) + for (i = 0; i < 1024; ++i) + #pragma omp tile sizes (2, 2, 2) + for (j = 0; j < 1024; ++j) + #pragma omp tile sizes (3, 3) + for (k = 0; k < 1024; ++k) + #pragma omp tile sizes (4) + for (l = 0; l < i - 2; ++l) /* { dg-message "non-rectangular loops from generated loops unsupported" } */ + ; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-11.c b/gcc/testsuite/c-c++-common/gomp/tile-11.c new file mode 100644 index 00000000000..7659fc5a072 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-11.c @@ -0,0 +1,110 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp tile sizes(0) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(-1) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes() /* { dg-error "expected expression before" "" { target c} } */ + /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(,) /* { dg-error "expected expression before" "" { target c } } */ + /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1,2 /* { dg-error "expected ',' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes /* { dg-error "expected '\\\(' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1) sizes(1) /* { dg-error "expected end of line before 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp unroll partia /* { dg-error "expected an OpenMP clause before 'partia'" } */ + #pragma omp tile sizes(1) /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp unroll /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1) + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(8,8) + #pragma omp unroll partial /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(8,8) + #pragma omp unroll partial /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" } */ + for (int i = 0; i < 100; ++i) + for (int j = i; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" } */ + for (int i = 0; i < 100; ++i) + for (int j = 2; j < i; ++j) + dummy (i); + + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + int s; + #pragma omp tile sizes(s) /* { dg-error "'sizes' argument needs positive integral constant" "" { target { ! c++98_only } } } */ + /* { dg-error "the value of 's' is not usable in a constant expression" "" { target { c++ && { ! c++98_only } } } .-1 } */ + /* { dg-error "'s' cannot appear in a constant-expression" "" { target c++98_only } .-2 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(42.0) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-12.c b/gcc/testsuite/c-c++-common/gomp/tile-12.c new file mode 100644 index 00000000000..8408d53b641 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-12.c @@ -0,0 +1,134 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp parallel for + #pragma omp tile sizes(0) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(-1) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes(5, -42) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp tile sizes(0.5f) /* { dg-error "'sizes' argument needs positive integral constant" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes() /* { dg-error "expected expression before" "" { target c} } */ + /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(,) /* { dg-error "expected expression before" "" { target c } } */ + /* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1,2 /* { dg-error "expected ',' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes /* { dg-error "expected '\\\(' before end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) sizes(1) /* { dg-error "expected end of line before 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp unroll partia /* { dg-error "expected an OpenMP clause before 'partia'" } */ + #pragma omp tile sizes(1) /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .-1 } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp unroll /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(8,8) + #pragma omp unroll partial /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(8,8) + #pragma omp unroll partial /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = i; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = 2; j < i; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (j); + } + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + #pragma omp tile /* { dg-error "expected 'sizes'" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp tile sizes (1) sizes (1) /* { dg-error "expected end of line" } */ + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-13.c b/gcc/testsuite/c-c++-common/gomp/tile-13.c new file mode 100644 index 00000000000..6948a44f625 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-13.c @@ -0,0 +1,70 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp for + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = i; j < 100; ++j) + dummy (i); + + #pragma omp for + #pragma omp tile sizes(1, 2) /* { dg-error "non-rectangular 'tile'" "" { target c } } */ + for (int i = 0; i < 100; ++i) /* { dg-error "non-rectangular 'tile'" "" { target c++ } } */ + for (int j = 0; j < i; ++j) + dummy (i); + + + #pragma omp for collapse(2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(3) + #pragma omp tile sizes(1, 2) /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(5, 6) + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) /* { dg-error "not enough nested loops" } */ + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1) /* { dg-error "'tile' construct generates 1 loops with canonical form but 2 loops are needed" } */ + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(3) + #pragma omp tile sizes(1, 2) /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(3) + #pragma omp tile sizes(5, 6) /* { dg-error "'tile' construct generates 2 loops with canonical form but 3 loops are needed" } */ + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-14.c b/gcc/testsuite/c-c++-common/gomp/tile-14.c new file mode 100644 index 00000000000..1b3f6fc1dcb --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-14.c @@ -0,0 +1,53 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp for + #pragma omp tile sizes(2, 3) + #pragma omp tile sizes(3, 4, 5) + #pragma omp tile sizes(6, 7, 8, 9) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + for (int l = 0; l < 100; ++l) + dummy (i); + + #pragma omp for + #pragma omp tile sizes(2, 3) + for (int i = 0; i < 100; ++i) + #pragma omp tile sizes(3, 4, 5) + for (int j = 0; j < 100; ++j) + #pragma omp tile sizes(6, 7, 8, 9) + for (int k = 0; k < 100; ++k) + for (int l = 0; l < 100; ++l) + for (int m = 0; m < 100; ++m) + #pragma omp unroll partial(2) + for (int n = 0; n < 100; ++n) + dummy (i); + + #pragma omp for collapse(2) + for (int i = 0; i < 100; ++i) + #pragma omp tile sizes(2, 3) + #pragma omp tile sizes(3, 4, 5) + #pragma omp tile sizes(6, 7, 8, 9) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + for (int l = 0; l < 100; ++l) + for (int m = 0; m < 100; ++m) + dummy (i); + + #pragma omp for collapse(2) + for (int i = 0; i < 100; ++i) + #pragma omp tile sizes(2, 3) + for (int j = 0; j < 100; ++j) + #pragma omp tile sizes(3, 4, 5) + for (int k = 0; k < 100; ++k) + #pragma omp tile sizes(6, 7, 8, 9) + for (int l = 0; l < 100; ++l) + for (int m = 0; m < 100; ++m) + for (int n = 0; n < 100; ++n) + #pragma omp unroll partial(2) + for (int o = 0; o < 100; ++o) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-15.c b/gcc/testsuite/c-c++-common/gomp/tile-15.c new file mode 100644 index 00000000000..0308a1f13de --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-15.c @@ -0,0 +1,68 @@ +/* It isn't really clear what is supposed to be valid and what isn't when mixing + imperfectly nested loops with generated loops. Sorry for now until that is + clarified. */ +void foo (int, int); + +void +bar (void) +{ + #pragma omp for collapse(2) /* { dg-message "imperfectly nested loop using generated loops" "" { target c } } */ + for (int i = 0; i < 32; ++i) /* { dg-message "imperfectly nested loop using generated loops" "" { target c++ } } */ + { + foo (i, -1); + #pragma omp tile sizes (2) + for (int j = 0; j < 32; ++j) + foo (i, j); + foo (i, -2); + } +} + +void +baz (void) +{ + #pragma omp for collapse(2) /* { dg-message "imperfectly nested loop using generated loops" "" { target c } } */ + for (int i = 0; i < 32; ++i) /* { dg-message "imperfectly nested loop using generated loops" "" { target c++ } } */ + { + foo (i, -1); + #pragma omp tile sizes (2, 2) + for (int j = 0; j < 32; ++j) + #pragma omp tile sizes (2, 2) + for (int k = 0; k < 32; ++k) + for (int l = 0; l < 32; ++l) + foo (i + k, j + l); + foo (i, -2); + } +} + +void +qux (void) +{ + #pragma omp for collapse(2) /* { dg-message "imperfectly nested loop using generated loops" "" { target c } } */ + for (int i = 0; i < 32; ++i) /* { dg-message "imperfectly nested loop using generated loops" "" { target c++ } } */ + { + int m = i + 6; + foo (i, -1); + #pragma omp tile sizes (2) + for (int j = m; j < 32; ++j) + foo (i, j); + foo (i, -2); + } +} + +void +freddy (void) +{ + #pragma omp for collapse(2) /* { dg-message "imperfectly nested loop using generated loops" "" { target c } } */ + for (int i = 0; i < 32; ++i) /* { dg-message "imperfectly nested loop using generated loops" "" { target c++ } } */ + { + int m = i + 6; + foo (i, -1); + #pragma omp tile sizes (2, 2) + for (int j = 0; j < 32; ++j) + #pragma omp tile sizes (2, 2) + for (int k = 0; k < 32; ++k) + for (int l = m; l < 32; ++l) + foo (i + k, j + l); + foo (i, -2); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-2.c b/gcc/testsuite/c-c++-common/gomp/tile-2.c new file mode 100644 index 00000000000..5ca692c2544 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-2.c @@ -0,0 +1,67 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp parallel for + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(5, 6) + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + #pragma omp unroll partial + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp parallel for + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + { + dummy (i); + for (int j = 0; j < 100; ++j) + dummy (i); + } + + #pragma omp parallel for + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + { + for (int j = 0; j < 100; ++j) + dummy (j); + dummy (i); + } + + #pragma omp parallel for + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-3.c b/gcc/testsuite/c-c++-common/gomp/tile-3.c new file mode 100644 index 00000000000..4ba9d874faa --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-3.c @@ -0,0 +1,44 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp for collapse(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(1) + #pragma omp tile sizes(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp for collapse(1) + #pragma omp tile sizes(1) + #pragma omp tile sizes(1) + for (int i = 0; i < 100; ++i) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(1, 2) + #pragma omp tile sizes(1, 2) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + dummy (i); + + #pragma omp for collapse(2) + #pragma omp tile sizes(5, 6) + #pragma omp tile sizes(1, 2, 3) + for (int i = 0; i < 100; ++i) + for (int j = 0; j < 100; ++j) + for (int k = 0; k < 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-4.c b/gcc/testsuite/c-c++-common/gomp/tile-4.c new file mode 100644 index 00000000000..bcffbccf39e --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-4.c @@ -0,0 +1,320 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +test1 (void) +{ + int iter = 0; + int i; +#pragma omp tile sizes(3) + for (i = 0; i < 10; i = i + 2) + { + ASSERT_EQ (i, iter); + iter = iter + 2; + } + + ASSERT_EQ (i, 10); + return iter; +} + +int +test2 (void) +{ + int iter = 0; + int i; +#pragma omp tile sizes(3) + for (i = 0; i < 10; i = i + 2) + { + ASSERT_EQ (i, iter); + iter = iter + 2; + } + + ASSERT_EQ (i, 10); + return iter; +} + +int +test3 (void) +{ + int iter = 0; + int i; +#pragma omp tile sizes(8) + for (i = 0; i < 10; i = i + 2) + { + ASSERT_EQ (i, iter); + iter = iter + 2; + } + + ASSERT_EQ (i, 10); + return iter; +} + +int +test4 (void) +{ + int iter = 10; + int i; +#pragma omp tile sizes(8) + for (i = 10; i > 0; i = i - 2) + { + ASSERT_EQ (i, iter); + iter = iter - 2; + } + ASSERT_EQ (i, 0); + return iter; +} + +int +test5 (void) +{ + int iter = 10; + int i; +#pragma omp tile sizes(71) + for (i = 10; i > 0; i = i - 2) + { + ASSERT_EQ (i, iter); + iter = iter - 2; + } + + ASSERT_EQ (i, 0); + return iter; +} + +int +test6 (void) +{ + int iter = 10; + int i; +#pragma omp tile sizes(1) + for (i = 10; i > 0; i = i - 2) + { + ASSERT_EQ (i, iter); + iter = iter - 2; + } + ASSERT_EQ (i, 0); + return iter; +} + +int +test7 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(2) + for (i = 5; i < -5; i = i - 3) + { + fprintf (stderr, "%d\n", i); + __builtin_abort (); + iter = iter - 3; + } + + /* No iteration expected */ + return iter; +} + +int +test8 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(2) + for (i = 5; i > -5; i = i - 3) + { + ASSERT_EQ (i, iter); + /* Expect only first iteration of the last tile to execute */ + if (iter != -4) + iter = iter - 3; + } + + ASSERT_EQ (i, -7); + return iter; +} + + +int +test9 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(5) + for (i = 5; i >= -5; i = i - 4) + { + ASSERT_EQ (i, iter); + /* Expect only first iteration of the last tile to execute */ + if (iter != - 3) + iter = iter - 4; + } + + ASSERT_EQ (i, -7); + return iter; +} + +int +test10 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(5) + for (i = 5; i >= -5; i--) + { + ASSERT_EQ (i, iter); + iter--; + } + + ASSERT_EQ (i, -6); + return iter; +} + +int +test11 (void) +{ + int iter = 5; + int i; +#pragma omp tile sizes(15) + for (i = 5; i != -5; i--) + { + ASSERT_EQ (i, iter); + iter--; + } + ASSERT_EQ (i, -5); + return iter; +} + +int +test12 (void) +{ + int iter = 0; + unsigned i; +#pragma omp tile sizes(3) + for (i = 0; i != 5; i++) + { + ASSERT_EQ (i, iter); + iter++; + } + + ASSERT_EQ (i, 5); + return iter; +} + +int +test13 (void) +{ + int iter = -5; + long long unsigned int i = 42; +#pragma omp tile sizes(15) + for (int i = -5; i < 5; i = i + 3) + { + ASSERT_EQ (i, iter); + iter += 3; + } + + ASSERT_EQ (i, 42); + return iter; +} + +int +test14 (unsigned init, int step) +{ + int iter = init; + long long unsigned int i; +#pragma omp tile sizes(8) + for (i = init; i < 2 * init; i = i + step) + iter++; + + if (init) + ASSERT_EQ (i, 2 * init + (init == 5)); + return iter; +} + +int +test15 (unsigned init, int step) +{ + int iter = init; + int i; +#pragma omp tile sizes(8) + for (unsigned i = init; i > 2 * init; i = i + step) + iter++; + + return iter; +} + +int +main () +{ + int last_iter; + + last_iter = test1 (); + ASSERT_EQ (last_iter, 10); + + last_iter = test2 (); + ASSERT_EQ (last_iter, 10); + + last_iter = test3 (); + ASSERT_EQ (last_iter, 10); + + last_iter = test4 (); + ASSERT_EQ (last_iter, 0); + + last_iter = test5 (); + ASSERT_EQ (last_iter, 0); + + last_iter = test6 (); + ASSERT_EQ (last_iter, 0); + + last_iter = test7 (); + ASSERT_EQ (last_iter, 5); + + last_iter = test8 (); + ASSERT_EQ (last_iter, -4); + + last_iter = test9 (); + ASSERT_EQ (last_iter, -3); + + last_iter = test10 (); + ASSERT_EQ (last_iter, -6); + + last_iter = test11 (); + ASSERT_EQ (last_iter, -5); + + last_iter = test12 (); + ASSERT_EQ (last_iter, 5); + + last_iter = test13 (); + ASSERT_EQ (last_iter, 7); + + last_iter = test14 (0, 1); + ASSERT_EQ (last_iter, 0); + + last_iter = test14 (0, -1); + ASSERT_EQ (last_iter, 0); + + last_iter = test14 (8, 2); + ASSERT_EQ (last_iter, 12); + + last_iter = test14 (5, 3); + ASSERT_EQ (last_iter, 7); + + last_iter = test15 (8, -1); + ASSERT_EQ (last_iter, 8); + + last_iter = test15 (8, -2); + ASSERT_EQ (last_iter, 8); + + last_iter = test15 (5, -3); + ASSERT_EQ (last_iter, 5); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-5.c b/gcc/testsuite/c-c++-common/gomp/tile-5.c new file mode 100644 index 00000000000..45b40a44722 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-5.c @@ -0,0 +1,169 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +#define ASSERT_EQ_PTR(var, ptr) \ + do \ + { \ + if ((var) != (ptr)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %p, expected %p\n", \ + __FILE__, __LINE__, (var), (ptr)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +test1 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(5) + for (i = data; i < data + 10; i++) + { + ASSERT_EQ (*i, data[iter]); + ASSERT_EQ_PTR (i, data + iter); + iter++; + } + + ASSERT_EQ_PTR (i, data + 10); + return iter; +} + +int +test2 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(5) + for (i = data; i < data + 10; i = i + 2) + { + ASSERT_EQ_PTR (i, data + 2 * iter); + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 10); + return iter; +} + +int +test3 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(5) + for (i = data; i <= data + 9; i = i + 2) + { + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 10); + return iter; +} + +int +test4 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(5) + for (i = data; i != data + 10; i = i + 1) + { + ASSERT_EQ (*i, data[iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 10); + return iter; +} + +int +test5 (int data[15]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(3) + for (i = data + 14; i >= data + 5; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 4); + return iter; +} + +int +test6 (int data[15]) +{ + int iter = 0; + int *i; + #pragma omp tile sizes(3) + for (i = data + 14; i > data + 4; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + ASSERT_EQ_PTR (i, data + 4); + return iter; +} + +int +test7 (int data[15]) +{ + int iter = 0; + #pragma omp tile sizes(1) + for (int *i = data + 14; i != data + 4; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + return iter; +} + +int +main () +{ + int iter_count; + int data[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int data2[15] = { -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + iter_count = test1 (data); + ASSERT_EQ (iter_count, 10); + + iter_count = test2 (data); + ASSERT_EQ (iter_count, 5); + + iter_count = test3 (data); + ASSERT_EQ (iter_count, 5); + + iter_count = test4 (data); + ASSERT_EQ (iter_count, 10); + + iter_count = test5 (data2); + ASSERT_EQ (iter_count, 10); + + iter_count = test6 (data2); + ASSERT_EQ (iter_count, 10); + + iter_count = test7 (data2); + ASSERT_EQ (iter_count, 10); +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-6.c b/gcc/testsuite/c-c++-common/gomp/tile-6.c new file mode 100644 index 00000000000..9fcab428212 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-6.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +int +test1 (void) +{ + int sum = 0; + for (int k = 0; k < 10; k++) + { + #pragma omp tile sizes(5,7) + for (int i = 0; i < 10; i++) + for (int j = 0; j < 10; j = j + 2) + sum = sum + 1; + } + + return sum; +} + +int +main () +{ + int result = test1 (); + + if (result != 500) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-7.c b/gcc/testsuite/c-c++-common/gomp/tile-7.c new file mode 100644 index 00000000000..2c78b18e131 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-7.c @@ -0,0 +1,51 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +#define ASSERT_EQ_PTR(var, ptr) \ + do \ + { \ + if ((var) != (ptr)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %p, expected %p\n", \ + __FILE__, __LINE__, (var), (ptr)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +main () +{ + int iter_count; + int data[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int iter = 0; + int *i; + + #pragma omp tile sizes(1) + for (i = data; i < data + 10; i = i + 2) + { + ASSERT_EQ_PTR (i, data + 2 * iter); + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + unsigned long real_iter_count + = ((unsigned long)i - (unsigned long)data) / (sizeof (int) * 2); + ASSERT_EQ (real_iter_count, 5); + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-8.c b/gcc/testsuite/c-c++-common/gomp/tile-8.c new file mode 100644 index 00000000000..65b083b799d --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-8.c @@ -0,0 +1,50 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +main () +{ + int iter_j = 0, iter_k = 0; + unsigned i, j, k; + + #pragma omp tile sizes(3,5,8) + for (i = 0; i < 2; i=i+2) + for (j = 0; j < 3; j=j+1) + for (k = 0; k < 5; k=k+3) + { + /* fprintf (stderr, "i=%d j=%d k=%d\n", i, j, k); + fprintf (stderr, "iter_j=%d iter_k=%d\n", iter_j, iter_k); */ + ASSERT_EQ (i, 0); + if (k == 0) + { + ASSERT_EQ (j, iter_j); + iter_k = 0; + } + + ASSERT_EQ (k, iter_k); + + iter_k = iter_k + 3; + if (k == 3) + iter_j++; + } + + ASSERT_EQ (i, 2); + ASSERT_EQ (j, 3); + ASSERT_EQ (k, 6); + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/gomp/tile-9.c b/gcc/testsuite/c-c++-common/gomp/tile-9.c new file mode 100644 index 00000000000..02767511851 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/tile-9.c @@ -0,0 +1,19 @@ +/* { dg-additional-options "-O2" } */ + +int foo (int); + +void +mult (float *matrix1, float *matrix2, float *result, + unsigned dim0, unsigned dim1, unsigned dim2, unsigned dim3) +{ + #pragma omp taskloop collapse(3) + for (unsigned i = 0; i < dim0; i++) + #pragma omp tile sizes(2, 2) + #pragma omp tile sizes(2, 2) + #pragma omp tile sizes(2, 2) + for (unsigned j = 0; j < dim1; j += dim2 * foo (0)) + #pragma omp unroll partial(2) + #pragma omp unroll partial(2) + for (unsigned k = 0; k < dim1; k += dim3 * foo (1)) + result[i * dim1 + j] += matrix1[i * dim1 + k] * matrix2[k * dim0 + j]; +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-1.c b/gcc/testsuite/c-c++-common/gomp/unroll-1.c new file mode 100644 index 00000000000..514a9f8df64 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-1.c @@ -0,0 +1,132 @@ +extern void dummy (int); + +void +test1 (void) +{ + #pragma omp unroll partial + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test2 (void) +{ + #pragma omp unroll partial(10) + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test3 (void) +{ + #pragma omp unroll full + for (int i = 0; i < 100; ++i) + dummy (i); +} + +void +test4 (void) +{ + #pragma omp unroll full + for (int i = 0; i > 100; ++i) + dummy (i); +} + +void +test5 (void) +{ + #pragma omp unroll full + for (int i = 1; i <= 100; ++i) + dummy (i); +} + +void +test6 (void) +{ + #pragma omp unroll full + for (int i = 200; i >= 100; i--) + dummy (i); +} + +void +test7 (void) +{ + #pragma omp unroll full + for (int i = -100; i > 100; ++i) + dummy (i); +} + +void +test8 (void) +{ + #pragma omp unroll full + for (int i = 100; i > -200; --i) + dummy (i); +} + +void +test9 (void) +{ + #pragma omp unroll full + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test10 (void) +{ + #pragma omp unroll full + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test12 (void) +{ + #pragma omp unroll full + #pragma omp unroll partial + #pragma omp unroll partial + for (int i = -300; i != 100; ++i) + dummy (i); +} + +void +test13 (void) +{ + for (int i = 0; i < 100; ++i) + #pragma omp unroll full + #pragma omp unroll partial + #pragma omp unroll partial + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test14 (void) +{ + #pragma omp for + for (int i = 0; i < 100; ++i) + #pragma omp unroll full + #pragma omp unroll partial + #pragma omp unroll partial + for (int j = -300; j != 100; ++j) + dummy (i); +} + +void +test15 (void) +{ + #pragma omp for + for (int i = 0; i < 100; ++i) + { + dummy (i); + + #pragma omp unroll full + #pragma omp unroll partial + #pragma omp unroll partial + for (int j = -300; j != 100; ++j) + dummy (j); + + dummy (i); + } + } diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-2.c b/gcc/testsuite/c-c++-common/gomp/unroll-2.c new file mode 100644 index 00000000000..41dc81f82e2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-2.c @@ -0,0 +1,122 @@ +/* { dg-do compile { target { c || c++11 } } } */ +/* { dg-prune-output "error: invalid controlling predicate" } */ + +extern void dummy (int); + +void +test (void) +{ + #pragma omp unroll partial + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + #pragma omp unroll partial + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll full + #pragma omp unroll full /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll partial partial /* { dg-error "too many 'partial' clauses" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll full full /* { dg-error "too many 'full' clauses" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll partial + #pragma omp unroll /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + int i; + #pragma omp for /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + #pragma omp unroll( /* { dg-error "expected an OpenMP clause before '\\\(' token" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + #pragma omp unroll foo /* { dg-error "expected an OpenMP clause before 'foo'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll partial( /* { dg-error "expected expression before end of line" "" { target c } } */ + /* { dg-error "expected primary-expression before end of line" "" { target c++ } .-1 } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll partial() /* { dg-error "expected expression before '\\\)' token" "" { target c } } */ + /* { dg-error "expected primary-expression before '\\\)' token" "" { target c++ } .-1 } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll partial(i) + /* { dg-error "the value of 'i' is not usable in a constant expression" "" { target c++ } .-1 } */ + /* { dg-error "'partial' argument needs positive constant integer expression" "" { target *-*-* } .-2 } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp unroll parti /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll partial(1) /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + #pragma omp unroll parti /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + #pragma omp for + #pragma omp unroll partial(1) /* { dg-error "generated loop of 'unroll' construct without 'partial' clause does not have canonical form" "" { target *-*-* } .+1 } */ + #pragma omp unroll parti /* { dg-error "expected an OpenMP clause before 'parti'" } */ + for (int i = -300; i != 100; ++i) + dummy (i); + + int sum = 0; + #pragma omp parallel for reduction(+ : sum) collapse(2) + #pragma omp unroll partial(1) /* { dg-error "'unroll' construct with 'partial' clause generates just one loop with canonical form but 2 loops are needed" } */ + for (int i = 3; i < 10; ++i) + for (int j = -2; j < 7; ++j) + sum++; + + #pragma omp unroll partial full /* { dg-error "'full' clause must not be used together with 'partial' clause" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll full partial /* { dg-error "'full' clause must not be used together with 'partial' clause" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll partial(7) full /* { dg-error "'full' clause must not be used together with 'partial' clause" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll full partial(28) /* { dg-error "'full' clause must not be used together with 'partial' clause" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll partial(0.5) /* { dg-error "'partial' argument needs positive constant integer expression" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll partial(0) /* { dg-error "'partial' argument needs positive constant integer expression" } */ + for (int i = 0; i < 42; ++i) + dummy (i); + + #pragma omp unroll partial(-42) /* { dg-error "'partial' argument needs positive constant integer expression" } */ + for (int i = 0; i < 42; ++i) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-3.c b/gcc/testsuite/c-c++-common/gomp/unroll-3.c new file mode 100644 index 00000000000..81cc385c36c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-3.c @@ -0,0 +1,16 @@ +/* { dg-additional-options "-O2 -fdump-tree-cunroll -fdump-tree-original -fdump-tree-gimple" } */ + +extern void dummy (int); + +void +test1 (void) +{ +#pragma omp unroll full + for (int i = 0; i < 10; i++) + dummy (i); +} + +/* Loop should be removed with 10 copies of the body remaining */ +/* { dg-final { scan-tree-dump-times "dummy" 10 "cunroll" } } */ +/* { dg-final { scan-tree-dump "#pragma omp unroll" "original" } } */ +/* { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-4.c b/gcc/testsuite/c-c++-common/gomp/unroll-4.c new file mode 100644 index 00000000000..65c51cc0e50 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-4.c @@ -0,0 +1,18 @@ +/* { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } */ + +extern void dummy (int); + +void +test1 (void) +{ + int i; +#pragma omp unroll + for (int i = 0; i < 96; i++) + dummy (i); +} + +/* GCC unrolls the loop 8 times, but only during RTL optimizations. */ +/* { dg-final { scan-tree-dump "#pragma omp unroll" "original" } } */ +/* { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } */ +/* { dg-final { scan-tree-dump-times "dummy" 1 "gimple" } } */ +/* { dg-final { scan-assembler-times "dummy" 8 } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-5.c b/gcc/testsuite/c-c++-common/gomp/unroll-5.c new file mode 100644 index 00000000000..415d42136a7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-5.c @@ -0,0 +1,18 @@ +/* { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } */ + +extern void dummy (int); + +void +test1 (void) +{ + int i; +#pragma omp unroll partial + for (int i = 0; i < 96; i++) + dummy (i); +} + +/* GCC uses partial(8) for this case. */ +/* { dg-final { scan-tree-dump "#pragma omp unroll" "original" } } */ +/* { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } */ +/* { dg-final { scan-tree-dump-times "dummy" 1 "gimple" } } */ +/* { dg-final { scan-assembler-times "dummy" 8 } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-6.c b/gcc/testsuite/c-c++-common/gomp/unroll-6.c new file mode 100644 index 00000000000..840124de05a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-6.c @@ -0,0 +1,168 @@ +/* { dg-do run } */ +/* { dg-options "-O0 -fopenmp-simd" } */ + +#include + +#define ASSERT_EQ(var, val) \ + do \ + { \ + if ((var) != (val)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %d, expected %d\n", \ + __FILE__, __LINE__, (var), (val)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +#define ASSERT_EQ_PTR(var, ptr) \ + do \ + { \ + if ((var) != (ptr)) \ + { \ + fprintf (stderr, "%s:%d: Unexpected value %p, expected %p\n", \ + __FILE__, __LINE__, (var), (ptr)); \ + __builtin_abort (); \ + } \ + } \ + while (0) + +int +test1 (int data[10]) +{ + int iter = 0; + int *i; + + #pragma omp unroll partial(8) + for (i = data; i < data + 10; i++) + { + ASSERT_EQ (*i, data[iter]); + ASSERT_EQ_PTR (i, data + iter); + iter++; + } + + return iter; +} + +int +test2 (int data[10]) +{ + int iter = 0; + int *i; + + #pragma omp unroll partial(8) + for (i = data; i < data + 10; i = i + 2) + { + ASSERT_EQ_PTR (i, data + 2 * iter); + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + return iter; +} + +int +test3 (int data[10]) +{ + int iter = 0; + int *i; + + #pragma omp unroll partial(8) + for (i = data; i <= data + 9; i = i + 2) + { + ASSERT_EQ (*i, data[2 * iter]); + iter++; + } + + return iter; +} + +int +test4 (int data[10]) +{ + int iter = 0; + int *i; + #pragma omp unroll partial(8) + for (i = data; i != data + 10; i = i + 1) + { + ASSERT_EQ (*i, data[iter]); + iter++; + } + + return iter; +} + +int +test5 (int data[15]) +{ + int iter = 0; + int *i; + #pragma omp unroll partial(7) + for (i = data + 14; i >= data + 5; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + return iter; +} + +int +test6 (int data[15]) +{ + int iter = 0; + int *i; + + #pragma omp unroll partial(7) + for (i = data + 14; i > data + 4; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + return iter; +} + +int +test7 (int data[10]) +{ + int iter = 0; + + #pragma omp unroll partial(7) + for (int *i = data + 14; i != data + 4; i--) + { + ASSERT_EQ (*i, data[14 - iter]); + iter++; + } + + return iter; +} + +int +main () +{ + int iter_count; + int data[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + int data2[15] = { -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + iter_count = test1 (data); + ASSERT_EQ (iter_count, 10); + + iter_count = test2 (data); + ASSERT_EQ (iter_count, 5); + + iter_count = test3 (data); + ASSERT_EQ (iter_count, 5); + + iter_count = test4 (data); + ASSERT_EQ (iter_count, 10); + + iter_count = test5 (data2); + ASSERT_EQ (iter_count, 10); + + iter_count = test6 (data2); + ASSERT_EQ (iter_count, 10); + + iter_count = test7 (data2); + ASSERT_EQ (iter_count, 10); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-7.c b/gcc/testsuite/c-c++-common/gomp/unroll-7.c new file mode 100644 index 00000000000..b7480618db9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-7.c @@ -0,0 +1,18 @@ +extern void dummy (int); +int a[100]; + +void +test1 (void) +{ +#pragma omp unroll full + for (int i = -20; i < 20; i += 6) + dummy (i); +} + +void +test2 (void) +{ +#pragma omp unroll full + for (int *i = &a[6]; i < &a[78]; i += 4) + dummy (*i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-8.c b/gcc/testsuite/c-c++-common/gomp/unroll-8.c new file mode 100644 index 00000000000..8cf05005af1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-8.c @@ -0,0 +1,25 @@ +extern void dummy (int); + +void +test3 (int x) +{ +#pragma omp unroll full /* { dg-error "non-constant iteration count of 'unroll full' loop" } */ + for (int i = x; i < 20; i += 3) + dummy (i); +} + +void +test4 (int x) +{ +#pragma omp unroll full /* { dg-error "non-constant iteration count of 'unroll full' loop" } */ + for (int i = 5; i < x + 6; ++i) + dummy (i); +} + +void +test5 (int x) +{ +#pragma omp unroll full /* { dg-error "non-constant iteration count of 'unroll full' loop" } */ + for (int i = 5; i < 142; i += x) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-9.c b/gcc/testsuite/c-c++-common/gomp/unroll-9.c new file mode 100644 index 00000000000..0930a3c06a2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-9.c @@ -0,0 +1,13 @@ +/* { dg-additional-options "-O2 -fdump-tree-gimple" } */ + +void bar (int); + +void +foo (void) +{ + #pragma omp unroll full + for (int i = 1; i <= 100; i += 6) + bar (i); +} + +/* { dg-final { scan-tree-dump "\.ANNOTATE \\\(\[^\n\r]*, 1, 17\\\);" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-inner-1.c b/gcc/testsuite/c-c++-common/gomp/unroll-inner-1.c new file mode 100644 index 00000000000..5af2e29ad60 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-inner-1.c @@ -0,0 +1,11 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp unroll partial + for (int j = 0; j != 100; ++j) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-inner-2.c b/gcc/testsuite/c-c++-common/gomp/unroll-inner-2.c new file mode 100644 index 00000000000..b28de6e8857 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-inner-2.c @@ -0,0 +1,18 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp tile sizes(2) + for (int j = 0; j != 100; ++j) + dummy (i); + + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp tile sizes(2, 3) + for (int j = 0; j != 100; ++j) + for (int k = 0; k != 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-inner-3.c b/gcc/testsuite/c-c++-common/gomp/unroll-inner-3.c new file mode 100644 index 00000000000..cde8549ea8e --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-inner-3.c @@ -0,0 +1,11 @@ +extern void dummy (int); + +void +test (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp tile sizes(2, 3) + for (int j = 0; j != 100; ++j) /* { dg-error "not enough nested loops" } */ + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-1.c b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-1.c new file mode 100644 index 00000000000..fa3926176cb --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-1.c @@ -0,0 +1,30 @@ +extern void dummy (int); + +void +test1 (void) +{ + #pragma omp target parallel for collapse(3) + for (int i = -300; i != 100; ++i) + for (int j = i; j != i * 2; ++j) + #pragma omp unroll partial + for (int k = 2; k != 100; ++k) + dummy (i); + + #pragma omp unroll full + for (int i = -300; i != 100; ++i) + for (int j = i; j != i * 2; ++j) + for (int k = 2; k != 100; ++k) + dummy (i); + + for (int i = -300; i != 100; ++i) + #pragma omp unroll full + for (int j = i; j != i + 10; ++j) + for (int k = 2; k != 100; ++k) + dummy (i); + + for (int i = -300; i != 100; ++i) + #pragma omp unroll full + for (int j = i; j != i + 10; ++j) + for (int k = j; k != 100; ++k) + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-2.c b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-2.c new file mode 100644 index 00000000000..c4043f57ccf --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-2.c @@ -0,0 +1,22 @@ +extern void dummy (int); + +void +test1 (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp unroll partial + for (int j = 2; j != i; ++j) /* { dg-message "non-rectangular loops from generated loops unsupported" } */ + dummy (i); +} + +void +test2 (void) +{ + int i,j; + #pragma omp target parallel for collapse(2) + for (i = -300; i != 100; ++i) + #pragma omp unroll partial + for (j = 2; j != i; ++j) /* { dg-message "non-rectangular loops from generated loops unsupported" } */ + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-3.c b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-3.c new file mode 100644 index 00000000000..c371fca1f6d --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-non-rect-3.c @@ -0,0 +1,11 @@ +extern void dummy (int); + +void +test1 (void) +{ + #pragma omp target parallel for collapse(2) + for (int i = -300; i != 100; ++i) + #pragma omp unroll partial(2) + for (int j = i * 2; j <= i * 4 + 1; ++j) /* { dg-message "non-rectangular loops from generated loops unsupported" } */ + dummy (i); +} diff --git a/gcc/testsuite/c-c++-common/gomp/unroll-simd-1.c b/gcc/testsuite/c-c++-common/gomp/unroll-simd-1.c new file mode 100644 index 00000000000..aaef63cb47c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/unroll-simd-1.c @@ -0,0 +1,70 @@ +/* { dg-do run } */ +/* { dg-options "-fno-openmp -fopenmp-simd -fdump-tree-original -fdump-tree-gimple" } */ + +int +compute_sum1 (void) +{ + int sum = 0; + int i, j; + + #pragma omp simd reduction(+:sum) + for (i = 3; i < 10; ++i) + #pragma omp unroll full + for (j = -2; j < 7; ++j) + sum++; + + if (i != 10 || j != 7) + __builtin_abort (); + + return sum; +} + +int +compute_sum2 (void) +{ + int sum = 0; + int i, j; + + #pragma omp simd reduction(+:sum) + #pragma omp unroll partial(5) + for (i = 3; i < 10; ++i) + for (j = -2; j < 7; ++j) + sum++; + + if (i != 10 || j != 7) + __builtin_abort (); + + return sum; +} + +int +compute_sum3 (void) +{ + int sum = 0; + int i, j; + + #pragma omp simd reduction(+:sum) + #pragma omp unroll partial(1) + for (i = 3; i < 10; ++i) + for (j = -2; j < 7; ++j) + sum++; + + if (i != 10 || j != 7) + __builtin_abort (); + + return sum; +} + +int +main () +{ + if (compute_sum1 () != 7 * 9 + || compute_sum2 () != 7 * 9 + || compute_sum3 () != 7 * 9) + __builtin_abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump {omp unroll} "original" } } */ +/* { dg-final { scan-tree-dump-not {omp unroll} "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/initpri1-lto-static.c b/gcc/testsuite/c-c++-common/initpri1-lto-static.c new file mode 100644 index 00000000000..6393f7ec99b --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1-lto-static.c @@ -0,0 +1,7 @@ +/* { dg-do run { target init_priority } } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -O3" } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ +/* { dg-additional-options -DCDTOR_LINKAGE=static } */ + +#include "initpri1.c" diff --git a/gcc/testsuite/c-c++-common/initpri1-lto.c b/gcc/testsuite/c-c++-common/initpri1-lto.c new file mode 100644 index 00000000000..7fb4bf1aa82 --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1-lto.c @@ -0,0 +1,7 @@ +/* { dg-do run { target init_priority } } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -O3" } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ +/* { dg-additional-options -DCDTOR_LINKAGE= } */ + +#include "initpri1.c" diff --git a/gcc/testsuite/c-c++-common/initpri1-split-static.c b/gcc/testsuite/c-c++-common/initpri1-split-static.c new file mode 100644 index 00000000000..02d8b162e19 --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1-split-static.c @@ -0,0 +1,4 @@ +/* { dg-do run { target init_priority } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ +/* { dg-additional-sources {initpri1_part_c1.c initpri1_part_c2.c initpri1_part_c3.c initpri1_part_d1.c initpri1_part_d2.c initpri1_part_d3.c initpri1_part_cd4.c initpri1_part_main.c} } */ +/* { dg-additional-options -DCDTOR_LINKAGE=static } */ diff --git a/gcc/testsuite/c-c++-common/initpri1-split.c b/gcc/testsuite/c-c++-common/initpri1-split.c new file mode 100644 index 00000000000..f1482c7e0c1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1-split.c @@ -0,0 +1,4 @@ +/* { dg-do run { target init_priority } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ +/* { dg-additional-sources {initpri1_part_c1.c initpri1_part_c2.c initpri1_part_c3.c initpri1_part_d1.c initpri1_part_d2.c initpri1_part_d3.c initpri1_part_cd4.c initpri1_part_main.c} } */ +/* { dg-additional-options -DCDTOR_LINKAGE= } */ diff --git a/gcc/testsuite/c-c++-common/initpri1-static.c b/gcc/testsuite/c-c++-common/initpri1-static.c new file mode 100644 index 00000000000..ac101ff63cb --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1-static.c @@ -0,0 +1,5 @@ +/* { dg-do run { target init_priority } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ +/* { dg-additional-options -DCDTOR_LINKAGE=static } */ + +#include "initpri1.c" diff --git a/gcc/testsuite/c-c++-common/initpri1.c b/gcc/testsuite/c-c++-common/initpri1.c new file mode 100644 index 00000000000..73579cdd06b --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1.c @@ -0,0 +1,19 @@ +/* { dg-do run { target init_priority } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ +/* { dg-additional-options -DCDTOR_LINKAGE= } */ + +#include "initpri1_part_c1.c" + +#include "initpri1_part_c2.c" + +#include "initpri1_part_c3.c" + +#include "initpri1_part_d1.c" + +#include "initpri1_part_d2.c" + +#include "initpri1_part_d3.c" + +#include "initpri1_part_cd4.c" + +#include "initpri1_part_main.c" diff --git a/gcc/testsuite/c-c++-common/initpri1_part_c1.c b/gcc/testsuite/c-c++-common/initpri1_part_c1.c new file mode 100644 index 00000000000..da2f4e6c0bc --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1_part_c1.c @@ -0,0 +1,13 @@ +/* { dg-skip-if part { *-*-* } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ + +extern int i; + +CDTOR_LINKAGE +void c1() __attribute__((constructor (500))); + +CDTOR_LINKAGE +void c1() { + if (i++ != 0) + __builtin_abort (); +} diff --git a/gcc/testsuite/c-c++-common/initpri1_part_c2.c b/gcc/testsuite/c-c++-common/initpri1_part_c2.c new file mode 100644 index 00000000000..926608dc0d9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1_part_c2.c @@ -0,0 +1,13 @@ +/* { dg-skip-if part { *-*-* } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ + +extern int i; + +CDTOR_LINKAGE +void c2() __attribute__((constructor (700))); + +CDTOR_LINKAGE +void c2() { + if (i++ != 2) + __builtin_abort (); +} diff --git a/gcc/testsuite/c-c++-common/initpri1_part_c3.c b/gcc/testsuite/c-c++-common/initpri1_part_c3.c new file mode 100644 index 00000000000..59941ce7428 --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1_part_c3.c @@ -0,0 +1,13 @@ +/* { dg-skip-if part { *-*-* } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ + +extern int i; + +CDTOR_LINKAGE +void c3() __attribute__((constructor (600))); + +CDTOR_LINKAGE +void c3() { + if (i++ != 1) + __builtin_abort (); +} diff --git a/gcc/testsuite/c-c++-common/initpri1_part_cd4.c b/gcc/testsuite/c-c++-common/initpri1_part_cd4.c new file mode 100644 index 00000000000..c209db3718e --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1_part_cd4.c @@ -0,0 +1,15 @@ +/* { dg-skip-if part { *-*-* } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ + +extern int i; +extern int j; + +CDTOR_LINKAGE +void cd4() __attribute__((constructor (800), destructor (800))); + +CDTOR_LINKAGE +void cd4() { + if (i != 3) + __builtin_abort (); + ++j; +} diff --git a/gcc/testsuite/c-c++-common/initpri1_part_d1.c b/gcc/testsuite/c-c++-common/initpri1_part_d1.c new file mode 100644 index 00000000000..817603e275b --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1_part_d1.c @@ -0,0 +1,13 @@ +/* { dg-skip-if part { *-*-* } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ + +extern int i; + +CDTOR_LINKAGE +void d1() __attribute__((destructor (500))); + +CDTOR_LINKAGE +void d1() { + if (--i != 0) + __builtin_abort (); +} diff --git a/gcc/testsuite/c-c++-common/initpri1_part_d2.c b/gcc/testsuite/c-c++-common/initpri1_part_d2.c new file mode 100644 index 00000000000..1dcb7367726 --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1_part_d2.c @@ -0,0 +1,13 @@ +/* { dg-skip-if part { *-*-* } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ + +extern int i; + +CDTOR_LINKAGE +void d2() __attribute__((destructor (700))); + +CDTOR_LINKAGE +void d2() { + if (--i != 2) + __builtin_abort (); +} diff --git a/gcc/testsuite/c-c++-common/initpri1_part_d3.c b/gcc/testsuite/c-c++-common/initpri1_part_d3.c new file mode 100644 index 00000000000..ae290fa4594 --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1_part_d3.c @@ -0,0 +1,16 @@ +/* { dg-skip-if part { *-*-* } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ + +extern int i; +extern int j; + +CDTOR_LINKAGE +void d3() __attribute__((destructor (600))); + +CDTOR_LINKAGE +void d3() { + if (j != 2) + __builtin_abort (); + if (--i != 1) + __builtin_abort (); +} diff --git a/gcc/testsuite/c-c++-common/initpri1_part_main.c b/gcc/testsuite/c-c++-common/initpri1_part_main.c new file mode 100644 index 00000000000..bff58d75e68 --- /dev/null +++ b/gcc/testsuite/c-c++-common/initpri1_part_main.c @@ -0,0 +1,13 @@ +/* { dg-skip-if part { *-*-* } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ + +int i; +int j; + +int main () { + if (i != 3) + return 1; + if (j != 1) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/initpri2.c b/gcc/testsuite/c-c++-common/initpri2.c similarity index 92% rename from gcc/testsuite/gcc.dg/initpri2.c rename to gcc/testsuite/c-c++-common/initpri2.c index fa9fda0d7f3..bda2a626c64 100644 --- a/gcc/testsuite/gcc.dg/initpri2.c +++ b/gcc/testsuite/c-c++-common/initpri2.c @@ -1,4 +1,5 @@ /* { dg-do compile { target init_priority } } */ +/* Via the magic string "-std=*++" indicate that testing one (the default) C++ standard is sufficient. */ /* Priorities must be in the range [0, 65535]. */ void c1() diff --git a/gcc/testsuite/g++.dg/abi/aarch64_guard1.C b/gcc/testsuite/g++.dg/abi/aarch64_guard1.C index 52be32decc6..e2669a89fbf 100644 --- a/gcc/testsuite/g++.dg/abi/aarch64_guard1.C +++ b/gcc/testsuite/g++.dg/abi/aarch64_guard1.C @@ -12,6 +12,5 @@ int *foo () return &x; } -// { dg-final { scan-assembler _ZGVZ3foovE1x,8,8 { target { ! *-*-darwin* } } } } -// { dg-final { scan-assembler __DATA,__bss,__ZGVZ3foovE1x,8,3 { target *-*-darwin* } } } +// { dg-final { scan-assembler _ZGVZ3foovE1x,8,8 } } // { dg-final { scan-tree-dump "& 1" "original" } } diff --git a/gcc/testsuite/g++.dg/abi/arm_va_list.C b/gcc/testsuite/g++.dg/abi/arm_va_list.C index ff9fd8bcf0d..4f6f3a46da4 100644 --- a/gcc/testsuite/g++.dg/abi/arm_va_list.C +++ b/gcc/testsuite/g++.dg/abi/arm_va_list.C @@ -8,10 +8,8 @@ // #include typedef __builtin_va_list va_list; -// { dg-final { scan-assembler "\n_Z1fPSt9__va_list:" { target { ! *-*-darwin* } } } } -// { dg-final { scan-assembler "\n__Z1fPPc:" { target *-*-darwin* } } } +// { dg-final { scan-assembler "\n_Z1fPSt9__va_list:" } } void f(va_list*) {} -// { dg-final { scan-assembler "\n_Z1gSt9__va_listS_:" { target { ! *-*-darwin* } } } } -// { dg-final { scan-assembler "\n__Z1gPcS_:" { target *-*-darwin* } } } +// { dg-final { scan-assembler "\n_Z1gSt9__va_listS_:" } } void g(va_list, va_list) {} diff --git a/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc b/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc deleted file mode 100644 index 4f581694177..00000000000 --- a/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc +++ /dev/null @@ -1,17 +0,0 @@ -// PR c++/106435 -#include "pr106435.h" - -//#include - -Foo::Foo() { - ++num_calls; -// std::cout << "Foo::Foo(this=" << this << ")\n"; -} - -int Foo::func() { -// std::cout << "Foo::func(this=" << this << ")\n"; - return num_calls; -} - -thread_local Foo Bar::foo; -thread_local Foo Bar::baz; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr106435.C b/gcc/testsuite/g++.dg/cpp0x/pr106435.C deleted file mode 100644 index d600976f9f9..00000000000 --- a/gcc/testsuite/g++.dg/cpp0x/pr106435.C +++ /dev/null @@ -1,20 +0,0 @@ -// PR c++/106435 -// { dg-do run { target c++11 } } -// { dg-additional-sources "pr106435-b.cc" } - -#include "pr106435.h" - -int num_calls = 0; - -extern "C" __attribute__((__noreturn__)) void abort(); - -thread_local Foo Bar::bat; - -int main() { - int v = Bar::foo.func(); - if (v != 2) - abort(); - v = Bar::bat.func(); - if (v != 3) - abort(); -} diff --git a/gcc/testsuite/g++.dg/cpp0x/pr106435.h b/gcc/testsuite/g++.dg/cpp0x/pr106435.h deleted file mode 100644 index 240de1ee9a9..00000000000 --- a/gcc/testsuite/g++.dg/cpp0x/pr106435.h +++ /dev/null @@ -1,14 +0,0 @@ -// PR c++/106435 -#pragma once - -extern int num_calls; -struct Foo { - Foo(); - int func(); -}; - -struct Bar { - thread_local static Foo foo; - thread_local static Foo baz; - thread_local static Foo bat; -}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic185.C b/gcc/testsuite/g++.dg/cpp0x/variadic185.C new file mode 100644 index 00000000000..2c04afeda00 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic185.C @@ -0,0 +1,43 @@ +// PR c++/115012 +// { dg-do compile { target { c++11 } } } +// { dg-final { scan-assembler "_Z3fooIJidEEvDpFT_iE" } } +// { dg-final { scan-assembler "_Z3barIiEvPFT_iE" } } +// { dg-final { scan-assembler "_Z3bazIJidEEvDpFT_iE" } } + +template +void +foo (T... x (int)) +{ +} + +template +void +bar (T (int)) +{ +} + +template +void +baz (T... (int)) +{ +} + +int +f1 (int) +{ + return 0; +} + +double +f2 (int) +{ + return 0; +} + +void +corge () +{ + foo (f1, f2); + bar (f1); + baz (f1, f2); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C index cedd661710c..4162361d14f 100644 --- a/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C +++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto-103497.C @@ -1,7 +1,7 @@ // PR c++/103497 // { dg-do compile { target c++14 } } -void foo(decltype(auto)... args); // { dg-error "cannot declare a parameter with .decltype.auto.." } +void foo(decltype(auto)... args); // { dg-error "contains no parameter packs" } int main() { foo(); diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval37.C b/gcc/testsuite/g++.dg/cpp2a/consteval37.C new file mode 100644 index 00000000000..519d83d9bf8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/consteval37.C @@ -0,0 +1,16 @@ +// PR c++/111106 +// { dg-do compile { target c++20 } } + +consteval int id (int i) { return i; } + +constexpr int f (auto i) + requires requires { id (i) } // { dg-error "expected" } +{ + return i; +} + +void g () { + f (42); +} + +// { dg-excess-errors "" } diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C new file mode 100644 index 00000000000..efd4bb45d58 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ5.C @@ -0,0 +1,15 @@ +// PR c++/115378 +// { dg-do compile { target c++20 } } + +struct tt {}; + +template +constexpr auto __counter = 1; + +template +using _as_base = tt; + +template +struct env : _as_base>... {}; + +env t; diff --git a/gcc/testsuite/g++.dg/ext/arm-bf16/bf16-mangle-aarch64-1.C b/gcc/testsuite/g++.dg/ext/arm-bf16/bf16-mangle-aarch64-1.C index a017ce8ce5f..5426a1814b8 100644 --- a/gcc/testsuite/g++.dg/ext/arm-bf16/bf16-mangle-aarch64-1.C +++ b/gcc/testsuite/g++.dg/ext/arm-bf16/bf16-mangle-aarch64-1.C @@ -2,12 +2,12 @@ /* Test mangling */ -/* { dg-final { scan-assembler {\t.globa?l[ \t]_?_Z1fPu6__bf16} } } */ +/* { dg-final { scan-assembler "\t.global\t_Z1fPu6__bf16" } } */ void f (__bf16 *x) { } -/* { dg-final { scan-assembler {\t.globa?l[ \t]_?_Z1gPu6__bf16S_} } } */ +/* { dg-final { scan-assembler "\t.global\t_Z1gPu6__bf16S_" } } */ void g (__bf16 *x, __bf16 *y) { } -/* { dg-final { scan-assembler {\t.globa?l[ \t]_?_ZN1SIu6__bf16u6__bf16E1iE} } } */ +/* { dg-final { scan-assembler "\t.global\t_ZN1SIu6__bf16u6__bf16E1iE" } } */ template struct S { static int i; }; template <> int S<__bf16, __bf16>::i = 3; diff --git a/gcc/testsuite/g++.dg/gomp/attrs-4.C b/gcc/testsuite/g++.dg/gomp/attrs-4.C index 005add826ba..a730ad7db50 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-4.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-4.C @@ -49,7 +49,7 @@ foo (int x) for (int i = 0; i < 16; i++) ; #pragma omp for - [[omp::directive (master)]] // { dg-error "for statement expected before '\\\[' token" } + [[omp::directive (master)]] // { dg-error "loop nest expected before '\\\[' token" } ; #pragma omp target teams [[omp::directive (parallel)]] // { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" } diff --git a/gcc/testsuite/g++.dg/gomp/for-1.C b/gcc/testsuite/g++.dg/gomp/for-1.C index f8bb9d54727..0e042fd1381 100644 --- a/gcc/testsuite/g++.dg/gomp/for-1.C +++ b/gcc/testsuite/g++.dg/gomp/for-1.C @@ -24,7 +24,7 @@ void foo (int j, int k) // Malformed parallel loops. #pragma omp for - i = 0; // { dg-error "for statement expected" } + i = 0; // { dg-error "loop nest expected" } for ( ; i < 10; ) { baz (i); diff --git a/gcc/testsuite/g++.dg/gomp/pr94512.C b/gcc/testsuite/g++.dg/gomp/pr94512.C index 8ba0e65795f..1d5cf150987 100644 --- a/gcc/testsuite/g++.dg/gomp/pr94512.C +++ b/gcc/testsuite/g++.dg/gomp/pr94512.C @@ -8,7 +8,7 @@ void bar () { #pragma omp parallel master taskloop - foo (); // { dg-error "for statement expected before" } + foo (); // { dg-error "loop nest expected before" } } void diff --git a/gcc/testsuite/g++.dg/gomp/tile-1.C b/gcc/testsuite/g++.dg/gomp/tile-1.C new file mode 100644 index 00000000000..cc45dcdf880 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/tile-1.C @@ -0,0 +1,30 @@ +// { dg-do compile { target c++11 } } + +#include + +extern void dummy (int); + +template void +test1_template () +{ + std::vector v; + + for (unsigned i = 0; i < 10; i++) + v.push_back (i); + +#pragma omp teams distribute parallel for num_teams(V) + for (int i : v) + dummy (i); + +#pragma omp tile sizes (V, U) + for (T i : v) + for (T j : v) + for (T k : v) + dummy (i); +} + +void +test () +{ + test1_template (); +}; diff --git a/gcc/testsuite/g++.dg/gomp/tile-2.C b/gcc/testsuite/g++.dg/gomp/tile-2.C new file mode 100644 index 00000000000..dcaa8d736bb --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/tile-2.C @@ -0,0 +1,30 @@ +// { dg-do compile { target c++11 } } + +#include + +extern void dummy (int); + +template void +test1_template () +{ + std::vector v; + + for (unsigned i = 0; i < 10; i++) + v.push_back (i); + +#pragma omp for + for (int i : v) + dummy (i); + +#pragma omp tile sizes (U, 10, V) // { dg-error "'sizes' argument needs positive integral constant" } + for (T i : v) + for (T j : v) + for (T k : v) + dummy (i); +} + +void +test () +{ + test1_template (); +} diff --git a/gcc/testsuite/g++.dg/gomp/unroll-1.C b/gcc/testsuite/g++.dg/gomp/unroll-1.C new file mode 100644 index 00000000000..d4b73004b7c --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/unroll-1.C @@ -0,0 +1,42 @@ +// { dg-do compile { target c++11 } } + +#include + +extern void dummy (int); + +void +test1 () +{ + std::vector v; + + for (unsigned i = 0; i < 1000; i++) + v.push_back (i); + + #pragma omp for + for (int i : v) + dummy (i); + + #pragma omp unroll partial(5) + for (int i : v) + dummy (i); +} + +void +test2 () +{ + std::vector> v; + + for (unsigned i = 0; i < 10; i++) + { + std::vector u; + for (unsigned j = 0; j < 10; j++) + u.push_back (j); + v.push_back (u); + } + + #pragma omp for + #pragma omp unroll partial(5) + for (auto u : v) + for (int i : u) + dummy (i); +} diff --git a/gcc/testsuite/g++.dg/gomp/unroll-2.C b/gcc/testsuite/g++.dg/gomp/unroll-2.C new file mode 100644 index 00000000000..d214d728c3a --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/unroll-2.C @@ -0,0 +1,51 @@ +// { dg-do compile { target c++11 } } + +#include + +extern void dummy (int); + +template void +test_template () +{ + std::vector v; + + for (unsigned i = 0; i < 1000; i++) + v.push_back (i); + +#pragma omp for + for (int i : v) + dummy (i); + +#pragma omp unroll partial(U1) + for (T i : v) + dummy (i); + +#pragma omp unroll partial(U2) // { dg-error "'partial' argument needs positive constant integer expression" } + for (T i : v) + dummy (i); + +#pragma omp unroll partial(U3) // { dg-error "'partial' argument needs positive constant integer expression" } + for (T i : v) + dummy (i); + +#pragma omp for +#pragma omp unroll partial(U1) + for (T i : v) + dummy (i); + +#pragma omp for +#pragma omp unroll partial(U2) // { dg-error "'partial' argument needs positive constant integer expression" } + for (T i : v) + dummy (i); + +#pragma omp for +#pragma omp unroll partial(U3) // { dg-error "'partial' argument needs positive constant integer expression" } + for (T i : v) + dummy (i); +} + +void +test () +{ + test_template (); +} diff --git a/gcc/testsuite/g++.dg/gomp/unroll-3.C b/gcc/testsuite/g++.dg/gomp/unroll-3.C new file mode 100644 index 00000000000..6ef24ac2ffb --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/unroll-3.C @@ -0,0 +1,30 @@ +// { dg-do compile { target c++11 } } +// { dg-additional-options "-fdump-tree-original -fdump-tree-gimple" } + +#include + +extern void dummy (int); + +constexpr unsigned +fib (unsigned n) +{ + return n <= 2 ? 1 : fib (n-1) + fib (n-2); +} + +void +test1 () +{ + std::vector v; + + for (unsigned i = 0; i < 1000; i++) + v.push_back (i); + +#pragma omp unroll partial(fib(10)) + for (int i : v) + dummy (i); +} + + +// Loop should be unrolled fib(10) = 55 times +// { dg-final { scan-tree-dump {#pragma omp unroll partial\(55\)} "original" } } +// { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } diff --git a/gcc/testsuite/g++.dg/modules/dashinclude-1_a.H b/gcc/testsuite/g++.dg/modules/dashinclude-1_a.H new file mode 100644 index 00000000000..c1b40a53924 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/dashinclude-1_a.H @@ -0,0 +1,5 @@ +// { dg-module-do run } +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +inline int f() { return 0; } diff --git a/gcc/testsuite/g++.dg/modules/dashinclude-1_b.C b/gcc/testsuite/g++.dg/modules/dashinclude-1_b.C new file mode 100644 index 00000000000..6e6a33407a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/dashinclude-1_b.C @@ -0,0 +1,9 @@ +// Test that include translation works with command-line -include. +// { dg-additional-options "-fmodules-ts -fdump-lang-module -include $srcdir/g++.dg/modules/dashinclude-1_a.H" } + +int main () +{ + return f(); +} + +// { dg-final { scan-lang-dump {Translating include to import} module } } diff --git a/gcc/testsuite/g++.dg/opt/icf1.C b/gcc/testsuite/g++.dg/opt/icf1.C index e13020b9c88..fbb275e635a 100644 --- a/gcc/testsuite/g++.dg/opt/icf1.C +++ b/gcc/testsuite/g++.dg/opt/icf1.C @@ -1,7 +1,6 @@ // Test that -fipa-icf combines i and j. // { dg-do run { target c++11 } } // { dg-options -fipa-icf } -// { dg-xfail-run-if "PR111067" { *-*-darwin* } } [[no_unique_address]] extern const int i[] = { 1,2,3 }; [[no_unique_address]] extern const int j[] = { 1,2,3 }; diff --git a/gcc/testsuite/g++.dg/opt/icf2.C b/gcc/testsuite/g++.dg/opt/icf2.C index b5cb8c81f36..1ad48f6173d 100644 --- a/gcc/testsuite/g++.dg/opt/icf2.C +++ b/gcc/testsuite/g++.dg/opt/icf2.C @@ -1,7 +1,6 @@ // Test that -fipa-icf combines the backing arrays for a and b. // { dg-do run { target c++11 } } // { dg-options -fipa-icf } -// { dg-xfail-run-if "PR111067" { *-*-darwin* } } #include diff --git a/gcc/testsuite/g++.dg/opt/icf3.C b/gcc/testsuite/g++.dg/opt/icf3.C index 514926bae68..8b86982b542 100644 --- a/gcc/testsuite/g++.dg/opt/icf3.C +++ b/gcc/testsuite/g++.dg/opt/icf3.C @@ -1,7 +1,6 @@ // Test that -fipa-icf combines the backing arrays for a and b. // { dg-do run { target c++11 } } // { dg-options -fipa-icf } -// { dg-xfail-run-if "PR111067" { *-*-darwin* } } #include diff --git a/gcc/testsuite/g++.dg/overload/using6.C b/gcc/testsuite/g++.dg/overload/using6.C new file mode 100644 index 00000000000..4f89f68a30f --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/using6.C @@ -0,0 +1,5 @@ +// PR c++/109958 + +struct B { static int f(); }; +struct D : B { using B::f; }; +void f(D d) { &d.f; } diff --git a/gcc/testsuite/g++.dg/parse/crash73.C b/gcc/testsuite/g++.dg/parse/crash73.C new file mode 100644 index 00000000000..97b8b5e8325 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/crash73.C @@ -0,0 +1,19 @@ +// PR c++/103338 +// { dg-do compile { target c++11 } } + +template +struct zip_view { + struct Iterator; +}; + +template +struct zip_transform_view; + +template +struct zip_view::Iterator { // { dg-error "no class template" } + template + template + friend class zip_transform_view::Iterator; +}; + +zip_view<>::Iterator iter; diff --git a/gcc/testsuite/g++.dg/parse/crash74.C b/gcc/testsuite/g++.dg/parse/crash74.C new file mode 100644 index 00000000000..a7ba5094be6 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/crash74.C @@ -0,0 +1,11 @@ +// PR c++/107575 + +void f (void) { + virtual int f (void) const; // { dg-line line_4 } + virtual int f (void); // { dg-line line_5 } +} + +// { dg-error "outside class declaration" {} { target *-*-* } line_4 } +// { dg-error "cannot have cv-qualifier" {} { target *-*-* } line_4 } +// { dg-error "ambiguating new declaration of" {} { target *-*-* } line_4 } +// { dg-error "outside class declaration" {} { target *-*-* } line_5 } diff --git a/gcc/testsuite/g++.dg/pch/pch.exp b/gcc/testsuite/g++.dg/pch/pch.exp index 583f91284ba..a443e8fc392 100644 --- a/gcc/testsuite/g++.dg/pch/pch.exp +++ b/gcc/testsuite/g++.dg/pch/pch.exp @@ -31,7 +31,7 @@ set old_dg_do_what_default "${dg-do-what-default}" foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.C]] { # We don't try to use the loop-optimizing options, since they are highly # unlikely to make any difference to PCH. - dg-pch $subdir $test [list "-g -Winvalid-pch" "-O2 -g -Winvalid-pch" "-O2 -Winvalid-pch"] ".H" + dg-pch $subdir $test [list "-g" "-O2 -g" "-O2"] ".H" } set dg-do-what-default "$old_dg_do_what_default" diff --git a/gcc/testsuite/g++.dg/special/initpri1.C b/gcc/testsuite/g++.dg/special/initpri1.C deleted file mode 100644 index bd24961e46b..00000000000 --- a/gcc/testsuite/g++.dg/special/initpri1.C +++ /dev/null @@ -1,62 +0,0 @@ -/* { dg-do run { target init_priority } } */ - -extern "C" void abort (); - -int i; -int j; - -void c1() __attribute__((constructor (500))); -void c2() __attribute__((constructor (700))); -void c3() __attribute__((constructor (600))); - -void c1() { - if (i++ != 0) - abort (); -} - -void c2() { - if (i++ != 2) - abort (); -} - -void c3() { - if (i++ != 1) - abort (); -} - -void d1() __attribute__((destructor (500))); -void d2() __attribute__((destructor (700))); -void d3() __attribute__((destructor (600))); - -void d1() { - if (--i != 0) - abort (); -} - -void d2() { - if (--i != 2) - abort (); -} - -void d3() { - if (j != 2) - abort (); - if (--i != 1) - abort (); -} - -void cd4() __attribute__((constructor (800), destructor (800))); - -void cd4() { - if (i != 3) - abort (); - ++j; -} - -int main () { - if (i != 3) - return 1; - if (j != 1) - abort (); - return 0; -} diff --git a/gcc/testsuite/g++.dg/special/initpri2.C b/gcc/testsuite/g++.dg/special/initpri2.C deleted file mode 100644 index fa9fda0d7f3..00000000000 --- a/gcc/testsuite/g++.dg/special/initpri2.C +++ /dev/null @@ -1,39 +0,0 @@ -/* { dg-do compile { target init_priority } } */ - -/* Priorities must be in the range [0, 65535]. */ -void c1() - __attribute__((constructor (-1))); /* { dg-error "priorities" } */ -void c2() - __attribute__((constructor (65536))); /* { dg-error "priorities" } */ -void d1() - __attribute__((destructor (-1))); /* { dg-error "priorities" } */ -void d2() - __attribute__((destructor (65536))); /* { dg-error "priorities" } */ - -/* Priorities 0-100 are reserved for system libraries. */ -void c3() - __attribute__((constructor (50))); /* { dg-warning "reserved" } */ -void d3() - __attribute__((constructor (50))); /* { dg-warning "reserved" } */ - -/* Priorities must be integral constants. */ - -/* Pointers, even with constant values, are not allowed. */ -void c4() - __attribute__((constructor ((void*) 500))); /* { dg-error "priorities" } */ -void d4() - __attribute__((destructor ((void*) 500))); /* { dg-error "priorities" } */ - -/* Integer variables are not allowed. */ -int i; -void c5() - __attribute__((constructor ((i)))); /* { dg-error "priorities" } */ -void d5() - __attribute__((destructor ((i)))); /* { dg-error "priorities" } */ - -/* Enumeration constants are allowed. */ -enum E { e = 500 }; -void c6() - __attribute__((constructor ((e)))); -void d6() - __attribute__((destructor ((e)))); diff --git a/gcc/testsuite/g++.dg/template/pr95672.C b/gcc/testsuite/g++.dg/template/pr95672.C index c752b4a2c08..d97b8db2e97 100644 --- a/gcc/testsuite/g++.dg/template/pr95672.C +++ b/gcc/testsuite/g++.dg/template/pr95672.C @@ -1,3 +1,3 @@ // PR c++/95672 // { dg-do compile { target c++14 } } -struct g_class : decltype (auto) ... { }; // { dg-error "invalid use of pack expansion" } +struct g_class : decltype (auto) ... { }; // { dg-error "contains no parameter packs" } diff --git a/gcc/testsuite/g++.dg/torture/darwin-cfstring-3.C b/gcc/testsuite/g++.dg/torture/darwin-cfstring-3.C index eabb3b517a4..ee4b385b17f 100644 --- a/gcc/testsuite/g++.dg/torture/darwin-cfstring-3.C +++ b/gcc/testsuite/g++.dg/torture/darwin-cfstring-3.C @@ -26,5 +26,5 @@ void foo(void) { /* { dg-final { scan-assembler "\\.long\[ \\t\]+___CFConstantStringClassReference\n\[ \\t\]*\\.long\[ \\t\]+1992\n\[ \\t\]*\\.long\[ \\t\]+\[lL\]C.*\n\[ \\t\]*\\.long\[ \\t\]+4\n" { target { *-*-darwin* && { ! lp64 } } } } } */ /* { dg-final { scan-assembler "\\.long\[ \\t\]+___CFConstantStringClassReference\n\[ \\t\]*\\.long\[ \\t\]+1992\n\[ \\t\]*\\.long\[ \\t\]+\[lL\]C.*\n\[ \\t\]*\\.long\[ \\t\]+10\n" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t___CFConstantStringClassReference\n\t.(long|word)\t1992\n\t.space 4\n\t.(quad|xword)\t.*\n\t.(quad|xword)\t4\n} { target { *-*-darwin* && { lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t___CFConstantStringClassReference\n\t.(long|word)\t1992\n\t.space 4\n\t.(quad|xword)\t.*\n\t.(quad|xword)\t10\n} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t___CFConstantStringClassReference\n\t.long\t1992\n\t.space 4\n\t.quad\t.*\n\t.quad\t4\n" { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t___CFConstantStringClassReference\n\t.long\t1992\n\t.space 4\n\t.quad\t.*\n\t.quad\t10\n" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/testsuite/g++.dg/ubsan/pr63956.C b/gcc/testsuite/g++.dg/ubsan/pr63956.C index 6fd0b4f893e..9c15dbd8d54 100644 --- a/gcc/testsuite/g++.dg/ubsan/pr63956.C +++ b/gcc/testsuite/g++.dg/ubsan/pr63956.C @@ -1,6 +1,6 @@ // PR sanitizer/63956 // { dg-do compile } -// { dg-options "-std=c++14 -fsanitize=undefined,float-divide-by-zero,float-cast-overflow" } +// { dg-options "-std=c++14 -fsanitize=undefined,float-divide-by-zero" } #define SA(X) static_assert((X),#X) #define INT_MIN (-__INT_MAX__ - 1) @@ -162,8 +162,13 @@ fn11 (double d) return i * 2; } +void +__attribute__((optimize("no-trapping-math"))) +foo () +{ constexpr int r1 = fn11 (3.4); constexpr int r2 = fn11 (__builtin_inf ()); // { dg-message "in .constexpr. expansion of " } +} constexpr int fn12 (int i) diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C b/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C index 3b6d1f3c437..d6332140b14 100644 --- a/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C +++ b/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C @@ -3,7 +3,7 @@ gcc/testsuite/gcc.dg/Wconversion-real-integer.c */ /* { dg-do compile } -/* { dg-options "-Wconversion -ftrack-macro-expansion=0" } */ +/* { dg-options "-Wconversion -ftrack-macro-expansion=0 -fno-trapping-math" } */ /* { dg-require-effective-target int32plus } */ #include diff --git a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align16-O2-extra.C b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align16-O2-extra.C index acc95ba827d..52f9cdd1ee9 100644 --- a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align16-O2-extra.C +++ b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align16-O2-extra.C @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps -Wno-narrowing" } */ #define ALIGN 16 diff --git a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align16-O2.C b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align16-O2.C index 41e40b3519c..9ff4e46645b 100644 --- a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align16-O2.C +++ b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align16-O2.C @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps -Wno-narrowing" } */ #define ALIGN 16 diff --git a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align32-O2-extra.C b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align32-O2-extra.C index 1460a04bb16..55dcbfe4b7c 100644 --- a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align32-O2-extra.C +++ b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align32-O2-extra.C @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps -Wno-narrowing" } */ #define ALIGN 32 diff --git a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align32-O2.C b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align32-O2.C index 769b15acdb5..6bb8778ee90 100644 --- a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align32-O2.C +++ b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align32-O2.C @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps -Wno-narrowing" } */ #define ALIGN 32 diff --git a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align8-O2.C b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align8-O2.C index 31273c3f1c4..41bcc894a2b 100644 --- a/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align8-O2.C +++ b/gcc/testsuite/g++.target/aarch64/bitfield-abi-warning-align8-O2.C @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps -Wno-narrowing" } */ #define ALIGN 8 diff --git a/gcc/testsuite/g++.target/aarch64/float128-darwin-1.C b/gcc/testsuite/g++.target/aarch64/float128-darwin-1.C deleted file mode 100644 index 0dbed063a71..00000000000 --- a/gcc/testsuite/g++.target/aarch64/float128-darwin-1.C +++ /dev/null @@ -1,41 +0,0 @@ -/* { dg-do run { target { aarch64*-*-darwin* } } } */ -/* { dg-options "-std=c++11 -std=gnu++98" } */ - -#include -#include -#include - -void foo () -{ - float x1 = 1.0q; - double x2 = 1.0q; - long double x3 = 1.0q; - - _Float128 w1 = 0; - __float128 w2 = 0; - - float y1 = w1; // { dg-warning "with greater conversion rank" } - double y2 = w1; // { dg-warning "with greater conversion rank" } - long double y3 = w1; // { dg-warning "with greater conversion rank" } - - float z1 = w2; - double z2 = w2; - long double z3 = w2; -} - -int main () -{ - // Check the correct mangling of floating-point types - if (typeid(float).name() != std::string("f")) - __builtin_abort(); - if (typeid(double).name() != std::string("d")) - __builtin_abort(); - if (typeid(long double).name() != std::string("e")) - __builtin_abort(); - if (typeid(__float128).name() != std::string("g")) - __builtin_abort(); - if (typeid(_Float128).name() != std::string("DF128_")) - __builtin_abort(); - if (typeid(1.0q).name() != std::string("g")) - __builtin_abort(); -} diff --git a/gcc/testsuite/g++.target/aarch64/no_unique_address_1.C b/gcc/testsuite/g++.target/aarch64/no_unique_address_1.C index 5faf915fa54..5fc68ea5d6d 100644 --- a/gcc/testsuite/g++.target/aarch64/no_unique_address_1.C +++ b/gcc/testsuite/g++.target/aarch64/no_unique_address_1.C @@ -1,5 +1,5 @@ /* { dg-options "-std=c++11 -O -foptimize-sibling-calls -fpeephole2" } */ -/* { dg-final { check-function-bodies "**" "" "" { target { lp64 && { ! aarch64*-*-darwin* } } } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ struct X { }; struct Y { int : 0; }; diff --git a/gcc/testsuite/g++.target/aarch64/no_unique_address_2.C b/gcc/testsuite/g++.target/aarch64/no_unique_address_2.C index 322ec127c79..f0717133ccd 100644 --- a/gcc/testsuite/g++.target/aarch64/no_unique_address_2.C +++ b/gcc/testsuite/g++.target/aarch64/no_unique_address_2.C @@ -1,5 +1,5 @@ /* { dg-options "-std=c++17 -O -foptimize-sibling-calls -fpeephole2" } */ -/* { dg-final { check-function-bodies "**" "" "" { target { lp64 && { ! aarch64*-*-darwin* } } } } } */ +/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ struct X { }; struct Y { int : 0; }; diff --git a/gcc/testsuite/g++.target/aarch64/pr109661-1.C b/gcc/testsuite/g++.target/aarch64/pr109661-1.C index 5b9645e9253..d668a544fa7 100644 --- a/gcc/testsuite/g++.target/aarch64/pr109661-1.C +++ b/gcc/testsuite/g++.target/aarch64/pr109661-1.C @@ -1,5 +1,4 @@ /* { dg-options "-O2 -Wpsabi" } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ #include diff --git a/gcc/testsuite/g++.target/aarch64/pr109661-2.C b/gcc/testsuite/g++.target/aarch64/pr109661-2.C index 0bb95ab3ef1..f081417da95 100644 --- a/gcc/testsuite/g++.target/aarch64/pr109661-2.C +++ b/gcc/testsuite/g++.target/aarch64/pr109661-2.C @@ -1,5 +1,4 @@ /* { dg-options "-O2 -Wpsabi" } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ #include diff --git a/gcc/testsuite/g++.target/aarch64/pr109661-3.C b/gcc/testsuite/g++.target/aarch64/pr109661-3.C index 497efac2c8f..dab2fb295d3 100644 --- a/gcc/testsuite/g++.target/aarch64/pr109661-3.C +++ b/gcc/testsuite/g++.target/aarch64/pr109661-3.C @@ -1,5 +1,4 @@ /* { dg-options "-O2 -Wpsabi" } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ #include diff --git a/gcc/testsuite/g++.target/aarch64/pr109661-4.C b/gcc/testsuite/g++.target/aarch64/pr109661-4.C index 28a2b1565fb..d87e60fcc5d 100644 --- a/gcc/testsuite/g++.target/aarch64/pr109661-4.C +++ b/gcc/testsuite/g++.target/aarch64/pr109661-4.C @@ -1,5 +1,4 @@ /* { dg-options "-O2 -Wpsabi" } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ #include diff --git a/gcc/testsuite/g++.target/aarch64/sme/exceptions_1.C b/gcc/testsuite/g++.target/aarch64/sme/exceptions_1.C index 8b66d8a0f60..a245546d8b1 100644 --- a/gcc/testsuite/g++.target/aarch64/sme/exceptions_1.C +++ b/gcc/testsuite/g++.target/aarch64/sme/exceptions_1.C @@ -9,10 +9,10 @@ void callee_normal(); /* ** _Z5test1v: ** ... -** bl _?__arm_tpidr2_save +** bl __arm_tpidr2_save ** ... -** bl _?__cxa_begin_catch -** bl _?__cxa_end_catch +** bl __cxa_begin_catch +** bl __cxa_end_catch ** mov w0, #?2 ** ... */ @@ -33,14 +33,14 @@ test1 () /* ** _Z5test2v: ** ... -** bl _?__arm_tpidr2_save +** bl __arm_tpidr2_save ** ... -** bl _?__cxa_begin_catch +** bl __cxa_begin_catch ** smstart za -** bl _?_Z10callee_outv -** bl _?_Z9callee_inv +** bl _Z10callee_outv +** bl _Z9callee_inv ** smstop za -** bl _?__cxa_end_catch +** bl __cxa_end_catch ** mov w0, #?2 ** ... */ @@ -63,18 +63,18 @@ test2 () /* ** _Z5test3v: ** ... -** bl _?__arm_tpidr2_save +** bl __arm_tpidr2_save ** ... ** smstop za ** ... -** bl _?_Z13callee_normalv +** bl _Z13callee_normalv ** ... -** bl _?__cxa_begin_catch +** bl __cxa_begin_catch ** smstart za -** bl _?_Z10callee_outv -** bl _?_Z9callee_inv +** bl _Z10callee_outv +** bl _Z9callee_inv ** smstop za -** bl _?__cxa_end_catch +** bl __cxa_end_catch ** mov w0, #?2 ** ... */ @@ -114,28 +114,28 @@ test4 () /* ** _Z5test5v: ** ... -** bl _?__arm_tpidr2_save +** bl __arm_tpidr2_save ** ... ** smstart za ** ... -** bl _?_Z12callee_inoutv +** bl _Z12callee_inoutv ** add (x[0-9]+), [^\n]+ ** msr tpidr2_el0, \1 -** bl _?_Z13callee_normalv +** bl _Z13callee_normalv ** msr tpidr2_el0, xzr ** smstop za ** ... -** bl _?__cxa_begin_catch +** bl __cxa_begin_catch ** ... ** mrs x[0-9]+, tpidr2_el0 ** ... ** smstart za ** ... -** bl _?__arm_tpidr2_restore +** bl __arm_tpidr2_restore ** msr tpidr2_el0, xzr -** bl _?_Z12callee_inoutv +** bl _Z12callee_inoutv ** smstop za -** bl _?__cxa_end_catch +** bl __cxa_end_catch ** mov w0, #?2 ** ... */ @@ -159,17 +159,17 @@ test5 () ** _Z5test6v: ** ... ** msr tpidr2_el0, x[0-9]+ -** bl _?_Z13callee_normalv +** bl _Z13callee_normalv ** msr tpidr2_el0, xzr ** ... -** bl _?__cxa_begin_catch -** bl _?__cxa_end_catch +** bl __cxa_begin_catch +** bl __cxa_end_catch ** ... ** mrs x[0-9]+, tpidr2_el0 ** ... ** smstart za ** ... -** bl _?__arm_tpidr2_restore +** bl __arm_tpidr2_restore ** msr tpidr2_el0, xzr ** ... */ diff --git a/gcc/testsuite/g++.target/aarch64/sme/exceptions_2.C b/gcc/testsuite/g++.target/aarch64/sme/exceptions_2.C index c149c38cd26..f791b6ecc54 100644 --- a/gcc/testsuite/g++.target/aarch64/sme/exceptions_2.C +++ b/gcc/testsuite/g++.target/aarch64/sme/exceptions_2.C @@ -30,11 +30,11 @@ void n_caller1() ** cntd (x[0-9]+) ** str \1, [^\n]+ ** ... -** bl _?__cxa_begin_catch +** bl __cxa_begin_catch ** smstart sm -** bl _?_Z11s_callee_nev +** bl _Z11s_callee_nev ** smstop sm -** bl _?__cxa_end_catch +** bl __cxa_end_catch ** ... */ void n_caller2() @@ -53,7 +53,7 @@ void n_caller2() /* ** _Z9s_caller1v: ** ... -** bl _?__cxa_end_catch +** bl __cxa_end_catch ** smstart sm ** ... */ @@ -73,11 +73,11 @@ int s_caller1() __arm_streaming /* ** _Z9s_caller2v: ** ... -** bl _?__cxa_begin_catch +** bl __cxa_begin_catch ** smstart sm -** bl _?_Z11s_callee_nev +** bl _Z11s_callee_nev ** smstop sm -** bl _?__cxa_end_catch +** bl __cxa_end_catch ** smstart sm ** ... */ @@ -103,7 +103,7 @@ int s_caller2() __arm_streaming ** mrs (x[0-9]+), svcr ** str \2, ([^\n]+) ** ... -** bl _?__cxa_end_catch +** bl __cxa_end_catch ** ldr (x[0-9]+), \3 ** tbz \4, 0, [^\n]+ ** smstart sm @@ -128,11 +128,11 @@ int sc_caller1() __arm_streaming_compatible ** cntd (x[0-9]+) ** str \1, [^\n]+ ** ... -** bl _?__cxa_begin_catch +** bl __cxa_begin_catch ** smstart sm -** bl _?_Z12sc_callee_nev +** bl _Z12sc_callee_nev ** smstop sm -** bl _?__cxa_end_catch +** bl __cxa_end_catch ** ... */ __arm_locally_streaming void ls_caller1() diff --git a/gcc/testsuite/g++.target/aarch64/sme2/aarch64-sme2-acle-asm.exp b/gcc/testsuite/g++.target/aarch64/sme2/aarch64-sme2-acle-asm.exp index 2918b4dc202..f7536820b85 100644 --- a/gcc/testsuite/g++.target/aarch64/sme2/aarch64-sme2-acle-asm.exp +++ b/gcc/testsuite/g++.target/aarch64/sme2/aarch64-sme2-acle-asm.exp @@ -24,11 +24,6 @@ if {![istarget aarch64*-*-*] } { return } -# Darwin's assembler support for sme2 appears incomplete. -if { [istarget *-*-darwin*] && ![info exists env(DARWIN_TEST_SME2)]} then { - return -} - # Load support procs. load_lib g++-dg.exp diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp b/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp index 8ad0722d5ea..4bb70cd37cb 100644 --- a/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp +++ b/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp @@ -24,11 +24,6 @@ if { ![istarget aarch64*-*-*] } { return } -# Darwin doesn't support sve -if { [istarget *-*-darwin*] } then { - return -} - # Load support procs. load_lib g++-dg.exp diff --git a/gcc/testsuite/g++.target/i386/pr115351.C b/gcc/testsuite/g++.target/i386/pr115351.C new file mode 100644 index 00000000000..24132f3b8c7 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr115351.C @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -std=c++11" } */ + +struct complex +{ + double real; + double imag; +}; + +complex blub(complex z) +{ + return { + z.real * z.real - z.imag * z.imag, + 2 * z.real * z.imag + }; +} + +/* { dg-final { scan-assembler-not "movq" } } */ +/* { dg-final { scan-assembler-not "xchg" } } */ diff --git a/gcc/testsuite/gcc.c-torture/execute/20031003-1.c b/gcc/testsuite/gcc.c-torture/execute/20031003-1.c index 5d39d799e50..5e6f5089fc6 100644 --- a/gcc/testsuite/gcc.c-torture/execute/20031003-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/20031003-1.c @@ -1,5 +1,7 @@ /* PR optimization/9325 */ +/* { dg-additional-options "-fno-trapping-math" } */ + #include extern void abort (void); diff --git a/gcc/testsuite/gcc.c-torture/execute/pr108789.c b/gcc/testsuite/gcc.c-torture/execute/pr108789.c new file mode 100644 index 00000000000..32ee19be1c4 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr108789.c @@ -0,0 +1,39 @@ +/* PR middle-end/108789 */ + +int +add (unsigned *r, const unsigned *a, const unsigned *b) +{ + return __builtin_add_overflow (*a, *b, r); +} + +int +mul (unsigned *r, const unsigned *a, const unsigned *b) +{ + return __builtin_mul_overflow (*a, *b, r); +} + +int +main () +{ + unsigned x; + + /* 1073741824U + 1073741824U should not overflow. */ + x = (__INT_MAX__ + 1U) / 2; + if (add (&x, &x, &x)) + __builtin_abort (); + + /* 256U * 256U should not overflow */ + x = 1U << (sizeof (int) * __CHAR_BIT__ / 4); + if (mul (&x, &x, &x)) + __builtin_abort (); + + /* 2147483648U + 2147483648U should overflow */ + x = __INT_MAX__ + 1U; + if (!add (&x, &x, &x)) + __builtin_abort (); + + /* 65536U * 65536U should overflow */ + x = 1U << (sizeof (int) * __CHAR_BIT__ / 2); + if (!mul (&x, &x, &x)) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c b/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c index e8bc9db237d..69281c7d71e 100644 --- a/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c +++ b/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c @@ -6,7 +6,7 @@ /* { dg-do compile } */ /* { dg-skip-if "doubles are floats,ints are 16bits" { "avr-*-*" } } */ -/* { dg-options " -std=c99 -pedantic -Wconversion " } */ +/* { dg-options " -std=c99 -pedantic -Wconversion -fno-trapping-math" } */ /* { dg-require-effective-target int32plus } */ /* { dg-require-effective-target double64plus } */ diff --git a/gcc/testsuite/gcc.dg/Wconversion-real-integer.c b/gcc/testsuite/gcc.dg/Wconversion-real-integer.c index 92e6987d9ec..ca6007f4fe8 100644 --- a/gcc/testsuite/gcc.dg/Wconversion-real-integer.c +++ b/gcc/testsuite/gcc.dg/Wconversion-real-integer.c @@ -3,7 +3,7 @@ /* { dg-do compile } */ /* { dg-skip-if "doubles are floats,ints are 16bits" { "avr-*-*" } } */ -/* { dg-options "-std=c99 -Wconversion" } */ +/* { dg-options "-std=c99 -Wconversion -fno-trapping-math" } */ /* { dg-require-effective-target int32plus } */ /* { dg-require-effective-target double64plus } */ #include diff --git a/gcc/testsuite/gcc.dg/analyzer/allocation-size-multiline-4.c b/gcc/testsuite/gcc.dg/analyzer/allocation-size-multiline-4.c new file mode 100644 index 00000000000..6408ef800e1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/allocation-size-multiline-4.c @@ -0,0 +1,64 @@ +/* Verify that we report events that occur at returns from functions + with valid-looking interprocedural paths. + + C only: there are only minor C/C++ differences in e.g. how the + function names are printed. Trying to handle both would overcomplicate + the test. */ + +/* { dg-additional-options "-fdiagnostics-show-line-numbers" } */ +/* { dg-enable-nn-line-numbers "" } */ +/* { dg-additional-options "-fdiagnostics-path-format=inline-events" } */ +/* { dg-additional-options "-fdiagnostics-show-caret" } */ +/* { dg-additional-options "-fdiagnostics-show-path-depths" } */ + +#include +#include + +void *create_buffer (int32_t n) +{ + return malloc(n); +} + +void test_9 (void) +{ + int32_t *buf = (int32_t *) create_buffer(42); /* { dg-warning "allocated buffer size is not a multiple of the pointee's size" } */ + free (buf); +} + +/* { dg-begin-multiline-output "" } + NN | int32_t *buf = (int32_t *) create_buffer(42); + | ^~~~~~~~~~~~~~~~~ + 'test_9': events 1-2 (depth 1) + | + | NN | void test_9 (void) + | | ^~~~~~ + | | | + | | (1) entry to 'test_9' + | NN | { + | NN | int32_t *buf = (int32_t *) create_buffer(42); + | | ~~~~~~~~~~~~~~~~~ + | | | + | | (2) calling 'create_buffer' from 'test_9' + | + +--> 'create_buffer': events 3-4 (depth 2) + | + | NN | void *create_buffer (int32_t n) + | | ^~~~~~~~~~~~~ + | | | + | | (3) entry to 'create_buffer' + | NN | { + | NN | return malloc(n); + | | ~~~~~~~~~ + | | | + | | (4) allocated 42 bytes here + | + <------+ + | + 'test_9': event 5 (depth 1) + | + | NN | int32_t *buf = (int32_t *) create_buffer(42); + | | ^~~~~~~~~~~~~~~~~ + | | | + | | (5) assigned to 'int32_t *' + | + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-accept.c b/gcc/testsuite/gcc.dg/analyzer/fd-accept.c index d07ab154d0f..5724a389e2e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-accept.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-accept.c @@ -1,5 +1,6 @@ /* { dg-require-effective-target sockets } */ /* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "PR analyzer/107750" { *-*-solaris2* } } */ #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-access-mode-target-headers.c b/gcc/testsuite/gcc.dg/analyzer/fd-access-mode-target-headers.c index 9fc32638a3d..1386ac2de1e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-access-mode-target-headers.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-access-mode-target-headers.c @@ -1,4 +1,5 @@ /* { dg-skip-if "" { { powerpc*-*-aix* avr-*-* *-*-vxworks* } || newlib } } */ +/* { dg-skip-if "PR analyzer/107750" { *-*-solaris2* } } */ #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-connect.c b/gcc/testsuite/gcc.dg/analyzer/fd-connect.c index 43e435eaf12..3fe99d9530c 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-connect.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-connect.c @@ -1,5 +1,6 @@ /* { dg-require-effective-target sockets } */ /* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "PR analyzer/107750" { *-*-solaris2* } } */ #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-datagram-socket.c b/gcc/testsuite/gcc.dg/analyzer/fd-datagram-socket.c index 59e80c831e3..8d32e858111 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-datagram-socket.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-datagram-socket.c @@ -1,5 +1,6 @@ /* { dg-require-effective-target sockets } */ /* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "PR analyzer/107750" { *-*-solaris2* } } */ #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-listen.c b/gcc/testsuite/gcc.dg/analyzer/fd-listen.c index 3ac7a990042..1444af72e3a 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-listen.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-listen.c @@ -1,5 +1,6 @@ /* { dg-require-effective-target sockets } */ /* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "PR analyzer/107750" { *-*-solaris2* } } */ #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-socket-misuse.c b/gcc/testsuite/gcc.dg/analyzer/fd-socket-misuse.c index 914948644bb..8771c0cbe03 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-socket-misuse.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-socket-misuse.c @@ -2,6 +2,7 @@ /* { dg-require-effective-target sockets } */ /* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "PR analyzer/107750" { *-*-solaris2* } } */ #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-active-open.c b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-active-open.c index b39dbf85c3d..e8b01dd2985 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-active-open.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-active-open.c @@ -1,5 +1,6 @@ /* { dg-require-effective-target sockets } */ /* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "PR analyzer/107750" { *-*-solaris2* } } */ #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-passive-open.c b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-passive-open.c index e161098b96b..e3e7f3062d2 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-passive-open.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket-passive-open.c @@ -4,6 +4,7 @@ /* { dg-require-effective-target sockets } */ /* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "PR analyzer/107750" { *-*-solaris2* } } */ #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket.c b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket.c index 7e0e26ab40b..1da9634c81d 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-stream-socket.c @@ -1,5 +1,6 @@ /* { dg-require-effective-target sockets } */ /* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "PR analyzer/107750" { *-*-solaris2* } } */ #include #include diff --git a/gcc/testsuite/gcc.dg/analyzer/taint-alloc-4.c b/gcc/testsuite/gcc.dg/analyzer/taint-alloc-4.c index 9df9422491c..7fe813d4e9e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/taint-alloc-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/taint-alloc-4.c @@ -23,6 +23,6 @@ test_1 (void *data) /* { dg-message "\\(1\\) function 'test_1' marked with '__at __analyzer_dump_state ("taint", args); /* { dg-warning "state: 'tainted'" } */ __analyzer_dump_state ("taint", args->sz); /* { dg-warning "state: 'tainted'" } */ - p = malloc (args->sz); /* { dg-warning "use of attacker-controlled value '\\*args.sz' as allocation size without upper-bounds checking" "warning" } */ - /* { dg-message "\\(\[0-9\]+\\) use of attacker-controlled value '\\*args.sz' as allocation size without upper-bounds checking" "final event" { target *-*-* } .-1 } */ + p = malloc (args->sz); /* { dg-warning "use of attacker-controlled value '\[^'\]*.sz' as allocation size without upper-bounds checking" "warning" } */ + /* { dg-message "\\(\[0-9\]+\\) use of attacker-controlled value '\[^'\]*.sz' as allocation size without upper-bounds checking" "final event" { target *-*-* } .-1 } */ } diff --git a/gcc/testsuite/gcc.dg/bitint-106.c b/gcc/testsuite/gcc.dg/bitint-106.c new file mode 100644 index 00000000000..a36e8836690 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-106.c @@ -0,0 +1,29 @@ +/* PR tree-optimization/115337 */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-O2" } */ + +#if __BITINT_MAXWIDTH__ >= 129 +#define N 128 +#else +#define N 63 +#endif + +_BitInt (N) g; +int c; + +void +foo (unsigned _BitInt (N + 1) z, _BitInt (N) *ret) +{ + c = __builtin_stdc_first_leading_one (z << N); + _BitInt (N) y = *(_BitInt (N) *) __builtin_memset (&g, c, 5); + *ret = y; +} + +int +main () +{ + _BitInt (N) x; + foo (0, &x); + if (c || g || x) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc/testsuite/gcc.dg/builtin-apply2.c index d1e70b3a3e5..0f350f4ac16 100644 --- a/gcc/testsuite/gcc.dg/builtin-apply2.c +++ b/gcc/testsuite/gcc.dg/builtin-apply2.c @@ -1,7 +1,7 @@ /* { dg-do run } */ /* { dg-require-effective-target untyped_assembly } */ /* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "avr-*-* nds32*-*-* amdgcn-*-*" } } */ -/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "csky*-*-* riscv*-*-* or1k*-*-* msp430-*-* pru-*-* loongarch*-*-* aarch64-apple-darwin*" } } */ +/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "csky*-*-* riscv*-*-* or1k*-*-* msp430-*-* pru-*-* loongarch*-*-*" } } */ /* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm*-*-* && arm_hf_eabi } } */ /* PR target/12503 */ diff --git a/gcc/testsuite/gcc.dg/c90-const-expr-11.c b/gcc/testsuite/gcc.dg/c90-const-expr-11.c index a2720c47bf4..65aab10a129 100644 --- a/gcc/testsuite/gcc.dg/c90-const-expr-11.c +++ b/gcc/testsuite/gcc.dg/c90-const-expr-11.c @@ -2,7 +2,7 @@ constant expressions. */ /* Origin: Joseph Myers */ /* { dg-do compile } */ -/* { dg-options "-std=iso9899:1990 -pedantic-errors -O2" } */ +/* { dg-options "-std=iso9899:1990 -pedantic-errors -O2 -fno-trapping-math" } */ #include #include diff --git a/gcc/testsuite/gcc.dg/completion-2.c b/gcc/testsuite/gcc.dg/completion-2.c index 166bfdc1424..99e65312201 100644 --- a/gcc/testsuite/gcc.dg/completion-2.c +++ b/gcc/testsuite/gcc.dg/completion-2.c @@ -4,6 +4,7 @@ /* { dg-begin-multiline-output "" } -flto-partition=1to1 -flto-partition=balanced +-flto-partition=cache -flto-partition=max -flto-partition=none -flto-partition=one diff --git a/gcc/testsuite/gcc.dg/cwsc1.c b/gcc/testsuite/gcc.dg/cwsc1.c index 7d8b472bdf6..e793e26116a 100644 --- a/gcc/testsuite/gcc.dg/cwsc1.c +++ b/gcc/testsuite/gcc.dg/cwsc1.c @@ -6,11 +6,7 @@ #elif defined(__i386__) # define CHAIN "%ecx" #elif defined(__aarch64__) -# if defined(__APPLE__) -# define CHAIN "x16" -# else -# define CHAIN "x18" -# endif +# define CHAIN "x18" #elif defined(__alpha__) # define CHAIN "$1" #elif defined(__arm__) diff --git a/gcc/testsuite/gcc.dg/darwin-segaddr.c b/gcc/testsuite/gcc.dg/darwin-segaddr.c index 26ceee11aad..77112ddb484 100644 --- a/gcc/testsuite/gcc.dg/darwin-segaddr.c +++ b/gcc/testsuite/gcc.dg/darwin-segaddr.c @@ -1,6 +1,5 @@ /* Check that -segaddr gets through and works. */ /* { dg-do run { target *-*-darwin* } } */ -/* { dg-xfail-run-if "no-pie exes are not allowed" { aarch64-*-darwin* } } */ /* { dg-options "-O0 -segaddr __TEST 0x200000 -fno-pie" { target { *-*-darwin* && { ! lp64 } } } } */ /* { dg-options "-O0 -segaddr __TEST 0x110000000 -fno-pie" { target { *-*-darwin* && lp64 } } } */ /* { dg-prune-output "-no_pie is deprecated when targeting new OS versions" } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro.c b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro.c index 7d7d0e695ac..fd61296b2f1 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro.c @@ -1,7 +1,7 @@ /* Test to make sure the mcaro info includes a start file command for the main source */ /* { dg-do compile } */ /* { dg-options "-g3 -gdwarf -dA -fverbose-asm" } */ -/* { dg-final { scan-assembler "Start new file" { xfail *-*-darwin23* } } } */ +/* { dg-final { scan-assembler "Start new file" } } */ #define ADD(x) (M + x) diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro2.c index 3baecb9599c..3dfa2908ef3 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro2.c +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2-macro2.c @@ -1,7 +1,7 @@ /* Test to make sure the macro info includes the predefined macros with line number 0. */ /* { dg-do compile } */ /* { dg-options "-g3 -gdwarf -dA -fverbose-asm" } */ -/* { dg-final { scan-assembler "At line number 0" { xfail *-*-darwin23* } } } */ +/* { dg-final { scan-assembler "At line number 0" } } */ #define FOO 1 int i; diff --git a/gcc/testsuite/gcc.dg/gomp/attrs-4.c b/gcc/testsuite/gcc.dg/gomp/attrs-4.c index 710b70a36ae..5d422b3ba72 100644 --- a/gcc/testsuite/gcc.dg/gomp/attrs-4.c +++ b/gcc/testsuite/gcc.dg/gomp/attrs-4.c @@ -50,7 +50,7 @@ foo (int x) for (int i = 0; i < 16; i++) ; #pragma omp for - [[omp::directive (master)]] /* { dg-error "for statement expected before '\\\[' token" } */ + [[omp::directive (master)]] /* { dg-error "loop nest expected before '\\\[' token" } */ ; #pragma omp target teams [[omp::directive (parallel)]] /* { dg-error "mixing OpenMP directives with attribute and pragma syntax on the same statement" } */ diff --git a/gcc/testsuite/gcc.dg/gomp/for-1.c b/gcc/testsuite/gcc.dg/gomp/for-1.c index 80e0d0be844..ecaf0c55796 100644 --- a/gcc/testsuite/gcc.dg/gomp/for-1.c +++ b/gcc/testsuite/gcc.dg/gomp/for-1.c @@ -26,7 +26,7 @@ void foo (int j, int k) /* Malformed parallel loops. */ #pragma omp for - i = 0; /* { dg-error "3:for statement expected" } */ + i = 0; /* { dg-error "3:loop nest expected" } */ for ( ; i < 10; ) { baz (i); diff --git a/gcc/testsuite/gcc.dg/gomp/for-11.c b/gcc/testsuite/gcc.dg/gomp/for-11.c index 8c747cdb981..abafa487283 100644 --- a/gcc/testsuite/gcc.dg/gomp/for-11.c +++ b/gcc/testsuite/gcc.dg/gomp/for-11.c @@ -30,7 +30,7 @@ void foo (int j, int k) /* Malformed parallel loops. */ #pragma omp for - i = 0; /* { dg-error "for statement expected" } */ + i = 0; /* { dg-error "loop nest expected" } */ for ( ; i < 10; ) { baz (i); diff --git a/gcc/testsuite/gcc.dg/initpri1.c b/gcc/testsuite/gcc.dg/initpri1.c deleted file mode 100644 index b6afd7690de..00000000000 --- a/gcc/testsuite/gcc.dg/initpri1.c +++ /dev/null @@ -1,62 +0,0 @@ -/* { dg-do run { target init_priority } } */ - -extern void abort (void); - -int i; -int j; - -void c1() __attribute__((constructor (500))); -void c2() __attribute__((constructor (700))); -void c3() __attribute__((constructor (600))); - -void c1() { - if (i++ != 0) - abort (); -} - -void c2() { - if (i++ != 2) - abort (); -} - -void c3() { - if (i++ != 1) - abort (); -} - -void d1() __attribute__((destructor (500))); -void d2() __attribute__((destructor (700))); -void d3() __attribute__((destructor (600))); - -void d1() { - if (--i != 0) - abort (); -} - -void d2() { - if (--i != 2) - abort (); -} - -void d3() { - if (j != 2) - abort (); - if (--i != 1) - abort (); -} - -void cd4() __attribute__((constructor (800), destructor (800))); - -void cd4() { - if (i != 3) - abort (); - ++j; -} - -int main () { - if (i != 3) - return 1; - if (j != 1) - abort (); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/initpri3.c b/gcc/testsuite/gcc.dg/initpri3.c deleted file mode 100644 index 1633da0141f..00000000000 --- a/gcc/testsuite/gcc.dg/initpri3.c +++ /dev/null @@ -1,64 +0,0 @@ -/* { dg-do run { target init_priority } } */ -/* { dg-require-effective-target lto } */ -/* { dg-options "-flto -O3" } */ - -extern void abort (); - -int i; -int j; - -void c1() __attribute__((constructor (500))); -void c2() __attribute__((constructor (700))); -void c3() __attribute__((constructor (600))); - -void c1() { - if (i++ != 0) - abort (); -} - -void c2() { - if (i++ != 2) - abort (); -} - -void c3() { - if (i++ != 1) - abort (); -} - -void d1() __attribute__((destructor (500))); -void d2() __attribute__((destructor (700))); -void d3() __attribute__((destructor (600))); - -void d1() { - if (--i != 0) - abort (); -} - -void d2() { - if (--i != 2) - abort (); -} - -void d3() { - if (j != 2) - abort (); - if (--i != 1) - abort (); -} - -void cd4() __attribute__((constructor (800), destructor (800))); - -void cd4() { - if (i != 3) - abort (); - ++j; -} - -int main () { - if (i != 3) - return 1; - if (j != 1) - abort (); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/lto/20091216-1_0.c b/gcc/testsuite/gcc.dg/lto/20091216-1_0.c index ac6ea79bae0..7bcf1f38ddf 100644 --- a/gcc/testsuite/gcc.dg/lto/20091216-1_0.c +++ b/gcc/testsuite/gcc.dg/lto/20091216-1_0.c @@ -2,7 +2,7 @@ #include "../nop.h" -asm (".globl start_\n\t.p2align 2\nstart_: " NOP); +asm (".globl start_\nstart_: " NOP); int main () diff --git a/gcc/testsuite/gcc.dg/overflow-warn-8.c b/gcc/testsuite/gcc.dg/overflow-warn-8.c index e76bcac5e07..75bfa74f3dc 100644 --- a/gcc/testsuite/gcc.dg/overflow-warn-8.c +++ b/gcc/testsuite/gcc.dg/overflow-warn-8.c @@ -1,5 +1,6 @@ #include +/* { dg-options " -fno-trapping-math" } */ void foo (int j) { int i1 = (int)(double)1.0 + INT_MAX; /* { dg-warning "integer overflow" } */ diff --git a/gcc/testsuite/gcc.dg/pch/pch.exp b/gcc/testsuite/gcc.dg/pch/pch.exp index 0767b1dd7f1..4aad846db20 100644 --- a/gcc/testsuite/gcc.dg/pch/pch.exp +++ b/gcc/testsuite/gcc.dg/pch/pch.exp @@ -38,7 +38,7 @@ foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.c]] { # unlikely to make any difference to PCH. However, we do want to # add -O0 -g, since users who want PCH usually want debugging and quick # compiles. - dg-pch $subdir $test [concat [list {-O0 -g -Winvalid-pch}] $torture_without_loops] ".h" + dg-pch $subdir $test [concat [list {-O0 -g}] $torture_without_loops] ".h" } set test "largefile.c" @@ -53,7 +53,7 @@ puts $f "#include \"largefile.h\"" close $f set f [open $testh w] close $f -dg-pch $subdir $test [concat [list {-O0 -g -Winvalid-pch}] $torture_without_loops] ".h" +dg-pch $subdir $test [concat [list {-O0 -g}] $torture_without_loops] ".h" file delete $test file delete $testh diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.c b/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.c index 1fc43007cf1..b53b347bb4f 100644 --- a/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.c @@ -274,6 +274,11 @@ public: return NULL; } + void update_event_loc_info (event_loc_info &) final override + { + /* No-op. */ + } + private: const exploded_graph &m_eg; tree m_var; diff --git a/gcc/testsuite/gcc.dg/pr100927.c b/gcc/testsuite/gcc.dg/pr100927.c new file mode 100644 index 00000000000..8a7d69c3831 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr100927.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftrapping-math -fdump-tree-optimized -fdump-rtl-final" } */ +/* { dg-final { scan-tree-dump-times {(?n)= \(int\)} 3 "optimized" } } */ +/* { dg-final { scan-rtl-dump-times {(?n)^[ \t]*\(fix:SI} 3 "final" } } */ + +int +foo_ofr () +{ + union {float a; + int b;}c; + c.b = 0x4f000000; + return (int)c.a; +} + +int +foo_inf () +{ + union {float a; + int b;}c; + c.b = 0xff800000; + return (int)c.a; +} + +int +foo_nan () +{ + union {float a; + int b;}c; + c.b = 0xff800001; + return (int)c.a; +} diff --git a/gcc/testsuite/gcc.dg/pr114493-1.c b/gcc/testsuite/gcc.dg/pr114493-1.c new file mode 100644 index 00000000000..446f33eac3b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114493-1.c @@ -0,0 +1,19 @@ +/* PR c/114493 */ +/* { dg-do compile { target lto } } */ +/* { dg-options "-O2 -flto" } */ + +void foo (void); +struct S; +struct S bar (struct S **); +struct S qux (const struct S **); + +struct __attribute__((__may_alias__)) S { + int s; +}; + +struct S +baz (void) +{ + foo (); + return (struct S) {}; +} diff --git a/gcc/testsuite/gcc.dg/pr114493-2.c b/gcc/testsuite/gcc.dg/pr114493-2.c new file mode 100644 index 00000000000..1b4a5792dc9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114493-2.c @@ -0,0 +1,26 @@ +/* PR c/114493 */ +/* { dg-do compile { target lto } } */ +/* { dg-options "-O2 -flto -std=c23" } */ + +void foo (void); +struct S; +struct S bar (struct S **); +struct S qux (const struct S **); + +void +corge (void) +{ + struct S { int s; } s; + s.s = 0; +} + +struct __attribute__((__may_alias__)) S { + int s; +}; + +struct S +baz (void) +{ + foo (); + return (struct S) {}; +} diff --git a/gcc/testsuite/gcc.dg/pr26427.c b/gcc/testsuite/gcc.dg/pr26427.c index 834cf2cc50c..add13ca209e 100644 --- a/gcc/testsuite/gcc.dg/pr26427.c +++ b/gcc/testsuite/gcc.dg/pr26427.c @@ -1,4 +1,4 @@ -/* { dg-warning "this target does not support" "" { target *86*-*-darwin* } 0 } */ +/* { dg-warning "this target does not support" "" {target *86*-*-darwin* } 0 } */ /* { dg-do run { target { *-*-darwin* } } } */ /* { dg-options { -fsection-anchors -O } } */ /* PR target/26427 */ diff --git a/gcc/testsuite/gcc.dg/pr97172-2.c b/gcc/testsuite/gcc.dg/pr97172-2.c index 61f05626ebe..99cc6c29ff4 100644 --- a/gcc/testsuite/gcc.dg/pr97172-2.c +++ b/gcc/testsuite/gcc.dg/pr97172-2.c @@ -2,7 +2,6 @@ streams { dg-do link } { dg-options "-Wall -flto -fpic -shared" } - { dg-additional-options "-Wl,-undefined,dynamic_lookup" { target *-*-darwin* } } { dg-require-effective-target fpic } { dg-require-effective-target shared } { dg-require-effective-target lto } */ diff --git a/gcc/testsuite/gcc.dg/pubtypes-2.c b/gcc/testsuite/gcc.dg/pubtypes-2.c index b3d1231ad44..116e3489bc0 100644 --- a/gcc/testsuite/gcc.dg/pubtypes-2.c +++ b/gcc/testsuite/gcc.dg/pubtypes-2.c @@ -2,8 +2,7 @@ /* { dg-options "-O0 -gdwarf-2 -dA" } */ /* { dg-skip-if "Unmatchable assembly" { mmix-*-* } } */ /* { dg-final { scan-assembler "__debug_pubtypes" } } */ -/* { dg-final { scan-assembler {long+[ \t]+0x14d+[ \t]+[#;]+[ \t]+Pub Info Length} { target { ! aarch64-*-darwin* } } } } */ -/* { dg-final { scan-assembler {long+[ \t]+0x163+[ \t]+[#;]+[ \t]+Pub Info Length} { target aarch64-*-darwin* } } } */ +/* { dg-final { scan-assembler {long+[ \t]+0x14d+[ \t]+[#;]+[ \t]+Pub Info Length} } } */ /* { dg-final { scan-assembler "used_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "unused_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ diff --git a/gcc/testsuite/gcc.dg/pubtypes-3.c b/gcc/testsuite/gcc.dg/pubtypes-3.c index 950a9ba72fc..3fb3468fb00 100644 --- a/gcc/testsuite/gcc.dg/pubtypes-3.c +++ b/gcc/testsuite/gcc.dg/pubtypes-3.c @@ -2,8 +2,7 @@ /* { dg-options "-O0 -gdwarf-2 -dA" } */ /* { dg-skip-if "Unmatchable assembly" { mmix-*-* } } */ /* { dg-final { scan-assembler "__debug_pubtypes" } } */ -/* { dg-final { scan-assembler {long+[ \t]+0x14d+[ \t]+[#;]+[ \t]+Pub Info Length} { target { ! aarch64-*-darwin* } } } } */ -/* { dg-final { scan-assembler {long+[ \t]+0x163+[ \t]+[#;]+[ \t]+Pub Info Length} { target aarch64-*-darwin* } } } */ +/* { dg-final { scan-assembler {long+[ \t]+0x14d+[ \t]+[#;]+[ \t]+Pub Info Length} } } */ /* { dg-final { scan-assembler "used_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "unused_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "\"list_name_type\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ diff --git a/gcc/testsuite/gcc.dg/pubtypes-4.c b/gcc/testsuite/gcc.dg/pubtypes-4.c index 7250771587b..83fba8dfabc 100644 --- a/gcc/testsuite/gcc.dg/pubtypes-4.c +++ b/gcc/testsuite/gcc.dg/pubtypes-4.c @@ -2,8 +2,7 @@ /* { dg-options "-O0 -gdwarf-2 -dA" } */ /* { dg-skip-if "Unmatchable assembly" { mmix-*-* } } */ /* { dg-final { scan-assembler "__debug_pubtypes" } } */ -/* { dg-final { scan-assembler {long+[ \t]+0x184+[ \t]+[#;]+[ \t]+Pub Info Length} { target { ! aarch64-*-darwin* } } } } */ -/* { dg-final { scan-assembler {long+[ \t]+0x19a+[ \t]+[#;]+[ \t]+Pub Info Length} { target aarch64-*-darwin* } } } */ +/* { dg-final { scan-assembler {long+[ \t]+0x184+[ \t]+[#;]+[ \t]+Pub Info Length} } } */ /* { dg-final { scan-assembler "used_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "unused_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler "\"list_name_type\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/big-endian-cse-1.c b/gcc/testsuite/gcc.dg/rtl/aarch64/big-endian-cse-1.c index aa2da0cbca5..1559a489f25 100644 --- a/gcc/testsuite/gcc.dg/rtl/aarch64/big-endian-cse-1.c +++ b/gcc/testsuite/gcc.dg/rtl/aarch64/big-endian-cse-1.c @@ -1,5 +1,4 @@ /* { dg-do compile { target aarch64*-*-* } } */ -/* { dg-skip-if "Darwin platforms do not support big-endian arm64" *-*-darwin* } */ /* { dg-require-effective-target lp64 } */ /* { dg-options "-O3 -mbig-endian" } */ diff --git a/gcc/testsuite/gcc.dg/scantest-lto.c b/gcc/testsuite/gcc.dg/scantest-lto.c index 9a6e816b1ff..46c21f20bfc 100644 --- a/gcc/testsuite/gcc.dg/scantest-lto.c +++ b/gcc/testsuite/gcc.dg/scantest-lto.c @@ -1,6 +1,5 @@ /* { dg-do compile { target lto } } /* { dg-options "-O2 -flto" } */ -/* { dg-additional-options "-fno-unwind-tables -fno-asynchronous-unwind-tables" { target *-*-darwin* } } */ void foo () { diff --git a/gcc/testsuite/gcc.dg/stack-check-10.c b/gcc/testsuite/gcc.dg/stack-check-10.c index 2be2a8a2b6a..2f5a090cb7a 100644 --- a/gcc/testsuite/gcc.dg/stack-check-10.c +++ b/gcc/testsuite/gcc.dg/stack-check-10.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */ -/* { dg-additional-options "-fomit-frame-pointer" { target aarch64-*-darwin* } } */ /* { dg-require-effective-target supports_stack_clash_protection } */ int f (int *); diff --git a/gcc/testsuite/gcc.dg/stack-check-5.c b/gcc/testsuite/gcc.dg/stack-check-5.c index a86455528ea..0243147939c 100644 --- a/gcc/testsuite/gcc.dg/stack-check-5.c +++ b/gcc/testsuite/gcc.dg/stack-check-5.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */ -/* { dg-additional-options "-fomit-frame-pointer" { target aarch64-*-darwin* } } */ /* { dg-require-effective-target supports_stack_clash_protection } */ /* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ diff --git a/gcc/testsuite/gcc.dg/stack-check-6.c b/gcc/testsuite/gcc.dg/stack-check-6.c index 0b276470ad9..fe75612b737 100644 --- a/gcc/testsuite/gcc.dg/stack-check-6.c +++ b/gcc/testsuite/gcc.dg/stack-check-6.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */ -/* { dg-additional-options "-fomit-frame-pointer" { target aarch64-*-darwin* } } */ /* { dg-require-effective-target supports_stack_clash_protection } */ /* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ diff --git a/gcc/testsuite/gcc.dg/stack-check-9.c b/gcc/testsuite/gcc.dg/stack-check-9.c index 96e6ee7c0bc..b84075b9b43 100644 --- a/gcc/testsuite/gcc.dg/stack-check-9.c +++ b/gcc/testsuite/gcc.dg/stack-check-9.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */ -/* { dg-additional-options "-fomit-frame-pointer" { target aarch64-*-darwin* } } */ /* { dg-require-effective-target supports_stack_clash_protection } */ double f1 (void); diff --git a/gcc/testsuite/gcc.dg/tls/pr78796.c b/gcc/testsuite/gcc.dg/tls/pr78796.c index 3868697cb41..96f87d47ba4 100644 --- a/gcc/testsuite/gcc.dg/tls/pr78796.c +++ b/gcc/testsuite/gcc.dg/tls/pr78796.c @@ -1,7 +1,7 @@ /* PR target/78796 */ /* { dg-do run } */ /* { dg-options "-O2" } */ -/* { dg-additional-options "-mcmodel=large -fno-pie -no-pie" { target { { aarch64-*-* } && { ! aarch64-*-darwin* } } } } */ +/* { dg-additional-options "-mcmodel=large -fno-pie -no-pie" { target aarch64-*-* } } */ /* { dg-require-effective-target tls_runtime } */ /* { dg-add-options tls } */ diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c b/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c index 10086210346..fa27a774b62 100644 --- a/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c +++ b/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c @@ -3,7 +3,6 @@ /* { dg-options "" } */ /* { dg-add-options bfloat16 } */ /* { dg-require-effective-target bfloat16_runtime } */ -/* { dg-xfail-if "PR111876" { aarch64-*-darwin* } } */ extern void exit (int); extern void abort (void); diff --git a/gcc/testsuite/gcc.dg/torture/bitint-71.c b/gcc/testsuite/gcc.dg/torture/bitint-71.c new file mode 100644 index 00000000000..8ebd42b30b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bitint-71.c @@ -0,0 +1,28 @@ +/* PR middle-end/115352 */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-std=c23" } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */ + +#if __BITINT_MAXWIDTH__ >= 385 +int +foo (_BitInt (385) b) +{ + return __builtin_sub_overflow_p (0, b, (_BitInt (65)) 0); +} +#endif + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 385 + if (!foo (-(_BitInt (385)) 0x00000000000000000c377e8a3fd1881fff035bb487a51c9ed1f7350befa7ec4450000000000000000a3cf8d1ebb723981wb)) + __builtin_abort (); + if (!foo (-0x1ffffffffffffffffc377e8a3fd1881fff035bb487a51c9ed1f7350befa7ec445ffffffffffffffffa3cf8d1ebb723981uwb)) + __builtin_abort (); + if (!foo (-(_BitInt (385)) 0x00000000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000a3cf8d1ebb723981wb)) + __builtin_abort (); + if (!foo (-0x1ffffffffffffffff00000000000000000000000000000000ffffffffffffffffffffffffffffffffa3cf8d1ebb723981uwb)) + __builtin_abort (); +#endif +} diff --git a/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c b/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c index 6bcf3b146fd..3e4ecb57ba6 100644 --- a/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c +++ b/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c @@ -37,16 +37,9 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\t__bid_truncsdhf} 2 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_truncddhf} 2 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_truncddsd2} 2 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_trunctdhf} 2 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_trunctdsd2} 2 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_trunctddd2} 2 { target { dfp_bid && { ! *-*-darwin* } } } } } */ - -/* { dg-final { scan-assembler-times {\t___bid_truncsdhf} 1 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_truncddhf} 1 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_truncddsd2} 1 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_trunctdhf} 1 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_trunctdsd2} 1 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_trunctddd2} 1 { target { dfp_bid && *-*-darwin* } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_truncsdhf} 2 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_truncddhf} 2 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_truncddsd2} 2 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_trunctdhf} 2 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_trunctdsd2} 2 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_trunctddd2} 2 { target { dfp_bid } } } } */ diff --git a/gcc/testsuite/gcc.dg/torture/convert-dfp.c b/gcc/testsuite/gcc.dg/torture/convert-dfp.c index 7ad17b73503..ec136896ca7 100644 --- a/gcc/testsuite/gcc.dg/torture/convert-dfp.c +++ b/gcc/testsuite/gcc.dg/torture/convert-dfp.c @@ -55,16 +55,9 @@ int main() return 0; } -/* { dg-final { scan-assembler-times {\t__bid_extendsddd2} 3 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_extendsdtd2} 3 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_extendddtd2} 3 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_extendhfsd} 2 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_extendhfdd} 2 { target { dfp_bid && { ! *-*-darwin* } } } } } */ -/* { dg-final { scan-assembler-times {\t__bid_extendhftd} 2 { target { dfp_bid && { ! *-*-darwin* } } } } } */ - -/* { dg-final { scan-assembler-times {\t___bid_extendsddd2} 2 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_extendsdtd2} 2 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_extendddtd2} 2 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_extendhfsd} 1 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_extendhfdd} 1 { target { dfp_bid && *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\t___bid_extendhftd} 1 { target { dfp_bid && *-*-darwin* } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_extendsddd2} 3 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_extendsdtd2} 3 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_extendddtd2} 3 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_extendhfsd} 2 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_extendhfdd} 2 { target { dfp_bid } } } } */ +/* { dg-final { scan-assembler-times {\t__bid_extendhftd} 2 { target { dfp_bid } } } } */ diff --git a/gcc/testsuite/gcc.dg/torture/darwin-cfstring-3.c b/gcc/testsuite/gcc.dg/torture/darwin-cfstring-3.c index eabb3b517a4..ee4b385b17f 100644 --- a/gcc/testsuite/gcc.dg/torture/darwin-cfstring-3.c +++ b/gcc/testsuite/gcc.dg/torture/darwin-cfstring-3.c @@ -26,5 +26,5 @@ void foo(void) { /* { dg-final { scan-assembler "\\.long\[ \\t\]+___CFConstantStringClassReference\n\[ \\t\]*\\.long\[ \\t\]+1992\n\[ \\t\]*\\.long\[ \\t\]+\[lL\]C.*\n\[ \\t\]*\\.long\[ \\t\]+4\n" { target { *-*-darwin* && { ! lp64 } } } } } */ /* { dg-final { scan-assembler "\\.long\[ \\t\]+___CFConstantStringClassReference\n\[ \\t\]*\\.long\[ \\t\]+1992\n\[ \\t\]*\\.long\[ \\t\]+\[lL\]C.*\n\[ \\t\]*\\.long\[ \\t\]+10\n" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t___CFConstantStringClassReference\n\t.(long|word)\t1992\n\t.space 4\n\t.(quad|xword)\t.*\n\t.(quad|xword)\t4\n} { target { *-*-darwin* && { lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t___CFConstantStringClassReference\n\t.(long|word)\t1992\n\t.space 4\n\t.(quad|xword)\t.*\n\t.(quad|xword)\t10\n} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t___CFConstantStringClassReference\n\t.long\t1992\n\t.space 4\n\t.quad\t.*\n\t.quad\t4\n" { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t___CFConstantStringClassReference\n\t.long\t1992\n\t.space 4\n\t.quad\t.*\n\t.quad\t10\n" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c index 16643ceb198..552ca1433f4 100644 --- a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c +++ b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c @@ -9,7 +9,7 @@ /* arm_hf_eabi: Variadic funcs use Base AAPCS. Normal funcs use VFP variant. avr: Variadic funcs don't pass arguments in registers, while normal funcs do. */ -/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { csky*-*-* avr-*-* riscv*-*-* or1k*-*-* msp430-*-* amdgcn-*-* pru-*-* loongarch*-*-* aarch64-apple-darwin* } } } */ +/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { csky*-*-* avr-*-* riscv*-*-* or1k*-*-* msp430-*-* amdgcn-*-* pru-*-* loongarch*-*-* } } } */ /* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { nds32*-*-* } { v850*-*-* } } */ /* { dg-require-effective-target untyped_assembly } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c index 3684cffdc64..0224997f18a 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c @@ -25,9 +25,9 @@ f1 (int i, ...) /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -46,9 +46,9 @@ f2 (int i, ...) /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 8 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 1 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 8 GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 8 GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -62,10 +62,10 @@ f3 (int i, ...) /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and 1 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and 16 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and 16 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 8 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[1-9\]\[0-9\]* GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[1-9\]\[0-9\]* GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[1-9\]\[0-9\]* GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[1-9\]\[0-9\]* GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -81,9 +81,9 @@ f4 (int i, ...) /* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -100,9 +100,9 @@ f5 (int i, ...) /* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -121,9 +121,9 @@ f6 (int i, ...) /* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 24 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 3 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 24 GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 24 GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -139,9 +139,9 @@ f7 (int i, ...) /* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -159,9 +159,9 @@ f8 (int i, ...) /* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -177,9 +177,9 @@ f9 (int i, ...) /* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -197,9 +197,9 @@ f10 (int i, ...) /* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -218,9 +218,9 @@ f11 (int i, ...) /* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save 24 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save 3 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save 24 GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save 24 GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -239,9 +239,9 @@ f12 (int i, ...) /* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ /* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save 24 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save 0 GPR units and 3 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save 0 GPR units and 48 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save 0 GPR units and 48 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -260,9 +260,9 @@ f13 (int i, ...) /* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ /* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save 24 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save 0 GPR units and 3 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save 0 GPR units and 48 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save 0 GPR units and 48 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -281,9 +281,9 @@ f14 (int i, ...) /* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ /* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save 24 GPR units and 3" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save 1 GPR units and 2 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save 8 GPR units and 32 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save 8 GPR units and 32 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ inline void __attribute__((always_inline)) @@ -305,11 +305,11 @@ f15 (int i, ...) /* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */ /* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ /* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save 1 GPR units and 2 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f15: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f15: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target aarch64*-*-* } } } */ /* We may be able to improve upon this after fixing PR66010/PR66013. */ /* { dg-final { scan-tree-dump "f15: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump-not "f15: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump-not "f15: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump-not "f15: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump-not "f15: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-4.c b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-4.c index 77cdf384df4..1a637d6efe4 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-4.c @@ -27,9 +27,9 @@ f1 (int i, ...) /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f1: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -45,9 +45,9 @@ f2 (int i, ...) /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 0 GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 0 GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 0 GPR units and all FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 0 GPR units and all FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f2: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ /* Here va_arg can be executed at most as many times as va_start. @@ -69,9 +69,9 @@ f3 (int i, ...) /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 8 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 1 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 8 GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 8 GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ void @@ -91,7 +91,7 @@ f4 (int i, ...) /* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 8 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 0 GPR units and 1 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 0 GPR units and 16 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 0 GPR units and 16 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ia32 } } } } */ -/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-5.c b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-5.c index b0484f2f053..c8ad4fe320d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-5.c @@ -25,8 +25,7 @@ f1 (int i, ...) /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ -/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units" "stdarg" { target aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ void f2 (int i, ...) @@ -40,8 +39,7 @@ f2 (int i, ...) /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ -/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units" "stdarg" { target aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ /* Here va_arg can be executed at most as many times as va_start. */ void @@ -60,8 +58,7 @@ f3 (int i, ...) /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 32 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 1 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 8 GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ -/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 8 GPR units" "stdarg" { target aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 8 GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ void f4 (int i, ...) @@ -80,8 +77,7 @@ f4 (int i, ...) /* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 16 GPR units and 16 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 24 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 2 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 24 GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ -/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 24 GPR units" "stdarg" { target aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 24 GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ void f5 (int i, ...) @@ -96,8 +92,7 @@ f5 (int i, ...) /* { dg-final { scan-tree-dump "f5: va_list escapes 0, needs to save 16 GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */ /* { dg-final { scan-tree-dump "f5: va_list escapes 0, needs to save 32 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f5: va_list escapes 0, needs to save (4|2) GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f5: va_list escapes 0, needs to save 16 GPR units and 0 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ -/* { dg-final { scan-tree-dump "f5: va_list escapes 0, needs to save 16 GPR units" "stdarg" { target aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 0, needs to save 16 GPR units and 0 FPR units" "stdarg" { target aarch64*-*-* } } } */ void f6 (int i, ...) @@ -112,8 +107,7 @@ f6 (int i, ...) /* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 8 GPR units and 32 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */ /* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 32 GPR units and 3" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|2) GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 8 GPR units and 32 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ -/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 24 GPR units" "stdarg" { target aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 8 GPR units and 32 FPR units" "stdarg" { target aarch64*-*-* } } } */ void f7 (int i, ...) @@ -128,5 +122,4 @@ f7 (int i, ...) /* { dg-final { scan-tree-dump "f7: va_list escapes 0, needs to save 0 GPR units and 64 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && { ! { ia32 || llp64 } } } } } } */ /* { dg-final { scan-tree-dump "f7: va_list escapes 0, needs to save 32 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ /* { dg-final { scan-tree-dump "f7: va_list escapes 0, needs to save 2 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ -/* { dg-final { scan-tree-dump "f7: va_list escapes 0, needs to save 0 GPR units and 64 FPR units" "stdarg" { target { { aarch64*-*-* } && { ! aarch64-apple-darwin* } } } } } */ -/* { dg-final { scan-tree-dump "f7: va_list escapes 0, needs to save 32 GPR units" "stdarg" { target aarch64-apple-darwin* } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 0, needs to save 0 GPR units and 64 FPR units" "stdarg" { target aarch64*-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/dynamic-lmul2-7.c b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/dynamic-lmul2-7.c index 49ea3c2cf72..754f84ae0a0 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/dynamic-lmul2-7.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/dynamic-lmul2-7.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -ftree-vectorize -mrvv-max-lmul=dynamic" } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -ftree-vectorize -mrvv-max-lmul=dynamic -mno-vector-strict-align" } */ int x264_pixel_8x8 (unsigned char *pix1, unsigned char *pix2, int i_stride_pix2) diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-10.c b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-10.c index 144479324d7..d0a0f4208ee 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-10.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-10.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-max-lmul=m4 -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-max-lmul=m4 -fno-schedule-insns -fno-schedule-insns2 -mno-vector-strict-align" } */ #include diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-11.c b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-11.c index 13ae8bd3bcf..5a779a9ee75 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-11.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-11.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-max-lmul=m8 -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-max-lmul=m8 -fno-schedule-insns -fno-schedule-insns2 -mno-vector-strict-align" } */ #include diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-12.c b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-12.c index 1f9fa48264e..e7e4e841bb8 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-12.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-12.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-max-lmul=dynamic -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-max-lmul=dynamic -fno-schedule-insns -fno-schedule-insns2 -mno-vector-strict-align" } */ #include diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-8.c b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-8.c index ea6a7cbe2b1..0e5b4522de5 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-8.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-8.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gcv -mabi=lp64d -O3" } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mno-vector-strict-align" } */ #include diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-9.c b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-9.c index cb4abeca989..5276e0b2f6c 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-9.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/riscv/rvv/vla_vs_vls-9.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-max-lmul=m2" } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -mrvv-max-lmul=m2 -mno-vector-strict-align" } */ #include diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-7.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-7.c index 87048422013..e796e6ba216 100644 --- a/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-7.c +++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-7.c @@ -77,4 +77,4 @@ int main (void) } /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { target vect_widen_mult_hi_to_si } } } */ -/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target vect_widen_mult_hi_to_si } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target vect_widen_mult_hi_to_si } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-vect-iv-3.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-vect-iv-3.c index 6f2b2210b11..f268d4a5131 100644 --- a/gcc/testsuite/gcc.dg/vect/no-scevccp-vect-iv-3.c +++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-vect-iv-3.c @@ -30,4 +30,4 @@ unsigned int main1 () } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ -/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr112325.c b/gcc/testsuite/gcc.dg/vect/pr112325.c index 71cf4099253..143903beab2 100644 --- a/gcc/testsuite/gcc.dg/vect/pr112325.c +++ b/gcc/testsuite/gcc.dg/vect/pr112325.c @@ -1,7 +1,9 @@ /* { dg-do compile } */ /* { dg-options "-O3 -funroll-loops -fdump-tree-vect-details" } */ /* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target vect_shift } */ /* { dg-additional-options "-mavx2" { target x86_64-*-* i?86-*-* } } */ +/* { dg-additional-options "--param max-completely-peeled-insns=200" { target powerpc64*-*-* } } */ typedef unsigned short ggml_fp16_t; static float table_f32_f16[1 << 16]; diff --git a/gcc/testsuite/gcc.dg/vect/slp-24-big-array.c b/gcc/testsuite/gcc.dg/vect/slp-24-big-array.c index 5eaea9600ac..63f744338a1 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-24-big-array.c +++ b/gcc/testsuite/gcc.dg/vect/slp-24-big-array.c @@ -92,4 +92,4 @@ int main (void) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align && ilp32 } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { xfail { vect_no_align && ilp32 } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { xfail { vect_no_align && ilp32 } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-24.c b/gcc/testsuite/gcc.dg/vect/slp-24.c index 59178f2c0f2..7814d7c324e 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-24.c +++ b/gcc/testsuite/gcc.dg/vect/slp-24.c @@ -78,4 +78,4 @@ int main (void) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align && ilp32 } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { xfail { vect_no_align && ilp32 } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { xfail { vect_no_align && ilp32 } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-gap-1.c b/gcc/testsuite/gcc.dg/vect/slp-gap-1.c index 36463ca22c5..9856da7a7f4 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-gap-1.c +++ b/gcc/testsuite/gcc.dg/vect/slp-gap-1.c @@ -15,4 +15,4 @@ void pixel_sub_wxh(int16_t * __restrict diff, uint8_t *pix1, uint8_t *pix2) { /* We can vectorize this without peeling for gaps and thus without epilogue, but the only thing we can reliably scan is the zero-padding trick for the partial loads. */ -/* { dg-final { scan-tree-dump-times "\{_\[0-9\]\+, 0" 6 "vect" { target vect64 } } } */ +/* { dg-final { scan-tree-dump-times "\{_\[0-9\]\+, 0" 6 "vect" { target { vect64 && { vect_unpack && vect_perm } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-6.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-6.c index 1fd15aa3c87..5566705a704 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-6.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-6.c @@ -45,6 +45,5 @@ int main (void) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail { vect_no_int_add || { ! { vect_unpack || vect_strided2 } } } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */ /* { dg-final { scan-tree-dump-times "different interleaving chains in one node" 1 "vect" { target { ! vect_no_int_add } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-reduc-4.c b/gcc/testsuite/gcc.dg/vect/vect-cond-reduc-4.c index 27f18dc5bda..e9d414287e8 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-cond-reduc-4.c +++ b/gcc/testsuite/gcc.dg/vect/vect-cond-reduc-4.c @@ -42,6 +42,6 @@ main (void) } /* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 2 "vect" } } */ -/* { dg-final { scan-tree-dump-times "optimizing condition reduction with FOLD_EXTRACT_LAST(?:(?!failed)(?!Re-trying).)*succeeded" 2 "vect" { target { vect_fold_extract_last && vect_pack_trunc } } } } */ +/* { dg-final { scan-tree-dump-times "optimizing condition reduction with FOLD_EXTRACT_LAST(?:(?!Analysis failed).)*Analysis succeeded" 2 "vect" { target { vect_fold_extract_last && vect_pack_trunc } } } } */ /* { dg-final { scan-tree-dump-times "condition expression based on integer induction." 2 "vect" { target { ! vect_fold_extract_last } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-live-2.c b/gcc/testsuite/gcc.dg/vect/vect-live-2.c index 0a49c96d4e0..7c605d81c17 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-live-2.c +++ b/gcc/testsuite/gcc.dg/vect/vect-live-2.c @@ -58,4 +58,4 @@ main (void) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ -/* { dg-final { scan-tree-dump-times "vec_stmt_relevant_p: stmt live but not relevant(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" } } */ +/* { dg-final { scan-tree-dump-times "vec_stmt_relevant_p: stmt live but not relevant(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-4c-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-outer-4c-big-array.c index 4aaf2932006..5d61e0d284e 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-outer-4c-big-array.c +++ b/gcc/testsuite/gcc.dg/vect/vect-outer-4c-big-array.c @@ -24,4 +24,4 @@ foo (){ } /* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { target { vect_short_mult && { ! vect_no_align } } } } } */ -/* { dg-final { scan-tree-dump-times "zero step in outer loop.(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_short_mult && { ! vect_no_align } } } } } */ +/* { dg-final { scan-tree-dump-times "zero step in outer loop.(?:(?!Analysys failed).)*Analysis succeeded" 1 "vect" { target { vect_short_mult && { ! vect_no_align } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s16a.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s16a.c index 86fdcf37df8..000b2047fc0 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s16a.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s16a.c @@ -51,7 +51,7 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_sdot_hi || vect_widen_mult_hi_to_si } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { vect_sdot_hi || vect_widen_mult_hi_to_si } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_sdot_hi } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_mult_hi_to_si } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s8a.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s8a.c index 99c53d0ff02..a300d976eb1 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s8a.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s8a.c @@ -55,8 +55,8 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_sdot_qi || { vect_widen_mult_qi_to_hi && vect_widen_sum_hi_to_si } } } } } */ -/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_sdot_qi || { vect_widen_mult_qi_to_hi && vect_widen_sum_hi_to_si } } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { vect_sdot_qi || { vect_widen_mult_qi_to_hi && vect_widen_sum_hi_to_si } } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { vect_sdot_qi || { vect_widen_mult_qi_to_hi && vect_widen_sum_hi_to_si } } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_sdot_qi } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_mult_qi_to_hi && vect_widen_sum_hi_to_si } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s8b.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s8b.c index f66f8ddfbc0..b33bb4cc907 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s8b.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-s8b.c @@ -53,8 +53,8 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target vect_widen_mult_qi_to_hi } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target vect_widen_mult_qi_to_hi } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_mult_qi_to_hi } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16a.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16a.c index 9adb23a32f6..5d8a6fd8d15 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16a.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16a.c @@ -48,5 +48,5 @@ int main (void) } /* The initialization loop in main also gets vectorized. */ -/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_short_mult && vect_widen_sum_hi_to_si } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16b.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16b.c index e6b88423cf0..6660888c7c5 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16b.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16b.c @@ -46,6 +46,6 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_pack_trunc || vect_udot_hi } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { vect_pack_trunc || vect_udot_hi } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_pack_trunc || vect_udot_hi } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8a.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8a.c index f81562b7e65..259628edeeb 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8a.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8a.c @@ -53,7 +53,7 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_udot_qi || { vect_widen_mult_qi_to_hi && vect_widen_sum_qi_to_si } } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { vect_udot_qi || { vect_widen_mult_qi_to_hi && vect_widen_sum_qi_to_si } } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_udot_qi } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_mult_qi_to_hi && vect_widen_sum_qi_to_si } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8b.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8b.c index 3d04fa0a0bc..7b06d7e09f3 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8b.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u8b.c @@ -45,7 +45,7 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { { vect_widen_mult_qi_to_hi } || { vect_udot_qi || vect_unpack } } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { { vect_widen_mult_qi_to_hi } || { vect_udot_qi || vect_unpack } } } } } */ /* When the vectorizer is enhanced to vectorize accumulation into short for targets that support accumulation into int (powerpc, ia64) we'd have: diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1a.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1a.c index 2a1b07a515a..75b3b3b9f66 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1a.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1a.c @@ -41,6 +41,6 @@ main (void) return foo (); } -/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { ! vect_widen_sum_hi_to_si } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1b-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1b-big-array.c index 6f9735f6f05..13d29f46d83 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1b-big-array.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1b-big-array.c @@ -41,6 +41,6 @@ main (void) return foo (); } -/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_widen_sum_qi_to_si || vect_unpack } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { vect_widen_sum_qi_to_si || vect_unpack } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_sum_qi_to_si || vect_unpack } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { { ! vect_widen_sum_qi_to_si } && { ! vect_unpack } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1c-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1c-big-array.c index 9b503502756..7876f08ae6e 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1c-big-array.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-1c-big-array.c @@ -41,6 +41,6 @@ main (void) return foo (); } -/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target vect_widen_sum_qi_to_hi } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target vect_widen_sum_qi_to_hi } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_sum_qi_to_hi } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { ! vect_widen_sum_qi_to_hi } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-2a.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-2a.c index c77e29a80b1..f362a055004 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-2a.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-2a.c @@ -41,6 +41,6 @@ main (void) return foo (); } -/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_widen_sum_hi_to_si } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { ! vect_widen_sum_hi_to_si } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-2b-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-2b-big-array.c index d9d448292a1..e674c514c5b 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-2b-big-array.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-pattern-2b-big-array.c @@ -42,6 +42,6 @@ main (void) return foo (); } -/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_widen_sum_qi_to_si && vect_unpack } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_sum_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { vect_widen_sum_qi_to_si && vect_unpack } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_sum_qi_to_si && vect_unpack } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { target { { ! vect_widen_sum_qi_to_si } && { ! vect_unpack } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c b/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c index 24858e16281..72080af5923 100644 --- a/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c +++ b/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c @@ -46,8 +46,8 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */ -/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected(?:(?!failed)(?!Re-trying).)*succeeded" 1 "vect" { target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */ +/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected(?:(?!Analysis failed).)*Analysis succeeded" 1 "vect" { target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */ /* When vectorizer is enhanced to vectorize accumulation into short for targets that support accumulation into int (e.g. ia64) we'd have: diff --git a/gcc/testsuite/gcc.misc-tests/outputs.exp b/gcc/testsuite/gcc.misc-tests/outputs.exp index 5892a9e8e6e..50b147ded33 100644 --- a/gcc/testsuite/gcc.misc-tests/outputs.exp +++ b/gcc/testsuite/gcc.misc-tests/outputs.exp @@ -60,8 +60,6 @@ if !$skip_lto { # created, and thus fail. Configuring the compiler --with-gnu-ld # fixes this. set gld [check_effective_target_gld] -# Darwin's linker is not silent about missing -L values. -set ld64 [istarget *-*-darwin*] # Prepare additional options to be used for linking. # We do not compile to an executable, because that requires naming an output. @@ -187,7 +185,7 @@ proc outest { test sources opts dirs outputs } { foreach og $olist { if { [string index $og 0] == "!" } { global gspd ltop - global gld ld64 + global gld set cond [expr $og] continue } @@ -373,12 +371,7 @@ if !$skip_atsave { outest "$b-22 exe savetmp namedb-2" $sing "@$devnull -o $b.exe -save-temps" {} {{--0.i --0.s --0.o .args.0 !!$gld .ld1_args !0 .exe}} outest "$b-23 exe savetmp named2-2" $mult "@$devnull -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o .args.0 !!$gld .ld1_args !0 .exe}} outest "$b-24 exe savetmp named2-3" $mult "@$devnull -I dummy -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o -args.0 -args.1 .args.2 !!$gld .ld1_args !0 .exe}} - if $ld64 { - # Darwin's linker warns about missing args to -L. - outest "$b-25 exe savetmp named2-4" $mult "@$devnull -I dummy -L dummy -o $b.exe -save-temps -Wl,-w" {} {{--1.i --1.s --1.o --2.i --2.s --2.o -args.0 -args.1 .args.2 !!0 .args.3 !!$gld .ld1_args !0 .exe}} - } else { - outest "$b-25 exe savetmp named2-4" $mult "@$devnull -I dummy -L dummy -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o -args.0 -args.1 .args.2 .args.3 !!$gld .ld1_args !0 .exe}} - } +outest "$b-25 exe savetmp named2-4" $mult "@$devnull -I dummy -L dummy -o $b.exe -save-temps" {} {{--1.i --1.s --1.o --2.i --2.s --2.o -args.0 -args.1 .args.2 .args.3 !!$gld .ld1_args !0 .exe}} } # Setting the main output to a dir selects it as the default aux&dump diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/aapcs64.exp b/gcc/testsuite/gcc.target/aarch64/aapcs64/aapcs64.exp index e0851f7b38f..e361d1ef36f 100644 --- a/gcc/testsuite/gcc.target/aarch64/aapcs64/aapcs64.exp +++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/aapcs64.exp @@ -25,11 +25,6 @@ if { ![istarget aarch64*-*-*] } then { return } -if { [istarget *-*-darwin*] } then { - # darwinpcs and mach-o will need different test mechanisms. - return -} - torture-init set-torture-options $C_TORTURE_OPTIONS set additional_flags "-W -Wall -Wno-abi -fno-pie -no-pie" diff --git a/gcc/testsuite/gcc.target/aarch64/ands_3.c b/gcc/testsuite/gcc.target/aarch64/ands_3.c index 31ba769392e..42cb7f0f0bc 100644 --- a/gcc/testsuite/gcc.target/aarch64/ands_3.c +++ b/gcc/testsuite/gcc.target/aarch64/ands_3.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ -/* { dg-skip-if "darwinpcs extends in the caller" *-*-darwin* } */ int f9 (unsigned char x, int y) diff --git a/gcc/testsuite/gcc.target/aarch64/arm_align_max_pwr.c b/gcc/testsuite/gcc.target/aarch64/arm_align_max_pwr.c index 38b9ef01eb7..ffa4d229922 100644 --- a/gcc/testsuite/gcc.target/aarch64/arm_align_max_pwr.c +++ b/gcc/testsuite/gcc.target/aarch64/arm_align_max_pwr.c @@ -19,7 +19,5 @@ dummy () return result; } -/* { dg-final { scan-assembler-times "zero\t4" 2 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler "zero\t268435452" { target { ! *-*-darwin*} } } } */ -/* { dg-final { scan-assembler-times ".zerofill __DATA,__bss,_y,4,28" 1 { target { *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times ".zerofill __DATA,__bss,_x,4,28" 1 { target { *-*-darwin* } } } } */ +/* { dg-final { scan-assembler-times "zero\t4" 2 } } */ +/* { dg-final { scan-assembler "zero\t268435452" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-2.c b/gcc/testsuite/gcc.target/aarch64/auto-init-2.c index 3a0387a5952..375befd325b 100644 --- a/gcc/testsuite/gcc.target/aarch64/auto-init-2.c +++ b/gcc/testsuite/gcc.target/aarch64/auto-init-2.c @@ -12,11 +12,11 @@ enum E { N3 }; -extern void bar (unsigned char, short, int, enum E, long, long long, int *, bool); +extern void bar (char, short, int, enum E, long, long long, int *, bool); void foo() { - unsigned char temp1; + char temp1; short temp2; int temp3; enum E temp4; diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-3.c b/gcc/testsuite/gcc.target/aarch64/auto-init-3.c index 85a4e4daeb6..7008f76b294 100644 --- a/gcc/testsuite/gcc.target/aarch64/auto-init-3.c +++ b/gcc/testsuite/gcc.target/aarch64/auto-init-3.c @@ -2,19 +2,13 @@ /* { dg-do compile } */ /* { dg-options "-ftrivial-auto-var-init=zero -fdump-rtl-expand" } */ -#ifdef __APPLE__ -# define TYPE _Float128 -#else -# define TYPE long double -#endif +long double result; -TYPE result; - -TYPE foo() +long double foo() { float temp1; double temp2; - TYPE temp3; + long double temp3; result = temp1 + temp2 + temp3; return result; diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-4.c b/gcc/testsuite/gcc.target/aarch64/auto-init-4.c index 0c6840ba224..10197045b4c 100644 --- a/gcc/testsuite/gcc.target/aarch64/auto-init-4.c +++ b/gcc/testsuite/gcc.target/aarch64/auto-init-4.c @@ -2,19 +2,13 @@ /* { dg-do compile } */ /* { dg-options "-O -ftrivial-auto-var-init=pattern -fdump-rtl-expand" } */ -#ifdef __APPLE__ -# define TYPE _Float128 -#else -# define TYPE long double -#endif +long double result; -TYPE result; - -TYPE foo() +long double foo() { float temp1; double temp2; - TYPE temp3; + long double temp3; result = temp1 + temp2 + temp3; return result; diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-5.c b/gcc/testsuite/gcc.target/aarch64/auto-init-5.c index 0dda3c201d3..ac69ac3df82 100644 --- a/gcc/testsuite/gcc.target/aarch64/auto-init-5.c +++ b/gcc/testsuite/gcc.target/aarch64/auto-init-5.c @@ -2,19 +2,14 @@ /* { dg-do compile } */ /* { dg-options "-ftrivial-auto-var-init=zero" } */ -#ifdef __APPLE__ -# define TYPE _Float128 -#else -# define TYPE long double -#endif -_Complex TYPE result; +_Complex long double result; -_Complex TYPE foo() +_Complex long double foo() { _Complex float temp1; _Complex double temp2; - _Complex TYPE temp3; + _Complex long double temp3; result = temp1 + temp2 + temp3; return result; diff --git a/gcc/testsuite/gcc.target/aarch64/auto-init-6.c b/gcc/testsuite/gcc.target/aarch64/auto-init-6.c index 23323115a11..0456c66f496 100644 --- a/gcc/testsuite/gcc.target/aarch64/auto-init-6.c +++ b/gcc/testsuite/gcc.target/aarch64/auto-init-6.c @@ -2,19 +2,14 @@ /* { dg-do compile } */ /* { dg-options "-ftrivial-auto-var-init=pattern" } */ -#ifdef __APPLE__ -# define TYPE _Float128 -#else -# define TYPE long double -#endif -_Complex TYPE result; +_Complex long double result; -_Complex TYPE foo() +_Complex long double foo() { _Complex float temp1; _Complex double temp2; - _Complex TYPE temp3; + _Complex long double temp3; result = temp1 + temp2 + temp3; return result; diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2-extra.c b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2-extra.c index d4442881445..3b2c932ac23 100644 --- a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2-extra.c +++ b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2-extra.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps" } */ #define ALIGN 16 diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2.c b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2.c index aca137ec793..ee5d6faa428 100644 --- a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2.c +++ b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align16-O2.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps" } */ #define ALIGN 16 diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2-extra.c b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2-extra.c index 782aab4856e..6d4a883a96e 100644 --- a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2-extra.c +++ b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2-extra.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps" } */ #define ALIGN 32 diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2.c b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2.c index 2511c3dcbcc..331daba354c 100644 --- a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2.c +++ b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align32-O2.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps" } */ #define ALIGN 32 diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align8-O2.c b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align8-O2.c index fef850147ae..e6d45f5dd5c 100644 --- a/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align8-O2.c +++ b/gcc/testsuite/gcc.target/aarch64/bitfield-abi-warning-align8-O2.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-options "-O2 -fno-stack-protector -save-temps" } */ #define ALIGN 8 diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-bitint-abi-align16.c b/gcc/testsuite/gcc.target/aarch64/bitfield-bitint-abi-align16.c index 6a607e93eab..4a228b0a1ce 100644 --- a/gcc/testsuite/gcc.target/aarch64/bitfield-bitint-abi-align16.c +++ b/gcc/testsuite/gcc.target/aarch64/bitfield-bitint-abi-align16.c @@ -1,6 +1,5 @@ /* { dg-do compile { target bitint } } */ /* { dg-additional-options "-std=c23 -O2 -fno-stack-protector -save-temps -fno-schedule-insns -fno-schedule-insns2" } */ -/* { dg-skip-if "aligned x-reg passing is altered by darwinpcs" { aarch64-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ #define ALIGN 16 diff --git a/gcc/testsuite/gcc.target/aarch64/bitfield-bitint-abi-align8.c b/gcc/testsuite/gcc.target/aarch64/bitfield-bitint-abi-align8.c index 2d6b974e727..e7f773640f0 100644 --- a/gcc/testsuite/gcc.target/aarch64/bitfield-bitint-abi-align8.c +++ b/gcc/testsuite/gcc.target/aarch64/bitfield-bitint-abi-align8.c @@ -1,6 +1,5 @@ /* { dg-do compile { target bitint } } */ /* { dg-additional-options "-std=c23 -O2 -fno-stack-protector -save-temps -fno-schedule-insns -fno-schedule-insns2" } */ -/* { dg-skip-if "aligned x-reg passing is altered by darwinpcs" { aarch64-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ #define ALIGN 8 diff --git a/gcc/testsuite/gcc.target/aarch64/bti-4.c b/gcc/testsuite/gcc.target/aarch64/bti-4.c index 109ab60fcb7..28495a5c199 100644 --- a/gcc/testsuite/gcc.target/aarch64/bti-4.c +++ b/gcc/testsuite/gcc.target/aarch64/bti-4.c @@ -56,7 +56,5 @@ retbr_trampolines2 (void *a, int b) return 0; } -/* Trampoline should have BTI C. - but Darwin trampolines are constructed on demand by a builtin and do not - appear in the generated code for this TU. */ -/* { dg-final { scan-assembler "\.LTRAMP0:\n\thint\t34" { target { ! *-*-darwin* } } } } */ +/* Trampoline should have BTI C. */ +/* { dg-final { scan-assembler "\.LTRAMP0:\n\thint\t34" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c b/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c index 86e4f5fa82c..ced96d04542 100644 --- a/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c +++ b/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c @@ -6,4 +6,4 @@ test (void) __asm__ ("@ %c0" : : "S" (test)); } -/* { dg-final { scan-assembler "@ _?test" } } */ +/* { dg-final { scan-assembler "@ test" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c b/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c index 4531a381518..8bde4cbeb0c 100644 --- a/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c +++ b/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c @@ -7,4 +7,4 @@ test (void) __asm__ ("@ %c0" : : "S" (&test + 4)); } -/* { dg-final { scan-assembler "@ _?test\\+4" } } */ +/* { dg-final { scan-assembler "@ test\\+4" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/c-output-template-4.c b/gcc/testsuite/gcc.target/aarch64/c-output-template-4.c index 800d52bfab8..c5a93915af1 100644 --- a/gcc/testsuite/gcc.target/aarch64/c-output-template-4.c +++ b/gcc/testsuite/gcc.target/aarch64/c-output-template-4.c @@ -7,4 +7,4 @@ test (void) __asm__ ("@ %c0" : : "S" (&test + 4)); } -/* { dg-final { scan-assembler "@ _?test\\+4" } } */ +/* { dg-final { scan-assembler "@ test\\+4" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/cpymem-size.c b/gcc/testsuite/gcc.target/aarch64/cpymem-size.c index b8ef4745c6d..4a6f2495d22 100644 --- a/gcc/testsuite/gcc.target/aarch64/cpymem-size.c +++ b/gcc/testsuite/gcc.target/aarch64/cpymem-size.c @@ -6,7 +6,7 @@ /* ** cpy_127: ** mov (w|x)2, 127 -** b _?memcpy +** b memcpy */ void cpy_127 (char *out, char *in) @@ -17,7 +17,7 @@ cpy_127 (char *out, char *in) /* ** cpy_128: ** mov (w|x)2, 128 -** b _?memcpy +** b memcpy */ void cpy_128 (char *out, char *in) diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/aarch64-darwin.exp b/gcc/testsuite/gcc.target/aarch64/darwin/aarch64-darwin.exp deleted file mode 100644 index b0b7f49aede..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/aarch64-darwin.exp +++ /dev/null @@ -1,46 +0,0 @@ -# Specific tests for the darwinpcs and codegen. -# Copyright (C) GNU Toolchain Authors -# Contributed by Iain Sandoe -# -# This file is part of GCC. -# -# GCC is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GCC is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# . */ - -# GCC testsuite that uses the `dg.exp' driver. - -# Exit immediately if this isn't aarch64-darwin. - -if { ![istarget aarch64*-*-darwin*] } then { - return -} - -# Load support procs. -load_lib gcc-dg.exp - -# If a testcase doesn't have special options, use these. -global DEFAULT_CFLAGS -if ![info exists DEFAULT_CFLAGS] then { - set DEFAULT_CFLAGS " -ansi -pedantic-errors" -} - -# Initialize `dg'. -dg-init - -# Main loop. -dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \ - "" $DEFAULT_CFLAGS - -# All done. -dg-finish diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/complex-in-regs.c b/gcc/testsuite/gcc.target/aarch64/darwin/complex-in-regs.c deleted file mode 100644 index 9c9e8b877e4..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/complex-in-regs.c +++ /dev/null @@ -1,95 +0,0 @@ -/* { dg-do compile } */ -/* we need this for complex and gnu initializers. */ -/* { dg-options "-std=gnu99 " } */ -/* We use the sections anchors to make the code easier to match. */ -/* { dg-additional-options " -O -fsection-anchors -fno-schedule-insns -fno-schedule-insns2 " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - - -__attribute__((__noinline__)) -_Complex char -cc_regs_fun (_Complex char r0, _Complex char r1, - _Complex char r2, _Complex char r3, - _Complex char r4, _Complex char r5, - _Complex char r6, _Complex char r7); - -/* -**call_cc_regs_fun: -** ... -** ldrh w7, \[x0\] -** ldrh w6, \[x0, 2\] -** ldrh w5, \[x0, 4\] -** ldrh w4, \[x0, 6\] -** ldrh w3, \[x0, 8\] -** ldrh w2, \[x0, 10\] -** ldrh w1, \[x0, 12\] -** ldrh w0, \[x0, 14]\ -** bl _cc_regs_fun -** ... -*/ - -_Complex char -call_cc_regs_fun (void) -{ - return cc_regs_fun ((_Complex char) (1 + 1i), (_Complex char) (2 + 2i), - (_Complex char) (3 + 3i), (_Complex char) (4 + 4i), - (_Complex char) (5 + 5i), (_Complex char) (6 + 6i), - (_Complex char) (7 + 7i), (_Complex char) (8 + 8i)); -} - - -__attribute__((__noinline__)) -_Complex short -cs_regs_fun (_Complex short r0, _Complex short r1, - _Complex short r2, _Complex short r3, - _Complex short r4, _Complex short r5, - _Complex short r6, _Complex short r7); - -/* -**call_cs_regs_fun: -** ... -** ldp w7, w6, \[x0, 16\] -** ldp w5, w4, \[x0, 24\] -** ldp w3, w2, \[x0, 32\] -** ldp w1, w0, \[x0, 40\] -** bl _cs_regs_fun -** ... -*/ - -__attribute__((__noinline__)) -_Complex short -call_cs_regs_fun (void) -{ - return cs_regs_fun ((_Complex short) (1 + 1i), (_Complex short) (2 + 2i), - (_Complex short) (3 + 3i), (_Complex short) (4 + 4i), - (_Complex short) (5 + 5i), (_Complex short) (6 + 6i), - (_Complex short) (7 + 7i), (_Complex short) (8 + 8i)); -} - -__attribute__((__noinline__)) -_Complex int -ci_regs_fun (_Complex int r0, _Complex int r1, - _Complex int r2, _Complex int r3, - _Complex int r4, _Complex int r5, - _Complex int r6, _Complex int r7); - -/* -**call_ci_regs_fun: -** ... -** ldp x7, x6, \[x0, 48\] -** ldp x5, x4, \[x0, 64\] -** ldp x3, x2, \[x0, 80\] -** ldp x1, x0, \[x0, 96\] -** bl _ci_regs_fun -** ... -*/ - -__attribute__((__noinline__)) -_Complex int -call_ci_regs_fun (void) -{ - return ci_regs_fun ((_Complex int) (1 + 1i), (_Complex int) (2 + 2i), - (_Complex int) (3 + 3i), (_Complex int) (4 + 4i), - (_Complex int) (5 + 5i), (_Complex int) (6 + 6i), - (_Complex int) (7 + 7i), (_Complex int) (8 + 8i)); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d1.c b/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d1.c deleted file mode 100644 index e2dd574fac7..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d1.c +++ /dev/null @@ -1,54 +0,0 @@ -/* { dg-do compile } */ -/* we need this for the empty struct. */ -/* { dg-options "-std=gnu99 " } */ -/* { dg-additional-options "-O -fno-schedule-insns -fno-schedule-insns2 " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -/* Make sure we do no consume any registers in passing zero-sized entities */ - -typedef struct es {} Empty; - -__attribute__((__noinline__)) void -use_no_regs (int a, Empty b, int c, Empty d, Empty e, int f); - -/* -**call_use_no_regs: -** ... -** mov w2, 3 -** mov w1, 2 -** mov w0, 1 -** bl _use_no_regs -** ... -*/ - -__attribute__((__noinline__)) void -call_use_no_regs (void) -{ - Empty e; - use_no_regs (1, e, 2, e, e, 3); -} - -/* Make sure we consume no stack in passing zero-sized entities. */ - -/* -**call_use_no_stack: -** ... -** mov w[0-9]+, 108 -** strb w[0-9]+, \[sp, 1\] -** mov w[0-9]+, 106 -** strb w[0-9]+, \[sp\] -** ... -** bl _use_no_stack -** ... -*/ - -__attribute__((__noinline__)) void -use_no_stack (int a, int b, int c, int d, int e, int f, int g, int h, - Empty i, char j, Empty k, char l); - -void -call_use_no_stack (void) -{ - Empty e; - use_no_stack (0, 1, 2, 3, 4, 5, 6, 7, e, 'j', e, 'l'); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-00.c b/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-00.c deleted file mode 100644 index 4b10db5f81e..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-00.c +++ /dev/null @@ -1,125 +0,0 @@ -/* { dg-do compile } */ -/* { dg-additional-options " -O -fno-schedule-insns -fno-schedule-insns2 " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -/* In each case we consume the parm registers with 8 ints, forcing - the test values to be spilled to the stack. */ - -/* The important thing here is that the chars are assigned to the stack - * with no padding - so that they occupy bytes 0-8. */ - -/* -**call_char_packing: -** ... -** mov w[0-9]+, 113 -** strb w[0-9]+, \[sp, 8\] -** mov w[0-9]+, 112 -** strb w[0-9]+, \[sp, 7\] -** mov w[0-9]+, 111 -** strb w[0-9]+, \[sp, 6\] -** mov w[0-9]+, 110 -** strb w[0-9]+, \[sp, 5\] -** mov w[0-9]+, 109 -** strb w[0-9]+, \[sp, 4\] -** mov w[0-9]+, 108 -** strb w[0-9]+, \[sp, 3\] -** mov w[0-9]+, 107 -** strb w[0-9]+, \[sp, 2\] -** mov w[0-9]+, 106 -** strb w[0-9]+, \[sp, 1\] -** mov w[0-9]+, 105 -** strb w[0-9]+, \[sp\] -** mov w7, 7 -** mov w6, 6 -** mov w5, 5 -** mov w4, 4 -** mov w3, 3 -** mov w2, 2 -** mov w1, 1 -** mov w0, 0 -** bl _char_packing -** ... -*/ - -__attribute__((__noinline__)) void -char_packing (int a, int b, int c, int d, int e, int f, int g, int h, - char i, char j, char k, char l, - char m, char n, char o, char p, - char q); - -void call_char_packing (void) -{ - char_packing (0, 1, 2, 3, 4, 5, 6, 7, - 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'); -} - -/* Here we should occupy the first 7 short words on the stack. */ - -/* -**call_short_packing: -** ... -** mov w[0-9]+, 12 -** strh w[0-9]+, \[sp, 8\] -** mov w[0-9]+, 11 -** strh w[0-9]+, \[sp, 6\] -** mov w[0-9]+, 10 -** strh w[0-9]+, \[sp, 4\] -** mov w[0-9]+, 9 -** strh w[0-9]+, \[sp, 2\] -** mov w[0-9]+, 8 -** strh w[0-9]+, \[sp\] -** mov w7, 7 -** mov w6, 6 -** mov w5, 5 -** mov w4, 4 -** mov w3, 3 -** mov w2, 2 -** mov w1, 1 -** mov w0, 0 -** bl _short_packing -** ... -*/ - -__attribute__((__noinline__)) void -short_packing (int a, int b, int c, int d, int e, int f, int g, int h, - short i, short j, short k, short l, - short m); - -void call_short_packing (void) -{ - short_packing (0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12); -} - -/* Here we should occupy the first 3 ints on the stack. */ - -/* -**call_int_packing: -** ... -** mov w[0-9]+, 10 -** str w[0-9]+, \[sp, 8\] -** mov w[0-9]+, 9 -** mov w[0-9]+, 8 -** stp w[0-9]+, w[0-9]+, \[sp\] -** mov w7, 7 -** mov w6, 6 -** mov w5, 5 -** mov w4, 4 -** mov w3, 3 -** mov w2, 2 -** mov w1, 1 -** mov w0, 0 -** bl _int_packing -** ... -*/ - -__attribute__((__noinline__)) void -int_packing (int a, int b, int c, int d, int e, int f, int g, int h, - int i, int j, int k); - -void call_int_packing (void) -{ - int_packing (0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10); -} - diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-01.c b/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-01.c deleted file mode 100644 index d21fd551b4a..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-01.c +++ /dev/null @@ -1,115 +0,0 @@ -/* { dg-do compile } */ -/* { dg-additional-options " -O -fno-schedule-insns -fno-schedule-insns2 " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -/* In each case we consume the parm registers with 8 ints, forcing - the test values to be spilled to the stack. */ - -/* char short char short - everything on 2byte boundaries */ - -/* -**call_c_s_packing: -** ... -** mov w[0-9]+, 109 -** strb w[0-9]+, \[sp, 8\] -** mov w[0-9]+, 9 -** strh w[0-9]+, \[sp, 6\] -** mov w[0-9]+, 107 -** strb w[0-9]+, \[sp, 4\] -** mov w[0-9]+, 8 -** strh w[0-9]+, \[sp, 2\] -** mov w[0-9]+, 105 -** strb w[0-9]+, \[sp\] -** mov w7, 7 -** mov w6, 6 -** mov w5, 5 -** mov w4, 4 -** mov w3, 3 -** mov w2, 2 -** mov w1, 1 -** mov w0, 0 -** bl _c_s_packing -** ... -*/ - -__attribute__((__noinline__)) void -c_s_packing (int a, int b, int c, int d, int e, int f, int g, int h, - char i, short j, char k, short l, - char m); - -void call_c_s_packing (void) -{ - c_s_packing (0, 1, 2, 3, 4, 5, 6, 7, - 'i', 8 , 'k', 9, 'm'); -} - -/* -**call_s_c_packing: -** ... -** mov w[0-9]+, 109 -** strb w[0-9]+, \[sp, 7\] -** mov w[0-9]+, 108 -** strb w[0-9]+, \[sp, 6\] -** mov w[0-9]+, 9 -** strh w[0-9]+, \[sp, 4\] -** mov w[0-9]+, 106 -** strb w[0-9]+, \[sp, 2\] -** mov w[0-9]+, 8 -** strh w[0-9]+, \[sp\] -** mov w7, 7 -** mov w6, 6 -** mov w5, 5 -** mov w4, 4 -** mov w3, 3 -** mov w2, 2 -** mov w1, 1 -** mov w0, 0 -** bl _s_c_packing -** ... -*/ - -__attribute__((__noinline__)) void -s_c_packing (int a, int b, int c, int d, int e, int f, int g, int h, - short i, char j, short k, char l, - char m); - -void call_s_c_packing (void) -{ - s_c_packing (0, 1, 2, 3, 4, 5, 6, 7, - 8, 'j' , 9, 'l', 'm'); -} - -/* 0, 2, 4, 0 */ - -/* -**call_csi_packing: -** ... -** mov w[0-9]+, 108 -** strb w[0-9]+, \[sp, 8\] -** mov w[0-9]+, 9 -** str w[0-9]+, \[sp, 4\] -** mov w[0-9]+, 8 -** strh w[0-9]+, \[sp, 2\] -** mov w[0-9]+, 105 -** strb w[0-9]+, \[sp\] -** mov w7, 7 -** mov w6, 6 -** mov w5, 5 -** mov w4, 4 -** mov w3, 3 -** mov w2, 2 -** mov w1, 1 -** mov w0, 0 -** bl _csi_packing -** ... -*/ - -__attribute__((__noinline__)) void -csi_packing (int a, int b, int c, int d, int e, int f, int g, int h, - char i, short j, int k, char l); - -void call_csi_packing (void) -{ - csi_packing (0, 1, 2, 3, 4, 5, 6, 7, - 'i', 8 , 9, 'l'); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-02.c b/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-02.c deleted file mode 100644 index 03851637afe..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-02.c +++ /dev/null @@ -1,73 +0,0 @@ -/* { dg-do compile } */ -/* we need this for complex literals. */ -/* { dg-options "-std=gnu99 " } */ -/* { dg-additional-options "-O -fsection-anchors -fno-schedule-insns -fno-schedule-insns2 " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - - -__attribute__((__noinline__)) void -c_cc_packing (int a, int b, int c, int d, int e, int f, int g, int h, - _Complex char i, _Complex char j); - -/* We check that these values are not packed on the stack. -**call_c_cc_packing: -** ... -** ldrh w[0-9]+, \[x[0-9]+\] -** strh w[0-9]+, \[sp, 8\] -** ldrh w[0-9]+, \[x[0-9]+, 2\] -** strh w[0-9]+, \[sp\] -** ... -** bl _c_cc_packing -** ... -*/ - -void -call_c_cc_packing (void) -{ - c_cc_packing (0, 1, 2, 3, 4, 5, 6, 7, - (_Complex char) (1 + 1i),(_Complex char) (2 + 2i)); -} - - -__attribute__((__noinline__)) void -c_cs_packing (int a, int b, int c, int d, int e, int f, int g, int h, - _Complex short i, _Complex short j); - -/* -**call_c_cs_packing: -** ... -** ldp (w[0-9]+), (w[0-9]+), \[x[0-9]+, 4\] -** str \1, \[sp, 8\] -** str \2, \[sp\] -** ... -** bl _c_cs_packing -** ... -*/ - -void -call_c_cs_packing (void) -{ - c_cs_packing (0, 1, 2, 3, 4, 5, 6, 7, - (_Complex short) (1 + 1i),(_Complex short) (2 + 2i)); -} - -void c_ci_packing (int a, int b, int c, int d, int e, int f, int g, int h, - _Complex int i, _Complex int j); - -/* -**call_c_ci_packing: -** ... -** ldr (x[0-9]+), \[x[0-9]+, 12\] -** ldr (x[0-9]+), \[x[0-9]+, 20\] -** stp \2, \1, \[sp\] -** ... -** bl _c_ci_packing -** ... -*/ - -void -call_c_ci_packing (void) -{ - c_ci_packing (0, 1, 2, 3, 4, 5, 6, 7, - (_Complex int) (1 + 1i),(_Complex int) (2 + 2i)); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-03.c b/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-03.c deleted file mode 100644 index 9ebf4f54de6..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-03.c +++ /dev/null @@ -1,66 +0,0 @@ -/* { dg-do compile } */ - -/* { dg-additional-options "-O2 -fno-schedule-insns -fno-schedule-insns2 " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -typedef union u { char a; short b; } U; -typedef struct sf { float a; float b; float c;} SF; - -__attribute__((__noinline__)) void -u_packing (int a, int b, int c, int d, int e, int f, int g, int h, - U i, U j); - -/* We check that these values are not packed on the stack. -**call_u_packing: -** ... -** strh w[0-9]+, \[sp, 8\] -** strh w[0-9]+, \[sp\] -** ... -** bl _u_packing -** ... -*/ - -void -call_u_packing (void) -{ - U x = { 'a' }; - u_packing (0, 1, 2, 3, 4, 5, 6, 7, x, x); -} - -/* But a homogeneous float aggregate is treated as if it were the contained - floats. */ - -__attribute__((__noinline__)) void -sf_packing (float a, float b, float c, float d, - float e, float f, float g, float h, - SF i, SF j); - -/* So the stores to sp+12 and 20 pack the floats onto the stack. -**call_sf_packing: -** ... -** mov (x[0-9]+), 1065353216 -** movk \1, 0x4000, lsl 48 -** mov w[0-9]+, 1077936128 -** fmov s7, 7.0e\+0 -** fmov s6, 6.0e\+0 -** fmov s5, 5.0e\+0 -** fmov s4, 4.0e\+0 -** fmov s3, 3.0e\+0 -** fmov s2, 2.0e\+0 -** fmov s1, 1.0e\+0 -** movi v0.2s, #0 -** str x[0-9]+, \[sp\] -** str w[0-9]+, \[sp, 8\] -** str x[0-9]+, \[sp, 12\] -** str w[0-9]+, \[sp, 20\] -** bl _sf_packing -** ... -*/ - -void -call_sf_packing (void) -{ - SF A = {1.0F, 2.0F, 3.0F}; - sf_packing (0.0F, 1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F, 7.0F, - A, A); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-04.c b/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-04.c deleted file mode 100644 index 1d1af4e7425..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d2-04.c +++ /dev/null @@ -1,64 +0,0 @@ -/* { dg-do compile } */ - -/* { dg-additional-options "-O -fno-schedule-insns -fno-schedule-insns2 " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -typedef short v2hi __attribute__ ((vector_size (4))); -typedef int v4si __attribute__ ((vector_size (16))); - -v4si t; -int al = __alignof__ (t); - -__attribute__((__noinline__)) void -v2hi_packing (v2hi a, v2hi b, v2hi c, v2hi d, v2hi e, v2hi f, v2hi g, v2hi h, - v2hi i, v2hi j); - -/* We check that v2hi is packed on the stack. -**call_v2hi_packing: -** ... -** mov w[0-9]+, 1 -** movk (w[0-9]+), 0x2, lsl 16 -** stp \1, \1, \[sp\] -** mov w7, \1 -** mov w6, \1 -** mov w5, \1 -** mov w4, \1 -** mov w3, \1 -** mov w2, \1 -** mov w1, \1 -** bl _v2hi_packing -** ... -*/ - -void -call_v2hi_packing (void) -{ - v2hi x = {1,2}; - v2hi_packing (x, x, x, x, x, x, x, x, x, x); -} - - -__attribute__((__noinline__)) void -v4si_packing (int r0, int r1, int r2, int r3, int r4, int r5, int r6, int r7, - v4si a, v4si b, v4si c, v4si d, v4si e, v4si f, v4si g, v4si h, - int stack, v4si i, v4si j); - -/* Test that we align a 16b vector on the stack. -**call_v4si_packing: -** ... -** adrp x0, lC0@PAGE -** ldr (q[0-9]+), \[x[0-9]+, #lC0@PAGEOFF\] -** stp \1, \1, \[sp, 16\] -** mov w[0-9]+, 42 -** str w[0-9]+, \[sp\] -** ... -** bl _v4si_packing -** ... -*/ - -void -call_v4si_packing (void) -{ - v4si x = {3,1,2,4}; - v4si_packing (0, 1, 2, 3, 4, 5, 6, 7, x, x, x, x, x, x, x, x, 42, x, x); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d3.c b/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d3.c deleted file mode 100644 index 21c6b696b7c..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d3.c +++ /dev/null @@ -1,40 +0,0 @@ -/* { dg-do compile } */ -/* { dg-additional-options "-O " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -/* This will fail, because of issue #74 -**foo: -** cmp w0, w1 -** cset w0, eq -** ret -*/ - -__attribute__((__noinline__)) -int -foo (char a, unsigned char b) -{ - return a == b ? 1 : 0; -} - -__attribute__((__noinline__)) -int -bar (short a, unsigned short b) -{ - return a == b ? 1 : 0; -} - -void pop (char *, unsigned char *, short *, unsigned short *); - -int main () -{ - char a; - unsigned char b; - short c; - unsigned short d; - int result; - pop (&a, &b, &c, &d); - - result = foo (a, b); - result += bar (c, d); - return result; -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d4.c b/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d4.c deleted file mode 100644 index 2aab48260f4..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/darwinpcs-d4.c +++ /dev/null @@ -1,62 +0,0 @@ -/* { dg-do compile } */ -/* we need this for __int128. */ -/* { dg-options "-std=gnu99 " } */ -/* { dg-additional-options "-O -fno-schedule-insns -fno-schedule-insns2 " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -/* we should use x0, x1 and x2 - not skip x1. -**foo: -** eor x0, x0, x1 -** orr x0, x0, x2 -** cmp x0, 0 -** cset w0, eq -** ret -*/ - -__attribute__((__noinline__)) -int -foo (unsigned long long x,unsigned __int128 y) -{ - return x == y ? 1 : 0; -} - -/* we should use x0, x1 and x2. -**bar: -** eor x2, x2, x0 -** orr x2, x2, x1 -** cmp x2, 0 -** cset w0, eq -** ret -*/ - -__attribute__((__noinline__)) -int -bar (unsigned __int128 y, unsigned long long x) -{ - return x == y ? 1 : 0; -} - -int fooo (unsigned long long x, unsigned __int128 y); -int baro (unsigned __int128 y, unsigned long long x); - -/* we should use x0, x1 and x2 in both calls. -**main: -** ... -** mov x1, 25 -** mov x2, 0 -** mov x0, 10 -** bl _fooo -** mov x2, 10 -** mov x0, 25 -** mov x1, 0 -** bl _baro -** ... -*/ - -int main () -{ - unsigned long long x = 10; - unsigned __int128 y = 25; - int r = fooo (x, y); - r += baro (y, x); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/float128-00.c b/gcc/testsuite/gcc.target/aarch64/darwin/float128-00.c deleted file mode 100644 index 29aec80fbaa..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/float128-00.c +++ /dev/null @@ -1,38 +0,0 @@ - -/* we need this for _Float128. */ -/* { dg-options "-std=gnu99 " } */ -/* We use the sections anchors to make the code easier to match. */ -/* { dg-additional-options " -O2 -fsection-anchors " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -/* we should just pass q0 and q1 through -**foo: -** ... -** bl ___addtf3 -** ... -*/ - -__attribute__((__noinline__)) -_Float128 -foo (_Float128 a, _Float128 b) -{ - return a + b; -} - - -/* we should just load q0 and q1 -**call_foo: -** ... -** ldr q1, \[x[0-9]+\] -** ... -** ldr q0, \[x[0-9]+\] -** b _foo -** ... -*/ - -__attribute__((__noinline__)) -_Float128 -call_foo (void) -{ - return foo (1.0, 2.0); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/float128-01.c b/gcc/testsuite/gcc.target/aarch64/darwin/float128-01.c deleted file mode 100644 index 93f6d24cebc..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/float128-01.c +++ /dev/null @@ -1,48 +0,0 @@ -/* { dg-do run } */ -/* we need this for _Float128. */ -/* { dg-options "-std=gnu99 " } */ -/* { dg-additional-options "-Wfloat-conversion" } */ - -float f1 (__float128 z1, _Float128 z2) -{ - float x, y; - x = z1; /* { dg-warning "conversion from '_Float128' to 'float'" } */ - y = z2; /* { dg-warning "conversion from '_Float128' to 'float'" } */ - return x + y; -} - -__float128 f2 () { - float f = 0.q; - return f; -} - -_Float128 f3 () { - float f = 0.q; - return f; -} - -int main () -{ - __float128 x1 = __builtin_huge_valq (); - __float128 x2 = __builtin_infq (); - - _Float128 y1 = __builtin_huge_valq (); - _Float128 y2 = __builtin_infq (); - - if (!__builtin_isinf (x1)) - __builtin_abort(); - if (!__builtin_isinf (x2)) - __builtin_abort(); - - if (!__builtin_isinf (y1)) - __builtin_abort(); - if (!__builtin_isinf (y2)) - __builtin_abort(); - - if (x1 != x2) - __builtin_abort(); - if (y1 != y2) - __builtin_abort(); - - return 0; -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/float128-02.c b/gcc/testsuite/gcc.target/aarch64/darwin/float128-02.c deleted file mode 100644 index 5a8522f9622..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/float128-02.c +++ /dev/null @@ -1,101 +0,0 @@ -/* { dg-do run } */ -/* we need this for _Float128. */ -/* { dg-options "-std=gnu99 " } */ - -void test (__float128 z1, __float128 z2, __float128 z3, __float128 z4) -{ - __float128 w; - - if (!__builtin_isinf (z1)) - __builtin_abort(); - if (__builtin_isnan (z1)) - __builtin_abort(); - if (__builtin_isfinite (z1)) - __builtin_abort(); - if (__builtin_isnormal (z1)) - __builtin_abort(); - if (__builtin_signbit (z1)) - __builtin_abort(); - - if (__builtin_isinf (z2)) - __builtin_abort(); - if (!__builtin_isnan (z2)) - __builtin_abort(); - if (__builtin_isfinite (z2)) - __builtin_abort(); - if (__builtin_isnormal (z2)) - __builtin_abort(); - if (__builtin_signbit (z2)) - __builtin_abort(); - - if (__builtin_isinf (z3)) - __builtin_abort(); - if (!__builtin_isnan (z3)) - __builtin_abort(); - if (__builtin_isfinite (z3)) - __builtin_abort(); - if (__builtin_isnormal (z3)) - __builtin_abort(); - if (__builtin_signbit (z3)) - __builtin_abort(); - - if (__builtin_isinf (z4)) - __builtin_abort(); - if (__builtin_isnan (z4)) - __builtin_abort(); - if (!__builtin_isfinite (z4)) - __builtin_abort(); - if (!__builtin_isnormal (z4)) - __builtin_abort(); - if (__builtin_signbit (z4)) - __builtin_abort(); - - w = __builtin_copysignq (z1, -z4); - if (!__builtin_signbit (w)) - __builtin_abort(); - - w = __builtin_copysignq (z2, -z4); - if (!__builtin_signbit (w)) - __builtin_abort(); - - w = __builtin_copysignq (z3, -z4); - if (!__builtin_signbit (w)) - __builtin_abort(); - - w = __builtin_copysignq (z4, -z4); - if (!__builtin_signbit (w)) - __builtin_abort(); - - w = __builtin_copysignq (z1, -z4); - w = __builtin_fabsq (w); - if (__builtin_signbit (w)) - __builtin_abort(); - - w = __builtin_copysignq (z2, -z4); - w = __builtin_fabsq (w); - if (__builtin_signbit (w)) - __builtin_abort(); - - w = __builtin_copysignq (z3, -z4); - w = __builtin_fabsq (w); - if (__builtin_signbit (w)) - __builtin_abort(); - - w = __builtin_copysignq (z4, -z4); - w = __builtin_fabsq (w); - if (__builtin_signbit (w)) - __builtin_abort(); - -} - -int main () -{ - __float128 x1 = __builtin_infq (); - __float128 x2 = __builtin_nanq (""); - __float128 x3 = __builtin_nansq (""); - __float128 x4 = 41.1094721q; - - test (x1, x2, x3, x4); - - return 0; -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/homogeneous-aggr.c b/gcc/testsuite/gcc.target/aarch64/darwin/homogeneous-aggr.c deleted file mode 100644 index bee97557a4d..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/homogeneous-aggr.c +++ /dev/null @@ -1,25 +0,0 @@ -/* { dg-do compile } */ -/* { dg-additional-options "-O " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -typedef struct sf { float a; float b; float c;} SF; - -__attribute__((__noinline__)) void -hmg_f (SF a); - -/* we should use registers for each item -**call_hmg_f: -** ... -** fmov s0, 1.0e\+0 -** fmov s1, 2.0e\+0 -** fmov s2, 3.0e\+0 -** bl _hmg_f -** ... -*/ - -void -call_hmg_f (void) -{ - SF A = { 1.0F, 2.0F, 3.0F }; - hmg_f (A); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/k+r-00.c b/gcc/testsuite/gcc.target/aarch64/darwin/k+r-00.c deleted file mode 100644 index 443fb968811..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/k+r-00.c +++ /dev/null @@ -1,28 +0,0 @@ -/* { dg-do compile } */ - -/* { dg-options "-std=gnu99 " } */ -/* { dg-additional-options "-O2 -fsection-anchors" } */ - - -/* What we care about here is that we get int loads from sp, sp+4 and sp+8. - * This code will change when we implement darwinpcs d.3 - since the - * promotions will no longer be needed (although they are harmless). -**test_k_r00: -** ldrsb w[0-9]+, \[sp, 4\] -** ldr x[0-9]+, \[sp, 8\] -** ... -** ldrsb w[0-9]+, \[sp\] -** ... -*/ - -const char * -test_k_r00 (r0, r1, r2, r3, r4, r5, r6, r7, a, b, c) - char r0, r1, r2, r3, r4, r5, r6, r7; - char a; - char b; - const char *c; -{ - if (a > 10 && b < 100) - return c; - return (char *)0; -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/tu-accesses-0.c b/gcc/testsuite/gcc.target/aarch64/darwin/tu-accesses-0.c deleted file mode 100644 index ba5cc493bc9..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/tu-accesses-0.c +++ /dev/null @@ -1,82 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O -fcommon -mno-pc-relative-literal-loads" } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -/* This checks that we perform the correct accesses for file-scope vars - including GOT indirections. */ - -double gd = 1.0; - -__attribute__((__weak__)) -double wd = 2.0; - -__attribute__((__visibility__("hidden"))) -double hd = 3.0; - -__attribute__((__weak__, __visibility__("hidden"))) -double whd = 4.0; - -extern double ed; - -double cd; - -static double sd = 5.0; - -struct { - double a; - double b; -} two_dbls = { 1.0, 42.0 }; - -double arr[3] = { 6.0, 7.0, 8.0 }; - -/* -**test: -** adrp x[0-9]+, _gd@PAGE -** ldr d[0-9]+, \[x[0-9]+, #_gd@PAGEOFF\] -** adrp x[0-9]+, lC0@PAGE -** ldr d[0-9]+, \[x[0-9]+, #lC0@PAGEOFF\] -** fadd d[0-9]+, d[0-9]+, d[0-9]+ -** adrp x[0-9]+, _wd@GOTPAGE -** ldr x[0-9]+, \[x[0-9]+, _wd@GOTPAGEOFF\] -** ldr d[0-9]+, \[x[0-9]+\] -** fadd d[0-9]+, d[0-9]+, d[0-9]+ -** adrp x[0-9]+, _hd@PAGE -** ldr d[0-9]+, \[x[0-9]+, #_hd@PAGEOFF\] -** fadd d[0-9]+, d[0-9]+, d[0-9]+ -** adrp x[0-9]+, _whd@PAGE -** ldr d[0-9]+, \[x[0-9]+, #_whd@PAGEOFF\] -** fadd d[0-9]+, d[0-9]+, d[0-9]+ -** adrp x[0-9]+, _ed@GOTPAGE -** ldr x[0-9]+, \[x[0-9]+, _ed@GOTPAGEOFF\] -** ldr d[0-9]+, \[x[0-9]+\] -** fadd d[0-9]+, d[0-9]+, d[0-9]+ -** adrp x[0-9]+, _cd@GOTPAGE -** ldr x[0-9]+, \[x[0-9]+, _cd@GOTPAGEOFF\] -** ldr d[0-9]+, \[x[0-9]+\] -** fadd d[0-9]+, d[0-9]+, d[0-9]+ -** fmov d[0-9]+, 5.0e\+0 -** fadd d[0-9]+, d[0-9]+, d[0-9]+ -** adrp x[0-9]+, _two_dbls@PAGE\+8 -** ldr d[0-9]+, \[x[0-9]+, #_two_dbls@PAGEOFF\+8\] -** fadd d[0-9]+, d[0-9]+, d[0-9]+ -** adrp x[0-9]+, _arr@PAGE\+16 -** ldr d[0-9]+, \[x[0-9]+, #_arr@PAGEOFF\+16\] -** fadd d[0-9]+, d[0-9]+, d[0-9]+ -** ret -*/ - -double test (void) -{ - double x = 123456123456123456.0; - x += gd; - x += wd; - x += hd; - x += whd; - x += ed; - x += cd; - x += sd; - x += two_dbls.b; - x += arr[2]; - - return x; -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/variadic-00.c b/gcc/testsuite/gcc.target/aarch64/darwin/variadic-00.c deleted file mode 100644 index 6420fca11d5..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/variadic-00.c +++ /dev/null @@ -1,91 +0,0 @@ -/* { dg-do compile } */ - -/* We use the sections anchors to make the code easier to match. */ -/* { dg-additional-options " -O -fsection-anchors -fno-schedule-insns -fno-schedule-insns2 " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -#include - -/* What we care about here is that the load of w0 is from the incoming [SP] -**fooi: -** sub sp, sp, #16 -** add x[0-9]+, sp, 24 -** str x[0-9]+, \[sp, 8\] -** ldr w0, \[sp, 16\] -** ... -*/ - -__attribute__((__noinline__)) int -fooi (int a, ...) -{ - int x; - va_list ap; - va_start(ap, a); - x = va_arg(ap, int); - va_end(ap); - return x; -} - -__attribute__((__noinline__)) int -fooo (char a, ...); - -/* -**call_foo: -** ... -** mov w[0-9]+, 42 -** str w[0-9]+, \[sp\] -** mov w0, 1 -** bl _fooo -** ... -*/ - -__attribute__((__noinline__)) int -call_foo (void) -{ - int y = fooo (1, 42); - return y; -} - -/* What we care about here is that the load of w0 is from the incoming [SP+8] -**bari: -** sub sp, sp, #16 -** add x[0-9]+, sp, 32 -** str x[0-9]+, \[sp, 8\] -** ldr w0, \[sp, 24\] -** ... -*/ - -__attribute__((__noinline__)) int -bari (int a, int b, int c, int d, int e, int f, int g, int h, - int i, ...) -{ - int x; - va_list ap; - va_start(ap, i); - x = va_arg(ap, int); - va_end(ap); - return x; -} - -/* -**call_bar: -** ... -** mov w[0-9]+, 42 -** str w[0-9]+, \[sp, 8\] -** mov w[0-9]+, 9 -** str w[0-9]+, \[sp\] -** ... - bl _baro -** ... -*/ - -__attribute__((__noinline__)) int -baro (int a, int b, int c, int d, int e, int f, int g, int h, - int i, ...); - -__attribute__((__noinline__)) int -call_bar (void) -{ - int y = baro (1, 2, 3, 4, 5, 6, 7, 8, 9, 42); - return y; -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/variadic-01.c b/gcc/testsuite/gcc.target/aarch64/darwin/variadic-01.c deleted file mode 100644 index 141958c998f..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/variadic-01.c +++ /dev/null @@ -1,104 +0,0 @@ -/* { dg-do compile } */ - -/* we need this for _Float128. */ -/* { dg-options "-std=gnu99 " } */ -/* We use the sections anchors to make the code easier to match. */ -/* { dg-additional-options " -O2 -fsection-anchors " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -#include - -/* What we care about here is that q0 and q1 are loaded from incoming sp and - sp+16. -**foo: -** ... -** mov x29, sp -** add (x[0-9]+), x29, 32 -** ... -** ldp q1, q0, \[\1\] -** ... -** bl ___addtf3 -** ... -*/ - -__attribute__((__noinline__)) -_Float128 -foo (int n, ...) -{ - _Float128 a, b; - va_list ap; - - va_start(ap, n); - a = va_arg(ap, _Float128); - b = va_arg(ap, _Float128); - va_end(ap); - return a + b; -} - -/* -**call_foo: -** ... -** mov w0, 2 -** stp q[0-9]+, q[0-9]+, \[sp\] -** bl _foo -** ... -*/ - -__attribute__((__noinline__)) -_Float128 -call_foo (void) -{ - return foo (2, (_Float128)1.0, (_Float128)2.0); -} - -/* What we care about here is that q0 and q1 are loaded from incoming sp and - sp+32 (with the int at sp+16). -**bar: -** ... -** ldr w[0-9]+, \[x[0-9]+, 16\] -** ... -** ldr q0, \[x[0-9]+\] -** ... -** ldr q1, \[x[0-9]+, 32\] -** bl ___addtf3 -** ... -*/ - -__attribute__((__noinline__)) -_Float128 -bar (int n, ...) -{ - _Float128 a, b; - va_list ap; - - va_start(ap, n); - a = va_arg(ap, _Float128); - n = va_arg(ap, int); - if (n != 42) - __builtin_abort (); - b = va_arg(ap, _Float128); - va_end(ap); - return a + b; -} - -/* -**call_bar: -** ... -** mov (w[0-9]+), 42 -** ... -** str \1, \[sp, 16\] -** ... -** mov w0, 2 -** str q[0-9]+, \[sp, 32\] -** str q[0-9]+, \[sp\] -** bl _bar -** ... -*/ - -__attribute__((__noinline__)) -_Float128 -call_bar (void) -{ - return bar (2, (_Float128)1.0, - 42, (_Float128)2.0); -} diff --git a/gcc/testsuite/gcc.target/aarch64/darwin/variadic-02.c b/gcc/testsuite/gcc.target/aarch64/darwin/variadic-02.c deleted file mode 100644 index dcd1de61f0a..00000000000 --- a/gcc/testsuite/gcc.target/aarch64/darwin/variadic-02.c +++ /dev/null @@ -1,104 +0,0 @@ -/* { dg-do compile } */ - -/* we need this for __int128. */ -/* { dg-options "-std=gnu99 " } */ -/* We use the sections anchors to make the code easier to match. */ -/* { dg-additional-options " -O2 -fsection-anchors " } */ -/* { dg-final { check-function-bodies "**" "" "" { target *-*-darwin* } } } */ - -#include - -/* What we care about here is that we load the values from incoming sp and - sp + 16. -**foo: -** sub sp, sp, #16 -** add (x[0-9]+), sp, 16 -** add (x[0-9]+), sp, 32 -** ... -** ldp x[0-9]+, x[0-9]+, \[\2\] -** ldp x[0-9]+, x[0-9]+, \[\1\] -** ... -*/ - -__attribute__((__noinline__)) -__int128 -foo (int n, ...) -{ - __int128 a, b; - va_list ap; - - va_start(ap, n); - a = va_arg(ap, __int128); - b = va_arg(ap, __int128); - va_end(ap); - return a + b; -} - -/* -**call_foo: -** ... -** mov w0, 2 -** stp x[0-9]+, x[0-9]+, \[sp\] -** stp x[0-9]+, x[0-9]+, \[sp, 16\] -** bl _foo -** ... -*/ - -__attribute__((__noinline__)) -__int128 -call_foo (void) -{ - return foo (2, (__int128)1, (__int128)2); -} - - -/* sp = one int128, sp+16 = int sp + 32 = other int128 -**bar: -** ... -** sub sp, sp, #16 -** add (x[0-9]+), sp, 16 -** add (x[0-9]+), sp, 48 -** ... -** ldp x[0-9]+, x[0-9]+, \[\2\] -** ldp x[0-9]+, x[0-9]+, \[\1\] -** ... -*/ - -__attribute__((__noinline__)) -__int128 -bar (int n, ...) -{ - __int128 a, b; - va_list ap; - - va_start(ap, n); - a = va_arg(ap, __int128); - n = va_arg(ap, int); - b = va_arg(ap, __int128); - va_end(ap); - return a + b; -} - -__attribute__((__noinline__)) -__int128 -baro (int n, ...); - -/* -**call_bar: -** ... -** mov w[0-9]+, 42 -** ... -** mov w0, 2 -** stp x[0-9]+, x[0-9]+, \[sp\] -** str w[0-9]+, \[sp, 16\] -** stp x[0-9]+, x[0-9]+, \[sp, 32\] -** bl _baro -** ... -*/ - -__attribute__((__noinline__)) -__int128 -call_bar (void) -{ - return baro (2, (__int128)1, 42, (__int128)2); -} diff --git a/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c b/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c index 33f01d47c42..4838f74d052 100644 --- a/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c +++ b/gcc/testsuite/gcc.target/aarch64/dbl_mov_immediate_1.c @@ -41,10 +41,8 @@ double d4(void) /* { dg-final { scan-assembler-times "movi\td\[0-9\]+, #?0" 1 } } */ -/* { dg-final { scan-assembler-times "adrp\tx\[0-9\]+, \.LC\[0-9\]" 2 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times "ldr\td\[0-9\]+, \\\[x\[0-9\], #:lo12:\.LC\[0-9\]\\\]" 2 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times "adrp\tx\[0-9\]+, lC\[0-9\]@PAGE" 2 { target *-*-darwin* } } } */ -/* { dg-final { scan-assembler-times "ldr\td\[0-9\]+, \\\[x\[0-9\], #lC\[0-9\]@PAGEOFF\\\]" 2 { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times "adrp\tx\[0-9\]+, \.LC\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "ldr\td\[0-9\]+, \\\[x\[0-9\], #:lo12:\.LC\[0-9\]\\\]" 2 } } */ /* { dg-final { scan-assembler-times "fmov\td\[0-9\]+, 1\\\.5e\\\+0" 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/dwarf-cfa-reg.c b/gcc/testsuite/gcc.target/aarch64/dwarf-cfa-reg.c index 8a691add222..ae5b3797021 100644 --- a/gcc/testsuite/gcc.target/aarch64/dwarf-cfa-reg.c +++ b/gcc/testsuite/gcc.target/aarch64/dwarf-cfa-reg.c @@ -1,6 +1,5 @@ /* Verify that CFA register is restored to SP after FP is restored. */ /* { dg-do compile } */ -/* { dg-skip-if "no cfi insn support yet" *-*-darwin* } */ /* { dg-options "-O0 -gdwarf-2" } */ /* { dg-final { scan-assembler ".cfi_restore 30" } } */ /* { dg-final { scan-assembler ".cfi_restore 29" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/extend-vec.c b/gcc/testsuite/gcc.target/aarch64/extend-vec.c new file mode 100644 index 00000000000..f62418888d5 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/extend-vec.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +/* { dg-final { scan-assembler-times {fcvtl\tv[0-9]+.2d, v[0-9]+.2s} 1 } } */ +void +f (float *__restrict a, double *__restrict b) +{ + b[0] = a[0]; + b[1] = a[1]; +} + +/* { dg-final { scan-assembler-times {fcvtl\tv[0-9]+.4s, v[0-9]+.4h} 1 } } */ +void +f1 (_Float16 *__restrict a, float *__restrict b) +{ + + b[0] = a[0]; + b[1] = a[1]; + b[2] = a[2]; + b[3] = a[3]; +} diff --git a/gcc/testsuite/gcc.target/aarch64/extend.c b/gcc/testsuite/gcc.target/aarch64/extend.c index 9556d4c2f18..f399e55ce8b 100644 --- a/gcc/testsuite/gcc.target/aarch64/extend.c +++ b/gcc/testsuite/gcc.target/aarch64/extend.c @@ -95,16 +95,14 @@ subdi_uxth (unsigned long long a, unsigned short i) unsigned long long subdi_uxth0 (unsigned long long a, unsigned short i) { - /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*uxth\n" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*uxtw" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*uxth\n" } } */ return a - i; } long long subdi_sxth (long long a, short i) { - /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*sxth #?1" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*sxtw #?1" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*sxth #?1" } } */ return a - ((long long)i << 1); } @@ -118,63 +116,55 @@ subdi_sxth0 (long long a, short i) unsigned int subsi_uxth (unsigned int a, unsigned short i) { - /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*uxth #?1" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*lsl #?1" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*uxth #?1" } } */ return a - ((unsigned int)i << 1); } unsigned int subsi_uxth0 (unsigned int a, unsigned short i) { - /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*uxth\n" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "sub\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*uxth\n" } } */ return a - i; } int subsi_sxth (int a, short i) { - /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*sxth #?1" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*lsl #?1" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*sxth #?1" } } */ return a - ((int)i << 1); } int subsi_sxth0 (int a, short i) { - /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*sxth\n" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "sub\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "sub\tw\[0-9\]+,.*sxth\n" } } */ return a - (int)i; } unsigned int addsi_uxth (unsigned int a, unsigned short i) { - /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*uxth #?1" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*lsl #?1" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*uxth #?1" } } */ return a + ((unsigned int)i << 1); } unsigned int addsi_uxth0 (unsigned int a, unsigned short i) { - /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*uxth\n" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "add\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*uxth\n" } } */ return a + i; } int addsi_sxth (int a, short i) { - /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*sxth #?1" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*lsl #?1" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*sxth #?1" } } */ return a + ((int)i << 1); } int addsi_sxth0 (int a, short i) { - /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*sxth\n" { target { ! *-*-darwin* } } } } */ - /* { dg-final { scan-assembler "add\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" { target *-*-darwin* } } } */ + /* { dg-final { scan-assembler "add\tw\[0-9\]+,.*sxth\n" } } */ return a + (int)i; } diff --git a/gcc/testsuite/gcc.target/aarch64/fmovld-zero-mem.c b/gcc/testsuite/gcc.target/aarch64/fmovld-zero-mem.c index d17a889b389..e649404ae07 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmovld-zero-mem.c +++ b/gcc/testsuite/gcc.target/aarch64/fmovld-zero-mem.c @@ -1,14 +1,8 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ -#if __APPLE__ -#define F128TYPE __float128 -#else -#define F128TYPE long double -#endif - void -foo (F128TYPE *output) +foo (long double *output) { *output = 0.0; } diff --git a/gcc/testsuite/gcc.target/aarch64/fmovld-zero-reg.c b/gcc/testsuite/gcc.target/aarch64/fmovld-zero-reg.c index f9aa405a608..ca602cb381f 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmovld-zero-reg.c +++ b/gcc/testsuite/gcc.target/aarch64/fmovld-zero-reg.c @@ -1,13 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ -#if __APPLE__ -#define F128TYPE __float128 -#else -#define F128TYPE long double -#endif - -void bar (F128TYPE); +void bar (long double); void foo (void) { diff --git a/gcc/testsuite/gcc.target/aarch64/fuse_adrp_add_1.c b/gcc/testsuite/gcc.target/aarch64/fuse_adrp_add_1.c index 1361452c661..d66fe3a4b23 100644 --- a/gcc/testsuite/gcc.target/aarch64/fuse_adrp_add_1.c +++ b/gcc/testsuite/gcc.target/aarch64/fuse_adrp_add_1.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-require-effective-target aarch64_small } */ -/* { dg-skip-if "Darwin ABI indirects externs" { *-*-darwin* } } */ /* { dg-options "-O3 -mcpu=cortex-a57 -fno-pie" } */ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS, diff --git a/gcc/testsuite/gcc.target/aarch64/inline-lrint_1.c b/gcc/testsuite/gcc.target/aarch64/inline-lrint_1.c index 9a2b2e44893..478875ff874 100644 --- a/gcc/testsuite/gcc.target/aarch64/inline-lrint_1.c +++ b/gcc/testsuite/gcc.target/aarch64/inline-lrint_1.c @@ -15,4 +15,4 @@ TEST (fllf, float , long long, l) /* { dg-final { scan-assembler-times "frintx\t\[d,s\]\[0-9\]+, \[d,s\]\[0-9\]+" 6 } } */ /* { dg-final { scan-assembler-times "fcvtzs\tx\[0-9\]+, \[d,s\]\[0-9\]+" 6 } } */ -/* { dg-final { scan-assembler-not "bl\t" } } */ +/* { dg-final { scan-assembler-not "bl" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/inline-mem-set-pr112804.c b/gcc/testsuite/gcc.target/aarch64/inline-mem-set-pr112804.c index 652c1925010..fe841455986 100644 --- a/gcc/testsuite/gcc.target/aarch64/inline-mem-set-pr112804.c +++ b/gcc/testsuite/gcc.target/aarch64/inline-mem-set-pr112804.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-finline-stringops -mabi=ilp32 -ftrivial-auto-var-init=zero" } */ -/* { dg-skip-if "-mabi=ilp32 unsupported" { aarch64-*-darwin* } } */ short m(unsigned k) { const unsigned short *n[65]; diff --git a/gcc/testsuite/gcc.target/aarch64/ins_bitfield_2.c b/gcc/testsuite/gcc.target/aarch64/ins_bitfield_2.c index cf37fb91cd5..152418889fa 100644 --- a/gcc/testsuite/gcc.target/aarch64/ins_bitfield_2.c +++ b/gcc/testsuite/gcc.target/aarch64/ins_bitfield_2.c @@ -1,6 +1,5 @@ /* { dg-do assemble } */ /* { dg-options "-O2 -mbig-endian --save-temps" } */ -/* { dg-skip-if "no BE" { *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ typedef unsigned char v16qi __attribute__((vector_size(16))); diff --git a/gcc/testsuite/gcc.target/aarch64/ins_bitfield_4.c b/gcc/testsuite/gcc.target/aarch64/ins_bitfield_4.c index ca428ea4e80..98e25c86959 100644 --- a/gcc/testsuite/gcc.target/aarch64/ins_bitfield_4.c +++ b/gcc/testsuite/gcc.target/aarch64/ins_bitfield_4.c @@ -1,6 +1,5 @@ /* { dg-do assemble } */ /* { dg-options "-O2 -mbig-endian --save-temps" } */ -/* { dg-skip-if "no BE" { *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ struct di_qi_1 { unsigned char c[4]; unsigned int x; }; diff --git a/gcc/testsuite/gcc.target/aarch64/ins_bitfield_6.c b/gcc/testsuite/gcc.target/aarch64/ins_bitfield_6.c index 21d56cba69f..cb8af6b0623 100644 --- a/gcc/testsuite/gcc.target/aarch64/ins_bitfield_6.c +++ b/gcc/testsuite/gcc.target/aarch64/ins_bitfield_6.c @@ -1,6 +1,5 @@ /* { dg-do assemble } */ /* { dg-options "-O2 -mbig-endian --save-temps" } */ -/* { dg-skip-if "no BE" { *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ struct di_qi_1 { unsigned char c[4]; unsigned int x; }; diff --git a/gcc/testsuite/gcc.target/aarch64/ldar_1.c b/gcc/testsuite/gcc.target/aarch64/ldar_1.c index 5fba03a1879..d968a72b30f 100644 --- a/gcc/testsuite/gcc.target/aarch64/ldar_1.c +++ b/gcc/testsuite/gcc.target/aarch64/ldar_1.c @@ -1,7 +1,6 @@ /* Test the LDAR instruction generation from atomic acquire loads. */ /* { dg-do assemble } */ /* { dg-additional-options "--save-temps -O1" } */ -/* { dg-additional-options "--save-temps -O2" { target *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ #include diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_13.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_13.c index 52c90a92114..9cc3942f153 100644 --- a/gcc/testsuite/gcc.target/aarch64/ldp_stp_13.c +++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_13.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-require-effective-target arm_mabi_ilp32 } */ /* { dg-options "-O2 -mabi=ilp32" } */ long long diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.c index 3cee5ba21cc..c7b5f7d6b39 100644 --- a/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.c +++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_14.c @@ -1,5 +1,4 @@ /* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */ -/* { dg-additional-options "-mtune=generic -fomit-frame-pointer" { target *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include "ldp_stp_14.h" diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_15.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_15.c index f265b7a5170..131cd0a63c8 100644 --- a/gcc/testsuite/gcc.target/aarch64/ldp_stp_15.c +++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_15.c @@ -1,5 +1,4 @@ /* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */ -/* { dg-additional-options "-mtune=generic -fomit-frame-pointer" { target *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include "ldp_stp_14.h" diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c index 252d756d50b..95835aa2eb4 100644 --- a/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c +++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_16.c @@ -1,5 +1,4 @@ /* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */ -/* { dg-additional-options "-mtune=generic -fomit-frame-pointer" { target *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include "ldp_stp_14.h" diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_18.c b/gcc/testsuite/gcc.target/aarch64/ldp_stp_18.c index 8b602033691..eaa855c3859 100644 --- a/gcc/testsuite/gcc.target/aarch64/ldp_stp_18.c +++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_18.c @@ -1,5 +1,4 @@ /* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */ -/* { dg-additional-options "-mtune=generic -fomit-frame-pointer" { target *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */ #include "ldp_stp_14.h" diff --git a/gcc/testsuite/gcc.target/aarch64/lse128-flag.c b/gcc/testsuite/gcc.target/aarch64/lse128-flag.c index 2fbf3e84e0a..71339c3af6d 100644 --- a/gcc/testsuite/gcc.target/aarch64/lse128-flag.c +++ b/gcc/testsuite/gcc.target/aarch64/lse128-flag.c @@ -6,6 +6,5 @@ int main() return 0; } -/* { dg-final { scan-assembler {\.arch armv9\.4-a\+crc\+lse128} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv9\.4-a\+lse128} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv9\.4-a\+crc\+lse128} } } */ /* Test a normal looking procinfo. */ diff --git a/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c index dec73f98506..9ee96f33255 100644 --- a/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c +++ b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases-2.c @@ -7,7 +7,7 @@ /* 127 bytes should use libcall for size. **set127byte: ** mov x2, 127 -** b _?memset +** b memset */ void __attribute__((__noinline__)) set127byte (int64_t *src, int c) @@ -18,7 +18,7 @@ set127byte (int64_t *src, int c) /* 128 bytes should use libcall for size. **set128byte: ** mov x2, 128 -** b _?memset +** b memset */ void __attribute__((__noinline__)) set128byte (int64_t *src, int c) diff --git a/gcc/testsuite/gcc.target/aarch64/memset-corner-cases.c b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases.c index 2d9c95a0d86..d4c752711f8 100644 --- a/gcc/testsuite/gcc.target/aarch64/memset-corner-cases.c +++ b/gcc/testsuite/gcc.target/aarch64/memset-corner-cases.c @@ -77,7 +77,7 @@ set256byte (int64_t *src, char c) **set257byte: ** mov x2, 257 ** mov w1, 99 -** b _?memset +** b memset */ void __attribute__((__noinline__)) set257byte (int64_t *src) diff --git a/gcc/testsuite/gcc.target/aarch64/mops_4.c b/gcc/testsuite/gcc.target/aarch64/mops_4.c index 49b5c39667c..dd796115cb4 100644 --- a/gcc/testsuite/gcc.target/aarch64/mops_4.c +++ b/gcc/testsuite/gcc.target/aarch64/mops_4.c @@ -124,9 +124,9 @@ set1 (char *x, char y, long z, char **res) ** ret */ void -set2 (unsigned char *x, unsigned char *yptr, long z, unsigned char *res) +set2 (char *x, char *yptr, long z, char *res) { - unsigned char y = *yptr; + char y = *yptr; __builtin_memset (x, y, z); *res = y; } diff --git a/gcc/testsuite/gcc.target/aarch64/movhi_1.c b/gcc/testsuite/gcc.target/aarch64/movhi_1.c index 145b9bae1b1..8017abc5f19 100644 --- a/gcc/testsuite/gcc.target/aarch64/movhi_1.c +++ b/gcc/testsuite/gcc.target/aarch64/movhi_1.c @@ -49,7 +49,7 @@ zero_to_fpr () /* ** fpr_to_gpr: -** (fmov w0, s0|umov w0, v0.h\[0\]) +** fmov w0, s0 ** ret */ uint16_t diff --git a/gcc/testsuite/gcc.target/aarch64/movqi_1.c b/gcc/testsuite/gcc.target/aarch64/movqi_1.c index c1d93d55b36..401a79630f4 100644 --- a/gcc/testsuite/gcc.target/aarch64/movqi_1.c +++ b/gcc/testsuite/gcc.target/aarch64/movqi_1.c @@ -49,7 +49,7 @@ zero_to_fpr () /* ** fpr_to_gpr: -** (fmov w0, s0|umov w0, v0.b\[0\]) +** fmov w0, s0 ** ret */ uint8_t diff --git a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c index 7f504ad687f..d5e9200562c 100644 --- a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c +++ b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c @@ -14,6 +14,6 @@ TEST (dlld, double, long long, l) TEST (fllf, float , long long, l) /* { dg-final { scan-assembler-times "frintx\t\[d,s\]\[0-9\]+, \[d,s\]\[0-9\]+" 6 } } */ -/* { dg-final { scan-assembler-times "bl\t_*lrint" 4 } } */ -/* { dg-final { scan-assembler-times "bl\t_*llrint" 2 } } */ +/* { dg-final { scan-assembler-times "bl\tlrint" 4 } } */ +/* { dg-final { scan-assembler-times "bl\tllrint" 2 } } */ /* { dg-final { scan-assembler-not "fcvtzs" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_1.c b/gcc/testsuite/gcc.target/aarch64/options_set_1.c index ed2aa86e469..dc5eff8c901 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_1.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_1.c @@ -6,7 +6,6 @@ int main () return 0; } -/* Darwin's assembler does not need this fix, and we need to omit it. */ -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc} 1 { xfail *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\n} 1 } } */ /* Check to see if crc is output by default. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_11.c b/gcc/testsuite/gcc.target/aarch64/options_set_11.c index 2c7473a25f7..e0e82cf514d 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_11.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_11.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.2-a} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\n} } } */ /* FP is default on, no need to pass on to assembler. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_12.c b/gcc/testsuite/gcc.target/aarch64/options_set_12.c index e18053589fb..aef44b33113 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_12.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_12.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+fp16} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16\n} } } */ /* fp16 not default, should be emitted. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_13.c b/gcc/testsuite/gcc.target/aarch64/options_set_13.c index 23b32428ba9..b116e08e75b 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_13.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_13.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+fp16} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16\n} } } */ /* FP is part of FP16, don't emit it. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_14.c b/gcc/testsuite/gcc.target/aarch64/options_set_14.c index 530d05b0b27..e9fc3e5dc2c 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_14.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_14.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16fml\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+fp16fml} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16fml\n} } } */ /* fmp16fml is smallest option to emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_15.c b/gcc/testsuite/gcc.target/aarch64/options_set_15.c index 94e076200ca..999791b9f0d 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_15.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_15.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16fml*\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+fp16fml*} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16fml*\n} } } */ /* fp included in fp16fml, only emit latter. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_16.c b/gcc/testsuite/gcc.target/aarch64/options_set_16.c index 72a31f6da76..477b71c3817 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_16.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_16.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16fml\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+fp16fml} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.2-a\+crc\+fp16fml\n} } } */ /* fp16fml is smallest options to emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_17.c b/gcc/testsuite/gcc.target/aarch64/options_set_17.c index b8900e0d101..b1603fbcf2a 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_17.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_17.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+dotprod\+crc\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.2-a\+dotprod} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.2-a\+dotprod\+crc\n} } } */ /* dotprod needs to be emitted pre armv8.4. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_18.c b/gcc/testsuite/gcc.target/aarch64/options_set_18.c index 28c74ed40ab..977b41e3e21 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_18.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_18.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-not {\+dotprod} } } */ +/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\n} } } */ /* dotprod is default in armv8.4-a, don't emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_19.c b/gcc/testsuite/gcc.target/aarch64/options_set_19.c index d27e7cb0352..0b2ec02e5c6 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_19.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_19.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-not {\+fp} } } */ +/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\n} } } */ /* fp default, don't emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_2.c b/gcc/testsuite/gcc.target/aarch64/options_set_2.c index 117979aaf39..937edc693c2 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_2.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_2.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto\n} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto} 1 { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto\n} 1 } } */ /* Check to see if crc and crypto are maintained if crypto specified. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_20.c b/gcc/testsuite/gcc.target/aarch64/options_set_20.c index 52688e269fc..452b48c7291 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_20.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_20.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+fp16} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} } } */ /* fp16 smallest set to emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_21.c b/gcc/testsuite/gcc.target/aarch64/options_set_21.c index 1e2fbf0742e..f142e70fb51 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_21.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_21.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+fp16} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} } } */ /* fp16 smallest set to emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_22.c b/gcc/testsuite/gcc.target/aarch64/options_set_22.c index 61ce788eb58..04ddd461857 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_22.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_22.c @@ -6,8 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+fp16} { target *-*-darwin* } } } */ -/* { dg-final { scan-assembler-not {\+fp16fml} } } */ +/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} } } */ /* fp16 smallest set to emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_23.c b/gcc/testsuite/gcc.target/aarch64/options_set_23.c index e6cb3bb4e63..81cfe0189e0 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_23.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_23.c @@ -6,8 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+fp16} { target *-*-darwin* } } } */ -/* { dg-final { scan-assembler-not {\+fp16fml} } } */ +/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} } } */ /* fp16 smallest set to emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_24.c b/gcc/testsuite/gcc.target/aarch64/options_set_24.c index 395444837a9..425cc513eee 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_24.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_24.c @@ -6,8 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+fp16} { target *-*-darwin* } } } */ -/* { dg-final { scan-assembler-not {\+fp16fml} } } */ +/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} } } */ /* fp16 smallest set to emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_25.c b/gcc/testsuite/gcc.target/aarch64/options_set_25.c index 9a2b1df720c..5a3c1059301 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_25.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_25.c @@ -6,8 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+fp16} { target *-*-darwin* } } } */ -/* { dg-final { scan-assembler-not {\+fp16fml} } } */ +/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} } } */ /* fp16 smallest set to emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_26.c b/gcc/testsuite/gcc.target/aarch64/options_set_26.c index 52688e269fc..452b48c7291 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_26.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_26.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler {\.arch armv8\.4-a\+fp16} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler {\.arch armv8\.4-a\+crc\+fp16\n} } } */ /* fp16 smallest set to emit. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_27.c b/gcc/testsuite/gcc.target/aarch64/options_set_27.c index 4fa94d224b8..e3574464013 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_27.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_27.c @@ -6,5 +6,4 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes\+sha3\n} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+aes\+sha3\n} 1 { target *-*-darwin* } } } */ \ No newline at end of file +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes\+sha3\n} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_28.c b/gcc/testsuite/gcc.target/aarch64/options_set_28.c index a00e8493997..d5b15f8bc58 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_28.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_28.c @@ -6,5 +6,4 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv9\.3\-a\+crc\+nopredres\+nomops\n} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\.arch armv9\.3\-a\+nopredres\+nomops\n} 1 { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times {\.arch armv9\.3\-a\+crc\+nopredres\+nomops\n} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_3.c b/gcc/testsuite/gcc.target/aarch64/options_set_3.c index ebe5a47e9d0..96140e36270 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_3.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_3.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto\n} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto} 1 { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto\n} 1 } } */ /* Check if smallest set is maintained when outputting. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_4.c b/gcc/testsuite/gcc.target/aarch64/options_set_4.c index fb2594e0ca9..7b00d09a47f 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_4.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_4.c @@ -6,8 +6,7 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto\n} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto} 1 { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto\n} 1 } } */ /* Check if individual bits that make up a grouping is specified that only the grouping is kept. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_5.c b/gcc/testsuite/gcc.target/aarch64/options_set_5.c index 81452696d67..028fbc46ef6 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_5.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_5.c @@ -6,8 +6,7 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes\n} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+aes} 1 { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes\n} 1 } } */ /* Check if turning off feature bits works correctly and grouping is no longer valid. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_6.c b/gcc/testsuite/gcc.target/aarch64/options_set_6.c index 1abe5d3fb56..09ebdaa212b 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_6.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_6.c @@ -6,7 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes\n} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+aes} 1 { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes\n} 1 } } */ /* +crypto turns on +aes and +sha2, but +nosha2 disables +crypto. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_7.c b/gcc/testsuite/gcc.target/aarch64/options_set_7.c index 6cf65a2e0aa..eb5724f74e0 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_7.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_7.c @@ -6,8 +6,6 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a\+crc\n} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a} 1 { target *-*-darwin* } } } */ -/* { dg-final { scan-assembler-not {\+dotprod} } } */ +/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a\+crc\n} 1 } } */ /* Checking if enabling default features drops the superfluous bits. */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_8.c b/gcc/testsuite/gcc.target/aarch64/options_set_8.c index eb9d5c61fe6..a0eacff9ce6 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_8.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_8.c @@ -6,9 +6,7 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a\+crc\+nodotprod\n} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a} 1 { target *-*-darwin* } } } */ -/* { dg-final { scan-assembler-not {\+dotprod} } } */ +/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a\+crc\+nodotprod\n} 1 } } */ /* Checking if trying to turn off default features propagates the commandline option. */ diff --git a/gcc/testsuite/gcc.target/aarch64/pcs_attribute-2.c b/gcc/testsuite/gcc.target/aarch64/pcs_attribute-2.c index 9eff866e0c8..e85465f25fb 100644 --- a/gcc/testsuite/gcc.target/aarch64/pcs_attribute-2.c +++ b/gcc/testsuite/gcc.target/aarch64/pcs_attribute-2.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Not applicable to darwinpcs" { *-*-darwin* } } */ /* { dg-require-effective-target aarch64_variant_pcs } */ /* Test that .variant_pcs is emitted for vector PCS symbol references. */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr100518.c b/gcc/testsuite/gcc.target/aarch64/pr100518.c index 4e7d6bc7d90..5ca599f5d2e 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr100518.c +++ b/gcc/testsuite/gcc.target/aarch64/pr100518.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-require-effective-target arm_mabi_ilp32 } */ /* { dg-options "-mabi=ilp32 -mstrict-align -O2" } */ int unsigned_range_min, unsigned_range_max, a11___trans_tmp_1; diff --git a/gcc/testsuite/gcc.target/aarch64/pr103147-10.c b/gcc/testsuite/gcc.target/aarch64/pr103147-10.c index 00b74191c9c..8ae44a7222d 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr103147-10.c +++ b/gcc/testsuite/gcc.target/aarch64/pr103147-10.c @@ -11,7 +11,7 @@ ** ( ** strb .* ** | -** bl _?memcpy +** bl memcpy ** ) ** ... */ @@ -29,7 +29,7 @@ ld2 (int32x4x2_t *a, int32_t *b) ** ( ** strb .* ** | -** bl _?memcpy +** bl memcpy ** ) ** ... */ @@ -47,7 +47,7 @@ ld3 (int32x4x3_t *a, int32_t *b) ** ( ** strb .* ** | -** bl _?memcpy +** bl memcpy ** ) ** ... */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr104689.c b/gcc/testsuite/gcc.target/aarch64/pr104689.c index de6d8f82a90..3b7adbdfe7d 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr104689.c +++ b/gcc/testsuite/gcc.target/aarch64/pr104689.c @@ -2,7 +2,6 @@ /* { dg-do run } */ /* { dg-require-effective-target lp64 } */ /* { dg-options "-fexceptions -O2" } */ -/* { dg-skip-if "asm incompatible with mach-o" { *-*-darwin* } } */ #include #include diff --git a/gcc/testsuite/gcc.target/aarch64/pr109072_1.c b/gcc/testsuite/gcc.target/aarch64/pr109072_1.c index 9b23d4b4143..0fc195a598f 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr109072_1.c +++ b/gcc/testsuite/gcc.target/aarch64/pr109072_1.c @@ -239,7 +239,7 @@ void consume (float32x4_t, float32x4_t, float32x4_t, float32x4_t); ** dup v1\.4s, v1\.s\[0\] ** dup v0\.4s, v0\.s\[0\] ** ) -** b _?consume +** b consume */ void produce_1 (float32_t a, float32_t b, float32_t c, float32_t d) @@ -267,7 +267,7 @@ produce_1 (float32_t a, float32_t b, float32_t c, float32_t d) ** dup v1\.4s, v1\.s\[0\] ** dup v0\.4s, v0\.s\[0\] ** ) -** b _?consume +** b consume */ void produce_2 (float32_t a, float32_t b, float32_t c, float32_t d) diff --git a/gcc/testsuite/gcc.target/aarch64/pr109661-1.c b/gcc/testsuite/gcc.target/aarch64/pr109661-1.c index f40fd5c77a6..5686b2b1cb5 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr109661-1.c +++ b/gcc/testsuite/gcc.target/aarch64/pr109661-1.c @@ -1,5 +1,4 @@ /* { dg-options "-O2 -Wpsabi" } */ -/* { dg-skip-if "Darwin ABI is different, test separately" { *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" "" } } */ enum __attribute__((aligned(16))) e { E }; diff --git a/gcc/testsuite/gcc.target/aarch64/pr113114.c b/gcc/testsuite/gcc.target/aarch64/pr113114.c index a2bd6beaff7..5b0383c2435 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr113114.c +++ b/gcc/testsuite/gcc.target/aarch64/pr113114.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-mabi=ilp32 -O -mearly-ldp-fusion -mlate-ldp-fusion" } */ -/* { dg-skip-if "-mabi=ilp32 unsupported" { aarch64-*-darwin* } } */ void foo_n(double *a) { int i = 1; for (; i < (int)foo_n; i++) diff --git a/gcc/testsuite/gcc.target/aarch64/pr62308.c b/gcc/testsuite/gcc.target/aarch64/pr62308.c index 4c1a733e84d..1cf6e212dca 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr62308.c +++ b/gcc/testsuite/gcc.target/aarch64/pr62308.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin platforms do not support big-endian arm64" *-*-darwin* } */ /* { dg-options "-mbig-endian" } */ typedef int __attribute__((vector_size(16))) v4si; diff --git a/gcc/testsuite/gcc.target/aarch64/pr63304_1.c b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c index 5077206d7d9..5d519d817cc 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr63304_1.c +++ b/gcc/testsuite/gcc.target/aarch64/pr63304_1.c @@ -1,8 +1,6 @@ /* { dg-do assemble } */ /* { dg-require-effective-target lp64 } */ /* { dg-options "-O1 --save-temps -fno-pie" } */ -/* { dg-xfail-if "issue #100" { *-*-darwin* } } */ - #pragma GCC push_options #pragma GCC target ("+nothing+simd,cmodel=small") @@ -47,4 +45,4 @@ cal3 (double a) return 1; } -/* { dg-final { scan-assembler-times "adrp" 6 { xfail *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times "adrp" 6 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr70120-2.c b/gcc/testsuite/gcc.target/aarch64/pr70120-2.c index a9671004825..8f5cdc93fe3 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr70120-2.c +++ b/gcc/testsuite/gcc.target/aarch64/pr70120-2.c @@ -1,7 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target lp64 } */ /* { dg-options "-Og -freorder-functions -g3 -mcmodel=large -fno-pie" } */ -/* { dg-xfail-if "issue #100" { *-*-darwin* } } */ typedef short v32u16 __attribute__ ((vector_size (32))); typedef int v32u32 __attribute__ ((vector_size (32))); diff --git a/gcc/testsuite/gcc.target/aarch64/pr78255.c b/gcc/testsuite/gcc.target/aarch64/pr78255.c index fc5d859ee68..b078cf3e1c1 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr78255.c +++ b/gcc/testsuite/gcc.target/aarch64/pr78255.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin platforms do not support tiny" *-*-darwin* } */ /* { dg-options "-O2 -mcmodel=tiny" } */ extern int bar (void *); diff --git a/gcc/testsuite/gcc.target/aarch64/pr78561.c b/gcc/testsuite/gcc.target/aarch64/pr78561.c index 635214edde1..048d2d7969f 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr78561.c +++ b/gcc/testsuite/gcc.target/aarch64/pr78561.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin platforms do not support tiny" *-*-darwin* } */ /* { dg-options "-Og -O3 -mcmodel=tiny" } */ int diff --git a/gcc/testsuite/gcc.target/aarch64/pr78733.c b/gcc/testsuite/gcc.target/aarch64/pr78733.c index da31d0ff153..8556ef3f371 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr78733.c +++ b/gcc/testsuite/gcc.target/aarch64/pr78733.c @@ -2,7 +2,6 @@ /* { dg-options "-O2 -mcmodel=large -mpc-relative-literal-loads -fno-pie" } */ /* { dg-require-effective-target lp64 } */ /* { dg-skip-if "-mcmodel=large, no support for -fpic" { aarch64-*-* } { "-fpic" } { "" } } */ -/* { dg-xfail-if "issue #100" { *-*-darwin* } } */ __int128 t (void) @@ -10,5 +9,5 @@ t (void) return ((__int128)0x123456789abcdef << 64) | 0xfedcba987654321; } -/* { dg-final { scan-assembler "adr" { xfail { *-*-darwin* } } } } */ +/* { dg-final { scan-assembler "adr" } } */ /* { dg-final { scan-assembler-not "adrp" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr79041-2.c b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c index da31d0ff153..8556ef3f371 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr79041-2.c +++ b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c @@ -2,7 +2,6 @@ /* { dg-options "-O2 -mcmodel=large -mpc-relative-literal-loads -fno-pie" } */ /* { dg-require-effective-target lp64 } */ /* { dg-skip-if "-mcmodel=large, no support for -fpic" { aarch64-*-* } { "-fpic" } { "" } } */ -/* { dg-xfail-if "issue #100" { *-*-darwin* } } */ __int128 t (void) @@ -10,5 +9,5 @@ t (void) return ((__int128)0x123456789abcdef << 64) | 0xfedcba987654321; } -/* { dg-final { scan-assembler "adr" { xfail { *-*-darwin* } } } } */ +/* { dg-final { scan-assembler "adr" } } */ /* { dg-final { scan-assembler-not "adrp" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr80295.c b/gcc/testsuite/gcc.target/aarch64/pr80295.c index 7a7f127b65f..b3866d8d6a9 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr80295.c +++ b/gcc/testsuite/gcc.target/aarch64/pr80295.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-require-effective-target arm_mabi_ilp32 } */ /* { dg-options "-mabi=ilp32" } */ void f (void *b) diff --git a/gcc/testsuite/gcc.target/aarch64/pr84882.c b/gcc/testsuite/gcc.target/aarch64/pr84882.c index e99d1048142..89b5d1a5805 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr84882.c +++ b/gcc/testsuite/gcc.target/aarch64/pr84882.c @@ -1,7 +1,6 @@ /* This is a copy of pr71727.c with scanning reversed. */ /* { dg-do compile } */ /* { dg-options "-mstrict-align -O3 -mno-strict-align" } */ -/* { dg-additional-options "-mtune=generic -fomit-frame-pointer" { target *-*-darwin* } } */ struct test_struct_s { diff --git a/gcc/testsuite/gcc.target/aarch64/pr87305.c b/gcc/testsuite/gcc.target/aarch64/pr87305.c index 6c47d6cc0e2..7a3e41820d6 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr87305.c +++ b/gcc/testsuite/gcc.target/aarch64/pr87305.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "Darwin platforms do not support big-endian arm64" *-*-darwin* } */ /* { dg-options "-fpermissive -Ofast -mbig-endian -w" } */ int cc; diff --git a/gcc/testsuite/gcc.target/aarch64/pr92424-1.c b/gcc/testsuite/gcc.target/aarch64/pr92424-1.c index 59f7435dc83..c413a2c306e 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr92424-1.c +++ b/gcc/testsuite/gcc.target/aarch64/pr92424-1.c @@ -1,7 +1,6 @@ /* { dg-do "compile" } */ /* { dg-options "-O1" } */ /* { dg-final { check-function-bodies "**" "" } } */ -/* { dg-skip-if "unimplemented patchable function entry" *-*-darwin* } */ /* Note: this test only checks the instructions in the function bodies, not the placement of the patch label or nops before the futncion. */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr92424-2.c b/gcc/testsuite/gcc.target/aarch64/pr92424-2.c index ce59d3eb5e4..0a79901108c 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr92424-2.c +++ b/gcc/testsuite/gcc.target/aarch64/pr92424-2.c @@ -1,6 +1,5 @@ /* { dg-do "compile" } */ /* { dg-options "-O1" } */ -/* { dg-skip-if "unimplemented patchable function entry" *-*-darwin* } */ /* Test the placement of the .LPFE0 label. */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr92424-3.c b/gcc/testsuite/gcc.target/aarch64/pr92424-3.c index 2ef99991ce3..854bb7f9fec 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr92424-3.c +++ b/gcc/testsuite/gcc.target/aarch64/pr92424-3.c @@ -1,6 +1,5 @@ /* { dg-do "compile" } */ /* { dg-options "-O1" } */ -/* { dg-skip-if "unimplemented patchable function entry" *-*-darwin* } */ /* Test the placement of the .LPFE0 label. */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr94201.c b/gcc/testsuite/gcc.target/aarch64/pr94201.c index ea1ac6b729f..3b9b79059e0 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr94201.c +++ b/gcc/testsuite/gcc.target/aarch64/pr94201.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-require-effective-target arm_mabi_ilp32 } */ /* { dg-options "-mcmodel=tiny -mabi=ilp32 -fPIC" } */ /* { dg-require-effective-target fpic } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr94530.c b/gcc/testsuite/gcc.target/aarch64/pr94530.c index e273b03576b..5dfdbe3311d 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr94530.c +++ b/gcc/testsuite/gcc.target/aarch64/pr94530.c @@ -1,7 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target lp64 } */ /* { dg-options "-Os -mcpu=falkor -mpc-relative-literal-loads -mcmodel=large -fno-pie" } */ -/* { dg-xfail-if "issue #100" { *-*-darwin* } } */ extern void bar(const char *); diff --git a/gcc/testsuite/gcc.target/aarch64/pr94577.c b/gcc/testsuite/gcc.target/aarch64/pr94577.c index afe18d42381..d51799fb0bb 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr94577.c +++ b/gcc/testsuite/gcc.target/aarch64/pr94577.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-require-effective-target arm_mabi_ilp32 } */ /* { dg-options "-mcmodel=large -mabi=ilp32 -fno-pie" } */ void diff --git a/gcc/testsuite/gcc.target/aarch64/pr97535.c b/gcc/testsuite/gcc.target/aarch64/pr97535.c index 6f1ee8035eb..7d4db485f1f 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr97535.c +++ b/gcc/testsuite/gcc.target/aarch64/pr97535.c @@ -13,4 +13,4 @@ void setRaw(const void *raw) /* At any optimization level this should be a function call and not inlined. */ -/* { dg-final { scan-assembler "bl\t_*memcpy" } } */ +/* { dg-final { scan-assembler "bl\tmemcpy" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr98776.c b/gcc/testsuite/gcc.target/aarch64/pr98776.c index 89a68717db6..b075b8f75ef 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr98776.c +++ b/gcc/testsuite/gcc.target/aarch64/pr98776.c @@ -1,6 +1,5 @@ /* { dg-do "compile" } */ /* { dg-options "-O1 -fpatchable-function-entry=1 -fasynchronous-unwind-tables" } */ -/* { dg-skip-if "unimplemented patchable function entry" *-*-darwin* } */ /* Test the placement of the .LPFE0 label. */ diff --git a/gcc/testsuite/gcc.target/aarch64/reg-alloc-4.c b/gcc/testsuite/gcc.target/aarch64/reg-alloc-4.c index 32c19597e11..ceb6f50de2d 100644 --- a/gcc/testsuite/gcc.target/aarch64/reg-alloc-4.c +++ b/gcc/testsuite/gcc.target/aarch64/reg-alloc-4.c @@ -22,7 +22,7 @@ struct L ** ldr (x[0-9]+), \[\2, #?16\] ** str \3, \[\2\] ** ldr \2, \[\2, #?8\] -** cbn?z \4, .?L[0-9]+ +** cbn?z \4, .* ** ... ** ret */ diff --git a/gcc/testsuite/gcc.target/aarch64/reload-valid-spoff.c b/gcc/testsuite/gcc.target/aarch64/reload-valid-spoff.c index 0859f0741bb..37e00ac9aa1 100644 --- a/gcc/testsuite/gcc.target/aarch64/reload-valid-spoff.c +++ b/gcc/testsuite/gcc.target/aarch64/reload-valid-spoff.c @@ -2,7 +2,6 @@ /* { dg-require-effective-target lp64 } */ /* { dg-options "-O2 -mcmodel=large -fno-builtin -fno-pie" } */ /* { dg-skip-if "-mcmodel=large -fPIC not currently supported" { aarch64-*-* } { "-fPIC" } { "" } } */ -/* { dg-skip-if "-mcmodel=large current unsupported" { aarch64-*-darwin* } } */ typedef long unsigned int size_t; typedef unsigned short int sa_family_t; diff --git a/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-2.c b/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-2.c index 193c65717ed..8eec6824f37 100644 --- a/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-2.c +++ b/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-2.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-Ofast" } */ -/* { dg-skip-if "no system variant_pcs support" *-*-darwin* } */ __attribute__ ((__simd__ ("notinbranch"))) __attribute__ ((__nothrow__ , __leaf__ , __const__)) @@ -13,5 +12,5 @@ void bar(double * f, int n) f[i] = foo(f[i]); } -/* { dg-final { scan-assembler-not {\.variant_pcs\t_?foo} } } */ -/* { dg-final { scan-assembler-times {\.variant_pcs\t_?_ZGVnN2v_foo} 1 } } */ +/* { dg-final { scan-assembler-not {\.variant_pcs\tfoo} } } */ +/* { dg-final { scan-assembler-times {\.variant_pcs\t_ZGVnN2v_foo} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-3.c b/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-3.c index 8d81105de02..c6dac6b104c 100644 --- a/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-3.c +++ b/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute-3.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-Ofast" } */ -/* { dg-skip-if "no system variant_pcs support" *-*-darwin* } */ __attribute__ ((__simd__)) __attribute__ ((__nothrow__ , __leaf__ , __const__)) diff --git a/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute.c b/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute.c index 62ee482a892..eddcef3597c 100644 --- a/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute.c +++ b/gcc/testsuite/gcc.target/aarch64/simd_pcs_attribute.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-Ofast" } */ -/* { dg-skip-if "no system variant_pcs support" *-*-darwin* } */ __attribute__ ((__simd__ ("notinbranch"))) __attribute__ ((__nothrow__ , __leaf__ , __const__)) @@ -13,5 +12,5 @@ void foo(double *f, int n) f[i] = log(f[i]); } -/* { dg-final { scan-assembler-not {\.variant_pcs\t_?log} } } */ -/* { dg-final { scan-assembler-times {\.variant_pcs\t_?_ZGVnN2v_log} 1 } } */ +/* { dg-final { scan-assembler-not {\.variant_pcs\tlog} } } */ +/* { dg-final { scan-assembler-times {\.variant_pcs\t_ZGVnN2v_log} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp index c4982183128..4b2fb4f24ba 100644 --- a/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp +++ b/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp @@ -24,11 +24,6 @@ if {![istarget aarch64*-*-*] } { return } -# Exit immediately if this is Darwin (for now). -if {[istarget *-*-darwin*] } { - return -} - # Load support procs. load_lib gcc-dg.exp diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/aarch64-sme2-acle-asm.exp b/gcc/testsuite/gcc.target/aarch64/sme2/aarch64-sme2-acle-asm.exp index e935b8567f7..2ef3966c6d8 100644 --- a/gcc/testsuite/gcc.target/aarch64/sme2/aarch64-sme2-acle-asm.exp +++ b/gcc/testsuite/gcc.target/aarch64/sme2/aarch64-sme2-acle-asm.exp @@ -24,11 +24,6 @@ if {![istarget aarch64*-*-*] } { return } -# Darwin's assembler support for sme2 appears incomplete. -if { [istarget *-*-darwin*] && ![info exists env(DARWIN_TEST_SME2)]} then { - return -} - # Load support procs. load_lib gcc-dg.exp diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-1.c b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-1.c index 8c71ab2ec0d..412a9ed1aab 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-1.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-1.c @@ -1,7 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16 -funwind-tables -fno-stack-protector" } */ /* { dg-require-effective-target supports_stack_clash_protection } */ -/* { dg-skip-if "no cfi insn support yet" *-*-darwin* } */ #define SIZE 128*1024 #include "stack-check-prologue.h" diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-2.c b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-2.c index 24cf904f489..e440569a078 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-2.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-2.c @@ -1,7 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-guard-size=16 -funwind-tables -fno-stack-protector" } */ /* { dg-require-effective-target supports_stack_clash_protection } */ -/* { dg-skip-if "no cfi insn support yet" *-*-darwin* } */ #define SIZE 1280*1024 + 512 #include "stack-check-prologue.h" diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-3.c b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-3.c index ccaf2e6f8cf..c4b7bb601c4 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-3.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-cfa-3.c @@ -1,7 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O3 -fopenmp-simd -march=armv8-a+sve -fstack-clash-protection --param stack-clash-protection-guard-size=16 -funwind-tables" } */ /* { dg-require-effective-target supports_stack_clash_protection } */ -/* { dg-skip-if "no cfi insn support yet" *-*-darwin* } */ #include "stack-check-prologue-16.c" diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c index 936d94ea447..1cf6fbbb085 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-17.c @@ -1,4 +1,3 @@ -/* { dg-skip-if "incompatible stack layout" { *-*-darwin* } } */ /* { dg-options "-O2 -fstack-clash-protection -fomit-frame-pointer --param stack-clash-protection-guard-size=12 -fno-stack-protector" } */ /* { dg-final { check-function-bodies "**" "" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c index 2791f3725e9..2e06346c158 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-18.c @@ -1,4 +1,3 @@ -/* { dg-skip-if "incompatible stack layout" { *-*-darwin* } } */ /* { dg-options "-O2 -fstack-clash-protection -fomit-frame-pointer --param stack-clash-protection-guard-size=12 -fno-stack-protector" } */ /* { dg-final { check-function-bodies "**" "" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c index bd7af360546..38eab4d36ab 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-check-prologue-19.c @@ -1,4 +1,3 @@ -/* { dg-skip-if "incompatible stack layout" { *-*-darwin* } } */ /* { dg-options "-O2 -fstack-clash-protection -fomit-frame-pointer --param stack-clash-protection-guard-size=12 -fsanitize=shadow-call-stack -ffixed-x18 -fno-stack-protector" } */ /* { dg-final { check-function-bodies "**" "" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-protector-1.c b/gcc/testsuite/gcc.target/aarch64/stack-protector-1.c index e3232b2cc97..73e83bc413f 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-protector-1.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-protector-1.c @@ -1,5 +1,4 @@ /* { dg-do run } */ -/* { dg-skip-if "incompatible asm" { *-*-darwin* } } */ /* { dg-require-effective-target fstack_protector } */ /* { dg-options "-fstack-protector-all -O2" } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-protector-2.c b/gcc/testsuite/gcc.target/aarch64/stack-protector-2.c index 48f044d03b4..266c36fdbc6 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-protector-2.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-protector-2.c @@ -1,5 +1,4 @@ /* { dg-do run } */ -/* { dg-skip-if "incompatible asm" { *-*-darwin* } } */ /* { dg-require-effective-target fstack_protector } */ /* { dg-require-effective-target fpic } */ /* { dg-options "-fstack-protector-all -O2 -fpic" } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-protector-3.c b/gcc/testsuite/gcc.target/aarch64/stack-protector-3.c index 3700e30c094..909e26c4c0a 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-protector-3.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-protector-3.c @@ -1,5 +1,4 @@ /* { dg-do run } */ -/* { dg-skip-if "incompatible asm" { *-*-darwin* } } */ /* { dg-require-effective-target fstack_protector } */ /* { dg-options "-fstack-protector-all -O2" } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-protector-4.c b/gcc/testsuite/gcc.target/aarch64/stack-protector-4.c index fa8a011815f..6334dd00908 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-protector-4.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-protector-4.c @@ -1,5 +1,4 @@ /* { dg-do run } */ -/* { dg-skip-if "incompatible asm" { *-*-darwin* } } */ /* { dg-require-effective-target fstack_protector } */ /* { dg-require-effective-target fpic } */ /* { dg-options "-fstack-protector-all -O2 -fpic" } */ diff --git a/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c b/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c index 8159efe862e..e71d820e365 100644 --- a/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c +++ b/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c @@ -1,5 +1,4 @@ /* { dg-options " -O -fstack-protector-strong -mstack-protector-guard=sysreg -mstack-protector-guard-reg=tpidr2_el0 -mstack-protector-guard-offset=16" } */ -/* { dg-skip-if "incompatible stack layout" { *-*-darwin* } } */ /* { dg-final { check-function-bodies "**" "" } } */ void g(void *); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/aarch64-sve.exp b/gcc/testsuite/gcc.target/aarch64/sve/aarch64-sve.exp index ccca9afdf81..2b4d1925c20 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/aarch64-sve.exp +++ b/gcc/testsuite/gcc.target/aarch64/sve/aarch64-sve.exp @@ -25,11 +25,6 @@ if {![istarget aarch64*-*-*] } then { return } -# Darwin doesn't have SVE and the testing is expensive, so make it optional. -if { [istarget *-*-darwin*] && ![info exists env(DARWIN_TEST_SVE)]} then { - return -} - # Load support procs. load_lib gcc-dg.exp diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp b/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp index 89cedf800b3..5bbdbd87bed 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle-asm.exp @@ -24,11 +24,6 @@ if {![istarget aarch64*-*-*] } { return } -# Darwin doesn't have SVE and the testing is expensive, so make it optional. -if { [istarget *-*-darwin*] && ![info exists env(DARWIN_TEST_SVE)]} then { - return -} - # Load support procs. load_lib gcc-dg.exp diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp b/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp index 8010f05fe49..9c57dc64427 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp @@ -25,11 +25,6 @@ if {![istarget aarch64*-*-*] } { return } -# Darwin doesn't have SVE and the testing is expensive, so make it optional. -if { [istarget *-*-darwin*] && ![info exists env(DARWIN_TEST_SVE)] } then { - return -} - # Load support procs. load_lib gcc-dg.exp diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c index 7daceb8a301..d494943a275 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O2 -mbig-endian" } */ /* To avoid needing big-endian header files. */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c index 2b27151d654..6f9f9f2f22f 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O2 -mbig-endian" } */ /* To avoid needing big-endian header files. */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_6.c index efd2251d2e7..20e692118f9 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_6.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_6.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O2 -mbig-endian" } */ /* To avoid needing big-endian header files. */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pcs/aarch64-sve-pcs.exp b/gcc/testsuite/gcc.target/aarch64/sve/pcs/aarch64-sve-pcs.exp index a07d80f2064..3ec0c0a5a4d 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pcs/aarch64-sve-pcs.exp +++ b/gcc/testsuite/gcc.target/aarch64/sve/pcs/aarch64-sve-pcs.exp @@ -25,11 +25,6 @@ if {![istarget aarch64*-*-*] } then { return } -# Darwin does not support .variant_pcs at present. -if { [istarget *-*-darwin*] } then { - return -} - # Load support procs. load_lib gcc-dg.exp diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr108603.c b/gcc/testsuite/gcc.target/aarch64/sve/pr108603.c index 6c196cd0c71..a2aea9f0b12 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pr108603.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr108603.c @@ -1,4 +1,3 @@ -/* { dg-skip-if "no 32b support" { aarch64-*-darwin* } } */ /* { dg-options "-O2 -mabi=ilp32 -fdata-sections" } */ int a[128]; diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr88847.c b/gcc/testsuite/gcc.target/aarch64/sve/pr88847.c index 1188f1c0d70..b7504add9a9 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pr88847.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr88847.c @@ -1,5 +1,4 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-additional-options "-O0 -msve-vector-bits=256 -mbig-endian --save-temps" } */ typedef struct _b { diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_1.c b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_1.c new file mode 100644 index 00000000000..25129e8d6f2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_1.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcpu=neoverse-n2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#pragma GCC target "+sve" + +#include + +extern void use(svbool_t); + +/* +** foo: +** ... +** ptrue p([1-3]).b, all +** cmplo p0.h, p\1/z, z0.h, z[0-9]+.h +** ... +*/ +void foo (svuint16_t a, uint16_t b) +{ + svbool_t p0 = svcmplt_n_u16 (svptrue_b16 (), a, b); + use (p0); +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_2.c b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_2.c new file mode 100644 index 00000000000..58badb66a43 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcpu=neoverse-v2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#pragma GCC target "+sve" + +#include + +extern void use(svbool_t); + +/* +** foo: +** ... +** ptrue p([1-9][0-9]?).b, all +** cmplo p0.h, p\1/z, z0.h, z[0-9]+.h +** ... +*/ +void foo (svuint16_t a, uint16_t b) +{ + svbool_t p0 = svcmplt_n_u16 (svptrue_b16 (), a, b); + use (p0); +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_3.c b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_3.c new file mode 100644 index 00000000000..c67c2bd3422 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_3.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcpu=neoverse-v1" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#pragma GCC target "+sve" + +#include + +extern void use(svbool_t); + +/* +** foo: +** ... +** ptrue p([1-9][0-9]?).b, all +** cmplo p0.h, p\1/z, z0.h, z[0-9]+.h +** ... +*/ +void foo (svuint16_t a, uint16_t b) +{ + svbool_t p0 = svcmplt_n_u16 (svptrue_b16 (), a, b); + use (p0); +} + diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_4.c b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_4.c new file mode 100644 index 00000000000..c0120afe5d5 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_4.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#pragma GCC target "+sve" + +#include + +extern void use(svbool_t); + +/* +** foo: +** ... +** ptrue p0.b, all +** cmplo p0.h, p0/z, z0.h, z[0-9]+.h +** ... +*/ +void foo (svuint16_t a, uint16_t b) +{ + svbool_t p0 = svcmplt_n_u16 (svptrue_b16 (), a, b); + use (p0); +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/revb_2.c b/gcc/testsuite/gcc.target/aarch64/sve/revb_2.c index a5b176629e7..389739cc85d 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/revb_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/revb_2.c @@ -1,5 +1,4 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps -mbig-endian" } */ #include "revb_1.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/revh_2.c b/gcc/testsuite/gcc.target/aarch64/sve/revh_2.c index 9fff2270422..e821b64027e 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/revh_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/revh_2.c @@ -1,5 +1,4 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps -mbig-endian" } */ #include "revh_1.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/revhw_2.c b/gcc/testsuite/gcc.target/aarch64/sve/revhw_2.c index b231066b56c..7634d01b2c4 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/revhw_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/revhw_2.c @@ -1,5 +1,4 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O -msve-vector-bits=2048 -mbig-endian --save-temps" } */ /* { dg-final { check-function-bodies "**" "" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/revw_2.c b/gcc/testsuite/gcc.target/aarch64/sve/revw_2.c index fca6e8fea7a..17243c05c5e 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/revw_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/revw_2.c @@ -1,5 +1,4 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O -msve-vector-bits=256 --save-temps -mbig-endian" } */ #include "revw_1.c" diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_move_1.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_move_1.c index f8e6efff415..16e48bef044 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/struct_move_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_move_1.c @@ -1,5 +1,4 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O -msve-vector-bits=256 -mbig-endian --save-temps" } */ typedef char vnx16qi __attribute__((vector_size(32))); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_move_2.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_move_2.c index c18730a2ac9..6041f2a2a49 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/struct_move_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_move_2.c @@ -1,5 +1,4 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O -msve-vector-bits=256 -mbig-endian --save-temps" } */ typedef char vnx16qi __attribute__((vector_size(32))); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_move_3.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_move_3.c index 88339cb99e0..19011384f9b 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/struct_move_3.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_move_3.c @@ -1,5 +1,4 @@ /* { dg-do assemble { target aarch64_asm_sve_ok } } */ -/* { dg-skip-if "no BE support" { aarch64-*-darwin* } } */ /* { dg-options "-O -msve-vector-bits=256 -mbig-endian --save-temps" } */ typedef char vnx16qi __attribute__((vector_size(32))); diff --git a/gcc/testsuite/gcc.target/aarch64/symbol-range-tiny.c b/gcc/testsuite/gcc.target/aarch64/symbol-range-tiny.c index 2d9e94bc625..fc6a4f3ec78 100644 --- a/gcc/testsuite/gcc.target/aarch64/symbol-range-tiny.c +++ b/gcc/testsuite/gcc.target/aarch64/symbol-range-tiny.c @@ -1,5 +1,4 @@ /* { dg-do link } */ -/* { dg-skip-if "no mcmodel tiny" *-*-darwin* } */ /* { dg-options "-O3 -save-temps -mcmodel=tiny" } */ char fixed_regs[0x00080000]; diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_1.c b/gcc/testsuite/gcc.target/aarch64/target_attr_1.c index 3a297931d00..4a3a1ee233a 100644 --- a/gcc/testsuite/gcc.target/aarch64/target_attr_1.c +++ b/gcc/testsuite/gcc.target/aarch64/target_attr_1.c @@ -10,5 +10,5 @@ foo (int a) return a + 1; } -/* { dg-final { scan-assembler "(//|;).tune cortex-a72.cortex-a53" } } */ +/* { dg-final { scan-assembler "//.tune cortex-a72.cortex-a53" } } */ /* { dg-final { scan-assembler-not "thunderx" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_7.c b/gcc/testsuite/gcc.target/aarch64/target_attr_7.c index 2260e510180..6067ffed30e 100644 --- a/gcc/testsuite/gcc.target/aarch64/target_attr_7.c +++ b/gcc/testsuite/gcc.target/aarch64/target_attr_7.c @@ -19,6 +19,6 @@ bam (int a) return a - bar (a); } -/* { dg-final { scan-assembler-times "(//|;).tune xgene1" 1 } } */ -/* { dg-final { scan-assembler-times "(//|;).tune cortex-a53" 1 } } */ +/* { dg-final { scan-assembler-times "//.tune xgene1" 1 } } */ +/* { dg-final { scan-assembler-times "//.tune cortex-a53" 1 } } */ /* { dg-final { scan-assembler-not "thunderx" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/tbz_1.c b/gcc/testsuite/gcc.target/aarch64/tbz_1.c index c98066d7ab1..39deb58e278 100644 --- a/gcc/testsuite/gcc.target/aarch64/tbz_1.c +++ b/gcc/testsuite/gcc.target/aarch64/tbz_1.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-O2 -std=c99 " } */ -/* { dg-additional-options " -fno-unwind-tables -fno-asynchronous-unwind-tables" { target { ! *-*-darwin* } } } */ +/* { dg-additional-options "-O2 -std=c99 -fno-unwind-tables -fno-asynchronous-unwind-tables" } */ /* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */ #include @@ -9,9 +8,9 @@ void h(void); /* ** g1: -** tbnz (w|x)[0-9]+, #?0, .?L([0-9]+) +** tbnz w[0-9]+, #?0, .L([0-9]+) ** ret -** ... +** ... */ void g1(bool x) { @@ -21,9 +20,9 @@ void g1(bool x) /* ** g2: -** tbz (w|x)[0-9]+, #?0, .?L([0-9]+) -** b _?h -** ... +** tbz w[0-9]+, #?0, .L([0-9]+) +** b h +** ... */ void g2(bool x) { @@ -33,8 +32,8 @@ void g2(bool x) /* ** g3_ge: -** tbnz w[0-9]+, #?31, .?L[0-9]+ -** b _?h +** tbnz w[0-9]+, #?31, .L[0-9]+ +** b h ** ... */ void g3_ge(int x) @@ -46,8 +45,8 @@ void g3_ge(int x) /* ** g3_gt: ** cmp w[0-9]+, 0 -** ble .?L[0-9]+ -** b _?h +** ble .L[0-9]+ +** b h ** ... */ void g3_gt(int x) @@ -58,8 +57,8 @@ void g3_gt(int x) /* ** g3_lt: -** tbz w[0-9]+, #?31, .?L[0-9]+ -** b _?h +** tbz w[0-9]+, #?31, .L[0-9]+ +** b h ** ... */ void g3_lt(int x) @@ -71,8 +70,8 @@ void g3_lt(int x) /* ** g3_le: ** cmp w[0-9]+, 0 -** bgt .?L[0-9]+ -** b _?h +** bgt .L[0-9]+ +** b h ** ... */ void g3_le(int x) @@ -85,8 +84,8 @@ void g3_le(int x) ** g5: ** mov w[0-9]+, 65279 ** tst w[0-9]+, w[0-9]+ -** beq .?L[0-9]+ -** b _?h +** beq .L[0-9]+ +** b h ** ... */ void g5(int x) diff --git a/gcc/testsuite/gcc.target/aarch64/tbz_2.c b/gcc/testsuite/gcc.target/aarch64/tbz_2.c index 8f7dfdbcab0..ec128b58f35 100644 --- a/gcc/testsuite/gcc.target/aarch64/tbz_2.c +++ b/gcc/testsuite/gcc.target/aarch64/tbz_2.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-O2 -std=c99 " } */ -/* { dg-additional-options " -fno-unwind-tables -fno-asynchronous-unwind-tables" { target { ! *-*-darwin* } } } */ +/* { dg-additional-options "-O2 -std=c99 -fno-unwind-tables -fno-asynchronous-unwind-tables" } */ /* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */ #include @@ -9,7 +8,7 @@ void h(void); /* ** g1: -** cbnz w0, .?L[0-9]+ +** cbnz w0, .L[0-9]+ ** ret ** ... */ @@ -21,7 +20,7 @@ void g1(int x) /* ** g2: -** tbnz x0, 0, .?L[0-9]+ +** tbnz x0, 0, .L[0-9]+ ** ret ** ... */ @@ -33,7 +32,7 @@ void g2(int x) /* ** g3: -** tbnz x0, 3, .?L[0-9]+ +** tbnz x0, 3, .L[0-9]+ ** ret ** ... */ @@ -45,7 +44,7 @@ void g3(int x) /* ** g4: -** tbnz w0, #31, .?L[0-9]+ +** tbnz w0, #31, .L[0-9]+ ** ret ** ... */ @@ -58,11 +57,11 @@ void g4(int x) /* ** g5: ** tst w0, 255 -** bne .?L[0-9]+ +** bne .L[0-9]+ ** ret ** ... */ -void g5(unsigned char x) +void g5(char x) { if (__builtin_expect (x, 0)) h (); @@ -70,7 +69,7 @@ void g5(unsigned char x) /* ** g6: -** tbnz (w|x)0, 0, .?L[0-9]+ +** tbnz w0, 0, .L[0-9]+ ** ret ** ... */ @@ -82,8 +81,8 @@ void g6(char x) /* ** g7: -** tst (w|x)0, 3 -** bne .?L[0-9]+ +** tst w0, 3 +** bne .L[0-9]+ ** ret ** ... */ @@ -95,11 +94,11 @@ void g7(char x) /* ** g8: -** tbnz (w|x)0, 7, .?L[0-9]+ +** tbnz w0, 7, .L[0-9]+ ** ret ** ... */ -void g8(unsigned char x) +void g8(char x) { if (__builtin_expect (x & (1 << 7), 0)) h (); @@ -107,7 +106,7 @@ void g8(unsigned char x) /* ** g9: -** tbnz (w|x)0, 0, .?L[0-9]+ +** tbnz w0, 0, .L[0-9]+ ** ret ** ... */ @@ -119,7 +118,7 @@ void g9(bool x) /* ** g10: -** tbnz (w|x)0, 0, .?L[0-9]+ +** tbnz w0, 0, .L[0-9]+ ** ret ** ... */ diff --git a/gcc/testsuite/gcc.target/aarch64/tbz_3.c b/gcc/testsuite/gcc.target/aarch64/tbz_3.c index 7c5ab7ec89f..74f758d33e2 100644 --- a/gcc/testsuite/gcc.target/aarch64/tbz_3.c +++ b/gcc/testsuite/gcc.target/aarch64/tbz_3.c @@ -15,5 +15,4 @@ f (unsigned int x, _Bool y) } } -/* { dg-final { scan-assembler-times {and\t} 1 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-not {and\t} { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times {and\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/test-framepointer-2.c b/gcc/testsuite/gcc.target/aarch64/test-framepointer-2.c index 2391991e3ff..9b2022aea5a 100644 --- a/gcc/testsuite/gcc.target/aarch64/test-framepointer-2.c +++ b/gcc/testsuite/gcc.target/aarch64/test-framepointer-2.c @@ -10,5 +10,5 @@ Since we asked to have no frame pointers anywhere, we expect no frame record in main or the leaf. */ -/* { dg-final { scan-assembler-not "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" { target { ! *-*-darwin* } } } } */ +/* { dg-final { scan-assembler-not "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/test-framepointer-3.c b/gcc/testsuite/gcc.target/aarch64/test-framepointer-3.c index f970b265a66..b8c23209cd4 100644 --- a/gcc/testsuite/gcc.target/aarch64/test-framepointer-3.c +++ b/gcc/testsuite/gcc.target/aarch64/test-framepointer-3.c @@ -10,5 +10,5 @@ Since we asked to have no frame pointers anywhere, we expect no frame record in main or the leaf. */ -/* { dg-final { scan-assembler-not "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" { target { ! *-*-darwin* } } } } */ +/* { dg-final { scan-assembler-not "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/test-framepointer-6.c b/gcc/testsuite/gcc.target/aarch64/test-framepointer-6.c index 41658785bfc..4af5d889686 100644 --- a/gcc/testsuite/gcc.target/aarch64/test-framepointer-6.c +++ b/gcc/testsuite/gcc.target/aarch64/test-framepointer-6.c @@ -10,5 +10,5 @@ Since we asked to have no frame pointers anywhere, we expect no frame record in main or the leaf. */ -/* { dg-final { scan-assembler-not "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" { target { ! *-*-darwin* } } } } */ +/* { dg-final { scan-assembler-not "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/uaddw-3.c b/gcc/testsuite/gcc.target/aarch64/uaddw-3.c index b4ed187bd2c..39cbd6b6cc2 100644 --- a/gcc/testsuite/gcc.target/aarch64/uaddw-3.c +++ b/gcc/testsuite/gcc.target/aarch64/uaddw-3.c @@ -1,11 +1,10 @@ /* { dg-do compile } */ /* { dg-options "-O3" } */ -/* { dg-additional-options "-fno-signed-char" { target *-*-darwin* } } */ #pragma GCC target "+nosve" int -t6(int len, void * dummy, unsigned char * __restrict x) +t6(int len, void * dummy, char * __restrict x) { len = len & ~31; unsigned short result = 0; diff --git a/gcc/testsuite/gcc.target/aarch64/vec-init-single-const.c b/gcc/testsuite/gcc.target/aarch64/vec-init-single-const.c index f8483a3a534..274b0b39ac4 100644 --- a/gcc/testsuite/gcc.target/aarch64/vec-init-single-const.c +++ b/gcc/testsuite/gcc.target/aarch64/vec-init-single-const.c @@ -46,8 +46,8 @@ int32x4_t f_s32(int32_t x) /* ** f_s64: -** adrp x[0-9]+, (.LC[0-9]+|lC[0-9]+@PAGE) -** ldr q0, \[x[0-9]+, #(:lo12:.LC[0-9]+|lC[0-9]+@PAGEOFF)\] +** adrp x[0-9]+, .LC[0-9]+ +** ldr q0, \[x[0-9]+, #:lo12:.LC[0-9]+\] ** ins v0\.d\[0\], x0 ** ret */ diff --git a/gcc/testsuite/gcc.target/aarch64/vect-cse-codegen.c b/gcc/testsuite/gcc.target/aarch64/vect-cse-codegen.c index 956d894fd26..2b8e64313bb 100644 --- a/gcc/testsuite/gcc.target/aarch64/vect-cse-codegen.c +++ b/gcc/testsuite/gcc.target/aarch64/vect-cse-codegen.c @@ -6,8 +6,8 @@ /* **test1: -** adrp x[0-9]+, (.LC[0-9]+|lC[0-9]+@PAGE) -** ldr q[0-9]+, \[x[0-9]+, #(:lo12:.LC[0-9]+|lC[0-9]+@PAGEOFF)\] +** adrp x[0-9]+, .LC[0-9]+ +** ldr q[0-9]+, \[x[0-9]+, #:lo12:.LC[0-9]+\] ** add v[0-9]+.2d, v[0-9]+.2d, v[0-9]+.2d ** str q[0-9]+, \[x[0-9]+\] ** fmov x[0-9]+, d[0-9]+ @@ -27,14 +27,13 @@ test1 (uint64_t a, uint64x2_t b, uint64x2_t* rt) /* **test2: -** adrp x[0-9]+, (.LC[0-1]+|lC[0-1]+@PAGE) -** ldr q[0-9]+, \[x[0-9]+, #(:lo12:.LC[0-9]+|lC[0-9]+@PAGEOFF)\] +** adrp x[0-9]+, .LC[0-1]+ +** ldr q[0-9]+, \[x[0-9]+, #:lo12:.LC[0-9]+\] ** add v[0-9]+.2d, v[0-9]+.2d, v[0-9]+.2d ** str q[0-9]+, \[x[0-9]+\] ** fmov x[0-9]+, d[0-9]+ ** orr x[0-9]+, x[0-9]+, x[0-9]+ ** ret - */ uint64_t @@ -49,8 +48,8 @@ test2 (uint64_t a, uint64x2_t b, uint64x2_t* rt) /* **test3: -** adrp x[0-9]+, (.LC[0-9]+|lC[0-9]+@PAGE) -** ldr q[0-9]+, \[x[0-9]+, #(:lo12:.LC[0-9]+|lC[0-9]+@PAGEOFF)\] +** adrp x[0-9]+, .LC[0-9]+ +** ldr q[0-9]+, \[x[0-9]+, #:lo12:.LC[0-9]+\] ** add v[0-9]+.4s, v[0-9]+.4s, v[0-9]+.4s ** str q[0-9]+, \[x1\] ** fmov w[0-9]+, s[0-9]+ diff --git a/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch.c b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch.c index a9cb4c2ff15..673b781eb6d 100644 --- a/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch.c +++ b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch.c @@ -15,7 +15,7 @@ int b[N] = {0}; ** cmgt v[0-9]+.4s, v[0-9]+.4s, #0 ** umaxp v[0-9]+.4s, v[0-9]+.4s, v[0-9]+.4s ** fmov x[0-9]+, d[0-9]+ -** cbn?z x[0-9]+, \.?L[0-9]+ +** cbn?z x[0-9]+, \.L[0-9]+ ** ... */ void f1 () @@ -34,7 +34,7 @@ void f1 () ** cmge v[0-9]+.4s, v[0-9]+.4s, #0 ** umaxp v[0-9]+.4s, v[0-9]+.4s, v[0-9]+.4s ** fmov x[0-9]+, d[0-9]+ -** cbn?z x[0-9]+, \.?L[0-9]+ +** cbn?z x[0-9]+, \.L[0-9]+ ** ... */ void f2 () @@ -53,7 +53,7 @@ void f2 () ** cmeq v[0-9]+.4s, v[0-9]+.4s, #0 ** umaxp v[0-9]+.4s, v[0-9]+.4s, v[0-9]+.4s ** fmov x[0-9]+, d[0-9]+ -** cbn?z x[0-9]+, \.?L[0-9]+ +** cbn?z x[0-9]+, \.L[0-9]+ ** ... */ void f3 () @@ -72,7 +72,7 @@ void f3 () ** cmtst v[0-9]+.4s, v[0-9]+.4s, v[0-9]+.4s ** umaxp v[0-9]+.4s, v[0-9]+.4s, v[0-9]+.4s ** fmov x[0-9]+, d[0-9]+ -** cbn?z x[0-9]+, \.?L[0-9]+ +** cbn?z x[0-9]+, \.L[0-9]+ ** ... */ void f4 () @@ -91,7 +91,7 @@ void f4 () ** cmlt v[0-9]+.4s, v[0-9]+.4s, #0 ** umaxp v[0-9]+.4s, v[0-9]+.4s, v[0-9]+.4s ** fmov x[0-9]+, d[0-9]+ -** cbn?z x[0-9]+, \.?L[0-9]+ +** cbn?z x[0-9]+, \.L[0-9]+ ** ... */ void f5 () @@ -110,7 +110,7 @@ void f5 () ** cmle v[0-9]+.4s, v[0-9]+.4s, #0 ** umaxp v[0-9]+.4s, v[0-9]+.4s, v[0-9]+.4s ** fmov x[0-9]+, d[0-9]+ -** cbn?z x[0-9]+, \.?L[0-9]+ +** cbn?z x[0-9]+, \.L[0-9]+ ** ... */ void f6 () diff --git a/gcc/testsuite/gcc.target/aarch64/xorsign.c b/gcc/testsuite/gcc.target/aarch64/xorsign.c index 8b93604c539..dfb7ba7f140 100644 --- a/gcc/testsuite/gcc.target/aarch64/xorsign.c +++ b/gcc/testsuite/gcc.target/aarch64/xorsign.c @@ -79,11 +79,8 @@ check_l_neg_rev (long double x, long double y) return __builtin_copysignl (-1.0, y) * x; } -/* Darwin's long double is the same as double. */ -/* { dg-final { scan-assembler-times {eor\tv[0-9]+\.16b, v[0-9]+\.16b, v[0-9]+\.16b} 8 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {and\tv[0-9]+\.16b, v[0-9]+\.16b, v[0-9]+\.16b} 8 { target { ! *-*-darwin* } } } } */ -/* { dg-final { scan-assembler-times {eor\tv[0-9]+\.16b, v[0-9]+\.16b, v[0-9]+\.16b} 12 { target *-*-darwin* } } } */ -/* { dg-final { scan-assembler-times {and\tv[0-9]+\.16b, v[0-9]+\.16b, v[0-9]+\.16b} 12 { target *-*-darwin* } } } */ +/* { dg-final { scan-assembler-times {eor\tv[0-9]+\.16b, v[0-9]+\.16b, v[0-9]+\.16b} 8 } } */ +/* { dg-final { scan-assembler-times {and\tv[0-9]+\.16b, v[0-9]+\.16b, v[0-9]+\.16b} 8 } } */ /* { dg-final { scan-assembler-not "copysign" } } */ /* { dg-final { scan-assembler-not "fmov" } } */ /* { dg-final { scan-assembler-not "\[ \t\]?orr\[ \t\]?" } } */ diff --git a/gcc/testsuite/gcc.target/arm/thumb2-switchstatement.c b/gcc/testsuite/gcc.target/arm/thumb2-switchstatement.c new file mode 100644 index 00000000000..8badf318e62 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb2-switchstatement.c @@ -0,0 +1,144 @@ +/* { dg-do compile } */ +/* { dg-options "-mthumb --param case-values-threshold=1 -fno-reorder-blocks -fno-tree-dce -O2" } */ +/* { dg-require-effective-target arm_thumb2_ok } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +#define NOP "nop;" +#define NOP2 NOP NOP +#define NOP4 NOP2 NOP2 +#define NOP8 NOP4 NOP4 +#define NOP16 NOP8 NOP8 +#define NOP32 NOP16 NOP16 +#define NOP64 NOP32 NOP32 +#define NOP128 NOP64 NOP64 +#define NOP256 NOP128 NOP128 +#define NOP512 NOP256 NOP256 +#define NOP1024 NOP512 NOP512 +#define NOP2048 NOP1024 NOP1024 +#define NOP4096 NOP2048 NOP2048 +#define NOP8192 NOP4096 NOP4096 +#define NOP16384 NOP8192 NOP8192 +#define NOP32768 NOP16384 NOP16384 +#define NOP65536 NOP32768 NOP32768 +#define NOP131072 NOP65536 NOP65536 + +enum z +{ + a = 1, + b, + c, + d, + e, + f = 7, +}; + +inline void QIFunction (const char* flag) +{ + asm volatile (NOP32); + return; +} + +inline void HIFunction (const char* flag) +{ + asm volatile (NOP512); + return; +} + +inline void SIFunction (const char* flag) +{ + asm volatile (NOP131072); + return; +} + +/* +**QImode_test: +** ... +** tbb \[pc, r[0-9]+\] +** ... +*/ +__attribute__ ((noinline)) __attribute__ ((noclone)) const char* QImode_test(enum z x) +{ + switch (x) + { + case d: + QIFunction("QItest"); + return "InlineASM"; + case f: + return "TEST"; + default: + return "Default"; + } +} + +/* { dg-final { scan-assembler ".byte" } } */ + +/* +**HImode_test: +** ... +** tbh \[pc, r[0-9]+, lsl #1\] +** ... +*/ +__attribute__ ((noinline)) __attribute__ ((noclone)) const char* HImode_test(enum z x) +{ + switch (x) + { + case d: + HIFunction("HItest"); + return "InlineASM"; + case f: + return "TEST"; + default: + return "Default"; + } +} + +/* { dg-final { scan-assembler ".2byte" } } */ + +/* +**SImode_test: +** ... +** adr (r[0-9]+), .L[0-9]+ +** ldr pc, \[\1, r[0-9]+, lsl #2\] +** ... +*/ +__attribute__ ((noinline)) __attribute__ ((noclone)) const char* SImode_test(enum z x) +{ + switch (x) + { + case d: + SIFunction("SItest"); + return "InlineASM"; + case f: + return "TEST"; + default: + return "Default"; + } +} + +/* { dg-final { scan-assembler ".word" } } */ + +/* +**backwards_branch_test: +** ... +** adr (r[0-9]+), .L[0-9]+ +** ldr pc, \[\1, r[0-9]+, lsl #2\] +** ... +*/ +__attribute__ ((noinline)) __attribute__ ((noclone)) const char* backwards_branch_test(enum z x, int flag) +{ + if (flag == 5) + { + backwards: + asm volatile (NOP512); + return "ASM"; + } + switch (x) + { + case d: + goto backwards; + case f: + return "TEST"; + default: + return "Default"; + } +} \ No newline at end of file diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c new file mode 100644 index 00000000000..6368bd205c5 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +int call_isinff (float f) +{ + int isinff (float); + return isinff (f); +} + +int call_isinf (double f) +{ + int isinf (double); + return isinf (f); +} + +int call_isinfl (long double f) +{ + int isinfl (long double); + return isinfl (f); +} + +/* { dg-final { scan-assembler-not "unord" } } */ diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c new file mode 100644 index 00000000000..10f7b553fb9 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c @@ -0,0 +1,55 @@ +/* { dg-do run { target { ! avr_tiny } } } */ + +extern int isinff (float); +extern int isinf (double); +extern int isinfl (long double); + +int tst_isinf (float x, int val) +{ + double y; + long double z; + + __asm ("" : "+r"(x)); + if (isinff (x) != val) + __builtin_exit (__LINE__); + + y = x; + __asm ("" : "+r"(y)); + if (isinf (y) != val) + __builtin_exit (__LINE__); + + z = x; + __asm ("" : "+r"(z)); + if (isinfl (z) != val) + __builtin_exit (__LINE__); +} + +static float make_f (__UINT32_TYPE__ i) +{ + float f; + __builtin_memcpy (&f, &i, 4); + return f; +} + +int main (void) +{ + tst_isinf (__builtin_huge_valf(), 1); + tst_isinf (-__builtin_huge_valf(), -1); + tst_isinf (__builtin_nanf(""), 0); + tst_isinf (0.0f, 0); + tst_isinf (-0.0f, 0); + tst_isinf (1.0f, 0); + tst_isinf (-1.0f, 0); + tst_isinf (make_f (0x7f800000), 1); + tst_isinf (make_f (0xff800000), -1); + tst_isinf (make_f (0x7f7fffff), 0); + tst_isinf (make_f (0xff7fffff), 0); + tst_isinf (make_f (0x7f800001), 0); + tst_isinf (make_f (0xff800001), 0); + tst_isinf (make_f (0x00800000), 0); + tst_isinf (make_f (0x80800000), 0); + tst_isinf (make_f (0x00400000), 0); + tst_isinf (make_f (0x80400000), 0); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/apx-ccmp-1.c b/gcc/testsuite/gcc.target/i386/apx-ccmp-1.c new file mode 100644 index 00000000000..e4e112f07e0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ccmp-1.c @@ -0,0 +1,104 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -ffast-math -mapx-features=ccmp" } */ + +int +f1 (int a) +{ + return a < 17 || a == 32; +} + +int +f2 (int a) +{ + return a > 33 || a == 18; +} + +int +f3 (int a, int b) +{ + return a != 19 && b > 34; +} + +int +f4 (int a, int b) +{ + return a < 35 && b == 20; +} + +int +f5 (short a) +{ + return a == 0 || a == 5; +} + +int +f6 (long long a) +{ + return a == 6 || a == 0; +} + +int +f7 (char a, char b) +{ + return a > 0 && b <= 7; +} + +int +f8 (int a, int b) +{ + return a == 9 && b > 0; +} + +int +f9 (int a, int b) +{ + a += b; + return a == 3 || a == 0; +} + +int +f10 (float a, int b, float c) +{ + return a > c || b < 19; +} + +int +f11 (float a, int b) +{ + return a == 0.0 && b > 21; +} + +int +f12 (double a, int b) +{ + return a < 3.0 && b != 23; +} + +int +f13 (double a, double b, int c, int d) +{ + a += b; + c += d; + return a != b || c == d; +} + +int +f14 (double a, int b) +{ + return b != 0 && a < 1.5; +} + +int +f15 (double a, double b, int c, int d) +{ + return c != d || a <= b; +} + +/* { dg-final { scan-assembler-times "ccmpg" 2 } } */ +/* { dg-final { scan-assembler-times "ccmple" 2 } } */ +/* { dg-final { scan-assembler-times "ccmpne" 4 } } */ +/* { dg-final { scan-assembler-times "ccmpe" 3 } } */ +/* { dg-final { scan-assembler-times "ccmpbe" 1 } } */ +/* { dg-final { scan-assembler-times "ccmpa" 1 } } */ +/* { dg-final { scan-assembler-times "ccmpbl" 2 } } */ + diff --git a/gcc/testsuite/gcc.target/i386/apx-ccmp-2.c b/gcc/testsuite/gcc.target/i386/apx-ccmp-2.c new file mode 100644 index 00000000000..0123a686d2c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ccmp-2.c @@ -0,0 +1,104 @@ +/* { dg-do run { target { ! ia32 } } } */ +/* { dg-require-effective-target apxf } */ +/* { dg-options "-O3 -mno-apxf" } */ + +__attribute__((noinline, noclone, target("apxf"))) +int foo_apx(int a, int b, int c, int d) +{ + int sum = a; + + if (a != c) + { + c += d; + a += b; + sum += a + c; + if (b != d && sum < c || sum > d) + { + b += d; + sum += b; + } + } + + return sum; +} + +__attribute__((noinline, noclone, target("no-apxf"))) +int foo_noapx(int a, int b, int c, int d) +{ + int sum = a; + + if (a != c) + { + c += d; + a += b; + sum += a + c; + if (b != d && sum < c || sum > d) + { + b += d; + sum += b; + } + } + + return sum; +} + +__attribute__((noinline, noclone, + optimize(("finite-math-only")), target("apxf"))) +double foo_fp_apx(int a, double b, int c, double d) +{ + int sum = a; + double sumd = b; + + if (a != c) + { + sum += a; + if (a < c || sumd != d || sum > c) + { + c += a; + sum += a + c; + } + } + + return sum + sumd; +} + +__attribute__((noinline, noclone, + optimize(("finite-math-only")), target("no-apxf"))) +double foo_fp_noapx(int a, double b, int c, double d) +{ + int sum = a; + double sumd = b; + + if (a != c) + { + sum += a; + if (a < c || sumd != d || sum > c) + { + c += a; + sum += a + c; + } + } + + return sum + sumd; +} + + +int main (void) +{ + if (!__builtin_cpu_supports ("apxf")) + return 0; + + int val1 = foo_noapx (23, 17, 32, 44); + int val2 = foo_apx (23, 17, 32, 44); + + if (val1 != val2) + __builtin_abort (); + + double val3 = foo_fp_noapx (24, 7.5, 32, 2.0); + double val4 = foo_fp_apx (24, 7.5, 32, 2.0); + + if (val3 != val4) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd.c b/gcc/testsuite/gcc.target/i386/apx-ndd.c index 0eb751ad225..0ff4df0780c 100644 --- a/gcc/testsuite/gcc.target/i386/apx-ndd.c +++ b/gcc/testsuite/gcc.target/i386/apx-ndd.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-mapxf -march=x86-64 -O2" } */ +/* { dg-options "-mapx-features=egpr,push2pop2,ndd,ppx -march=x86-64 -O2" } */ /* { dg-final { scan-assembler-not "movl"} } */ #include diff --git a/gcc/testsuite/gcc.target/i386/apx-nf.c b/gcc/testsuite/gcc.target/i386/apx-nf.c new file mode 100644 index 00000000000..ed859b399b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-nf.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mapx-features=egpr,push2pop2,ndd,ppx,nf -march=x86-64 -O2" } */ +/* { dg-final { scan-assembler-times "\{nf\} and" 1 } } */ +/* { dg-final { scan-assembler-times "\{nf\} or" 1 } } */ +/* { dg-final { scan-assembler-times "\{nf\} rol" 4 } } */ + +struct B { unsigned bit0 : 1; unsigned bit1 : 1; }; + +void +foo (struct B *b) +{ + b->bit0 = b->bit0 | b->bit1; +} +long int f1 (int x) { return ~(1ULL << (x & 0x3f)); } +long int f2 (int x) { return ~(1ULL << x); } +long int f3 (unsigned char *x) { return ~(1ULL << (x[0] & 0x3f)); } +long int f4 (unsigned char *x) { return ~(1ULL << x[0]); } diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-25.c b/gcc/testsuite/gcc.target/i386/avx10_1-25.c new file mode 100644 index 00000000000..5bd2b88fb08 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-25.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx" } */ +/* { dg-require-ifunc "" } */ + +#include +__attribute__((target_clones ("default","avx10.1-256"))) +__m256d foo(__m256d a, __m256d b) +{ + return a + b; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-26.c b/gcc/testsuite/gcc.target/i386/avx10_1-26.c new file mode 100644 index 00000000000..cf8c976e21f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-26.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx512f" } */ +/* { dg-require-ifunc "" } */ + +#include +__attribute__((target_clones ("default","avx10.1-512"))) +__m512d foo(__m512d a, __m512d b) +{ + return a + b; +} diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-1.c index a88153a85db..b0984879eab 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-1.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-mavx512f -O2" } */ -/* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-3.c new file mode 100644 index 00000000000..fc66a9f5572 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-3.c @@ -0,0 +1,955 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx512f" } */ + +typedef unsigned int V __attribute__ ((__vector_size__ (16))); + +V foo_0_1(V a, V b, V c) { return (V){0,0,0,0}; } + +V foo_1_1(V a, V b, V c) { return ~((b|a)|c); } + +V foo_2_1(V a, V b, V c) { return (~(b|a))&c; } + +V foo_3_1(V a, V b, V c) { return ~(b|a); } + +V foo_4_1(V a, V b, V c) { return (~(c|a))&b; } + +V foo_5_1(V a, V b, V c) { return ~(c|a); } + +V foo_6_1(V a, V b, V c) { return (c^b)&~a; } + +V foo_7_1(V a, V b, V c) { return ~((c&b)|a); } + +V foo_8_1(V a, V b, V c) { return (~a&c)&b; } +V foo_8_2(V a, V b, V c) { return (~a&b)&c; } +V foo_8_3(V a, V b, V c) { return (c&b)&~a; } + +V foo_9_1(V a, V b, V c) { return ~((c^b)|a); } + +V foo_10_1(V a, V b, V c) { return ~a&c; } + +V foo_11_1(V a, V b, V c) { return ~((~c&b)|a); } +V foo_11_2(V a, V b, V c) { return (~b|c)&~a; } + +V foo_12_1(V a, V b, V c) { return ~a&b; } + +V foo_13_1(V a, V b, V c) { return ~((~b&c)|a); } +V foo_13_2(V a, V b, V c) { return (~c|b)&~a; } + +V foo_14_1(V a, V b, V c) { return (c|b)&~a; } + +V foo_15_1(V a, V b, V c) { return ~a; } + +V foo_16_1(V a, V b, V c) { return (~(c|b))&a; } + +V foo_17_1(V a, V b, V c) { return ~(c|b); } + +V foo_18_1(V a, V b, V c) { return (c^a)&~b; } + +V foo_19_1(V a, V b, V c) { return ~((c&a)|b); } + +V foo_20_1(V a, V b, V c) { return (b^a)&~c; } + +V foo_21_1(V a, V b, V c) { return ~((b&a)|c); } + +V foo_22_1(V a, V b, V c) { return ((b^a)|(c&b))^c; } +V foo_22_2(V a, V b, V c) { return ((c^a)|(c&b))^b; } +V foo_22_3(V a, V b, V c) { return ((c^b)|(c&a))^a; } +V foo_22_4(V a, V b, V c) { return ((b&a)|c)^(b|a); } +V foo_22_5(V a, V b, V c) { return ((c&a)|b)^(c|a); } +V foo_22_6(V a, V b, V c) { return ((c&b)|a)^(c|b); } + +V foo_23_1(V a, V b, V c) { return ~(((b^a)&(c^a))^a); } +V foo_23_2(V a, V b, V c) { return ((b^a)&(c^a))^~a; } +V foo_23_3(V a, V b, V c) { return ((b^a)&(c^b))^~b; } +V foo_23_4(V a, V b, V c) { return ((b^a)&c)^(~(b&a)); } +V foo_23_5(V a, V b, V c) { return ((c^a)&(c^b))^~c; } +V foo_23_6(V a, V b, V c) { return ((c^a)&b)^(~(c&a)); } +V foo_23_7(V a, V b, V c) { return ((c^b)&a)^(~(c&b)); } +V foo_23_8(V a, V b, V c) { return (~((c^b)&a))^(c&b); } +V foo_23_9(V a, V b, V c) { return (~((c^a)&b))^(c&a); } +V foo_23_10(V a, V b, V c) { return (~((c^a)&(c^b)))^c; } +V foo_23_11(V a, V b, V c) { return (~((b^a)&c))^(b&a); } +V foo_23_12(V a, V b, V c) { return (~((b^a)&(c^b)))^b; } +V foo_23_13(V a, V b, V c) { return (~((b^a)&(c^a)))^a; } +V foo_23_14(V a, V b, V c) { return ((~(b^a))|c)^(b|a); } +V foo_23_15(V a, V b, V c) { return ((~(c^a))|b)^(c|a); } +V foo_23_16(V a, V b, V c) { return ((~(c^b))|a)^(c|b); } + +V foo_24_1(V a, V b, V c) { return (b^a)&(c^a); } + +V foo_25_1(V a, V b, V c) { return ~((c^b)|(c&a)); } +V foo_25_2(V a, V b, V c) { return ((c&a)|~b)^c; } +V foo_25_3(V a, V b, V c) { return ((b&a)|~c)^b; } + +V foo_26_1(V a, V b, V c) { return ((b&a)|c)^a; } + +V foo_27_1(V a, V b, V c) { return ~(((b^a)&c)^b); } +V foo_27_2(V a, V b, V c) { return ((b^a)&c)^~b; } +V foo_27_3(V a, V b, V c) { return (~b|c)^(c&a); } +V foo_27_4(V a, V b, V c) { return (~((b^a)&c))^b; } +V foo_27_5(V a, V b, V c) { return ((~(b^a))|c)^a; } +V foo_27_6(V a, V b, V c) { return (~c|a)^(c|b); } + +V foo_28_1(V a, V b, V c) { return ((c&a)|b)^a; } + +V foo_29_1(V a, V b, V c) { return ~(((c^a)&b)^c); } +V foo_29_2(V a, V b, V c) { return ((c^a)&b)^~c; } +V foo_29_3(V a, V b, V c) { return (~((c^a)&b))^c; } +V foo_29_4(V a, V b, V c) { return (~c|b)^(b&a); } +V foo_29_5(V a, V b, V c) { return ((~(c^a))|b)^a; } +V foo_29_6(V a, V b, V c) { return (~b|a)^(c|b); } + +V foo_30_1(V a, V b, V c) { return (c|b)^a; } + +V foo_31_1(V a, V b, V c) { return ~((c|b)&a); } + +V foo_32_1(V a, V b, V c) { return (~b&c)&a; } +V foo_32_2(V a, V b, V c) { return (~b&a)&c; } +V foo_32_3(V a, V b, V c) { return (c&a)&~b; } + +V foo_33_1(V a, V b, V c) { return ~((c^a)|b); } + +V foo_34_1(V a, V b, V c) { return ~b&c; } + +V foo_35_1(V a, V b, V c) { return ~((~c&a)|b); } +V foo_35_2(V a, V b, V c) { return (~a|c)&~b; } + +V foo_36_1(V a, V b, V c) { return (b^a)&(c^b); } + +V foo_37_1(V a, V b, V c) { return ~((c^a)|(c&b)); } +V foo_37_2(V a, V b, V c) { return ((c&b)|~a)^c; } +V foo_37_3(V a, V b, V c) { return ((b&a)|~c)^a; } + +V foo_38_1(V a, V b, V c) { return ((b&a)|c)^b; } + +V foo_39_1(V a, V b, V c) { return ~(((b^a)&c)^a); } +V foo_39_2(V a, V b, V c) { return ((b^a)&c)^~a; } +V foo_39_3(V a, V b, V c) { return (~a|c)^(c&b); } +V foo_39_4(V a, V b, V c) { return ((~(b^a))|c)^b; } +V foo_39_5(V a, V b, V c) { return (~((b^a)&c))^a; } +V foo_39_6(V a, V b, V c) { return (~c|b)^(c|a); } + +V foo_40_1(V a, V b, V c) { return (b^a)&c; } + +V foo_41_1(V a, V b, V c) { return ~((((b&a)|c)^a)^b); } +V foo_41_2(V a, V b, V c) { return (((b&a)|c)^b)^~a; } +V foo_41_3(V a, V b, V c) { return (~((b&a)|c))^(b^a); } +V foo_41_4(V a, V b, V c) { return (((b&a)|c)^a)^~b; } +V foo_41_5(V a, V b, V c) { return ((b&a)|c)^(~(b^a)); } +V foo_41_6(V a, V b, V c) { return (~(((b&a)|c)^a))^b; } +V foo_41_7(V a, V b, V c) { return ((b&a)|~c)^(b|a); } +V foo_41_8(V a, V b, V c) { return (~(((b&a)|c)^b))^a; } + +V foo_42_1(V a, V b, V c) { return (~(b&a))&c; } + +V foo_43_1(V a, V b, V c) { return ~(((b^a)&(c^a))^b); } +V foo_43_2(V a, V b, V c) { return ((b^a)&c)|(~(b|a)); } +V foo_43_3(V a, V b, V c) { return ((b^a)&c)^(~(b|a)); } +V foo_43_4(V a, V b, V c) { return ((b^a)&(c^b))^~a; } +V foo_43_5(V a, V b, V c) { return ((b^a)&(c^a))^~b; } +V foo_43_6(V a, V b, V c) { return ((b^a)|(c^a))^~c; } +V foo_43_7(V a, V b, V c) { return (~((b^a)|(c^a)))^c; } +V foo_43_8(V a, V b, V c) { return ((~(b^a))|c)^(b&a); } +V foo_43_9(V a, V b, V c) { return (~((b^a)&(c^a)))^b; } +V foo_43_10(V a, V b, V c) { return (~((b^a)&c))^(b|a); } +V foo_43_11(V a, V b, V c) { return (~((b^a)&(c^b)))^a; } +V foo_43_12(V a, V b, V c) { return ((c^b)|a)^(~c|b); } +V foo_43_13(V a, V b, V c) { return ((c^a)|b)^(~c|a); } + +V foo_44_1(V a, V b, V c) { return (b^a)&(c|b); } +V foo_44_2(V a, V b, V c) { return ((c|b)&a)^b; } + +V foo_45_1(V a, V b, V c) { return (~c|b)^a; } + +V foo_46_1(V a, V b, V c) { return (b&a)^(c|b); } +V foo_46_2(V a, V b, V c) { return ((c^a)|b)^a; } + +V foo_47_1(V a, V b, V c) { return ~((~c|b)&a); } +V foo_47_2(V a, V b, V c) { return (~b&c)|~a; } + +V foo_48_1(V a, V b, V c) { return ~b&a; } + +V foo_49_1(V a, V b, V c) { return ~((~a&c)|b); } +V foo_49_2(V a, V b, V c) { return (~c|a)&~b; } + +V foo_50_1(V a, V b, V c) { return (c|a)&~b; } + +V foo_51_1(V a, V b, V c) { return ~b; } + +V foo_52_1(V a, V b, V c) { return ((c&b)|a)^b; } + +V foo_53_1(V a, V b, V c) { return ~(((c^b)&a)^c); } +V foo_53_2(V a, V b, V c) { return ((c^b)&a)^~c; } +V foo_53_3(V a, V b, V c) { return (~((c^b)&a))^c; } +V foo_53_4(V a, V b, V c) { return (~c|a)^(b&a); } +V foo_53_5(V a, V b, V c) { return ((~(c^b))|a)^b; } +V foo_53_6(V a, V b, V c) { return (~a|b)^(c|a); } + +V foo_54_1(V a, V b, V c) { return (c|a)^b; } + +V foo_55_1(V a, V b, V c) { return ~((c|a)&b); } + +V foo_56_1(V a, V b, V c) { return (b^a)&(c|a); } +V foo_56_2(V a, V b, V c) { return ((c|a)&b)^a; } + +V foo_57_1(V a, V b, V c) { return (~c|a)^b; } + +V foo_58_1(V a, V b, V c) { return (b&a)^(c|a); } +V foo_58_2(V a, V b, V c) { return ((c^b)|a)^b; } + +V foo_59_1(V a, V b, V c) { return ~((~c|a)&b); } +V foo_59_2(V a, V b, V c) { return (~a&c)|~b; } + +V foo_60_1(V a, V b, V c) { return b^a; } + +V foo_61_1(V a, V b, V c) { return (~(c|a))|(b^a); } +V foo_61_2(V a, V b, V c) { return (~(c|b))|(b^a); } +V foo_61_3(V a, V b, V c) { return ((~(c|b))|a)^b; } +V foo_61_4(V a, V b, V c) { return ((~(c|a))|b)^a; } + +V foo_62_1(V a, V b, V c) { return (~a&c)|(b^a); } +V foo_62_2(V a, V b, V c) { return (~b&c)|(b^a); } +V foo_62_3(V a, V b, V c) { return ((~b&c)|a)^b; } +V foo_62_4(V a, V b, V c) { return ((~a&c)|b)^a; } + +V foo_63_1(V a, V b, V c) { return ~(b&a); } + +V foo_64_1(V a, V b, V c) { return (~c&b)&a; } +V foo_64_2(V a, V b, V c) { return (~c&a)&b; } +V foo_64_3(V a, V b, V c) { return (b&a)&~c; } + +V foo_65_1(V a, V b, V c) { return ~((b^a)|c); } + +V foo_66_1(V a, V b, V c) { return (c^a)&(c^b); } + +V foo_67_1(V a, V b, V c) { return ~((b^a)|(c&b)); } +V foo_67_2(V a, V b, V c) { return ((c&b)|~a)^b; } +V foo_67_3(V a, V b, V c) { return ((c&a)|~b)^a; } + +V foo_68_1(V a, V b, V c) { return ~c&b; } + +V foo_69_1(V a, V b, V c) { return ~((~b&a)|c); } +V foo_69_2(V a, V b, V c) { return (~a|b)&~c; } + +V foo_70_1(V a, V b, V c) { return ((c&a)|b)^c; } + +V foo_71_1(V a, V b, V c) { return ~(((c^a)&b)^a); } +V foo_71_2(V a, V b, V c) { return ((c^a)&b)^~a; } +V foo_71_3(V a, V b, V c) { return (~a|b)^(c&b); } +V foo_71_4(V a, V b, V c) { return ((~(c^a))|b)^c; } +V foo_71_5(V a, V b, V c) { return (~((c^a)&b))^a; } +V foo_71_6(V a, V b, V c) { return (~b|c)^(b|a); } + +V foo_72_1(V a, V b, V c) { return (c^a)&b; } + +V foo_73_1(V a, V b, V c) { return ~((((c&a)|b)^a)^c); } +V foo_73_2(V a, V b, V c) { return (((c&a)|b)^c)^~a; } +V foo_73_3(V a, V b, V c) { return (~((c&a)|b))^(c^a); } +V foo_73_4(V a, V b, V c) { return (((c&a)|b)^a)^~c; } +V foo_73_5(V a, V b, V c) { return ((c&a)|b)^(~(c^a)); } +V foo_73_6(V a, V b, V c) { return (~(((c&a)|b)^a))^c; } +V foo_73_7(V a, V b, V c) { return ((c&a)|~b)^(c|a); } +V foo_73_8(V a, V b, V c) { return (~(((c&a)|b)^c))^a; } + +V foo_74_1(V a, V b, V c) { return (c^a)&(c|b); } +V foo_74_2(V a, V b, V c) { return ((c|b)&a)^c; } + +V foo_75_1(V a, V b, V c) { return (~b|c)^a; } + +V foo_76_1(V a, V b, V c) { return (~(c&a))&b; } + +V foo_77_1(V a, V b, V c) { return ~(((b^a)&(c^a))^c); } +V foo_77_2(V a, V b, V c) { return ((c^a)&b)|(~(c|a)); } +V foo_77_3(V a, V b, V c) { return ((c^a)&b)^(~(c|a)); } +V foo_77_4(V a, V b, V c) { return ((c^a)&(c^b))^~a; } +V foo_77_5(V a, V b, V c) { return ((b^a)&(c^a))^~c; } +V foo_77_6(V a, V b, V c) { return ((b^a)|(c^a))^~b; } +V foo_77_7(V a, V b, V c) { return (~((b^a)|(c^a)))^b; } +V foo_77_8(V a, V b, V c) { return ((~(c^a))|b)^(c&a); } +V foo_77_9(V a, V b, V c) { return (~((b^a)&(c^a)))^c; } +V foo_77_10(V a, V b, V c) { return (~((c^a)&b))^(c|a); } +V foo_77_11(V a, V b, V c) { return ((c^b)|a)^(~b|c); } +V foo_77_12(V a, V b, V c) { return (~((c^a)&(c^b)))^a; } +V foo_77_13(V a, V b, V c) { return ((b^a)|c)^(~b|a); } + +V foo_78_1(V a, V b, V c) { return (c&a)^(c|b); } +V foo_78_2(V a, V b, V c) { return ((b^a)|c)^a; } + +V foo_79_1(V a, V b, V c) { return ~((~b|c)&a); } +V foo_79_2(V a, V b, V c) { return (~c&b)|~a; } + +V foo_80_1(V a, V b, V c) { return ~c&a; } + +V foo_81_1(V a, V b, V c) { return ~((~a&b)|c); } +V foo_81_2(V a, V b, V c) { return (~b|a)&~c; } + +V foo_82_1(V a, V b, V c) { return ((c&b)|a)^c; } + +V foo_83_1(V a, V b, V c) { return ~(((c^b)&a)^b); } +V foo_83_2(V a, V b, V c) { return ((c^b)&a)^~b; } +V foo_83_3(V a, V b, V c) { return (~((c^b)&a))^b; } +V foo_83_4(V a, V b, V c) { return (~b|a)^(c&a); } +V foo_83_5(V a, V b, V c) { return ((~(c^b))|a)^c; } +V foo_83_6(V a, V b, V c) { return (~a|c)^(b|a); } + +V foo_84_1(V a, V b, V c) { return (b|a)&~c; } + +V foo_85_1(V a, V b, V c) { return ~c; } + +V foo_86_1(V a, V b, V c) { return (b|a)^c; } + +V foo_87_1(V a, V b, V c) { return ~((b|a)&c); } + +V foo_88_1(V a, V b, V c) { return (c^a)&(b|a); } +V foo_88_2(V a, V b, V c) { return ((b|a)&c)^a; } + +V foo_89_1(V a, V b, V c) { return (~b|a)^c; } + +V foo_90_1(V a, V b, V c) { return c^a; } + +V foo_91_1(V a, V b, V c) { return (~(b|a))|(c^a); } +V foo_91_2(V a, V b, V c) { return (~(c|b))|(c^a); } +V foo_91_3(V a, V b, V c) { return ((~(c|b))|a)^c; } +V foo_91_4(V a, V b, V c) { return ((~(b|a))|c)^a; } + +V foo_92_1(V a, V b, V c) { return (c&a)^(b|a); } +V foo_92_2(V a, V b, V c) { return ((c^b)|a)^c; } + +V foo_93_1(V a, V b, V c) { return ~((~b|a)&c); } +V foo_93_2(V a, V b, V c) { return (~a&b)|~c; } + +V foo_94_1(V a, V b, V c) { return (~a&b)|(c^a); } +V foo_94_2(V a, V b, V c) { return (~c&b)|(c^a); } +V foo_94_3(V a, V b, V c) { return ((~c&b)|a)^c; } +V foo_94_4(V a, V b, V c) { return ((~a&b)|c)^a; } + +V foo_95_1(V a, V b, V c) { return ~(c&a); } + +V foo_96_1(V a, V b, V c) { return (c^b)&a; } + +V foo_97_1(V a, V b, V c) { return ~(((c|b)^a)|(c&b)); } +V foo_97_2(V a, V b, V c) { return (~((c&b)|a))^(c^b); } +V foo_97_3(V a, V b, V c) { return (((c&b)|a)^c)^~b; } +V foo_97_4(V a, V b, V c) { return (((c&b)|a)^b)^~c; } +V foo_97_5(V a, V b, V c) { return ((c&b)|~a)^(c|b); } +V foo_97_6(V a, V b, V c) { return ((c&b)|a)^(~(c^b)); } +V foo_97_7(V a, V b, V c) { return (~(((c&b)|a)^b))^c; } +V foo_97_8(V a, V b, V c) { return (~(((c&b)|a)^c))^b; } + +V foo_98_1(V a, V b, V c) { return (c^b)&(c|a); } +V foo_98_2(V a, V b, V c) { return ((c|a)&b)^c; } + +V foo_99_1(V a, V b, V c) { return (~a|c)^b; } + +V foo_100_1(V a, V b, V c) { return (c^b)&(b|a); } +V foo_100_2(V a, V b, V c) { return ((b|a)&c)^b; } + +V foo_101_1(V a, V b, V c) { return (~a|b)^c; } + +V foo_102_1(V a, V b, V c) { return c^b; } + +V foo_103_1(V a, V b, V c) { return (~(b|a))|(c^b); } +V foo_103_2(V a, V b, V c) { return (~(c|a))|(c^b); } +V foo_103_3(V a, V b, V c) { return ((~(c|a))|b)^c; } +V foo_103_4(V a, V b, V c) { return ((~(b|a))|c)^b; } + +V foo_104_1(V a, V b, V c) { return ((b&a)^c)&(b|a); } +V foo_104_2(V a, V b, V c) { return ((c&a)^b)&(c|a); } +V foo_104_3(V a, V b, V c) { return ((c&b)^a)&(c|b); } +V foo_104_4(V a, V b, V c) { return ((c|b)&a)^(c&b); } +V foo_104_5(V a, V b, V c) { return ((c|a)&b)^(c&a); } +V foo_104_6(V a, V b, V c) { return ((b|a)&c)^(b&a); } + +V foo_105_1(V a, V b, V c) { return ~((b^a)^c); } +V foo_105_2(V a, V b, V c) { return (c^b)^~a; } +V foo_105_3(V a, V b, V c) { return (c^a)^~b; } +V foo_105_4(V a, V b, V c) { return (b^a)^~c; } +V foo_105_5(V a, V b, V c) { return (~(c^b))^a; } +V foo_105_6(V a, V b, V c) { return (~(c^a))^b; } +V foo_105_7(V a, V b, V c) { return (~(b^a))^c; } + +V foo_106_1(V a, V b, V c) { return (b&a)^c; } + +V foo_107_1(V a, V b, V c) { return ~(((b|a)&c)^(b^a)); } +V foo_107_2(V a, V b, V c) { return ((b&a)^c)|(~(b|a)); } +V foo_107_3(V a, V b, V c) { return ((c^b)&(b|a))^~a; } +V foo_107_4(V a, V b, V c) { return ((c^a)&(b|a))^~b; } +V foo_107_5(V a, V b, V c) { return (~((b|a)&c))^(b^a); } +V foo_107_6(V a, V b, V c) { return (~((c^b)&(b|a)))^a; } +V foo_107_7(V a, V b, V c) { return (~((c^a)&(b|a)))^b; } +V foo_107_8(V a, V b, V c) { return ((b|a)&c)^(~(b^a)); } +V foo_107_9(V a, V b, V c) { return ((~(b|a))|c)^(b&a); } + +V foo_108_1(V a, V b, V c) { return (c&a)^b; } + +V foo_109_1(V a, V b, V c) { return ~(((b^a)&(c|a))^c); } +V foo_109_2(V a, V b, V c) { return ((c&a)^b)|(~(c|a)); } +V foo_109_3(V a, V b, V c) { return ((c^b)&(c|a))^~a; } +V foo_109_4(V a, V b, V c) { return (~((c|a)&b))^(c^a); } +V foo_109_5(V a, V b, V c) { return ((b^a)&(c|a))^~c; } +V foo_109_6(V a, V b, V c) { return (~((c^b)&(c|a)))^a; } +V foo_109_7(V a, V b, V c) { return ((~(c|a))|b)^(c&a); } +V foo_109_8(V a, V b, V c) { return ((c|a)&b)^(~(c^a)); } +V foo_109_9(V a, V b, V c) { return (~((b^a)&(c|a)))^c; } + +V foo_110_1(V a, V b, V c) { return (~a&c)|(c^b); } +V foo_110_2(V a, V b, V c) { return (~a&b)|(c^b); } +V foo_110_3(V a, V b, V c) { return ((~b|a)&c)^b; } +V foo_110_4(V a, V b, V c) { return ((~c|a)&b)^c; } + +V foo_111_1(V a, V b, V c) { return (c^b)|~a; } + +V foo_112_1(V a, V b, V c) { return (~(c&b))&a; } + +V foo_113_1(V a, V b, V c) { return ~(((b^a)&(c^b))^c); } +V foo_113_2(V a, V b, V c) { return ((b^a)|(c^a))^~a; } +V foo_113_3(V a, V b, V c) { return ((c^b)&a)|(~(c|b)); } +V foo_113_4(V a, V b, V c) { return ((c^b)&a)^(~(c|b)); } +V foo_113_5(V a, V b, V c) { return ((b^a)&(c^b))^~c; } +V foo_113_6(V a, V b, V c) { return ((c^a)&(c^b))^~b; } +V foo_113_7(V a, V b, V c) { return (~((b^a)|(c^a)))^a; } +V foo_113_8(V a, V b, V c) { return ((~(c^b))|a)^(c&b); } +V foo_113_9(V a, V b, V c) { return (~((c^b)&a))^(c|b); } +V foo_113_10(V a, V b, V c) { return (~((b^a)&(c^b)))^c; } +V foo_113_11(V a, V b, V c) { return ((c^a)|b)^(~a|c); } +V foo_113_12(V a, V b, V c) { return (~((c^a)&(c^b)))^b; } +V foo_113_13(V a, V b, V c) { return ((b^a)|c)^(~a|b); } + +V foo_114_1(V a, V b, V c) { return (c&b)^(c|a); } +V foo_114_2(V a, V b, V c) { return ((b^a)|c)^b; } + +V foo_115_1(V a, V b, V c) { return ~((~a|c)&b); } +V foo_115_2(V a, V b, V c) { return (~c&a)|~b; } + +V foo_116_1(V a, V b, V c) { return (c&b)^(b|a); } +V foo_116_2(V a, V b, V c) { return ((c^a)|b)^c; } + +V foo_117_1(V a, V b, V c) { return ~((~a|b)&c); } +V foo_117_2(V a, V b, V c) { return (~b&a)|~c; } + +V foo_118_1(V a, V b, V c) { return (~b&a)|(c^b); } +V foo_118_2(V a, V b, V c) { return (~c&a)|(c^b); } +V foo_118_3(V a, V b, V c) { return ((~c&a)|b)^c; } +V foo_118_4(V a, V b, V c) { return ((~b&a)|c)^b; } + +V foo_119_1(V a, V b, V c) { return ~(c&b); } + +V foo_120_1(V a, V b, V c) { return (c&b)^a; } + +V foo_121_1(V a, V b, V c) { return ~(((b^a)&(c|b))^c); } +V foo_121_2(V a, V b, V c) { return ((c&b)^a)|(~(c|b)); } +V foo_121_3(V a, V b, V c) { return (~((c|b)&a))^(c^b); } +V foo_121_4(V a, V b, V c) { return ((b^a)&(c|b))^~c; } +V foo_121_5(V a, V b, V c) { return ((c^a)&(c|b))^~b; } +V foo_121_6(V a, V b, V c) { return ((~(c|b))|a)^(c&b); } +V foo_121_7(V a, V b, V c) { return ((c|b)&a)^(~(c^b)); } +V foo_121_8(V a, V b, V c) { return (~((b^a)&(c|b)))^c; } +V foo_121_9(V a, V b, V c) { return (~((c^a)&(c|b)))^b; } + +V foo_122_1(V a, V b, V c) { return (~b&c)|(c^a); } +V foo_122_2(V a, V b, V c) { return (~b&a)|(c^a); } +V foo_122_3(V a, V b, V c) { return ((~a|b)&c)^a; } +V foo_122_4(V a, V b, V c) { return ((~c|b)&a)^c; } + +V foo_123_1(V a, V b, V c) { return (c^a)|~b; } + +V foo_124_1(V a, V b, V c) { return (~c&b)|(b^a); } +V foo_124_2(V a, V b, V c) { return (~c&a)|(b^a); } +V foo_124_3(V a, V b, V c) { return ((~a|c)&b)^a; } +V foo_124_4(V a, V b, V c) { return ((~b|c)&a)^b; } + +V foo_125_1(V a, V b, V c) { return (b^a)|~c; } + +V foo_126_1(V a, V b, V c) { return (b^a)|(c^a); } +V foo_126_2(V a, V b, V c) { return (b^a)|(c^b); } +V foo_126_3(V a, V b, V c) { return (c^a)|(c^b); } + +V foo_127_1(V a, V b, V c) { return ~((c&b)&a); } + +V foo_128_1(V a, V b, V c) { return (c&b)&a; } +V foo_128_2(V a, V b, V c) { return (c&a)&b; } +V foo_128_3(V a, V b, V c) { return (b&a)&c; } + +V foo_129_1(V a, V b, V c) { return ~((b^a)|(c^a)); } + +V foo_130_1(V a, V b, V c) { return (~(b^a))&c; } + +V foo_131_1(V a, V b, V c) { return ~((~c&b)|(b^a)); } +V foo_131_2(V a, V b, V c) { return ((~a|c)&b)^~a; } +V foo_131_3(V a, V b, V c) { return ((~b|c)&a)^~b; } +V foo_131_4(V a, V b, V c) { return (~((~b|c)&a))^b; } +V foo_131_5(V a, V b, V c) { return (~((~a|c)&b))^a; } +V foo_131_6(V a, V b, V c) { return (~a|c)&(~(b^a)); } +V foo_131_7(V a, V b, V c) { return (~b|c)&(~(b^a)); } + +V foo_132_1(V a, V b, V c) { return (~(c^a))&b; } + +V foo_133_1(V a, V b, V c) { return ~((~b&c)|(c^a)); } +V foo_133_2(V a, V b, V c) { return ((~a|b)&c)^~a; } +V foo_133_3(V a, V b, V c) { return (~((~c|b)&a))^c; } +V foo_133_4(V a, V b, V c) { return ((~c|b)&a)^~c; } +V foo_133_5(V a, V b, V c) { return (~((~a|b)&c))^a; } +V foo_133_6(V a, V b, V c) { return (~(c^a))&(~a|b); } +V foo_133_7(V a, V b, V c) { return (~(c^a))&(~c|b); } + +V foo_134_1(V a, V b, V c) { return ((b^a)&(c|b))^c; } +V foo_134_2(V a, V b, V c) { return ((c^a)&(c|b))^b; } +V foo_134_3(V a, V b, V c) { return ((c|b)&a)^(c^b); } +V foo_134_4(V a, V b, V c) { return ((b^a)^c)&(c|b); } + +V foo_135_1(V a, V b, V c) { return ~((c&b)^a); } +V foo_135_2(V a, V b, V c) { return (c&b)^~a; } +V foo_135_3(V a, V b, V c) { return (~(c&b))^a; } + +V foo_136_1(V a, V b, V c) { return c&b; } + +V foo_137_1(V a, V b, V c) { return ~((~b&a)|(c^b)); } +V foo_137_2(V a, V b, V c) { return (~((~c&a)|b))^c; } +V foo_137_3(V a, V b, V c) { return ((~b&a)|c)^~b; } +V foo_137_4(V a, V b, V c) { return (~((~b&a)|c))^b; } +V foo_137_5(V a, V b, V c) { return ((~c&a)|b)^~c; } +V foo_137_6(V a, V b, V c) { return (~(c^b))&(~a|c); } +V foo_137_7(V a, V b, V c) { return (~(c^b))&(~a|b); } + +V foo_138_1(V a, V b, V c) { return (~a|b)&c; } + +V foo_139_1(V a, V b, V c) { return ~((c&b)^(b|a)); } +V foo_139_2(V a, V b, V c) { return (~(b|a))|(c&b); } +V foo_139_3(V a, V b, V c) { return (~(b|a))^(c&b); } +V foo_139_4(V a, V b, V c) { return (~((c^a)|b))^c; } +V foo_139_5(V a, V b, V c) { return ((c^a)|b)^~c; } +V foo_139_6(V a, V b, V c) { return (~(c&b))^(b|a); } +V foo_139_7(V a, V b, V c) { return ((c^a)|~b)^a; } + +V foo_140_1(V a, V b, V c) { return (~a|c)&b; } + +V foo_141_1(V a, V b, V c) { return ~((c&b)^(c|a)); } +V foo_141_2(V a, V b, V c) { return (~(c|a))|(c&b); } +V foo_141_3(V a, V b, V c) { return (~(c|a))^(c&b); } +V foo_141_4(V a, V b, V c) { return ((b^a)|c)^~b; } +V foo_141_5(V a, V b, V c) { return (~((b^a)|c))^b; } +V foo_141_6(V a, V b, V c) { return (~(c&b))^(c|a); } +V foo_141_7(V a, V b, V c) { return ((b^a)|~c)^a; } + +V foo_142_1(V a, V b, V c) { return ((b^a)&(c^b))^c; } +V foo_142_2(V a, V b, V c) { return ((c^a)&(c^b))^b; } +V foo_142_3(V a, V b, V c) { return ((c^b)&a)^(c|b); } +V foo_142_4(V a, V b, V c) { return ((b^a)|(c^a))^a; } + +V foo_143_1(V a, V b, V c) { return (c&b)|~a; } + +V foo_144_1(V a, V b, V c) { return (~(c^b))&a; } + +V foo_145_1(V a, V b, V c) { return ~((~a&c)|(c^b)); } +V foo_145_2(V a, V b, V c) { return ((~b|a)&c)^~b; } +V foo_145_3(V a, V b, V c) { return (~((~c|a)&b))^c; } +V foo_145_4(V a, V b, V c) { return ((~c|a)&b)^~c; } +V foo_145_5(V a, V b, V c) { return (~((~b|a)&c))^b; } +V foo_145_6(V a, V b, V c) { return (~(c^b))&(~b|a); } +V foo_145_7(V a, V b, V c) { return (~(c^b))&(~c|a); } + +V foo_146_1(V a, V b, V c) { return ((b^a)&(c|a))^c; } +V foo_146_2(V a, V b, V c) { return ((c|a)&b)^(c^a); } +V foo_146_3(V a, V b, V c) { return ((c^b)&(c|a))^a; } +V foo_146_4(V a, V b, V c) { return ((b^a)^c)&(c|a); } + +V foo_147_1(V a, V b, V c) { return ~((c&a)^b); } +V foo_147_2(V a, V b, V c) { return (c&a)^~b; } +V foo_147_3(V a, V b, V c) { return (~(c&a))^b; } + +V foo_148_1(V a, V b, V c) { return ((b|a)&c)^(b^a); } +V foo_148_2(V a, V b, V c) { return ((c^a)&(b|a))^b; } +V foo_148_3(V a, V b, V c) { return ((c^b)&(b|a))^a; } +V foo_148_4(V a, V b, V c) { return ((b^a)^c)&(b|a); } + +V foo_149_1(V a, V b, V c) { return ~((b&a)^c); } +V foo_149_2(V a, V b, V c) { return (~(b&a))^c; } +V foo_149_3(V a, V b, V c) { return (b&a)^~c; } + +V foo_150_1(V a, V b, V c) { return (b^a)^c; } +V foo_150_2(V a, V b, V c) { return (c^a)^b; } +V foo_150_3(V a, V b, V c) { return (c^b)^a; } + +V foo_151_1(V a, V b, V c) { return ~(((b&a)^c)&(b|a)); } +V foo_151_2(V a, V b, V c) { return ((b^a)^c)|(~(b|a)); } +V foo_151_3(V a, V b, V c) { return ((b^a)^c)|(~(c|a)); } +V foo_151_4(V a, V b, V c) { return ((b^a)^c)|(~(c|b)); } +V foo_151_5(V a, V b, V c) { return (~((c|b)&a))^(c&b); } +V foo_151_6(V a, V b, V c) { return (~((c|a)&b))^(c&a); } +V foo_151_7(V a, V b, V c) { return ((~(b|a))|c)^(b^a); } +V foo_151_8(V a, V b, V c) { return ((~(c|a))|(b^a))^c; } +V foo_151_9(V a, V b, V c) { return ((b|a)&c)^(~(b&a)); } +V foo_151_10(V a, V b, V c) { return (~((b|a)&c))^(b&a); } +V foo_151_11(V a, V b, V c) { return ((~(c|a))|b)^(c^a); } +V foo_151_12(V a, V b, V c) { return ((~(b|a))|(c^a))^b; } +V foo_151_13(V a, V b, V c) { return ((c|a)&b)^(~(c&a)); } +V foo_151_14(V a, V b, V c) { return ((~(c|b))|a)^(c^b); } +V foo_151_15(V a, V b, V c) { return ((~(b|a))|(c^b))^a; } +V foo_151_16(V a, V b, V c) { return ((c|b)&a)^(~(c&b)); } + +V foo_152_1(V a, V b, V c) { return ((c|a)&~b)^c; } +V foo_152_2(V a, V b, V c) { return ((b|a)&~c)^b; } +V foo_152_3(V a, V b, V c) { return (~(c^b))&(c|a); } +V foo_152_4(V a, V b, V c) { return (~(c^b))&(b|a); } + +V foo_153_1(V a, V b, V c) { return ~(c^b); } +V foo_153_2(V a, V b, V c) { return ~b^c; } +V foo_153_3(V a, V b, V c) { return ~c^b; } + +V foo_154_1(V a, V b, V c) { return (~b&a)^c; } + +V foo_155_1(V a, V b, V c) { return ~((c^b)&(b|a)); } +V foo_155_2(V a, V b, V c) { return ((b|a)&c)^~b; } +V foo_155_3(V a, V b, V c) { return (~((b|a)&c))^b; } + +V foo_156_1(V a, V b, V c) { return (~c&a)^b; } + +V foo_157_1(V a, V b, V c) { return ~((c^b)&(c|a)); } +V foo_157_2(V a, V b, V c) { return (~((c|a)&b))^c; } +V foo_157_3(V a, V b, V c) { return ((c|a)&b)^~c; } + +V foo_158_1(V a, V b, V c) { return ((c|b)^a)|(c&b); } +V foo_158_2(V a, V b, V c) { return (((c&b)|a)^b)^c; } +V foo_158_3(V a, V b, V c) { return (((c&b)|a)^c)^b; } +V foo_158_4(V a, V b, V c) { return ((c&b)|a)^(c^b); } +V foo_158_5(V a, V b, V c) { return ((b^a)^c)|(c&b); } + +V foo_159_1(V a, V b, V c) { return ~((c^b)&a); } + +V foo_160_1(V a, V b, V c) { return c&a; } + +V foo_161_1(V a, V b, V c) { return ~((~a&b)|(c^a)); } +V foo_161_2(V a, V b, V c) { return (~((~c&b)|a))^c; } +V foo_161_3(V a, V b, V c) { return ((~a&b)|c)^~a; } +V foo_161_4(V a, V b, V c) { return (~((~a&b)|c))^a; } +V foo_161_5(V a, V b, V c) { return ((~c&b)|a)^~c; } +V foo_161_6(V a, V b, V c) { return (~(c^a))&(~b|c); } +V foo_161_7(V a, V b, V c) { return (~(c^a))&(~b|a); } + +V foo_162_1(V a, V b, V c) { return (~b|a)&c; } + +V foo_163_1(V a, V b, V c) { return ~((c&a)^(b|a)); } +V foo_163_2(V a, V b, V c) { return (~(b|a))|(c&a); } +V foo_163_3(V a, V b, V c) { return (~(b|a))^(c&a); } +V foo_163_4(V a, V b, V c) { return (~((c^b)|a))^c; } +V foo_163_5(V a, V b, V c) { return ((c^b)|a)^~c; } +V foo_163_6(V a, V b, V c) { return (~(c&a))^(b|a); } +V foo_163_7(V a, V b, V c) { return ((c^b)|~a)^b; } + +V foo_164_1(V a, V b, V c) { return ((c|b)&~a)^c; } +V foo_164_2(V a, V b, V c) { return ((b|a)&~c)^a; } +V foo_164_3(V a, V b, V c) { return (~(c^a))&(c|b); } +V foo_164_4(V a, V b, V c) { return (~(c^a))&(b|a); } + +V foo_165_1(V a, V b, V c) { return ~(c^a); } +V foo_165_2(V a, V b, V c) { return ~a^c; } +V foo_165_3(V a, V b, V c) { return ~c^a; } + +V foo_166_1(V a, V b, V c) { return (~a&b)^c; } + +V foo_167_1(V a, V b, V c) { return ~((c^a)&(b|a)); } +V foo_167_2(V a, V b, V c) { return ((b|a)&c)^~a; } +V foo_167_3(V a, V b, V c) { return (~((b|a)&c))^a; } + +V foo_168_1(V a, V b, V c) { return (b|a)&c; } + +V foo_169_1(V a, V b, V c) { return ~((b|a)^c); } +V foo_169_2(V a, V b, V c) { return (~(b|a))^c; } +V foo_169_3(V a, V b, V c) { return (b|a)^~c; } + +V foo_170_1(V a, V b, V c) { return c; } + +V foo_171_1(V a, V b, V c) { return (~(b|a))|c; } + +V foo_172_1(V a, V b, V c) { return ((c^b)&a)^b; } + +V foo_173_1(V a, V b, V c) { return ~(((c&b)|a)^c); } +V foo_173_2(V a, V b, V c) { return (~((c&b)|a))^c; } +V foo_173_3(V a, V b, V c) { return ((c&b)|a)^~c; } +V foo_173_4(V a, V b, V c) { return (~(c^a))|(c&b); } + +V foo_174_1(V a, V b, V c) { return (~a&b)|c; } + +V foo_175_1(V a, V b, V c) { return ~a|c; } + +V foo_176_1(V a, V b, V c) { return (~b|c)&a; } + +V foo_177_1(V a, V b, V c) { return ~((c&a)^(c|b)); } +V foo_177_2(V a, V b, V c) { return ((b^a)|c)^~a; } +V foo_177_3(V a, V b, V c) { return (~(c|b))|(c&a); } +V foo_177_4(V a, V b, V c) { return (~(c|b))^(c&a); } +V foo_177_5(V a, V b, V c) { return (~((b^a)|c))^a; } +V foo_177_6(V a, V b, V c) { return (~(c&a))^(c|b); } +V foo_177_7(V a, V b, V c) { return ((b^a)|~c)^b; } + +V foo_178_1(V a, V b, V c) { return ((b^a)&(c^a))^c; } +V foo_178_2(V a, V b, V c) { return ((c^a)&(c^b))^a; } +V foo_178_3(V a, V b, V c) { return ((c^a)&b)^(c|a); } +V foo_178_4(V a, V b, V c) { return ((b^a)|(c^a))^b; } + +V foo_179_1(V a, V b, V c) { return (c&a)|~b; } + +V foo_180_1(V a, V b, V c) { return (~c&b)^a; } + +V foo_181_1(V a, V b, V c) { return ~((c^a)&(c|b)); } +V foo_181_2(V a, V b, V c) { return (~((c|b)&a))^c; } +V foo_181_3(V a, V b, V c) { return ((c|b)&a)^~c; } + +V foo_182_1(V a, V b, V c) { return (((c&a)|b)^a)^c; } +V foo_182_2(V a, V b, V c) { return ((c|a)^b)|(c&a); } +V foo_182_3(V a, V b, V c) { return (((c&a)|b)^c)^a; } +V foo_182_4(V a, V b, V c) { return ((c&a)|b)^(c^a); } +V foo_182_5(V a, V b, V c) { return ((b^a)^c)|(c&a); } + +V foo_183_1(V a, V b, V c) { return ~((c^a)&b); } + +V foo_184_1(V a, V b, V c) { return ((c^a)&b)^a; } + +V foo_185_1(V a, V b, V c) { return ~(((c&a)|b)^c); } +V foo_185_2(V a, V b, V c) { return (~((c&a)|b))^c; } +V foo_185_3(V a, V b, V c) { return ((c&a)|b)^~c; } +V foo_185_4(V a, V b, V c) { return (~(c^b))|(c&a); } + +V foo_186_1(V a, V b, V c) { return (~b&a)|c; } + +V foo_187_1(V a, V b, V c) { return ~b|c; } + +V foo_188_1(V a, V b, V c) { return (b^a)|(c&b); } +V foo_188_2(V a, V b, V c) { return (b^a)|(c&a); } + +V foo_189_1(V a, V b, V c) { return ~((c^a)&(c^b)); } +V foo_189_2(V a, V b, V c) { return (~(c^b))|(b^a); } +V foo_189_3(V a, V b, V c) { return (~(c^a))|(b^a); } + +V foo_190_1(V a, V b, V c) { return (b^a)|c; } + +V foo_191_1(V a, V b, V c) { return (~(b&a))|c; } + +V foo_192_1(V a, V b, V c) { return b&a; } + +V foo_193_1(V a, V b, V c) { return ~((~a&c)|(b^a)); } +V foo_193_2(V a, V b, V c) { return (~((~b&c)|a))^b; } +V foo_193_3(V a, V b, V c) { return ((~a&c)|b)^~a; } +V foo_193_4(V a, V b, V c) { return (~((~a&c)|b))^a; } +V foo_193_5(V a, V b, V c) { return ((~b&c)|a)^~b; } +V foo_193_6(V a, V b, V c) { return (~(b^a))&(~c|b); } +V foo_193_7(V a, V b, V c) { return (~(b^a))&(~c|a); } + +V foo_194_1(V a, V b, V c) { return ((c|b)&~a)^b; } +V foo_194_2(V a, V b, V c) { return ((c|a)&~b)^a; } +V foo_194_3(V a, V b, V c) { return (~(b^a))&(c|b); } +V foo_194_4(V a, V b, V c) { return (~(b^a))&(c|a); } + +V foo_195_1(V a, V b, V c) { return ~(b^a); } +V foo_195_2(V a, V b, V c) { return ~a^b; } +V foo_195_3(V a, V b, V c) { return ~b^a; } + +V foo_196_1(V a, V b, V c) { return (~c|a)&b; } + +V foo_197_1(V a, V b, V c) { return ~((b&a)^(c|a)); } +V foo_197_2(V a, V b, V c) { return (~(c|a))|(b&a); } +V foo_197_3(V a, V b, V c) { return (~(c|a))^(b&a); } +V foo_197_4(V a, V b, V c) { return (~((c^b)|a))^b; } +V foo_197_5(V a, V b, V c) { return ((c^b)|a)^~b; } +V foo_197_6(V a, V b, V c) { return (~(b&a))^(c|a); } +V foo_197_7(V a, V b, V c) { return ((c^b)|~a)^c; } + +V foo_198_1(V a, V b, V c) { return (~a&c)^b; } + +V foo_199_1(V a, V b, V c) { return ~((b^a)&(c|a)); } +V foo_199_2(V a, V b, V c) { return ((c|a)&b)^~a; } +V foo_199_3(V a, V b, V c) { return (~((c|a)&b))^a; } + +V foo_200_1(V a, V b, V c) { return (c|a)&b; } + +V foo_201_1(V a, V b, V c) { return ~((c|a)^b); } +V foo_201_2(V a, V b, V c) { return (~(c|a))^b; } +V foo_201_3(V a, V b, V c) { return (c|a)^~b; } + +V foo_202_1(V a, V b, V c) { return ((c^b)&a)^c; } + +V foo_203_1(V a, V b, V c) { return ~(((c&b)|a)^b); } +V foo_203_2(V a, V b, V c) { return (~((c&b)|a))^b; } +V foo_203_3(V a, V b, V c) { return ((c&b)|a)^~b; } +V foo_203_4(V a, V b, V c) { return (~(b^a))|(c&b); } + +V foo_204_1(V a, V b, V c) { return b; } + +V foo_205_1(V a, V b, V c) { return (~(c|a))|b; } + +V foo_206_1(V a, V b, V c) { return (~a&c)|b; } + +V foo_207_1(V a, V b, V c) { return ~a|b; } + +V foo_208_1(V a, V b, V c) { return (~c|b)&a; } + +V foo_209_1(V a, V b, V c) { return ~((b&a)^(c|b)); } +V foo_209_2(V a, V b, V c) { return ((c^a)|b)^~a; } +V foo_209_3(V a, V b, V c) { return (~(c|b))|(b&a); } +V foo_209_4(V a, V b, V c) { return (~(c|b))^(b&a); } +V foo_209_5(V a, V b, V c) { return (~((c^a)|b))^a; } +V foo_209_6(V a, V b, V c) { return (~(b&a))^(c|b); } +V foo_209_7(V a, V b, V c) { return ((c^a)|~b)^c; } + +V foo_210_1(V a, V b, V c) { return (~b&c)^a; } + +V foo_211_1(V a, V b, V c) { return ~((b^a)&(c|b)); } +V foo_211_2(V a, V b, V c) { return (~((c|b)&a))^b; } +V foo_211_3(V a, V b, V c) { return ((c|b)&a)^~b; } + +V foo_212_1(V a, V b, V c) { return ((b^a)&(c^a))^b; } +V foo_212_2(V a, V b, V c) { return ((b^a)&(c^b))^a; } +V foo_212_3(V a, V b, V c) { return ((b^a)&c)^(b|a); } +V foo_212_4(V a, V b, V c) { return ((b^a)|(c^a))^c; } + +V foo_213_1(V a, V b, V c) { return (b&a)|~c; } + +V foo_214_1(V a, V b, V c) { return (((b&a)|c)^a)^b; } +V foo_214_2(V a, V b, V c) { return (((b&a)|c)^b)^a; } +V foo_214_3(V a, V b, V c) { return ((b&a)|c)^(b^a); } +V foo_214_4(V a, V b, V c) { return ((b|a)^c)|(b&a); } +V foo_214_5(V a, V b, V c) { return ((b^a)^c)|(b&a); } + +V foo_215_1(V a, V b, V c) { return ~((b^a)&c); } + +V foo_216_1(V a, V b, V c) { return ((b^a)&c)^a; } + +V foo_217_1(V a, V b, V c) { return ~(((b&a)|c)^b); } +V foo_217_2(V a, V b, V c) { return (~((b&a)|c))^b; } +V foo_217_3(V a, V b, V c) { return ((b&a)|c)^~b; } +V foo_217_4(V a, V b, V c) { return (~(c^b))|(b&a); } + +V foo_218_1(V a, V b, V c) { return (c^a)|(c&b); } +V foo_218_2(V a, V b, V c) { return (c^a)|(b&a); } + +V foo_219_1(V a, V b, V c) { return ~((b^a)&(c^b)); } +V foo_219_2(V a, V b, V c) { return (~(c^b))|(c^a); } +V foo_219_3(V a, V b, V c) { return (~(b^a))|(c^a); } + +V foo_220_1(V a, V b, V c) { return (~c&a)|b; } + +V foo_221_1(V a, V b, V c) { return ~c|b; } + +V foo_222_1(V a, V b, V c) { return (c^a)|b; } + +V foo_223_1(V a, V b, V c) { return (~(c&a))|b; } + +V foo_224_1(V a, V b, V c) { return (c|b)&a; } + +V foo_225_1(V a, V b, V c) { return ~((c|b)^a); } +V foo_225_2(V a, V b, V c) { return (c|b)^~a; } +V foo_225_3(V a, V b, V c) { return (~(c|b))^a; } + +V foo_226_1(V a, V b, V c) { return ((c^a)&b)^c; } + +V foo_227_1(V a, V b, V c) { return ~(((c&a)|b)^a); } +V foo_227_2(V a, V b, V c) { return ((c&a)|b)^~a; } +V foo_227_3(V a, V b, V c) { return (~((c&a)|b))^a; } +V foo_227_4(V a, V b, V c) { return (~(b^a))|(c&a); } + +V foo_228_1(V a, V b, V c) { return ((b^a)&c)^b; } + +V foo_229_1(V a, V b, V c) { return ~(((b&a)|c)^a); } +V foo_229_2(V a, V b, V c) { return ((b&a)|c)^~a; } +V foo_229_3(V a, V b, V c) { return (~((b&a)|c))^a; } +V foo_229_4(V a, V b, V c) { return (~(c^a))|(b&a); } + +V foo_230_1(V a, V b, V c) { return (c^b)|(c&a); } +V foo_230_2(V a, V b, V c) { return (c^b)|(b&a); } + +V foo_231_1(V a, V b, V c) { return ~((b^a)&(c^a)); } +V foo_231_2(V a, V b, V c) { return (~(c^a))|(c^b); } +V foo_231_3(V a, V b, V c) { return (~(b^a))|(c^b); } + +V foo_232_1(V a, V b, V c) { return ((b^a)&(c^a))^a; } +V foo_232_2(V a, V b, V c) { return ((b^a)&(c^b))^b; } +V foo_232_3(V a, V b, V c) { return ((b^a)&c)|(b&a); } +V foo_232_4(V a, V b, V c) { return ((b^a)&c)^(b&a); } +V foo_232_5(V a, V b, V c) { return ((c^a)&(c^b))^c; } +V foo_232_6(V a, V b, V c) { return ((c^a)&b)|(c&a); } +V foo_232_7(V a, V b, V c) { return ((c^a)&b)^(c&a); } +V foo_232_8(V a, V b, V c) { return ((c^b)&a)|(c&b); } +V foo_232_9(V a, V b, V c) { return ((c^b)&a)^(c&b); } +V foo_232_10(V a, V b, V c) { return ((c|b)&a)|(c&b); } +V foo_232_11(V a, V b, V c) { return ((c|a)&b)|(c&a); } +V foo_232_12(V a, V b, V c) { return ((b|a)&c)|(b&a); } +V foo_232_13(V a, V b, V c) { return ((b&a)|c)&(b|a); } +V foo_232_14(V a, V b, V c) { return ((c&a)|b)&(c|a); } +V foo_232_15(V a, V b, V c) { return ((c&b)|a)&(c|b); } + +V foo_233_1(V a, V b, V c) { return ~(((b^a)|(c&b))^c); } +V foo_233_2(V a, V b, V c) { return ((b&a)|c)^(~(b|a)); } +V foo_233_3(V a, V b, V c) { return ((c&a)|b)^(~(c|a)); } +V foo_233_4(V a, V b, V c) { return (~((c&b)|a))^(c|b); } +V foo_233_5(V a, V b, V c) { return ((c^b)|(c&a))^~a; } +V foo_233_6(V a, V b, V c) { return ((c&b)|a)^(~(c|b)); } +V foo_233_7(V a, V b, V c) { return (~((c&a)|b))^(c|a); } +V foo_233_8(V a, V b, V c) { return (~((b&a)|c))^(b|a); } +V foo_233_9(V a, V b, V c) { return (~((c^b)|(c&a)))^a; } +V foo_233_10(V a, V b, V c) { return (~((c^a)|(c&b)))^b; } +V foo_233_11(V a, V b, V c) { return ((c^a)|(c&b))^~b; } +V foo_233_12(V a, V b, V c) { return ((b&a)|~c)^(b^a); } +V foo_233_13(V a, V b, V c) { return (~((b^a)|(c&b)))^c; } +V foo_233_14(V a, V b, V c) { return ((b^a)|(c&b))^~c; } +V foo_233_15(V a, V b, V c) { return ((c&a)|~b)^(c^a); } +V foo_233_16(V a, V b, V c) { return ((c&b)|~a)^(c^b); } +V foo_233_17(V a, V b, V c) { return (~((b^a)^c))|(c&b); } +V foo_233_18(V a, V b, V c) { return (~((b^a)^c))|(c&a); } +V foo_233_19(V a, V b, V c) { return (~((b^a)^c))|(b&a); } +V foo_233_20(V a, V b, V c) { return (~((c|b)^a))|(c&b); } +V foo_233_21(V a, V b, V c) { return (~((c|a)^b))|(c&a); } +V foo_233_22(V a, V b, V c) { return (~((b|a)^c))|(b&a); } + +V foo_234_1(V a, V b, V c) { return (b&a)|c; } + +V foo_235_1(V a, V b, V c) { return (~(b^a))|c; } + +V foo_236_1(V a, V b, V c) { return (c&a)|b; } + +V foo_237_1(V a, V b, V c) { return (~(c^a))|b; } + +V foo_238_1(V a, V b, V c) { return c|b; } + +V foo_239_1(V a, V b, V c) { return (c|b)|~a; } +V foo_239_2(V a, V b, V c) { return (~a|b)|c; } +V foo_239_3(V a, V b, V c) { return (~a|c)|b; } + +V foo_240_1(V a, V b, V c) { return a; } + +V foo_241_1(V a, V b, V c) { return (~(c|b))|a; } + +V foo_242_1(V a, V b, V c) { return (~b&c)|a; } + +V foo_243_1(V a, V b, V c) { return ~b|a; } + +V foo_244_1(V a, V b, V c) { return (~c&b)|a; } + +V foo_245_1(V a, V b, V c) { return ~c|a; } + +V foo_246_1(V a, V b, V c) { return (c^b)|a; } + +V foo_247_1(V a, V b, V c) { return (~(c&b))|a; } + +V foo_248_1(V a, V b, V c) { return (c&b)|a; } + +V foo_249_1(V a, V b, V c) { return (~(c^b))|a; } + +V foo_250_1(V a, V b, V c) { return c|a; } + +V foo_251_1(V a, V b, V c) { return (c|a)|~b; } +V foo_251_2(V a, V b, V c) { return (~b|a)|c; } +V foo_251_3(V a, V b, V c) { return (~b|c)|a; } + +V foo_252_1(V a, V b, V c) { return b|a; } + +V foo_253_1(V a, V b, V c) { return (b|a)|~c; } +V foo_253_2(V a, V b, V c) { return (~c|a)|b; } +V foo_253_3(V a, V b, V c) { return (~c|b)|a; } + +V foo_254_1(V a, V b, V c) { return (b|a)|c; } +V foo_254_2(V a, V b, V c) { return (c|a)|b; } +V foo_254_3(V a, V b, V c) { return (c|b)|a; } + +V foo_255_1(V a, V b, V c) { return (V){~0,~0,~0,~0}; } + +/* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]" 694 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-4.c b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-4.c new file mode 100644 index 00000000000..14296508cac --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-4.c @@ -0,0 +1,955 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx512f" } */ + +typedef unsigned int V __attribute__ ((__vector_size__ (32))); + +V foo_0_1(V a, V b, V c) { return (V){0,0,0,0}; } + +V foo_1_1(V a, V b, V c) { return ~((b|a)|c); } + +V foo_2_1(V a, V b, V c) { return (~(b|a))&c; } + +V foo_3_1(V a, V b, V c) { return ~(b|a); } + +V foo_4_1(V a, V b, V c) { return (~(c|a))&b; } + +V foo_5_1(V a, V b, V c) { return ~(c|a); } + +V foo_6_1(V a, V b, V c) { return (c^b)&~a; } + +V foo_7_1(V a, V b, V c) { return ~((c&b)|a); } + +V foo_8_1(V a, V b, V c) { return (~a&c)&b; } +V foo_8_2(V a, V b, V c) { return (~a&b)&c; } +V foo_8_3(V a, V b, V c) { return (c&b)&~a; } + +V foo_9_1(V a, V b, V c) { return ~((c^b)|a); } + +V foo_10_1(V a, V b, V c) { return ~a&c; } + +V foo_11_1(V a, V b, V c) { return ~((~c&b)|a); } +V foo_11_2(V a, V b, V c) { return (~b|c)&~a; } + +V foo_12_1(V a, V b, V c) { return ~a&b; } + +V foo_13_1(V a, V b, V c) { return ~((~b&c)|a); } +V foo_13_2(V a, V b, V c) { return (~c|b)&~a; } + +V foo_14_1(V a, V b, V c) { return (c|b)&~a; } + +V foo_15_1(V a, V b, V c) { return ~a; } + +V foo_16_1(V a, V b, V c) { return (~(c|b))&a; } + +V foo_17_1(V a, V b, V c) { return ~(c|b); } + +V foo_18_1(V a, V b, V c) { return (c^a)&~b; } + +V foo_19_1(V a, V b, V c) { return ~((c&a)|b); } + +V foo_20_1(V a, V b, V c) { return (b^a)&~c; } + +V foo_21_1(V a, V b, V c) { return ~((b&a)|c); } + +V foo_22_1(V a, V b, V c) { return ((b^a)|(c&b))^c; } +V foo_22_2(V a, V b, V c) { return ((c^a)|(c&b))^b; } +V foo_22_3(V a, V b, V c) { return ((c^b)|(c&a))^a; } +V foo_22_4(V a, V b, V c) { return ((b&a)|c)^(b|a); } +V foo_22_5(V a, V b, V c) { return ((c&a)|b)^(c|a); } +V foo_22_6(V a, V b, V c) { return ((c&b)|a)^(c|b); } + +V foo_23_1(V a, V b, V c) { return ~(((b^a)&(c^a))^a); } +V foo_23_2(V a, V b, V c) { return ((b^a)&(c^a))^~a; } +V foo_23_3(V a, V b, V c) { return ((b^a)&(c^b))^~b; } +V foo_23_4(V a, V b, V c) { return ((b^a)&c)^(~(b&a)); } +V foo_23_5(V a, V b, V c) { return ((c^a)&(c^b))^~c; } +V foo_23_6(V a, V b, V c) { return ((c^a)&b)^(~(c&a)); } +V foo_23_7(V a, V b, V c) { return ((c^b)&a)^(~(c&b)); } +V foo_23_8(V a, V b, V c) { return (~((c^b)&a))^(c&b); } +V foo_23_9(V a, V b, V c) { return (~((c^a)&b))^(c&a); } +V foo_23_10(V a, V b, V c) { return (~((c^a)&(c^b)))^c; } +V foo_23_11(V a, V b, V c) { return (~((b^a)&c))^(b&a); } +V foo_23_12(V a, V b, V c) { return (~((b^a)&(c^b)))^b; } +V foo_23_13(V a, V b, V c) { return (~((b^a)&(c^a)))^a; } +V foo_23_14(V a, V b, V c) { return ((~(b^a))|c)^(b|a); } +V foo_23_15(V a, V b, V c) { return ((~(c^a))|b)^(c|a); } +V foo_23_16(V a, V b, V c) { return ((~(c^b))|a)^(c|b); } + +V foo_24_1(V a, V b, V c) { return (b^a)&(c^a); } + +V foo_25_1(V a, V b, V c) { return ~((c^b)|(c&a)); } +V foo_25_2(V a, V b, V c) { return ((c&a)|~b)^c; } +V foo_25_3(V a, V b, V c) { return ((b&a)|~c)^b; } + +V foo_26_1(V a, V b, V c) { return ((b&a)|c)^a; } + +V foo_27_1(V a, V b, V c) { return ~(((b^a)&c)^b); } +V foo_27_2(V a, V b, V c) { return ((b^a)&c)^~b; } +V foo_27_3(V a, V b, V c) { return (~b|c)^(c&a); } +V foo_27_4(V a, V b, V c) { return (~((b^a)&c))^b; } +V foo_27_5(V a, V b, V c) { return ((~(b^a))|c)^a; } +V foo_27_6(V a, V b, V c) { return (~c|a)^(c|b); } + +V foo_28_1(V a, V b, V c) { return ((c&a)|b)^a; } + +V foo_29_1(V a, V b, V c) { return ~(((c^a)&b)^c); } +V foo_29_2(V a, V b, V c) { return ((c^a)&b)^~c; } +V foo_29_3(V a, V b, V c) { return (~((c^a)&b))^c; } +V foo_29_4(V a, V b, V c) { return (~c|b)^(b&a); } +V foo_29_5(V a, V b, V c) { return ((~(c^a))|b)^a; } +V foo_29_6(V a, V b, V c) { return (~b|a)^(c|b); } + +V foo_30_1(V a, V b, V c) { return (c|b)^a; } + +V foo_31_1(V a, V b, V c) { return ~((c|b)&a); } + +V foo_32_1(V a, V b, V c) { return (~b&c)&a; } +V foo_32_2(V a, V b, V c) { return (~b&a)&c; } +V foo_32_3(V a, V b, V c) { return (c&a)&~b; } + +V foo_33_1(V a, V b, V c) { return ~((c^a)|b); } + +V foo_34_1(V a, V b, V c) { return ~b&c; } + +V foo_35_1(V a, V b, V c) { return ~((~c&a)|b); } +V foo_35_2(V a, V b, V c) { return (~a|c)&~b; } + +V foo_36_1(V a, V b, V c) { return (b^a)&(c^b); } + +V foo_37_1(V a, V b, V c) { return ~((c^a)|(c&b)); } +V foo_37_2(V a, V b, V c) { return ((c&b)|~a)^c; } +V foo_37_3(V a, V b, V c) { return ((b&a)|~c)^a; } + +V foo_38_1(V a, V b, V c) { return ((b&a)|c)^b; } + +V foo_39_1(V a, V b, V c) { return ~(((b^a)&c)^a); } +V foo_39_2(V a, V b, V c) { return ((b^a)&c)^~a; } +V foo_39_3(V a, V b, V c) { return (~a|c)^(c&b); } +V foo_39_4(V a, V b, V c) { return ((~(b^a))|c)^b; } +V foo_39_5(V a, V b, V c) { return (~((b^a)&c))^a; } +V foo_39_6(V a, V b, V c) { return (~c|b)^(c|a); } + +V foo_40_1(V a, V b, V c) { return (b^a)&c; } + +V foo_41_1(V a, V b, V c) { return ~((((b&a)|c)^a)^b); } +V foo_41_2(V a, V b, V c) { return (((b&a)|c)^b)^~a; } +V foo_41_3(V a, V b, V c) { return (~((b&a)|c))^(b^a); } +V foo_41_4(V a, V b, V c) { return (((b&a)|c)^a)^~b; } +V foo_41_5(V a, V b, V c) { return ((b&a)|c)^(~(b^a)); } +V foo_41_6(V a, V b, V c) { return (~(((b&a)|c)^a))^b; } +V foo_41_7(V a, V b, V c) { return ((b&a)|~c)^(b|a); } +V foo_41_8(V a, V b, V c) { return (~(((b&a)|c)^b))^a; } + +V foo_42_1(V a, V b, V c) { return (~(b&a))&c; } + +V foo_43_1(V a, V b, V c) { return ~(((b^a)&(c^a))^b); } +V foo_43_2(V a, V b, V c) { return ((b^a)&c)|(~(b|a)); } +V foo_43_3(V a, V b, V c) { return ((b^a)&c)^(~(b|a)); } +V foo_43_4(V a, V b, V c) { return ((b^a)&(c^b))^~a; } +V foo_43_5(V a, V b, V c) { return ((b^a)&(c^a))^~b; } +V foo_43_6(V a, V b, V c) { return ((b^a)|(c^a))^~c; } +V foo_43_7(V a, V b, V c) { return (~((b^a)|(c^a)))^c; } +V foo_43_8(V a, V b, V c) { return ((~(b^a))|c)^(b&a); } +V foo_43_9(V a, V b, V c) { return (~((b^a)&(c^a)))^b; } +V foo_43_10(V a, V b, V c) { return (~((b^a)&c))^(b|a); } +V foo_43_11(V a, V b, V c) { return (~((b^a)&(c^b)))^a; } +V foo_43_12(V a, V b, V c) { return ((c^b)|a)^(~c|b); } +V foo_43_13(V a, V b, V c) { return ((c^a)|b)^(~c|a); } + +V foo_44_1(V a, V b, V c) { return (b^a)&(c|b); } +V foo_44_2(V a, V b, V c) { return ((c|b)&a)^b; } + +V foo_45_1(V a, V b, V c) { return (~c|b)^a; } + +V foo_46_1(V a, V b, V c) { return (b&a)^(c|b); } +V foo_46_2(V a, V b, V c) { return ((c^a)|b)^a; } + +V foo_47_1(V a, V b, V c) { return ~((~c|b)&a); } +V foo_47_2(V a, V b, V c) { return (~b&c)|~a; } + +V foo_48_1(V a, V b, V c) { return ~b&a; } + +V foo_49_1(V a, V b, V c) { return ~((~a&c)|b); } +V foo_49_2(V a, V b, V c) { return (~c|a)&~b; } + +V foo_50_1(V a, V b, V c) { return (c|a)&~b; } + +V foo_51_1(V a, V b, V c) { return ~b; } + +V foo_52_1(V a, V b, V c) { return ((c&b)|a)^b; } + +V foo_53_1(V a, V b, V c) { return ~(((c^b)&a)^c); } +V foo_53_2(V a, V b, V c) { return ((c^b)&a)^~c; } +V foo_53_3(V a, V b, V c) { return (~((c^b)&a))^c; } +V foo_53_4(V a, V b, V c) { return (~c|a)^(b&a); } +V foo_53_5(V a, V b, V c) { return ((~(c^b))|a)^b; } +V foo_53_6(V a, V b, V c) { return (~a|b)^(c|a); } + +V foo_54_1(V a, V b, V c) { return (c|a)^b; } + +V foo_55_1(V a, V b, V c) { return ~((c|a)&b); } + +V foo_56_1(V a, V b, V c) { return (b^a)&(c|a); } +V foo_56_2(V a, V b, V c) { return ((c|a)&b)^a; } + +V foo_57_1(V a, V b, V c) { return (~c|a)^b; } + +V foo_58_1(V a, V b, V c) { return (b&a)^(c|a); } +V foo_58_2(V a, V b, V c) { return ((c^b)|a)^b; } + +V foo_59_1(V a, V b, V c) { return ~((~c|a)&b); } +V foo_59_2(V a, V b, V c) { return (~a&c)|~b; } + +V foo_60_1(V a, V b, V c) { return b^a; } + +V foo_61_1(V a, V b, V c) { return (~(c|a))|(b^a); } +V foo_61_2(V a, V b, V c) { return (~(c|b))|(b^a); } +V foo_61_3(V a, V b, V c) { return ((~(c|b))|a)^b; } +V foo_61_4(V a, V b, V c) { return ((~(c|a))|b)^a; } + +V foo_62_1(V a, V b, V c) { return (~a&c)|(b^a); } +V foo_62_2(V a, V b, V c) { return (~b&c)|(b^a); } +V foo_62_3(V a, V b, V c) { return ((~b&c)|a)^b; } +V foo_62_4(V a, V b, V c) { return ((~a&c)|b)^a; } + +V foo_63_1(V a, V b, V c) { return ~(b&a); } + +V foo_64_1(V a, V b, V c) { return (~c&b)&a; } +V foo_64_2(V a, V b, V c) { return (~c&a)&b; } +V foo_64_3(V a, V b, V c) { return (b&a)&~c; } + +V foo_65_1(V a, V b, V c) { return ~((b^a)|c); } + +V foo_66_1(V a, V b, V c) { return (c^a)&(c^b); } + +V foo_67_1(V a, V b, V c) { return ~((b^a)|(c&b)); } +V foo_67_2(V a, V b, V c) { return ((c&b)|~a)^b; } +V foo_67_3(V a, V b, V c) { return ((c&a)|~b)^a; } + +V foo_68_1(V a, V b, V c) { return ~c&b; } + +V foo_69_1(V a, V b, V c) { return ~((~b&a)|c); } +V foo_69_2(V a, V b, V c) { return (~a|b)&~c; } + +V foo_70_1(V a, V b, V c) { return ((c&a)|b)^c; } + +V foo_71_1(V a, V b, V c) { return ~(((c^a)&b)^a); } +V foo_71_2(V a, V b, V c) { return ((c^a)&b)^~a; } +V foo_71_3(V a, V b, V c) { return (~a|b)^(c&b); } +V foo_71_4(V a, V b, V c) { return ((~(c^a))|b)^c; } +V foo_71_5(V a, V b, V c) { return (~((c^a)&b))^a; } +V foo_71_6(V a, V b, V c) { return (~b|c)^(b|a); } + +V foo_72_1(V a, V b, V c) { return (c^a)&b; } + +V foo_73_1(V a, V b, V c) { return ~((((c&a)|b)^a)^c); } +V foo_73_2(V a, V b, V c) { return (((c&a)|b)^c)^~a; } +V foo_73_3(V a, V b, V c) { return (~((c&a)|b))^(c^a); } +V foo_73_4(V a, V b, V c) { return (((c&a)|b)^a)^~c; } +V foo_73_5(V a, V b, V c) { return ((c&a)|b)^(~(c^a)); } +V foo_73_6(V a, V b, V c) { return (~(((c&a)|b)^a))^c; } +V foo_73_7(V a, V b, V c) { return ((c&a)|~b)^(c|a); } +V foo_73_8(V a, V b, V c) { return (~(((c&a)|b)^c))^a; } + +V foo_74_1(V a, V b, V c) { return (c^a)&(c|b); } +V foo_74_2(V a, V b, V c) { return ((c|b)&a)^c; } + +V foo_75_1(V a, V b, V c) { return (~b|c)^a; } + +V foo_76_1(V a, V b, V c) { return (~(c&a))&b; } + +V foo_77_1(V a, V b, V c) { return ~(((b^a)&(c^a))^c); } +V foo_77_2(V a, V b, V c) { return ((c^a)&b)|(~(c|a)); } +V foo_77_3(V a, V b, V c) { return ((c^a)&b)^(~(c|a)); } +V foo_77_4(V a, V b, V c) { return ((c^a)&(c^b))^~a; } +V foo_77_5(V a, V b, V c) { return ((b^a)&(c^a))^~c; } +V foo_77_6(V a, V b, V c) { return ((b^a)|(c^a))^~b; } +V foo_77_7(V a, V b, V c) { return (~((b^a)|(c^a)))^b; } +V foo_77_8(V a, V b, V c) { return ((~(c^a))|b)^(c&a); } +V foo_77_9(V a, V b, V c) { return (~((b^a)&(c^a)))^c; } +V foo_77_10(V a, V b, V c) { return (~((c^a)&b))^(c|a); } +V foo_77_11(V a, V b, V c) { return ((c^b)|a)^(~b|c); } +V foo_77_12(V a, V b, V c) { return (~((c^a)&(c^b)))^a; } +V foo_77_13(V a, V b, V c) { return ((b^a)|c)^(~b|a); } + +V foo_78_1(V a, V b, V c) { return (c&a)^(c|b); } +V foo_78_2(V a, V b, V c) { return ((b^a)|c)^a; } + +V foo_79_1(V a, V b, V c) { return ~((~b|c)&a); } +V foo_79_2(V a, V b, V c) { return (~c&b)|~a; } + +V foo_80_1(V a, V b, V c) { return ~c&a; } + +V foo_81_1(V a, V b, V c) { return ~((~a&b)|c); } +V foo_81_2(V a, V b, V c) { return (~b|a)&~c; } + +V foo_82_1(V a, V b, V c) { return ((c&b)|a)^c; } + +V foo_83_1(V a, V b, V c) { return ~(((c^b)&a)^b); } +V foo_83_2(V a, V b, V c) { return ((c^b)&a)^~b; } +V foo_83_3(V a, V b, V c) { return (~((c^b)&a))^b; } +V foo_83_4(V a, V b, V c) { return (~b|a)^(c&a); } +V foo_83_5(V a, V b, V c) { return ((~(c^b))|a)^c; } +V foo_83_6(V a, V b, V c) { return (~a|c)^(b|a); } + +V foo_84_1(V a, V b, V c) { return (b|a)&~c; } + +V foo_85_1(V a, V b, V c) { return ~c; } + +V foo_86_1(V a, V b, V c) { return (b|a)^c; } + +V foo_87_1(V a, V b, V c) { return ~((b|a)&c); } + +V foo_88_1(V a, V b, V c) { return (c^a)&(b|a); } +V foo_88_2(V a, V b, V c) { return ((b|a)&c)^a; } + +V foo_89_1(V a, V b, V c) { return (~b|a)^c; } + +V foo_90_1(V a, V b, V c) { return c^a; } + +V foo_91_1(V a, V b, V c) { return (~(b|a))|(c^a); } +V foo_91_2(V a, V b, V c) { return (~(c|b))|(c^a); } +V foo_91_3(V a, V b, V c) { return ((~(c|b))|a)^c; } +V foo_91_4(V a, V b, V c) { return ((~(b|a))|c)^a; } + +V foo_92_1(V a, V b, V c) { return (c&a)^(b|a); } +V foo_92_2(V a, V b, V c) { return ((c^b)|a)^c; } + +V foo_93_1(V a, V b, V c) { return ~((~b|a)&c); } +V foo_93_2(V a, V b, V c) { return (~a&b)|~c; } + +V foo_94_1(V a, V b, V c) { return (~a&b)|(c^a); } +V foo_94_2(V a, V b, V c) { return (~c&b)|(c^a); } +V foo_94_3(V a, V b, V c) { return ((~c&b)|a)^c; } +V foo_94_4(V a, V b, V c) { return ((~a&b)|c)^a; } + +V foo_95_1(V a, V b, V c) { return ~(c&a); } + +V foo_96_1(V a, V b, V c) { return (c^b)&a; } + +V foo_97_1(V a, V b, V c) { return ~(((c|b)^a)|(c&b)); } +V foo_97_2(V a, V b, V c) { return (~((c&b)|a))^(c^b); } +V foo_97_3(V a, V b, V c) { return (((c&b)|a)^c)^~b; } +V foo_97_4(V a, V b, V c) { return (((c&b)|a)^b)^~c; } +V foo_97_5(V a, V b, V c) { return ((c&b)|~a)^(c|b); } +V foo_97_6(V a, V b, V c) { return ((c&b)|a)^(~(c^b)); } +V foo_97_7(V a, V b, V c) { return (~(((c&b)|a)^b))^c; } +V foo_97_8(V a, V b, V c) { return (~(((c&b)|a)^c))^b; } + +V foo_98_1(V a, V b, V c) { return (c^b)&(c|a); } +V foo_98_2(V a, V b, V c) { return ((c|a)&b)^c; } + +V foo_99_1(V a, V b, V c) { return (~a|c)^b; } + +V foo_100_1(V a, V b, V c) { return (c^b)&(b|a); } +V foo_100_2(V a, V b, V c) { return ((b|a)&c)^b; } + +V foo_101_1(V a, V b, V c) { return (~a|b)^c; } + +V foo_102_1(V a, V b, V c) { return c^b; } + +V foo_103_1(V a, V b, V c) { return (~(b|a))|(c^b); } +V foo_103_2(V a, V b, V c) { return (~(c|a))|(c^b); } +V foo_103_3(V a, V b, V c) { return ((~(c|a))|b)^c; } +V foo_103_4(V a, V b, V c) { return ((~(b|a))|c)^b; } + +V foo_104_1(V a, V b, V c) { return ((b&a)^c)&(b|a); } +V foo_104_2(V a, V b, V c) { return ((c&a)^b)&(c|a); } +V foo_104_3(V a, V b, V c) { return ((c&b)^a)&(c|b); } +V foo_104_4(V a, V b, V c) { return ((c|b)&a)^(c&b); } +V foo_104_5(V a, V b, V c) { return ((c|a)&b)^(c&a); } +V foo_104_6(V a, V b, V c) { return ((b|a)&c)^(b&a); } + +V foo_105_1(V a, V b, V c) { return ~((b^a)^c); } +V foo_105_2(V a, V b, V c) { return (c^b)^~a; } +V foo_105_3(V a, V b, V c) { return (c^a)^~b; } +V foo_105_4(V a, V b, V c) { return (b^a)^~c; } +V foo_105_5(V a, V b, V c) { return (~(c^b))^a; } +V foo_105_6(V a, V b, V c) { return (~(c^a))^b; } +V foo_105_7(V a, V b, V c) { return (~(b^a))^c; } + +V foo_106_1(V a, V b, V c) { return (b&a)^c; } + +V foo_107_1(V a, V b, V c) { return ~(((b|a)&c)^(b^a)); } +V foo_107_2(V a, V b, V c) { return ((b&a)^c)|(~(b|a)); } +V foo_107_3(V a, V b, V c) { return ((c^b)&(b|a))^~a; } +V foo_107_4(V a, V b, V c) { return ((c^a)&(b|a))^~b; } +V foo_107_5(V a, V b, V c) { return (~((b|a)&c))^(b^a); } +V foo_107_6(V a, V b, V c) { return (~((c^b)&(b|a)))^a; } +V foo_107_7(V a, V b, V c) { return (~((c^a)&(b|a)))^b; } +V foo_107_8(V a, V b, V c) { return ((b|a)&c)^(~(b^a)); } +V foo_107_9(V a, V b, V c) { return ((~(b|a))|c)^(b&a); } + +V foo_108_1(V a, V b, V c) { return (c&a)^b; } + +V foo_109_1(V a, V b, V c) { return ~(((b^a)&(c|a))^c); } +V foo_109_2(V a, V b, V c) { return ((c&a)^b)|(~(c|a)); } +V foo_109_3(V a, V b, V c) { return ((c^b)&(c|a))^~a; } +V foo_109_4(V a, V b, V c) { return (~((c|a)&b))^(c^a); } +V foo_109_5(V a, V b, V c) { return ((b^a)&(c|a))^~c; } +V foo_109_6(V a, V b, V c) { return (~((c^b)&(c|a)))^a; } +V foo_109_7(V a, V b, V c) { return ((~(c|a))|b)^(c&a); } +V foo_109_8(V a, V b, V c) { return ((c|a)&b)^(~(c^a)); } +V foo_109_9(V a, V b, V c) { return (~((b^a)&(c|a)))^c; } + +V foo_110_1(V a, V b, V c) { return (~a&c)|(c^b); } +V foo_110_2(V a, V b, V c) { return (~a&b)|(c^b); } +V foo_110_3(V a, V b, V c) { return ((~b|a)&c)^b; } +V foo_110_4(V a, V b, V c) { return ((~c|a)&b)^c; } + +V foo_111_1(V a, V b, V c) { return (c^b)|~a; } + +V foo_112_1(V a, V b, V c) { return (~(c&b))&a; } + +V foo_113_1(V a, V b, V c) { return ~(((b^a)&(c^b))^c); } +V foo_113_2(V a, V b, V c) { return ((b^a)|(c^a))^~a; } +V foo_113_3(V a, V b, V c) { return ((c^b)&a)|(~(c|b)); } +V foo_113_4(V a, V b, V c) { return ((c^b)&a)^(~(c|b)); } +V foo_113_5(V a, V b, V c) { return ((b^a)&(c^b))^~c; } +V foo_113_6(V a, V b, V c) { return ((c^a)&(c^b))^~b; } +V foo_113_7(V a, V b, V c) { return (~((b^a)|(c^a)))^a; } +V foo_113_8(V a, V b, V c) { return ((~(c^b))|a)^(c&b); } +V foo_113_9(V a, V b, V c) { return (~((c^b)&a))^(c|b); } +V foo_113_10(V a, V b, V c) { return (~((b^a)&(c^b)))^c; } +V foo_113_11(V a, V b, V c) { return ((c^a)|b)^(~a|c); } +V foo_113_12(V a, V b, V c) { return (~((c^a)&(c^b)))^b; } +V foo_113_13(V a, V b, V c) { return ((b^a)|c)^(~a|b); } + +V foo_114_1(V a, V b, V c) { return (c&b)^(c|a); } +V foo_114_2(V a, V b, V c) { return ((b^a)|c)^b; } + +V foo_115_1(V a, V b, V c) { return ~((~a|c)&b); } +V foo_115_2(V a, V b, V c) { return (~c&a)|~b; } + +V foo_116_1(V a, V b, V c) { return (c&b)^(b|a); } +V foo_116_2(V a, V b, V c) { return ((c^a)|b)^c; } + +V foo_117_1(V a, V b, V c) { return ~((~a|b)&c); } +V foo_117_2(V a, V b, V c) { return (~b&a)|~c; } + +V foo_118_1(V a, V b, V c) { return (~b&a)|(c^b); } +V foo_118_2(V a, V b, V c) { return (~c&a)|(c^b); } +V foo_118_3(V a, V b, V c) { return ((~c&a)|b)^c; } +V foo_118_4(V a, V b, V c) { return ((~b&a)|c)^b; } + +V foo_119_1(V a, V b, V c) { return ~(c&b); } + +V foo_120_1(V a, V b, V c) { return (c&b)^a; } + +V foo_121_1(V a, V b, V c) { return ~(((b^a)&(c|b))^c); } +V foo_121_2(V a, V b, V c) { return ((c&b)^a)|(~(c|b)); } +V foo_121_3(V a, V b, V c) { return (~((c|b)&a))^(c^b); } +V foo_121_4(V a, V b, V c) { return ((b^a)&(c|b))^~c; } +V foo_121_5(V a, V b, V c) { return ((c^a)&(c|b))^~b; } +V foo_121_6(V a, V b, V c) { return ((~(c|b))|a)^(c&b); } +V foo_121_7(V a, V b, V c) { return ((c|b)&a)^(~(c^b)); } +V foo_121_8(V a, V b, V c) { return (~((b^a)&(c|b)))^c; } +V foo_121_9(V a, V b, V c) { return (~((c^a)&(c|b)))^b; } + +V foo_122_1(V a, V b, V c) { return (~b&c)|(c^a); } +V foo_122_2(V a, V b, V c) { return (~b&a)|(c^a); } +V foo_122_3(V a, V b, V c) { return ((~a|b)&c)^a; } +V foo_122_4(V a, V b, V c) { return ((~c|b)&a)^c; } + +V foo_123_1(V a, V b, V c) { return (c^a)|~b; } + +V foo_124_1(V a, V b, V c) { return (~c&b)|(b^a); } +V foo_124_2(V a, V b, V c) { return (~c&a)|(b^a); } +V foo_124_3(V a, V b, V c) { return ((~a|c)&b)^a; } +V foo_124_4(V a, V b, V c) { return ((~b|c)&a)^b; } + +V foo_125_1(V a, V b, V c) { return (b^a)|~c; } + +V foo_126_1(V a, V b, V c) { return (b^a)|(c^a); } +V foo_126_2(V a, V b, V c) { return (b^a)|(c^b); } +V foo_126_3(V a, V b, V c) { return (c^a)|(c^b); } + +V foo_127_1(V a, V b, V c) { return ~((c&b)&a); } + +V foo_128_1(V a, V b, V c) { return (c&b)&a; } +V foo_128_2(V a, V b, V c) { return (c&a)&b; } +V foo_128_3(V a, V b, V c) { return (b&a)&c; } + +V foo_129_1(V a, V b, V c) { return ~((b^a)|(c^a)); } + +V foo_130_1(V a, V b, V c) { return (~(b^a))&c; } + +V foo_131_1(V a, V b, V c) { return ~((~c&b)|(b^a)); } +V foo_131_2(V a, V b, V c) { return ((~a|c)&b)^~a; } +V foo_131_3(V a, V b, V c) { return ((~b|c)&a)^~b; } +V foo_131_4(V a, V b, V c) { return (~((~b|c)&a))^b; } +V foo_131_5(V a, V b, V c) { return (~((~a|c)&b))^a; } +V foo_131_6(V a, V b, V c) { return (~a|c)&(~(b^a)); } +V foo_131_7(V a, V b, V c) { return (~b|c)&(~(b^a)); } + +V foo_132_1(V a, V b, V c) { return (~(c^a))&b; } + +V foo_133_1(V a, V b, V c) { return ~((~b&c)|(c^a)); } +V foo_133_2(V a, V b, V c) { return ((~a|b)&c)^~a; } +V foo_133_3(V a, V b, V c) { return (~((~c|b)&a))^c; } +V foo_133_4(V a, V b, V c) { return ((~c|b)&a)^~c; } +V foo_133_5(V a, V b, V c) { return (~((~a|b)&c))^a; } +V foo_133_6(V a, V b, V c) { return (~(c^a))&(~a|b); } +V foo_133_7(V a, V b, V c) { return (~(c^a))&(~c|b); } + +V foo_134_1(V a, V b, V c) { return ((b^a)&(c|b))^c; } +V foo_134_2(V a, V b, V c) { return ((c^a)&(c|b))^b; } +V foo_134_3(V a, V b, V c) { return ((c|b)&a)^(c^b); } +V foo_134_4(V a, V b, V c) { return ((b^a)^c)&(c|b); } + +V foo_135_1(V a, V b, V c) { return ~((c&b)^a); } +V foo_135_2(V a, V b, V c) { return (c&b)^~a; } +V foo_135_3(V a, V b, V c) { return (~(c&b))^a; } + +V foo_136_1(V a, V b, V c) { return c&b; } + +V foo_137_1(V a, V b, V c) { return ~((~b&a)|(c^b)); } +V foo_137_2(V a, V b, V c) { return (~((~c&a)|b))^c; } +V foo_137_3(V a, V b, V c) { return ((~b&a)|c)^~b; } +V foo_137_4(V a, V b, V c) { return (~((~b&a)|c))^b; } +V foo_137_5(V a, V b, V c) { return ((~c&a)|b)^~c; } +V foo_137_6(V a, V b, V c) { return (~(c^b))&(~a|c); } +V foo_137_7(V a, V b, V c) { return (~(c^b))&(~a|b); } + +V foo_138_1(V a, V b, V c) { return (~a|b)&c; } + +V foo_139_1(V a, V b, V c) { return ~((c&b)^(b|a)); } +V foo_139_2(V a, V b, V c) { return (~(b|a))|(c&b); } +V foo_139_3(V a, V b, V c) { return (~(b|a))^(c&b); } +V foo_139_4(V a, V b, V c) { return (~((c^a)|b))^c; } +V foo_139_5(V a, V b, V c) { return ((c^a)|b)^~c; } +V foo_139_6(V a, V b, V c) { return (~(c&b))^(b|a); } +V foo_139_7(V a, V b, V c) { return ((c^a)|~b)^a; } + +V foo_140_1(V a, V b, V c) { return (~a|c)&b; } + +V foo_141_1(V a, V b, V c) { return ~((c&b)^(c|a)); } +V foo_141_2(V a, V b, V c) { return (~(c|a))|(c&b); } +V foo_141_3(V a, V b, V c) { return (~(c|a))^(c&b); } +V foo_141_4(V a, V b, V c) { return ((b^a)|c)^~b; } +V foo_141_5(V a, V b, V c) { return (~((b^a)|c))^b; } +V foo_141_6(V a, V b, V c) { return (~(c&b))^(c|a); } +V foo_141_7(V a, V b, V c) { return ((b^a)|~c)^a; } + +V foo_142_1(V a, V b, V c) { return ((b^a)&(c^b))^c; } +V foo_142_2(V a, V b, V c) { return ((c^a)&(c^b))^b; } +V foo_142_3(V a, V b, V c) { return ((c^b)&a)^(c|b); } +V foo_142_4(V a, V b, V c) { return ((b^a)|(c^a))^a; } + +V foo_143_1(V a, V b, V c) { return (c&b)|~a; } + +V foo_144_1(V a, V b, V c) { return (~(c^b))&a; } + +V foo_145_1(V a, V b, V c) { return ~((~a&c)|(c^b)); } +V foo_145_2(V a, V b, V c) { return ((~b|a)&c)^~b; } +V foo_145_3(V a, V b, V c) { return (~((~c|a)&b))^c; } +V foo_145_4(V a, V b, V c) { return ((~c|a)&b)^~c; } +V foo_145_5(V a, V b, V c) { return (~((~b|a)&c))^b; } +V foo_145_6(V a, V b, V c) { return (~(c^b))&(~b|a); } +V foo_145_7(V a, V b, V c) { return (~(c^b))&(~c|a); } + +V foo_146_1(V a, V b, V c) { return ((b^a)&(c|a))^c; } +V foo_146_2(V a, V b, V c) { return ((c|a)&b)^(c^a); } +V foo_146_3(V a, V b, V c) { return ((c^b)&(c|a))^a; } +V foo_146_4(V a, V b, V c) { return ((b^a)^c)&(c|a); } + +V foo_147_1(V a, V b, V c) { return ~((c&a)^b); } +V foo_147_2(V a, V b, V c) { return (c&a)^~b; } +V foo_147_3(V a, V b, V c) { return (~(c&a))^b; } + +V foo_148_1(V a, V b, V c) { return ((b|a)&c)^(b^a); } +V foo_148_2(V a, V b, V c) { return ((c^a)&(b|a))^b; } +V foo_148_3(V a, V b, V c) { return ((c^b)&(b|a))^a; } +V foo_148_4(V a, V b, V c) { return ((b^a)^c)&(b|a); } + +V foo_149_1(V a, V b, V c) { return ~((b&a)^c); } +V foo_149_2(V a, V b, V c) { return (~(b&a))^c; } +V foo_149_3(V a, V b, V c) { return (b&a)^~c; } + +V foo_150_1(V a, V b, V c) { return (b^a)^c; } +V foo_150_2(V a, V b, V c) { return (c^a)^b; } +V foo_150_3(V a, V b, V c) { return (c^b)^a; } + +V foo_151_1(V a, V b, V c) { return ~(((b&a)^c)&(b|a)); } +V foo_151_2(V a, V b, V c) { return ((b^a)^c)|(~(b|a)); } +V foo_151_3(V a, V b, V c) { return ((b^a)^c)|(~(c|a)); } +V foo_151_4(V a, V b, V c) { return ((b^a)^c)|(~(c|b)); } +V foo_151_5(V a, V b, V c) { return (~((c|b)&a))^(c&b); } +V foo_151_6(V a, V b, V c) { return (~((c|a)&b))^(c&a); } +V foo_151_7(V a, V b, V c) { return ((~(b|a))|c)^(b^a); } +V foo_151_8(V a, V b, V c) { return ((~(c|a))|(b^a))^c; } +V foo_151_9(V a, V b, V c) { return ((b|a)&c)^(~(b&a)); } +V foo_151_10(V a, V b, V c) { return (~((b|a)&c))^(b&a); } +V foo_151_11(V a, V b, V c) { return ((~(c|a))|b)^(c^a); } +V foo_151_12(V a, V b, V c) { return ((~(b|a))|(c^a))^b; } +V foo_151_13(V a, V b, V c) { return ((c|a)&b)^(~(c&a)); } +V foo_151_14(V a, V b, V c) { return ((~(c|b))|a)^(c^b); } +V foo_151_15(V a, V b, V c) { return ((~(b|a))|(c^b))^a; } +V foo_151_16(V a, V b, V c) { return ((c|b)&a)^(~(c&b)); } + +V foo_152_1(V a, V b, V c) { return ((c|a)&~b)^c; } +V foo_152_2(V a, V b, V c) { return ((b|a)&~c)^b; } +V foo_152_3(V a, V b, V c) { return (~(c^b))&(c|a); } +V foo_152_4(V a, V b, V c) { return (~(c^b))&(b|a); } + +V foo_153_1(V a, V b, V c) { return ~(c^b); } +V foo_153_2(V a, V b, V c) { return ~b^c; } +V foo_153_3(V a, V b, V c) { return ~c^b; } + +V foo_154_1(V a, V b, V c) { return (~b&a)^c; } + +V foo_155_1(V a, V b, V c) { return ~((c^b)&(b|a)); } +V foo_155_2(V a, V b, V c) { return ((b|a)&c)^~b; } +V foo_155_3(V a, V b, V c) { return (~((b|a)&c))^b; } + +V foo_156_1(V a, V b, V c) { return (~c&a)^b; } + +V foo_157_1(V a, V b, V c) { return ~((c^b)&(c|a)); } +V foo_157_2(V a, V b, V c) { return (~((c|a)&b))^c; } +V foo_157_3(V a, V b, V c) { return ((c|a)&b)^~c; } + +V foo_158_1(V a, V b, V c) { return ((c|b)^a)|(c&b); } +V foo_158_2(V a, V b, V c) { return (((c&b)|a)^b)^c; } +V foo_158_3(V a, V b, V c) { return (((c&b)|a)^c)^b; } +V foo_158_4(V a, V b, V c) { return ((c&b)|a)^(c^b); } +V foo_158_5(V a, V b, V c) { return ((b^a)^c)|(c&b); } + +V foo_159_1(V a, V b, V c) { return ~((c^b)&a); } + +V foo_160_1(V a, V b, V c) { return c&a; } + +V foo_161_1(V a, V b, V c) { return ~((~a&b)|(c^a)); } +V foo_161_2(V a, V b, V c) { return (~((~c&b)|a))^c; } +V foo_161_3(V a, V b, V c) { return ((~a&b)|c)^~a; } +V foo_161_4(V a, V b, V c) { return (~((~a&b)|c))^a; } +V foo_161_5(V a, V b, V c) { return ((~c&b)|a)^~c; } +V foo_161_6(V a, V b, V c) { return (~(c^a))&(~b|c); } +V foo_161_7(V a, V b, V c) { return (~(c^a))&(~b|a); } + +V foo_162_1(V a, V b, V c) { return (~b|a)&c; } + +V foo_163_1(V a, V b, V c) { return ~((c&a)^(b|a)); } +V foo_163_2(V a, V b, V c) { return (~(b|a))|(c&a); } +V foo_163_3(V a, V b, V c) { return (~(b|a))^(c&a); } +V foo_163_4(V a, V b, V c) { return (~((c^b)|a))^c; } +V foo_163_5(V a, V b, V c) { return ((c^b)|a)^~c; } +V foo_163_6(V a, V b, V c) { return (~(c&a))^(b|a); } +V foo_163_7(V a, V b, V c) { return ((c^b)|~a)^b; } + +V foo_164_1(V a, V b, V c) { return ((c|b)&~a)^c; } +V foo_164_2(V a, V b, V c) { return ((b|a)&~c)^a; } +V foo_164_3(V a, V b, V c) { return (~(c^a))&(c|b); } +V foo_164_4(V a, V b, V c) { return (~(c^a))&(b|a); } + +V foo_165_1(V a, V b, V c) { return ~(c^a); } +V foo_165_2(V a, V b, V c) { return ~a^c; } +V foo_165_3(V a, V b, V c) { return ~c^a; } + +V foo_166_1(V a, V b, V c) { return (~a&b)^c; } + +V foo_167_1(V a, V b, V c) { return ~((c^a)&(b|a)); } +V foo_167_2(V a, V b, V c) { return ((b|a)&c)^~a; } +V foo_167_3(V a, V b, V c) { return (~((b|a)&c))^a; } + +V foo_168_1(V a, V b, V c) { return (b|a)&c; } + +V foo_169_1(V a, V b, V c) { return ~((b|a)^c); } +V foo_169_2(V a, V b, V c) { return (~(b|a))^c; } +V foo_169_3(V a, V b, V c) { return (b|a)^~c; } + +V foo_170_1(V a, V b, V c) { return c; } + +V foo_171_1(V a, V b, V c) { return (~(b|a))|c; } + +V foo_172_1(V a, V b, V c) { return ((c^b)&a)^b; } + +V foo_173_1(V a, V b, V c) { return ~(((c&b)|a)^c); } +V foo_173_2(V a, V b, V c) { return (~((c&b)|a))^c; } +V foo_173_3(V a, V b, V c) { return ((c&b)|a)^~c; } +V foo_173_4(V a, V b, V c) { return (~(c^a))|(c&b); } + +V foo_174_1(V a, V b, V c) { return (~a&b)|c; } + +V foo_175_1(V a, V b, V c) { return ~a|c; } + +V foo_176_1(V a, V b, V c) { return (~b|c)&a; } + +V foo_177_1(V a, V b, V c) { return ~((c&a)^(c|b)); } +V foo_177_2(V a, V b, V c) { return ((b^a)|c)^~a; } +V foo_177_3(V a, V b, V c) { return (~(c|b))|(c&a); } +V foo_177_4(V a, V b, V c) { return (~(c|b))^(c&a); } +V foo_177_5(V a, V b, V c) { return (~((b^a)|c))^a; } +V foo_177_6(V a, V b, V c) { return (~(c&a))^(c|b); } +V foo_177_7(V a, V b, V c) { return ((b^a)|~c)^b; } + +V foo_178_1(V a, V b, V c) { return ((b^a)&(c^a))^c; } +V foo_178_2(V a, V b, V c) { return ((c^a)&(c^b))^a; } +V foo_178_3(V a, V b, V c) { return ((c^a)&b)^(c|a); } +V foo_178_4(V a, V b, V c) { return ((b^a)|(c^a))^b; } + +V foo_179_1(V a, V b, V c) { return (c&a)|~b; } + +V foo_180_1(V a, V b, V c) { return (~c&b)^a; } + +V foo_181_1(V a, V b, V c) { return ~((c^a)&(c|b)); } +V foo_181_2(V a, V b, V c) { return (~((c|b)&a))^c; } +V foo_181_3(V a, V b, V c) { return ((c|b)&a)^~c; } + +V foo_182_1(V a, V b, V c) { return (((c&a)|b)^a)^c; } +V foo_182_2(V a, V b, V c) { return ((c|a)^b)|(c&a); } +V foo_182_3(V a, V b, V c) { return (((c&a)|b)^c)^a; } +V foo_182_4(V a, V b, V c) { return ((c&a)|b)^(c^a); } +V foo_182_5(V a, V b, V c) { return ((b^a)^c)|(c&a); } + +V foo_183_1(V a, V b, V c) { return ~((c^a)&b); } + +V foo_184_1(V a, V b, V c) { return ((c^a)&b)^a; } + +V foo_185_1(V a, V b, V c) { return ~(((c&a)|b)^c); } +V foo_185_2(V a, V b, V c) { return (~((c&a)|b))^c; } +V foo_185_3(V a, V b, V c) { return ((c&a)|b)^~c; } +V foo_185_4(V a, V b, V c) { return (~(c^b))|(c&a); } + +V foo_186_1(V a, V b, V c) { return (~b&a)|c; } + +V foo_187_1(V a, V b, V c) { return ~b|c; } + +V foo_188_1(V a, V b, V c) { return (b^a)|(c&b); } +V foo_188_2(V a, V b, V c) { return (b^a)|(c&a); } + +V foo_189_1(V a, V b, V c) { return ~((c^a)&(c^b)); } +V foo_189_2(V a, V b, V c) { return (~(c^b))|(b^a); } +V foo_189_3(V a, V b, V c) { return (~(c^a))|(b^a); } + +V foo_190_1(V a, V b, V c) { return (b^a)|c; } + +V foo_191_1(V a, V b, V c) { return (~(b&a))|c; } + +V foo_192_1(V a, V b, V c) { return b&a; } + +V foo_193_1(V a, V b, V c) { return ~((~a&c)|(b^a)); } +V foo_193_2(V a, V b, V c) { return (~((~b&c)|a))^b; } +V foo_193_3(V a, V b, V c) { return ((~a&c)|b)^~a; } +V foo_193_4(V a, V b, V c) { return (~((~a&c)|b))^a; } +V foo_193_5(V a, V b, V c) { return ((~b&c)|a)^~b; } +V foo_193_6(V a, V b, V c) { return (~(b^a))&(~c|b); } +V foo_193_7(V a, V b, V c) { return (~(b^a))&(~c|a); } + +V foo_194_1(V a, V b, V c) { return ((c|b)&~a)^b; } +V foo_194_2(V a, V b, V c) { return ((c|a)&~b)^a; } +V foo_194_3(V a, V b, V c) { return (~(b^a))&(c|b); } +V foo_194_4(V a, V b, V c) { return (~(b^a))&(c|a); } + +V foo_195_1(V a, V b, V c) { return ~(b^a); } +V foo_195_2(V a, V b, V c) { return ~a^b; } +V foo_195_3(V a, V b, V c) { return ~b^a; } + +V foo_196_1(V a, V b, V c) { return (~c|a)&b; } + +V foo_197_1(V a, V b, V c) { return ~((b&a)^(c|a)); } +V foo_197_2(V a, V b, V c) { return (~(c|a))|(b&a); } +V foo_197_3(V a, V b, V c) { return (~(c|a))^(b&a); } +V foo_197_4(V a, V b, V c) { return (~((c^b)|a))^b; } +V foo_197_5(V a, V b, V c) { return ((c^b)|a)^~b; } +V foo_197_6(V a, V b, V c) { return (~(b&a))^(c|a); } +V foo_197_7(V a, V b, V c) { return ((c^b)|~a)^c; } + +V foo_198_1(V a, V b, V c) { return (~a&c)^b; } + +V foo_199_1(V a, V b, V c) { return ~((b^a)&(c|a)); } +V foo_199_2(V a, V b, V c) { return ((c|a)&b)^~a; } +V foo_199_3(V a, V b, V c) { return (~((c|a)&b))^a; } + +V foo_200_1(V a, V b, V c) { return (c|a)&b; } + +V foo_201_1(V a, V b, V c) { return ~((c|a)^b); } +V foo_201_2(V a, V b, V c) { return (~(c|a))^b; } +V foo_201_3(V a, V b, V c) { return (c|a)^~b; } + +V foo_202_1(V a, V b, V c) { return ((c^b)&a)^c; } + +V foo_203_1(V a, V b, V c) { return ~(((c&b)|a)^b); } +V foo_203_2(V a, V b, V c) { return (~((c&b)|a))^b; } +V foo_203_3(V a, V b, V c) { return ((c&b)|a)^~b; } +V foo_203_4(V a, V b, V c) { return (~(b^a))|(c&b); } + +V foo_204_1(V a, V b, V c) { return b; } + +V foo_205_1(V a, V b, V c) { return (~(c|a))|b; } + +V foo_206_1(V a, V b, V c) { return (~a&c)|b; } + +V foo_207_1(V a, V b, V c) { return ~a|b; } + +V foo_208_1(V a, V b, V c) { return (~c|b)&a; } + +V foo_209_1(V a, V b, V c) { return ~((b&a)^(c|b)); } +V foo_209_2(V a, V b, V c) { return ((c^a)|b)^~a; } +V foo_209_3(V a, V b, V c) { return (~(c|b))|(b&a); } +V foo_209_4(V a, V b, V c) { return (~(c|b))^(b&a); } +V foo_209_5(V a, V b, V c) { return (~((c^a)|b))^a; } +V foo_209_6(V a, V b, V c) { return (~(b&a))^(c|b); } +V foo_209_7(V a, V b, V c) { return ((c^a)|~b)^c; } + +V foo_210_1(V a, V b, V c) { return (~b&c)^a; } + +V foo_211_1(V a, V b, V c) { return ~((b^a)&(c|b)); } +V foo_211_2(V a, V b, V c) { return (~((c|b)&a))^b; } +V foo_211_3(V a, V b, V c) { return ((c|b)&a)^~b; } + +V foo_212_1(V a, V b, V c) { return ((b^a)&(c^a))^b; } +V foo_212_2(V a, V b, V c) { return ((b^a)&(c^b))^a; } +V foo_212_3(V a, V b, V c) { return ((b^a)&c)^(b|a); } +V foo_212_4(V a, V b, V c) { return ((b^a)|(c^a))^c; } + +V foo_213_1(V a, V b, V c) { return (b&a)|~c; } + +V foo_214_1(V a, V b, V c) { return (((b&a)|c)^a)^b; } +V foo_214_2(V a, V b, V c) { return (((b&a)|c)^b)^a; } +V foo_214_3(V a, V b, V c) { return ((b&a)|c)^(b^a); } +V foo_214_4(V a, V b, V c) { return ((b|a)^c)|(b&a); } +V foo_214_5(V a, V b, V c) { return ((b^a)^c)|(b&a); } + +V foo_215_1(V a, V b, V c) { return ~((b^a)&c); } + +V foo_216_1(V a, V b, V c) { return ((b^a)&c)^a; } + +V foo_217_1(V a, V b, V c) { return ~(((b&a)|c)^b); } +V foo_217_2(V a, V b, V c) { return (~((b&a)|c))^b; } +V foo_217_3(V a, V b, V c) { return ((b&a)|c)^~b; } +V foo_217_4(V a, V b, V c) { return (~(c^b))|(b&a); } + +V foo_218_1(V a, V b, V c) { return (c^a)|(c&b); } +V foo_218_2(V a, V b, V c) { return (c^a)|(b&a); } + +V foo_219_1(V a, V b, V c) { return ~((b^a)&(c^b)); } +V foo_219_2(V a, V b, V c) { return (~(c^b))|(c^a); } +V foo_219_3(V a, V b, V c) { return (~(b^a))|(c^a); } + +V foo_220_1(V a, V b, V c) { return (~c&a)|b; } + +V foo_221_1(V a, V b, V c) { return ~c|b; } + +V foo_222_1(V a, V b, V c) { return (c^a)|b; } + +V foo_223_1(V a, V b, V c) { return (~(c&a))|b; } + +V foo_224_1(V a, V b, V c) { return (c|b)&a; } + +V foo_225_1(V a, V b, V c) { return ~((c|b)^a); } +V foo_225_2(V a, V b, V c) { return (c|b)^~a; } +V foo_225_3(V a, V b, V c) { return (~(c|b))^a; } + +V foo_226_1(V a, V b, V c) { return ((c^a)&b)^c; } + +V foo_227_1(V a, V b, V c) { return ~(((c&a)|b)^a); } +V foo_227_2(V a, V b, V c) { return ((c&a)|b)^~a; } +V foo_227_3(V a, V b, V c) { return (~((c&a)|b))^a; } +V foo_227_4(V a, V b, V c) { return (~(b^a))|(c&a); } + +V foo_228_1(V a, V b, V c) { return ((b^a)&c)^b; } + +V foo_229_1(V a, V b, V c) { return ~(((b&a)|c)^a); } +V foo_229_2(V a, V b, V c) { return ((b&a)|c)^~a; } +V foo_229_3(V a, V b, V c) { return (~((b&a)|c))^a; } +V foo_229_4(V a, V b, V c) { return (~(c^a))|(b&a); } + +V foo_230_1(V a, V b, V c) { return (c^b)|(c&a); } +V foo_230_2(V a, V b, V c) { return (c^b)|(b&a); } + +V foo_231_1(V a, V b, V c) { return ~((b^a)&(c^a)); } +V foo_231_2(V a, V b, V c) { return (~(c^a))|(c^b); } +V foo_231_3(V a, V b, V c) { return (~(b^a))|(c^b); } + +V foo_232_1(V a, V b, V c) { return ((b^a)&(c^a))^a; } +V foo_232_2(V a, V b, V c) { return ((b^a)&(c^b))^b; } +V foo_232_3(V a, V b, V c) { return ((b^a)&c)|(b&a); } +V foo_232_4(V a, V b, V c) { return ((b^a)&c)^(b&a); } +V foo_232_5(V a, V b, V c) { return ((c^a)&(c^b))^c; } +V foo_232_6(V a, V b, V c) { return ((c^a)&b)|(c&a); } +V foo_232_7(V a, V b, V c) { return ((c^a)&b)^(c&a); } +V foo_232_8(V a, V b, V c) { return ((c^b)&a)|(c&b); } +V foo_232_9(V a, V b, V c) { return ((c^b)&a)^(c&b); } +V foo_232_10(V a, V b, V c) { return ((c|b)&a)|(c&b); } +V foo_232_11(V a, V b, V c) { return ((c|a)&b)|(c&a); } +V foo_232_12(V a, V b, V c) { return ((b|a)&c)|(b&a); } +V foo_232_13(V a, V b, V c) { return ((b&a)|c)&(b|a); } +V foo_232_14(V a, V b, V c) { return ((c&a)|b)&(c|a); } +V foo_232_15(V a, V b, V c) { return ((c&b)|a)&(c|b); } + +V foo_233_1(V a, V b, V c) { return ~(((b^a)|(c&b))^c); } +V foo_233_2(V a, V b, V c) { return ((b&a)|c)^(~(b|a)); } +V foo_233_3(V a, V b, V c) { return ((c&a)|b)^(~(c|a)); } +V foo_233_4(V a, V b, V c) { return (~((c&b)|a))^(c|b); } +V foo_233_5(V a, V b, V c) { return ((c^b)|(c&a))^~a; } +V foo_233_6(V a, V b, V c) { return ((c&b)|a)^(~(c|b)); } +V foo_233_7(V a, V b, V c) { return (~((c&a)|b))^(c|a); } +V foo_233_8(V a, V b, V c) { return (~((b&a)|c))^(b|a); } +V foo_233_9(V a, V b, V c) { return (~((c^b)|(c&a)))^a; } +V foo_233_10(V a, V b, V c) { return (~((c^a)|(c&b)))^b; } +V foo_233_11(V a, V b, V c) { return ((c^a)|(c&b))^~b; } +V foo_233_12(V a, V b, V c) { return ((b&a)|~c)^(b^a); } +V foo_233_13(V a, V b, V c) { return (~((b^a)|(c&b)))^c; } +V foo_233_14(V a, V b, V c) { return ((b^a)|(c&b))^~c; } +V foo_233_15(V a, V b, V c) { return ((c&a)|~b)^(c^a); } +V foo_233_16(V a, V b, V c) { return ((c&b)|~a)^(c^b); } +V foo_233_17(V a, V b, V c) { return (~((b^a)^c))|(c&b); } +V foo_233_18(V a, V b, V c) { return (~((b^a)^c))|(c&a); } +V foo_233_19(V a, V b, V c) { return (~((b^a)^c))|(b&a); } +V foo_233_20(V a, V b, V c) { return (~((c|b)^a))|(c&b); } +V foo_233_21(V a, V b, V c) { return (~((c|a)^b))|(c&a); } +V foo_233_22(V a, V b, V c) { return (~((b|a)^c))|(b&a); } + +V foo_234_1(V a, V b, V c) { return (b&a)|c; } + +V foo_235_1(V a, V b, V c) { return (~(b^a))|c; } + +V foo_236_1(V a, V b, V c) { return (c&a)|b; } + +V foo_237_1(V a, V b, V c) { return (~(c^a))|b; } + +V foo_238_1(V a, V b, V c) { return c|b; } + +V foo_239_1(V a, V b, V c) { return (c|b)|~a; } +V foo_239_2(V a, V b, V c) { return (~a|b)|c; } +V foo_239_3(V a, V b, V c) { return (~a|c)|b; } + +V foo_240_1(V a, V b, V c) { return a; } + +V foo_241_1(V a, V b, V c) { return (~(c|b))|a; } + +V foo_242_1(V a, V b, V c) { return (~b&c)|a; } + +V foo_243_1(V a, V b, V c) { return ~b|a; } + +V foo_244_1(V a, V b, V c) { return (~c&b)|a; } + +V foo_245_1(V a, V b, V c) { return ~c|a; } + +V foo_246_1(V a, V b, V c) { return (c^b)|a; } + +V foo_247_1(V a, V b, V c) { return (~(c&b))|a; } + +V foo_248_1(V a, V b, V c) { return (c&b)|a; } + +V foo_249_1(V a, V b, V c) { return (~(c^b))|a; } + +V foo_250_1(V a, V b, V c) { return c|a; } + +V foo_251_1(V a, V b, V c) { return (c|a)|~b; } +V foo_251_2(V a, V b, V c) { return (~b|a)|c; } +V foo_251_3(V a, V b, V c) { return (~b|c)|a; } + +V foo_252_1(V a, V b, V c) { return b|a; } + +V foo_253_1(V a, V b, V c) { return (b|a)|~c; } +V foo_253_2(V a, V b, V c) { return (~c|a)|b; } +V foo_253_3(V a, V b, V c) { return (~c|b)|a; } + +V foo_254_1(V a, V b, V c) { return (b|a)|c; } +V foo_254_2(V a, V b, V c) { return (c|a)|b; } +V foo_254_3(V a, V b, V c) { return (c|b)|a; } + +V foo_255_1(V a, V b, V c) { return (V){~0,~0,~0,~0}; } + +/* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]" 694 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-5.c b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-5.c new file mode 100644 index 00000000000..3dbd9545283 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogd-5.c @@ -0,0 +1,955 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx512f" } */ + +typedef unsigned int V __attribute__ ((__vector_size__ (64))); + +V foo_0_1(V a, V b, V c) { return (V){0,0,0,0}; } + +V foo_1_1(V a, V b, V c) { return ~((b|a)|c); } + +V foo_2_1(V a, V b, V c) { return (~(b|a))&c; } + +V foo_3_1(V a, V b, V c) { return ~(b|a); } + +V foo_4_1(V a, V b, V c) { return (~(c|a))&b; } + +V foo_5_1(V a, V b, V c) { return ~(c|a); } + +V foo_6_1(V a, V b, V c) { return (c^b)&~a; } + +V foo_7_1(V a, V b, V c) { return ~((c&b)|a); } + +V foo_8_1(V a, V b, V c) { return (~a&c)&b; } +V foo_8_2(V a, V b, V c) { return (~a&b)&c; } +V foo_8_3(V a, V b, V c) { return (c&b)&~a; } + +V foo_9_1(V a, V b, V c) { return ~((c^b)|a); } + +V foo_10_1(V a, V b, V c) { return ~a&c; } + +V foo_11_1(V a, V b, V c) { return ~((~c&b)|a); } +V foo_11_2(V a, V b, V c) { return (~b|c)&~a; } + +V foo_12_1(V a, V b, V c) { return ~a&b; } + +V foo_13_1(V a, V b, V c) { return ~((~b&c)|a); } +V foo_13_2(V a, V b, V c) { return (~c|b)&~a; } + +V foo_14_1(V a, V b, V c) { return (c|b)&~a; } + +V foo_15_1(V a, V b, V c) { return ~a; } + +V foo_16_1(V a, V b, V c) { return (~(c|b))&a; } + +V foo_17_1(V a, V b, V c) { return ~(c|b); } + +V foo_18_1(V a, V b, V c) { return (c^a)&~b; } + +V foo_19_1(V a, V b, V c) { return ~((c&a)|b); } + +V foo_20_1(V a, V b, V c) { return (b^a)&~c; } + +V foo_21_1(V a, V b, V c) { return ~((b&a)|c); } + +V foo_22_1(V a, V b, V c) { return ((b^a)|(c&b))^c; } +V foo_22_2(V a, V b, V c) { return ((c^a)|(c&b))^b; } +V foo_22_3(V a, V b, V c) { return ((c^b)|(c&a))^a; } +V foo_22_4(V a, V b, V c) { return ((b&a)|c)^(b|a); } +V foo_22_5(V a, V b, V c) { return ((c&a)|b)^(c|a); } +V foo_22_6(V a, V b, V c) { return ((c&b)|a)^(c|b); } + +V foo_23_1(V a, V b, V c) { return ~(((b^a)&(c^a))^a); } +V foo_23_2(V a, V b, V c) { return ((b^a)&(c^a))^~a; } +V foo_23_3(V a, V b, V c) { return ((b^a)&(c^b))^~b; } +V foo_23_4(V a, V b, V c) { return ((b^a)&c)^(~(b&a)); } +V foo_23_5(V a, V b, V c) { return ((c^a)&(c^b))^~c; } +V foo_23_6(V a, V b, V c) { return ((c^a)&b)^(~(c&a)); } +V foo_23_7(V a, V b, V c) { return ((c^b)&a)^(~(c&b)); } +V foo_23_8(V a, V b, V c) { return (~((c^b)&a))^(c&b); } +V foo_23_9(V a, V b, V c) { return (~((c^a)&b))^(c&a); } +V foo_23_10(V a, V b, V c) { return (~((c^a)&(c^b)))^c; } +V foo_23_11(V a, V b, V c) { return (~((b^a)&c))^(b&a); } +V foo_23_12(V a, V b, V c) { return (~((b^a)&(c^b)))^b; } +V foo_23_13(V a, V b, V c) { return (~((b^a)&(c^a)))^a; } +V foo_23_14(V a, V b, V c) { return ((~(b^a))|c)^(b|a); } +V foo_23_15(V a, V b, V c) { return ((~(c^a))|b)^(c|a); } +V foo_23_16(V a, V b, V c) { return ((~(c^b))|a)^(c|b); } + +V foo_24_1(V a, V b, V c) { return (b^a)&(c^a); } + +V foo_25_1(V a, V b, V c) { return ~((c^b)|(c&a)); } +V foo_25_2(V a, V b, V c) { return ((c&a)|~b)^c; } +V foo_25_3(V a, V b, V c) { return ((b&a)|~c)^b; } + +V foo_26_1(V a, V b, V c) { return ((b&a)|c)^a; } + +V foo_27_1(V a, V b, V c) { return ~(((b^a)&c)^b); } +V foo_27_2(V a, V b, V c) { return ((b^a)&c)^~b; } +V foo_27_3(V a, V b, V c) { return (~b|c)^(c&a); } +V foo_27_4(V a, V b, V c) { return (~((b^a)&c))^b; } +V foo_27_5(V a, V b, V c) { return ((~(b^a))|c)^a; } +V foo_27_6(V a, V b, V c) { return (~c|a)^(c|b); } + +V foo_28_1(V a, V b, V c) { return ((c&a)|b)^a; } + +V foo_29_1(V a, V b, V c) { return ~(((c^a)&b)^c); } +V foo_29_2(V a, V b, V c) { return ((c^a)&b)^~c; } +V foo_29_3(V a, V b, V c) { return (~((c^a)&b))^c; } +V foo_29_4(V a, V b, V c) { return (~c|b)^(b&a); } +V foo_29_5(V a, V b, V c) { return ((~(c^a))|b)^a; } +V foo_29_6(V a, V b, V c) { return (~b|a)^(c|b); } + +V foo_30_1(V a, V b, V c) { return (c|b)^a; } + +V foo_31_1(V a, V b, V c) { return ~((c|b)&a); } + +V foo_32_1(V a, V b, V c) { return (~b&c)&a; } +V foo_32_2(V a, V b, V c) { return (~b&a)&c; } +V foo_32_3(V a, V b, V c) { return (c&a)&~b; } + +V foo_33_1(V a, V b, V c) { return ~((c^a)|b); } + +V foo_34_1(V a, V b, V c) { return ~b&c; } + +V foo_35_1(V a, V b, V c) { return ~((~c&a)|b); } +V foo_35_2(V a, V b, V c) { return (~a|c)&~b; } + +V foo_36_1(V a, V b, V c) { return (b^a)&(c^b); } + +V foo_37_1(V a, V b, V c) { return ~((c^a)|(c&b)); } +V foo_37_2(V a, V b, V c) { return ((c&b)|~a)^c; } +V foo_37_3(V a, V b, V c) { return ((b&a)|~c)^a; } + +V foo_38_1(V a, V b, V c) { return ((b&a)|c)^b; } + +V foo_39_1(V a, V b, V c) { return ~(((b^a)&c)^a); } +V foo_39_2(V a, V b, V c) { return ((b^a)&c)^~a; } +V foo_39_3(V a, V b, V c) { return (~a|c)^(c&b); } +V foo_39_4(V a, V b, V c) { return ((~(b^a))|c)^b; } +V foo_39_5(V a, V b, V c) { return (~((b^a)&c))^a; } +V foo_39_6(V a, V b, V c) { return (~c|b)^(c|a); } + +V foo_40_1(V a, V b, V c) { return (b^a)&c; } + +V foo_41_1(V a, V b, V c) { return ~((((b&a)|c)^a)^b); } +V foo_41_2(V a, V b, V c) { return (((b&a)|c)^b)^~a; } +V foo_41_3(V a, V b, V c) { return (~((b&a)|c))^(b^a); } +V foo_41_4(V a, V b, V c) { return (((b&a)|c)^a)^~b; } +V foo_41_5(V a, V b, V c) { return ((b&a)|c)^(~(b^a)); } +V foo_41_6(V a, V b, V c) { return (~(((b&a)|c)^a))^b; } +V foo_41_7(V a, V b, V c) { return ((b&a)|~c)^(b|a); } +V foo_41_8(V a, V b, V c) { return (~(((b&a)|c)^b))^a; } + +V foo_42_1(V a, V b, V c) { return (~(b&a))&c; } + +V foo_43_1(V a, V b, V c) { return ~(((b^a)&(c^a))^b); } +V foo_43_2(V a, V b, V c) { return ((b^a)&c)|(~(b|a)); } +V foo_43_3(V a, V b, V c) { return ((b^a)&c)^(~(b|a)); } +V foo_43_4(V a, V b, V c) { return ((b^a)&(c^b))^~a; } +V foo_43_5(V a, V b, V c) { return ((b^a)&(c^a))^~b; } +V foo_43_6(V a, V b, V c) { return ((b^a)|(c^a))^~c; } +V foo_43_7(V a, V b, V c) { return (~((b^a)|(c^a)))^c; } +V foo_43_8(V a, V b, V c) { return ((~(b^a))|c)^(b&a); } +V foo_43_9(V a, V b, V c) { return (~((b^a)&(c^a)))^b; } +V foo_43_10(V a, V b, V c) { return (~((b^a)&c))^(b|a); } +V foo_43_11(V a, V b, V c) { return (~((b^a)&(c^b)))^a; } +V foo_43_12(V a, V b, V c) { return ((c^b)|a)^(~c|b); } +V foo_43_13(V a, V b, V c) { return ((c^a)|b)^(~c|a); } + +V foo_44_1(V a, V b, V c) { return (b^a)&(c|b); } +V foo_44_2(V a, V b, V c) { return ((c|b)&a)^b; } + +V foo_45_1(V a, V b, V c) { return (~c|b)^a; } + +V foo_46_1(V a, V b, V c) { return (b&a)^(c|b); } +V foo_46_2(V a, V b, V c) { return ((c^a)|b)^a; } + +V foo_47_1(V a, V b, V c) { return ~((~c|b)&a); } +V foo_47_2(V a, V b, V c) { return (~b&c)|~a; } + +V foo_48_1(V a, V b, V c) { return ~b&a; } + +V foo_49_1(V a, V b, V c) { return ~((~a&c)|b); } +V foo_49_2(V a, V b, V c) { return (~c|a)&~b; } + +V foo_50_1(V a, V b, V c) { return (c|a)&~b; } + +V foo_51_1(V a, V b, V c) { return ~b; } + +V foo_52_1(V a, V b, V c) { return ((c&b)|a)^b; } + +V foo_53_1(V a, V b, V c) { return ~(((c^b)&a)^c); } +V foo_53_2(V a, V b, V c) { return ((c^b)&a)^~c; } +V foo_53_3(V a, V b, V c) { return (~((c^b)&a))^c; } +V foo_53_4(V a, V b, V c) { return (~c|a)^(b&a); } +V foo_53_5(V a, V b, V c) { return ((~(c^b))|a)^b; } +V foo_53_6(V a, V b, V c) { return (~a|b)^(c|a); } + +V foo_54_1(V a, V b, V c) { return (c|a)^b; } + +V foo_55_1(V a, V b, V c) { return ~((c|a)&b); } + +V foo_56_1(V a, V b, V c) { return (b^a)&(c|a); } +V foo_56_2(V a, V b, V c) { return ((c|a)&b)^a; } + +V foo_57_1(V a, V b, V c) { return (~c|a)^b; } + +V foo_58_1(V a, V b, V c) { return (b&a)^(c|a); } +V foo_58_2(V a, V b, V c) { return ((c^b)|a)^b; } + +V foo_59_1(V a, V b, V c) { return ~((~c|a)&b); } +V foo_59_2(V a, V b, V c) { return (~a&c)|~b; } + +V foo_60_1(V a, V b, V c) { return b^a; } + +V foo_61_1(V a, V b, V c) { return (~(c|a))|(b^a); } +V foo_61_2(V a, V b, V c) { return (~(c|b))|(b^a); } +V foo_61_3(V a, V b, V c) { return ((~(c|b))|a)^b; } +V foo_61_4(V a, V b, V c) { return ((~(c|a))|b)^a; } + +V foo_62_1(V a, V b, V c) { return (~a&c)|(b^a); } +V foo_62_2(V a, V b, V c) { return (~b&c)|(b^a); } +V foo_62_3(V a, V b, V c) { return ((~b&c)|a)^b; } +V foo_62_4(V a, V b, V c) { return ((~a&c)|b)^a; } + +V foo_63_1(V a, V b, V c) { return ~(b&a); } + +V foo_64_1(V a, V b, V c) { return (~c&b)&a; } +V foo_64_2(V a, V b, V c) { return (~c&a)&b; } +V foo_64_3(V a, V b, V c) { return (b&a)&~c; } + +V foo_65_1(V a, V b, V c) { return ~((b^a)|c); } + +V foo_66_1(V a, V b, V c) { return (c^a)&(c^b); } + +V foo_67_1(V a, V b, V c) { return ~((b^a)|(c&b)); } +V foo_67_2(V a, V b, V c) { return ((c&b)|~a)^b; } +V foo_67_3(V a, V b, V c) { return ((c&a)|~b)^a; } + +V foo_68_1(V a, V b, V c) { return ~c&b; } + +V foo_69_1(V a, V b, V c) { return ~((~b&a)|c); } +V foo_69_2(V a, V b, V c) { return (~a|b)&~c; } + +V foo_70_1(V a, V b, V c) { return ((c&a)|b)^c; } + +V foo_71_1(V a, V b, V c) { return ~(((c^a)&b)^a); } +V foo_71_2(V a, V b, V c) { return ((c^a)&b)^~a; } +V foo_71_3(V a, V b, V c) { return (~a|b)^(c&b); } +V foo_71_4(V a, V b, V c) { return ((~(c^a))|b)^c; } +V foo_71_5(V a, V b, V c) { return (~((c^a)&b))^a; } +V foo_71_6(V a, V b, V c) { return (~b|c)^(b|a); } + +V foo_72_1(V a, V b, V c) { return (c^a)&b; } + +V foo_73_1(V a, V b, V c) { return ~((((c&a)|b)^a)^c); } +V foo_73_2(V a, V b, V c) { return (((c&a)|b)^c)^~a; } +V foo_73_3(V a, V b, V c) { return (~((c&a)|b))^(c^a); } +V foo_73_4(V a, V b, V c) { return (((c&a)|b)^a)^~c; } +V foo_73_5(V a, V b, V c) { return ((c&a)|b)^(~(c^a)); } +V foo_73_6(V a, V b, V c) { return (~(((c&a)|b)^a))^c; } +V foo_73_7(V a, V b, V c) { return ((c&a)|~b)^(c|a); } +V foo_73_8(V a, V b, V c) { return (~(((c&a)|b)^c))^a; } + +V foo_74_1(V a, V b, V c) { return (c^a)&(c|b); } +V foo_74_2(V a, V b, V c) { return ((c|b)&a)^c; } + +V foo_75_1(V a, V b, V c) { return (~b|c)^a; } + +V foo_76_1(V a, V b, V c) { return (~(c&a))&b; } + +V foo_77_1(V a, V b, V c) { return ~(((b^a)&(c^a))^c); } +V foo_77_2(V a, V b, V c) { return ((c^a)&b)|(~(c|a)); } +V foo_77_3(V a, V b, V c) { return ((c^a)&b)^(~(c|a)); } +V foo_77_4(V a, V b, V c) { return ((c^a)&(c^b))^~a; } +V foo_77_5(V a, V b, V c) { return ((b^a)&(c^a))^~c; } +V foo_77_6(V a, V b, V c) { return ((b^a)|(c^a))^~b; } +V foo_77_7(V a, V b, V c) { return (~((b^a)|(c^a)))^b; } +V foo_77_8(V a, V b, V c) { return ((~(c^a))|b)^(c&a); } +V foo_77_9(V a, V b, V c) { return (~((b^a)&(c^a)))^c; } +V foo_77_10(V a, V b, V c) { return (~((c^a)&b))^(c|a); } +V foo_77_11(V a, V b, V c) { return ((c^b)|a)^(~b|c); } +V foo_77_12(V a, V b, V c) { return (~((c^a)&(c^b)))^a; } +V foo_77_13(V a, V b, V c) { return ((b^a)|c)^(~b|a); } + +V foo_78_1(V a, V b, V c) { return (c&a)^(c|b); } +V foo_78_2(V a, V b, V c) { return ((b^a)|c)^a; } + +V foo_79_1(V a, V b, V c) { return ~((~b|c)&a); } +V foo_79_2(V a, V b, V c) { return (~c&b)|~a; } + +V foo_80_1(V a, V b, V c) { return ~c&a; } + +V foo_81_1(V a, V b, V c) { return ~((~a&b)|c); } +V foo_81_2(V a, V b, V c) { return (~b|a)&~c; } + +V foo_82_1(V a, V b, V c) { return ((c&b)|a)^c; } + +V foo_83_1(V a, V b, V c) { return ~(((c^b)&a)^b); } +V foo_83_2(V a, V b, V c) { return ((c^b)&a)^~b; } +V foo_83_3(V a, V b, V c) { return (~((c^b)&a))^b; } +V foo_83_4(V a, V b, V c) { return (~b|a)^(c&a); } +V foo_83_5(V a, V b, V c) { return ((~(c^b))|a)^c; } +V foo_83_6(V a, V b, V c) { return (~a|c)^(b|a); } + +V foo_84_1(V a, V b, V c) { return (b|a)&~c; } + +V foo_85_1(V a, V b, V c) { return ~c; } + +V foo_86_1(V a, V b, V c) { return (b|a)^c; } + +V foo_87_1(V a, V b, V c) { return ~((b|a)&c); } + +V foo_88_1(V a, V b, V c) { return (c^a)&(b|a); } +V foo_88_2(V a, V b, V c) { return ((b|a)&c)^a; } + +V foo_89_1(V a, V b, V c) { return (~b|a)^c; } + +V foo_90_1(V a, V b, V c) { return c^a; } + +V foo_91_1(V a, V b, V c) { return (~(b|a))|(c^a); } +V foo_91_2(V a, V b, V c) { return (~(c|b))|(c^a); } +V foo_91_3(V a, V b, V c) { return ((~(c|b))|a)^c; } +V foo_91_4(V a, V b, V c) { return ((~(b|a))|c)^a; } + +V foo_92_1(V a, V b, V c) { return (c&a)^(b|a); } +V foo_92_2(V a, V b, V c) { return ((c^b)|a)^c; } + +V foo_93_1(V a, V b, V c) { return ~((~b|a)&c); } +V foo_93_2(V a, V b, V c) { return (~a&b)|~c; } + +V foo_94_1(V a, V b, V c) { return (~a&b)|(c^a); } +V foo_94_2(V a, V b, V c) { return (~c&b)|(c^a); } +V foo_94_3(V a, V b, V c) { return ((~c&b)|a)^c; } +V foo_94_4(V a, V b, V c) { return ((~a&b)|c)^a; } + +V foo_95_1(V a, V b, V c) { return ~(c&a); } + +V foo_96_1(V a, V b, V c) { return (c^b)&a; } + +V foo_97_1(V a, V b, V c) { return ~(((c|b)^a)|(c&b)); } +V foo_97_2(V a, V b, V c) { return (~((c&b)|a))^(c^b); } +V foo_97_3(V a, V b, V c) { return (((c&b)|a)^c)^~b; } +V foo_97_4(V a, V b, V c) { return (((c&b)|a)^b)^~c; } +V foo_97_5(V a, V b, V c) { return ((c&b)|~a)^(c|b); } +V foo_97_6(V a, V b, V c) { return ((c&b)|a)^(~(c^b)); } +V foo_97_7(V a, V b, V c) { return (~(((c&b)|a)^b))^c; } +V foo_97_8(V a, V b, V c) { return (~(((c&b)|a)^c))^b; } + +V foo_98_1(V a, V b, V c) { return (c^b)&(c|a); } +V foo_98_2(V a, V b, V c) { return ((c|a)&b)^c; } + +V foo_99_1(V a, V b, V c) { return (~a|c)^b; } + +V foo_100_1(V a, V b, V c) { return (c^b)&(b|a); } +V foo_100_2(V a, V b, V c) { return ((b|a)&c)^b; } + +V foo_101_1(V a, V b, V c) { return (~a|b)^c; } + +V foo_102_1(V a, V b, V c) { return c^b; } + +V foo_103_1(V a, V b, V c) { return (~(b|a))|(c^b); } +V foo_103_2(V a, V b, V c) { return (~(c|a))|(c^b); } +V foo_103_3(V a, V b, V c) { return ((~(c|a))|b)^c; } +V foo_103_4(V a, V b, V c) { return ((~(b|a))|c)^b; } + +V foo_104_1(V a, V b, V c) { return ((b&a)^c)&(b|a); } +V foo_104_2(V a, V b, V c) { return ((c&a)^b)&(c|a); } +V foo_104_3(V a, V b, V c) { return ((c&b)^a)&(c|b); } +V foo_104_4(V a, V b, V c) { return ((c|b)&a)^(c&b); } +V foo_104_5(V a, V b, V c) { return ((c|a)&b)^(c&a); } +V foo_104_6(V a, V b, V c) { return ((b|a)&c)^(b&a); } + +V foo_105_1(V a, V b, V c) { return ~((b^a)^c); } +V foo_105_2(V a, V b, V c) { return (c^b)^~a; } +V foo_105_3(V a, V b, V c) { return (c^a)^~b; } +V foo_105_4(V a, V b, V c) { return (b^a)^~c; } +V foo_105_5(V a, V b, V c) { return (~(c^b))^a; } +V foo_105_6(V a, V b, V c) { return (~(c^a))^b; } +V foo_105_7(V a, V b, V c) { return (~(b^a))^c; } + +V foo_106_1(V a, V b, V c) { return (b&a)^c; } + +V foo_107_1(V a, V b, V c) { return ~(((b|a)&c)^(b^a)); } +V foo_107_2(V a, V b, V c) { return ((b&a)^c)|(~(b|a)); } +V foo_107_3(V a, V b, V c) { return ((c^b)&(b|a))^~a; } +V foo_107_4(V a, V b, V c) { return ((c^a)&(b|a))^~b; } +V foo_107_5(V a, V b, V c) { return (~((b|a)&c))^(b^a); } +V foo_107_6(V a, V b, V c) { return (~((c^b)&(b|a)))^a; } +V foo_107_7(V a, V b, V c) { return (~((c^a)&(b|a)))^b; } +V foo_107_8(V a, V b, V c) { return ((b|a)&c)^(~(b^a)); } +V foo_107_9(V a, V b, V c) { return ((~(b|a))|c)^(b&a); } + +V foo_108_1(V a, V b, V c) { return (c&a)^b; } + +V foo_109_1(V a, V b, V c) { return ~(((b^a)&(c|a))^c); } +V foo_109_2(V a, V b, V c) { return ((c&a)^b)|(~(c|a)); } +V foo_109_3(V a, V b, V c) { return ((c^b)&(c|a))^~a; } +V foo_109_4(V a, V b, V c) { return (~((c|a)&b))^(c^a); } +V foo_109_5(V a, V b, V c) { return ((b^a)&(c|a))^~c; } +V foo_109_6(V a, V b, V c) { return (~((c^b)&(c|a)))^a; } +V foo_109_7(V a, V b, V c) { return ((~(c|a))|b)^(c&a); } +V foo_109_8(V a, V b, V c) { return ((c|a)&b)^(~(c^a)); } +V foo_109_9(V a, V b, V c) { return (~((b^a)&(c|a)))^c; } + +V foo_110_1(V a, V b, V c) { return (~a&c)|(c^b); } +V foo_110_2(V a, V b, V c) { return (~a&b)|(c^b); } +V foo_110_3(V a, V b, V c) { return ((~b|a)&c)^b; } +V foo_110_4(V a, V b, V c) { return ((~c|a)&b)^c; } + +V foo_111_1(V a, V b, V c) { return (c^b)|~a; } + +V foo_112_1(V a, V b, V c) { return (~(c&b))&a; } + +V foo_113_1(V a, V b, V c) { return ~(((b^a)&(c^b))^c); } +V foo_113_2(V a, V b, V c) { return ((b^a)|(c^a))^~a; } +V foo_113_3(V a, V b, V c) { return ((c^b)&a)|(~(c|b)); } +V foo_113_4(V a, V b, V c) { return ((c^b)&a)^(~(c|b)); } +V foo_113_5(V a, V b, V c) { return ((b^a)&(c^b))^~c; } +V foo_113_6(V a, V b, V c) { return ((c^a)&(c^b))^~b; } +V foo_113_7(V a, V b, V c) { return (~((b^a)|(c^a)))^a; } +V foo_113_8(V a, V b, V c) { return ((~(c^b))|a)^(c&b); } +V foo_113_9(V a, V b, V c) { return (~((c^b)&a))^(c|b); } +V foo_113_10(V a, V b, V c) { return (~((b^a)&(c^b)))^c; } +V foo_113_11(V a, V b, V c) { return ((c^a)|b)^(~a|c); } +V foo_113_12(V a, V b, V c) { return (~((c^a)&(c^b)))^b; } +V foo_113_13(V a, V b, V c) { return ((b^a)|c)^(~a|b); } + +V foo_114_1(V a, V b, V c) { return (c&b)^(c|a); } +V foo_114_2(V a, V b, V c) { return ((b^a)|c)^b; } + +V foo_115_1(V a, V b, V c) { return ~((~a|c)&b); } +V foo_115_2(V a, V b, V c) { return (~c&a)|~b; } + +V foo_116_1(V a, V b, V c) { return (c&b)^(b|a); } +V foo_116_2(V a, V b, V c) { return ((c^a)|b)^c; } + +V foo_117_1(V a, V b, V c) { return ~((~a|b)&c); } +V foo_117_2(V a, V b, V c) { return (~b&a)|~c; } + +V foo_118_1(V a, V b, V c) { return (~b&a)|(c^b); } +V foo_118_2(V a, V b, V c) { return (~c&a)|(c^b); } +V foo_118_3(V a, V b, V c) { return ((~c&a)|b)^c; } +V foo_118_4(V a, V b, V c) { return ((~b&a)|c)^b; } + +V foo_119_1(V a, V b, V c) { return ~(c&b); } + +V foo_120_1(V a, V b, V c) { return (c&b)^a; } + +V foo_121_1(V a, V b, V c) { return ~(((b^a)&(c|b))^c); } +V foo_121_2(V a, V b, V c) { return ((c&b)^a)|(~(c|b)); } +V foo_121_3(V a, V b, V c) { return (~((c|b)&a))^(c^b); } +V foo_121_4(V a, V b, V c) { return ((b^a)&(c|b))^~c; } +V foo_121_5(V a, V b, V c) { return ((c^a)&(c|b))^~b; } +V foo_121_6(V a, V b, V c) { return ((~(c|b))|a)^(c&b); } +V foo_121_7(V a, V b, V c) { return ((c|b)&a)^(~(c^b)); } +V foo_121_8(V a, V b, V c) { return (~((b^a)&(c|b)))^c; } +V foo_121_9(V a, V b, V c) { return (~((c^a)&(c|b)))^b; } + +V foo_122_1(V a, V b, V c) { return (~b&c)|(c^a); } +V foo_122_2(V a, V b, V c) { return (~b&a)|(c^a); } +V foo_122_3(V a, V b, V c) { return ((~a|b)&c)^a; } +V foo_122_4(V a, V b, V c) { return ((~c|b)&a)^c; } + +V foo_123_1(V a, V b, V c) { return (c^a)|~b; } + +V foo_124_1(V a, V b, V c) { return (~c&b)|(b^a); } +V foo_124_2(V a, V b, V c) { return (~c&a)|(b^a); } +V foo_124_3(V a, V b, V c) { return ((~a|c)&b)^a; } +V foo_124_4(V a, V b, V c) { return ((~b|c)&a)^b; } + +V foo_125_1(V a, V b, V c) { return (b^a)|~c; } + +V foo_126_1(V a, V b, V c) { return (b^a)|(c^a); } +V foo_126_2(V a, V b, V c) { return (b^a)|(c^b); } +V foo_126_3(V a, V b, V c) { return (c^a)|(c^b); } + +V foo_127_1(V a, V b, V c) { return ~((c&b)&a); } + +V foo_128_1(V a, V b, V c) { return (c&b)&a; } +V foo_128_2(V a, V b, V c) { return (c&a)&b; } +V foo_128_3(V a, V b, V c) { return (b&a)&c; } + +V foo_129_1(V a, V b, V c) { return ~((b^a)|(c^a)); } + +V foo_130_1(V a, V b, V c) { return (~(b^a))&c; } + +V foo_131_1(V a, V b, V c) { return ~((~c&b)|(b^a)); } +V foo_131_2(V a, V b, V c) { return ((~a|c)&b)^~a; } +V foo_131_3(V a, V b, V c) { return ((~b|c)&a)^~b; } +V foo_131_4(V a, V b, V c) { return (~((~b|c)&a))^b; } +V foo_131_5(V a, V b, V c) { return (~((~a|c)&b))^a; } +V foo_131_6(V a, V b, V c) { return (~a|c)&(~(b^a)); } +V foo_131_7(V a, V b, V c) { return (~b|c)&(~(b^a)); } + +V foo_132_1(V a, V b, V c) { return (~(c^a))&b; } + +V foo_133_1(V a, V b, V c) { return ~((~b&c)|(c^a)); } +V foo_133_2(V a, V b, V c) { return ((~a|b)&c)^~a; } +V foo_133_3(V a, V b, V c) { return (~((~c|b)&a))^c; } +V foo_133_4(V a, V b, V c) { return ((~c|b)&a)^~c; } +V foo_133_5(V a, V b, V c) { return (~((~a|b)&c))^a; } +V foo_133_6(V a, V b, V c) { return (~(c^a))&(~a|b); } +V foo_133_7(V a, V b, V c) { return (~(c^a))&(~c|b); } + +V foo_134_1(V a, V b, V c) { return ((b^a)&(c|b))^c; } +V foo_134_2(V a, V b, V c) { return ((c^a)&(c|b))^b; } +V foo_134_3(V a, V b, V c) { return ((c|b)&a)^(c^b); } +V foo_134_4(V a, V b, V c) { return ((b^a)^c)&(c|b); } + +V foo_135_1(V a, V b, V c) { return ~((c&b)^a); } +V foo_135_2(V a, V b, V c) { return (c&b)^~a; } +V foo_135_3(V a, V b, V c) { return (~(c&b))^a; } + +V foo_136_1(V a, V b, V c) { return c&b; } + +V foo_137_1(V a, V b, V c) { return ~((~b&a)|(c^b)); } +V foo_137_2(V a, V b, V c) { return (~((~c&a)|b))^c; } +V foo_137_3(V a, V b, V c) { return ((~b&a)|c)^~b; } +V foo_137_4(V a, V b, V c) { return (~((~b&a)|c))^b; } +V foo_137_5(V a, V b, V c) { return ((~c&a)|b)^~c; } +V foo_137_6(V a, V b, V c) { return (~(c^b))&(~a|c); } +V foo_137_7(V a, V b, V c) { return (~(c^b))&(~a|b); } + +V foo_138_1(V a, V b, V c) { return (~a|b)&c; } + +V foo_139_1(V a, V b, V c) { return ~((c&b)^(b|a)); } +V foo_139_2(V a, V b, V c) { return (~(b|a))|(c&b); } +V foo_139_3(V a, V b, V c) { return (~(b|a))^(c&b); } +V foo_139_4(V a, V b, V c) { return (~((c^a)|b))^c; } +V foo_139_5(V a, V b, V c) { return ((c^a)|b)^~c; } +V foo_139_6(V a, V b, V c) { return (~(c&b))^(b|a); } +V foo_139_7(V a, V b, V c) { return ((c^a)|~b)^a; } + +V foo_140_1(V a, V b, V c) { return (~a|c)&b; } + +V foo_141_1(V a, V b, V c) { return ~((c&b)^(c|a)); } +V foo_141_2(V a, V b, V c) { return (~(c|a))|(c&b); } +V foo_141_3(V a, V b, V c) { return (~(c|a))^(c&b); } +V foo_141_4(V a, V b, V c) { return ((b^a)|c)^~b; } +V foo_141_5(V a, V b, V c) { return (~((b^a)|c))^b; } +V foo_141_6(V a, V b, V c) { return (~(c&b))^(c|a); } +V foo_141_7(V a, V b, V c) { return ((b^a)|~c)^a; } + +V foo_142_1(V a, V b, V c) { return ((b^a)&(c^b))^c; } +V foo_142_2(V a, V b, V c) { return ((c^a)&(c^b))^b; } +V foo_142_3(V a, V b, V c) { return ((c^b)&a)^(c|b); } +V foo_142_4(V a, V b, V c) { return ((b^a)|(c^a))^a; } + +V foo_143_1(V a, V b, V c) { return (c&b)|~a; } + +V foo_144_1(V a, V b, V c) { return (~(c^b))&a; } + +V foo_145_1(V a, V b, V c) { return ~((~a&c)|(c^b)); } +V foo_145_2(V a, V b, V c) { return ((~b|a)&c)^~b; } +V foo_145_3(V a, V b, V c) { return (~((~c|a)&b))^c; } +V foo_145_4(V a, V b, V c) { return ((~c|a)&b)^~c; } +V foo_145_5(V a, V b, V c) { return (~((~b|a)&c))^b; } +V foo_145_6(V a, V b, V c) { return (~(c^b))&(~b|a); } +V foo_145_7(V a, V b, V c) { return (~(c^b))&(~c|a); } + +V foo_146_1(V a, V b, V c) { return ((b^a)&(c|a))^c; } +V foo_146_2(V a, V b, V c) { return ((c|a)&b)^(c^a); } +V foo_146_3(V a, V b, V c) { return ((c^b)&(c|a))^a; } +V foo_146_4(V a, V b, V c) { return ((b^a)^c)&(c|a); } + +V foo_147_1(V a, V b, V c) { return ~((c&a)^b); } +V foo_147_2(V a, V b, V c) { return (c&a)^~b; } +V foo_147_3(V a, V b, V c) { return (~(c&a))^b; } + +V foo_148_1(V a, V b, V c) { return ((b|a)&c)^(b^a); } +V foo_148_2(V a, V b, V c) { return ((c^a)&(b|a))^b; } +V foo_148_3(V a, V b, V c) { return ((c^b)&(b|a))^a; } +V foo_148_4(V a, V b, V c) { return ((b^a)^c)&(b|a); } + +V foo_149_1(V a, V b, V c) { return ~((b&a)^c); } +V foo_149_2(V a, V b, V c) { return (~(b&a))^c; } +V foo_149_3(V a, V b, V c) { return (b&a)^~c; } + +V foo_150_1(V a, V b, V c) { return (b^a)^c; } +V foo_150_2(V a, V b, V c) { return (c^a)^b; } +V foo_150_3(V a, V b, V c) { return (c^b)^a; } + +V foo_151_1(V a, V b, V c) { return ~(((b&a)^c)&(b|a)); } +V foo_151_2(V a, V b, V c) { return ((b^a)^c)|(~(b|a)); } +V foo_151_3(V a, V b, V c) { return ((b^a)^c)|(~(c|a)); } +V foo_151_4(V a, V b, V c) { return ((b^a)^c)|(~(c|b)); } +V foo_151_5(V a, V b, V c) { return (~((c|b)&a))^(c&b); } +V foo_151_6(V a, V b, V c) { return (~((c|a)&b))^(c&a); } +V foo_151_7(V a, V b, V c) { return ((~(b|a))|c)^(b^a); } +V foo_151_8(V a, V b, V c) { return ((~(c|a))|(b^a))^c; } +V foo_151_9(V a, V b, V c) { return ((b|a)&c)^(~(b&a)); } +V foo_151_10(V a, V b, V c) { return (~((b|a)&c))^(b&a); } +V foo_151_11(V a, V b, V c) { return ((~(c|a))|b)^(c^a); } +V foo_151_12(V a, V b, V c) { return ((~(b|a))|(c^a))^b; } +V foo_151_13(V a, V b, V c) { return ((c|a)&b)^(~(c&a)); } +V foo_151_14(V a, V b, V c) { return ((~(c|b))|a)^(c^b); } +V foo_151_15(V a, V b, V c) { return ((~(b|a))|(c^b))^a; } +V foo_151_16(V a, V b, V c) { return ((c|b)&a)^(~(c&b)); } + +V foo_152_1(V a, V b, V c) { return ((c|a)&~b)^c; } +V foo_152_2(V a, V b, V c) { return ((b|a)&~c)^b; } +V foo_152_3(V a, V b, V c) { return (~(c^b))&(c|a); } +V foo_152_4(V a, V b, V c) { return (~(c^b))&(b|a); } + +V foo_153_1(V a, V b, V c) { return ~(c^b); } +V foo_153_2(V a, V b, V c) { return ~b^c; } +V foo_153_3(V a, V b, V c) { return ~c^b; } + +V foo_154_1(V a, V b, V c) { return (~b&a)^c; } + +V foo_155_1(V a, V b, V c) { return ~((c^b)&(b|a)); } +V foo_155_2(V a, V b, V c) { return ((b|a)&c)^~b; } +V foo_155_3(V a, V b, V c) { return (~((b|a)&c))^b; } + +V foo_156_1(V a, V b, V c) { return (~c&a)^b; } + +V foo_157_1(V a, V b, V c) { return ~((c^b)&(c|a)); } +V foo_157_2(V a, V b, V c) { return (~((c|a)&b))^c; } +V foo_157_3(V a, V b, V c) { return ((c|a)&b)^~c; } + +V foo_158_1(V a, V b, V c) { return ((c|b)^a)|(c&b); } +V foo_158_2(V a, V b, V c) { return (((c&b)|a)^b)^c; } +V foo_158_3(V a, V b, V c) { return (((c&b)|a)^c)^b; } +V foo_158_4(V a, V b, V c) { return ((c&b)|a)^(c^b); } +V foo_158_5(V a, V b, V c) { return ((b^a)^c)|(c&b); } + +V foo_159_1(V a, V b, V c) { return ~((c^b)&a); } + +V foo_160_1(V a, V b, V c) { return c&a; } + +V foo_161_1(V a, V b, V c) { return ~((~a&b)|(c^a)); } +V foo_161_2(V a, V b, V c) { return (~((~c&b)|a))^c; } +V foo_161_3(V a, V b, V c) { return ((~a&b)|c)^~a; } +V foo_161_4(V a, V b, V c) { return (~((~a&b)|c))^a; } +V foo_161_5(V a, V b, V c) { return ((~c&b)|a)^~c; } +V foo_161_6(V a, V b, V c) { return (~(c^a))&(~b|c); } +V foo_161_7(V a, V b, V c) { return (~(c^a))&(~b|a); } + +V foo_162_1(V a, V b, V c) { return (~b|a)&c; } + +V foo_163_1(V a, V b, V c) { return ~((c&a)^(b|a)); } +V foo_163_2(V a, V b, V c) { return (~(b|a))|(c&a); } +V foo_163_3(V a, V b, V c) { return (~(b|a))^(c&a); } +V foo_163_4(V a, V b, V c) { return (~((c^b)|a))^c; } +V foo_163_5(V a, V b, V c) { return ((c^b)|a)^~c; } +V foo_163_6(V a, V b, V c) { return (~(c&a))^(b|a); } +V foo_163_7(V a, V b, V c) { return ((c^b)|~a)^b; } + +V foo_164_1(V a, V b, V c) { return ((c|b)&~a)^c; } +V foo_164_2(V a, V b, V c) { return ((b|a)&~c)^a; } +V foo_164_3(V a, V b, V c) { return (~(c^a))&(c|b); } +V foo_164_4(V a, V b, V c) { return (~(c^a))&(b|a); } + +V foo_165_1(V a, V b, V c) { return ~(c^a); } +V foo_165_2(V a, V b, V c) { return ~a^c; } +V foo_165_3(V a, V b, V c) { return ~c^a; } + +V foo_166_1(V a, V b, V c) { return (~a&b)^c; } + +V foo_167_1(V a, V b, V c) { return ~((c^a)&(b|a)); } +V foo_167_2(V a, V b, V c) { return ((b|a)&c)^~a; } +V foo_167_3(V a, V b, V c) { return (~((b|a)&c))^a; } + +V foo_168_1(V a, V b, V c) { return (b|a)&c; } + +V foo_169_1(V a, V b, V c) { return ~((b|a)^c); } +V foo_169_2(V a, V b, V c) { return (~(b|a))^c; } +V foo_169_3(V a, V b, V c) { return (b|a)^~c; } + +V foo_170_1(V a, V b, V c) { return c; } + +V foo_171_1(V a, V b, V c) { return (~(b|a))|c; } + +V foo_172_1(V a, V b, V c) { return ((c^b)&a)^b; } + +V foo_173_1(V a, V b, V c) { return ~(((c&b)|a)^c); } +V foo_173_2(V a, V b, V c) { return (~((c&b)|a))^c; } +V foo_173_3(V a, V b, V c) { return ((c&b)|a)^~c; } +V foo_173_4(V a, V b, V c) { return (~(c^a))|(c&b); } + +V foo_174_1(V a, V b, V c) { return (~a&b)|c; } + +V foo_175_1(V a, V b, V c) { return ~a|c; } + +V foo_176_1(V a, V b, V c) { return (~b|c)&a; } + +V foo_177_1(V a, V b, V c) { return ~((c&a)^(c|b)); } +V foo_177_2(V a, V b, V c) { return ((b^a)|c)^~a; } +V foo_177_3(V a, V b, V c) { return (~(c|b))|(c&a); } +V foo_177_4(V a, V b, V c) { return (~(c|b))^(c&a); } +V foo_177_5(V a, V b, V c) { return (~((b^a)|c))^a; } +V foo_177_6(V a, V b, V c) { return (~(c&a))^(c|b); } +V foo_177_7(V a, V b, V c) { return ((b^a)|~c)^b; } + +V foo_178_1(V a, V b, V c) { return ((b^a)&(c^a))^c; } +V foo_178_2(V a, V b, V c) { return ((c^a)&(c^b))^a; } +V foo_178_3(V a, V b, V c) { return ((c^a)&b)^(c|a); } +V foo_178_4(V a, V b, V c) { return ((b^a)|(c^a))^b; } + +V foo_179_1(V a, V b, V c) { return (c&a)|~b; } + +V foo_180_1(V a, V b, V c) { return (~c&b)^a; } + +V foo_181_1(V a, V b, V c) { return ~((c^a)&(c|b)); } +V foo_181_2(V a, V b, V c) { return (~((c|b)&a))^c; } +V foo_181_3(V a, V b, V c) { return ((c|b)&a)^~c; } + +V foo_182_1(V a, V b, V c) { return (((c&a)|b)^a)^c; } +V foo_182_2(V a, V b, V c) { return ((c|a)^b)|(c&a); } +V foo_182_3(V a, V b, V c) { return (((c&a)|b)^c)^a; } +V foo_182_4(V a, V b, V c) { return ((c&a)|b)^(c^a); } +V foo_182_5(V a, V b, V c) { return ((b^a)^c)|(c&a); } + +V foo_183_1(V a, V b, V c) { return ~((c^a)&b); } + +V foo_184_1(V a, V b, V c) { return ((c^a)&b)^a; } + +V foo_185_1(V a, V b, V c) { return ~(((c&a)|b)^c); } +V foo_185_2(V a, V b, V c) { return (~((c&a)|b))^c; } +V foo_185_3(V a, V b, V c) { return ((c&a)|b)^~c; } +V foo_185_4(V a, V b, V c) { return (~(c^b))|(c&a); } + +V foo_186_1(V a, V b, V c) { return (~b&a)|c; } + +V foo_187_1(V a, V b, V c) { return ~b|c; } + +V foo_188_1(V a, V b, V c) { return (b^a)|(c&b); } +V foo_188_2(V a, V b, V c) { return (b^a)|(c&a); } + +V foo_189_1(V a, V b, V c) { return ~((c^a)&(c^b)); } +V foo_189_2(V a, V b, V c) { return (~(c^b))|(b^a); } +V foo_189_3(V a, V b, V c) { return (~(c^a))|(b^a); } + +V foo_190_1(V a, V b, V c) { return (b^a)|c; } + +V foo_191_1(V a, V b, V c) { return (~(b&a))|c; } + +V foo_192_1(V a, V b, V c) { return b&a; } + +V foo_193_1(V a, V b, V c) { return ~((~a&c)|(b^a)); } +V foo_193_2(V a, V b, V c) { return (~((~b&c)|a))^b; } +V foo_193_3(V a, V b, V c) { return ((~a&c)|b)^~a; } +V foo_193_4(V a, V b, V c) { return (~((~a&c)|b))^a; } +V foo_193_5(V a, V b, V c) { return ((~b&c)|a)^~b; } +V foo_193_6(V a, V b, V c) { return (~(b^a))&(~c|b); } +V foo_193_7(V a, V b, V c) { return (~(b^a))&(~c|a); } + +V foo_194_1(V a, V b, V c) { return ((c|b)&~a)^b; } +V foo_194_2(V a, V b, V c) { return ((c|a)&~b)^a; } +V foo_194_3(V a, V b, V c) { return (~(b^a))&(c|b); } +V foo_194_4(V a, V b, V c) { return (~(b^a))&(c|a); } + +V foo_195_1(V a, V b, V c) { return ~(b^a); } +V foo_195_2(V a, V b, V c) { return ~a^b; } +V foo_195_3(V a, V b, V c) { return ~b^a; } + +V foo_196_1(V a, V b, V c) { return (~c|a)&b; } + +V foo_197_1(V a, V b, V c) { return ~((b&a)^(c|a)); } +V foo_197_2(V a, V b, V c) { return (~(c|a))|(b&a); } +V foo_197_3(V a, V b, V c) { return (~(c|a))^(b&a); } +V foo_197_4(V a, V b, V c) { return (~((c^b)|a))^b; } +V foo_197_5(V a, V b, V c) { return ((c^b)|a)^~b; } +V foo_197_6(V a, V b, V c) { return (~(b&a))^(c|a); } +V foo_197_7(V a, V b, V c) { return ((c^b)|~a)^c; } + +V foo_198_1(V a, V b, V c) { return (~a&c)^b; } + +V foo_199_1(V a, V b, V c) { return ~((b^a)&(c|a)); } +V foo_199_2(V a, V b, V c) { return ((c|a)&b)^~a; } +V foo_199_3(V a, V b, V c) { return (~((c|a)&b))^a; } + +V foo_200_1(V a, V b, V c) { return (c|a)&b; } + +V foo_201_1(V a, V b, V c) { return ~((c|a)^b); } +V foo_201_2(V a, V b, V c) { return (~(c|a))^b; } +V foo_201_3(V a, V b, V c) { return (c|a)^~b; } + +V foo_202_1(V a, V b, V c) { return ((c^b)&a)^c; } + +V foo_203_1(V a, V b, V c) { return ~(((c&b)|a)^b); } +V foo_203_2(V a, V b, V c) { return (~((c&b)|a))^b; } +V foo_203_3(V a, V b, V c) { return ((c&b)|a)^~b; } +V foo_203_4(V a, V b, V c) { return (~(b^a))|(c&b); } + +V foo_204_1(V a, V b, V c) { return b; } + +V foo_205_1(V a, V b, V c) { return (~(c|a))|b; } + +V foo_206_1(V a, V b, V c) { return (~a&c)|b; } + +V foo_207_1(V a, V b, V c) { return ~a|b; } + +V foo_208_1(V a, V b, V c) { return (~c|b)&a; } + +V foo_209_1(V a, V b, V c) { return ~((b&a)^(c|b)); } +V foo_209_2(V a, V b, V c) { return ((c^a)|b)^~a; } +V foo_209_3(V a, V b, V c) { return (~(c|b))|(b&a); } +V foo_209_4(V a, V b, V c) { return (~(c|b))^(b&a); } +V foo_209_5(V a, V b, V c) { return (~((c^a)|b))^a; } +V foo_209_6(V a, V b, V c) { return (~(b&a))^(c|b); } +V foo_209_7(V a, V b, V c) { return ((c^a)|~b)^c; } + +V foo_210_1(V a, V b, V c) { return (~b&c)^a; } + +V foo_211_1(V a, V b, V c) { return ~((b^a)&(c|b)); } +V foo_211_2(V a, V b, V c) { return (~((c|b)&a))^b; } +V foo_211_3(V a, V b, V c) { return ((c|b)&a)^~b; } + +V foo_212_1(V a, V b, V c) { return ((b^a)&(c^a))^b; } +V foo_212_2(V a, V b, V c) { return ((b^a)&(c^b))^a; } +V foo_212_3(V a, V b, V c) { return ((b^a)&c)^(b|a); } +V foo_212_4(V a, V b, V c) { return ((b^a)|(c^a))^c; } + +V foo_213_1(V a, V b, V c) { return (b&a)|~c; } + +V foo_214_1(V a, V b, V c) { return (((b&a)|c)^a)^b; } +V foo_214_2(V a, V b, V c) { return (((b&a)|c)^b)^a; } +V foo_214_3(V a, V b, V c) { return ((b&a)|c)^(b^a); } +V foo_214_4(V a, V b, V c) { return ((b|a)^c)|(b&a); } +V foo_214_5(V a, V b, V c) { return ((b^a)^c)|(b&a); } + +V foo_215_1(V a, V b, V c) { return ~((b^a)&c); } + +V foo_216_1(V a, V b, V c) { return ((b^a)&c)^a; } + +V foo_217_1(V a, V b, V c) { return ~(((b&a)|c)^b); } +V foo_217_2(V a, V b, V c) { return (~((b&a)|c))^b; } +V foo_217_3(V a, V b, V c) { return ((b&a)|c)^~b; } +V foo_217_4(V a, V b, V c) { return (~(c^b))|(b&a); } + +V foo_218_1(V a, V b, V c) { return (c^a)|(c&b); } +V foo_218_2(V a, V b, V c) { return (c^a)|(b&a); } + +V foo_219_1(V a, V b, V c) { return ~((b^a)&(c^b)); } +V foo_219_2(V a, V b, V c) { return (~(c^b))|(c^a); } +V foo_219_3(V a, V b, V c) { return (~(b^a))|(c^a); } + +V foo_220_1(V a, V b, V c) { return (~c&a)|b; } + +V foo_221_1(V a, V b, V c) { return ~c|b; } + +V foo_222_1(V a, V b, V c) { return (c^a)|b; } + +V foo_223_1(V a, V b, V c) { return (~(c&a))|b; } + +V foo_224_1(V a, V b, V c) { return (c|b)&a; } + +V foo_225_1(V a, V b, V c) { return ~((c|b)^a); } +V foo_225_2(V a, V b, V c) { return (c|b)^~a; } +V foo_225_3(V a, V b, V c) { return (~(c|b))^a; } + +V foo_226_1(V a, V b, V c) { return ((c^a)&b)^c; } + +V foo_227_1(V a, V b, V c) { return ~(((c&a)|b)^a); } +V foo_227_2(V a, V b, V c) { return ((c&a)|b)^~a; } +V foo_227_3(V a, V b, V c) { return (~((c&a)|b))^a; } +V foo_227_4(V a, V b, V c) { return (~(b^a))|(c&a); } + +V foo_228_1(V a, V b, V c) { return ((b^a)&c)^b; } + +V foo_229_1(V a, V b, V c) { return ~(((b&a)|c)^a); } +V foo_229_2(V a, V b, V c) { return ((b&a)|c)^~a; } +V foo_229_3(V a, V b, V c) { return (~((b&a)|c))^a; } +V foo_229_4(V a, V b, V c) { return (~(c^a))|(b&a); } + +V foo_230_1(V a, V b, V c) { return (c^b)|(c&a); } +V foo_230_2(V a, V b, V c) { return (c^b)|(b&a); } + +V foo_231_1(V a, V b, V c) { return ~((b^a)&(c^a)); } +V foo_231_2(V a, V b, V c) { return (~(c^a))|(c^b); } +V foo_231_3(V a, V b, V c) { return (~(b^a))|(c^b); } + +V foo_232_1(V a, V b, V c) { return ((b^a)&(c^a))^a; } +V foo_232_2(V a, V b, V c) { return ((b^a)&(c^b))^b; } +V foo_232_3(V a, V b, V c) { return ((b^a)&c)|(b&a); } +V foo_232_4(V a, V b, V c) { return ((b^a)&c)^(b&a); } +V foo_232_5(V a, V b, V c) { return ((c^a)&(c^b))^c; } +V foo_232_6(V a, V b, V c) { return ((c^a)&b)|(c&a); } +V foo_232_7(V a, V b, V c) { return ((c^a)&b)^(c&a); } +V foo_232_8(V a, V b, V c) { return ((c^b)&a)|(c&b); } +V foo_232_9(V a, V b, V c) { return ((c^b)&a)^(c&b); } +V foo_232_10(V a, V b, V c) { return ((c|b)&a)|(c&b); } +V foo_232_11(V a, V b, V c) { return ((c|a)&b)|(c&a); } +V foo_232_12(V a, V b, V c) { return ((b|a)&c)|(b&a); } +V foo_232_13(V a, V b, V c) { return ((b&a)|c)&(b|a); } +V foo_232_14(V a, V b, V c) { return ((c&a)|b)&(c|a); } +V foo_232_15(V a, V b, V c) { return ((c&b)|a)&(c|b); } + +V foo_233_1(V a, V b, V c) { return ~(((b^a)|(c&b))^c); } +V foo_233_2(V a, V b, V c) { return ((b&a)|c)^(~(b|a)); } +V foo_233_3(V a, V b, V c) { return ((c&a)|b)^(~(c|a)); } +V foo_233_4(V a, V b, V c) { return (~((c&b)|a))^(c|b); } +V foo_233_5(V a, V b, V c) { return ((c^b)|(c&a))^~a; } +V foo_233_6(V a, V b, V c) { return ((c&b)|a)^(~(c|b)); } +V foo_233_7(V a, V b, V c) { return (~((c&a)|b))^(c|a); } +V foo_233_8(V a, V b, V c) { return (~((b&a)|c))^(b|a); } +V foo_233_9(V a, V b, V c) { return (~((c^b)|(c&a)))^a; } +V foo_233_10(V a, V b, V c) { return (~((c^a)|(c&b)))^b; } +V foo_233_11(V a, V b, V c) { return ((c^a)|(c&b))^~b; } +V foo_233_12(V a, V b, V c) { return ((b&a)|~c)^(b^a); } +V foo_233_13(V a, V b, V c) { return (~((b^a)|(c&b)))^c; } +V foo_233_14(V a, V b, V c) { return ((b^a)|(c&b))^~c; } +V foo_233_15(V a, V b, V c) { return ((c&a)|~b)^(c^a); } +V foo_233_16(V a, V b, V c) { return ((c&b)|~a)^(c^b); } +V foo_233_17(V a, V b, V c) { return (~((b^a)^c))|(c&b); } +V foo_233_18(V a, V b, V c) { return (~((b^a)^c))|(c&a); } +V foo_233_19(V a, V b, V c) { return (~((b^a)^c))|(b&a); } +V foo_233_20(V a, V b, V c) { return (~((c|b)^a))|(c&b); } +V foo_233_21(V a, V b, V c) { return (~((c|a)^b))|(c&a); } +V foo_233_22(V a, V b, V c) { return (~((b|a)^c))|(b&a); } + +V foo_234_1(V a, V b, V c) { return (b&a)|c; } + +V foo_235_1(V a, V b, V c) { return (~(b^a))|c; } + +V foo_236_1(V a, V b, V c) { return (c&a)|b; } + +V foo_237_1(V a, V b, V c) { return (~(c^a))|b; } + +V foo_238_1(V a, V b, V c) { return c|b; } + +V foo_239_1(V a, V b, V c) { return (c|b)|~a; } +V foo_239_2(V a, V b, V c) { return (~a|b)|c; } +V foo_239_3(V a, V b, V c) { return (~a|c)|b; } + +V foo_240_1(V a, V b, V c) { return a; } + +V foo_241_1(V a, V b, V c) { return (~(c|b))|a; } + +V foo_242_1(V a, V b, V c) { return (~b&c)|a; } + +V foo_243_1(V a, V b, V c) { return ~b|a; } + +V foo_244_1(V a, V b, V c) { return (~c&b)|a; } + +V foo_245_1(V a, V b, V c) { return ~c|a; } + +V foo_246_1(V a, V b, V c) { return (c^b)|a; } + +V foo_247_1(V a, V b, V c) { return (~(c&b))|a; } + +V foo_248_1(V a, V b, V c) { return (c&b)|a; } + +V foo_249_1(V a, V b, V c) { return (~(c^b))|a; } + +V foo_250_1(V a, V b, V c) { return c|a; } + +V foo_251_1(V a, V b, V c) { return (c|a)|~b; } +V foo_251_2(V a, V b, V c) { return (~b|a)|c; } +V foo_251_3(V a, V b, V c) { return (~b|c)|a; } + +V foo_252_1(V a, V b, V c) { return b|a; } + +V foo_253_1(V a, V b, V c) { return (b|a)|~c; } +V foo_253_2(V a, V b, V c) { return (~c|a)|b; } +V foo_253_3(V a, V b, V c) { return (~c|b)|a; } + +V foo_254_1(V a, V b, V c) { return (b|a)|c; } +V foo_254_2(V a, V b, V c) { return (c|a)|b; } +V foo_254_3(V a, V b, V c) { return (c|b)|a; } + +V foo_255_1(V a, V b, V c) { return (V){~0,~0,~0,~0}; } + +/* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]" 679 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpternlogq-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogq-1.c index ef302464765..8e5d22fd4d6 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vpternlogq-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogq-1.c @@ -1,6 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-mavx512f -O2" } */ -/* { dg-final { scan-assembler-times "vpternlogq\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogq\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogq\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vpternlogq-3.c b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogq-3.c new file mode 100644 index 00000000000..fb943da1956 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-vpternlogq-3.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4" } */ + +#include +__m256i +foo2 (__m256i** a, __m256i b) +{ + return ~(**a); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vpternlogd-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vpternlogd-1.c index 045a266664c..dd53563d39d 100644 --- a/gcc/testsuite/gcc.target/i386/avx512vl-vpternlogd-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512vl-vpternlogd-1.c @@ -1,7 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-mavx512vl -O2" } */ -/* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-vpternlogq-1.c b/gcc/testsuite/gcc.target/i386/avx512vl-vpternlogq-1.c index 3a6707c8f65..31fec3e0dde 100644 --- a/gcc/testsuite/gcc.target/i386/avx512vl-vpternlogq-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512vl-vpternlogq-1.c @@ -1,7 +1,5 @@ /* { dg-do compile } */ /* { dg-options "-mavx512vl -O2" } */ -/* { dg-final { scan-assembler-times "vpternlogq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "vpternlogq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "vpternlogq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}\{z\}(?:\n|\[ \\t\]+#)" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100711-4.c b/gcc/testsuite/gcc.target/i386/pr100711-4.c index 3ca524f8a8a..26152d63f8c 100644 --- a/gcc/testsuite/gcc.target/i386/pr100711-4.c +++ b/gcc/testsuite/gcc.target/i386/pr100711-4.c @@ -37,6 +37,6 @@ v8di foo_v8di (long long a, v8di b) return (__extension__ (v8di) {~a, ~a, ~a, ~a, ~a, ~a, ~a, ~a}) | b; } -/* { dg-final { scan-assembler-times "vpternlog\[dq\]\[ \\t\]+\\\$0xbb" 4 { target { ! ia32 } } } } */ -/* { dg-final { scan-assembler-times "vpternlog\[dq\]\[ \\t\]+\\\$0xbb" 2 { target { ia32 } } } } */ +/* { dg-final { scan-assembler-times "vpternlog\[dq\]\[ \\t\]+\\\$207" 4 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\\\$207" 2 { target { ia32 } } } } */ /* { dg-final { scan-assembler-times "vpternlog\[dq\]\[ \\t\]+\\\$0xdd" 2 { target { ia32 } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr100711-5.c b/gcc/testsuite/gcc.target/i386/pr100711-5.c index 161fbfcc256..820bed88ed5 100644 --- a/gcc/testsuite/gcc.target/i386/pr100711-5.c +++ b/gcc/testsuite/gcc.target/i386/pr100711-5.c @@ -37,4 +37,7 @@ v8di foo_v8di (long long a, v8di b) return (__extension__ (v8di) {~a, ~a, ~a, ~a, ~a, ~a, ~a, ~a}) ^ b; } -/* { dg-final { scan-assembler-times "vpternlog\[dq\]\[ \\t\]+\\\$0x99" 4 } } */ +/* { dg-final { scan-assembler-times "vpternlog\[dq\]\[ \\t\]+\\\$195" 4 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "vpternlogd\[ \\t\]+\\\$195" 2 { target { ia32 } } } } */ +/* { dg-final { scan-assembler-times "vpternlog\[dq\]\[ \\t\]+\\\$0x99" 2 { target { ia32 } } } } */ + diff --git a/gcc/testsuite/gcc.target/i386/pr112600-2a.c b/gcc/testsuite/gcc.target/i386/pr112600-2a.c new file mode 100644 index 00000000000..4df38e5a720 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112600-2a.c @@ -0,0 +1,15 @@ +/* PR middle-end/112600 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -msse2" } */ + +typedef unsigned char T; + +void foo (T *out, T *x, T *y, int n) +{ + int i; + + for (i = 0; i < n; i++) + out[i] = (x[i] - y[i]) & (-(T)(x[i] >= y[i])); +} + +/* { dg-final { scan-assembler "psubusb" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr112600-2b.c b/gcc/testsuite/gcc.target/i386/pr112600-2b.c new file mode 100644 index 00000000000..0f6345de704 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112600-2b.c @@ -0,0 +1,15 @@ +/* PR middle-end/112600 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -msse2" } */ + +typedef unsigned short T; + +void foo (T *out, T *x, T *y, int n) +{ + int i; + + for (i = 0; i < n; i++) + out[i] = (x[i] - y[i]) & (-(T)(x[i] >= y[i])); +} + +/* { dg-final { scan-assembler "psubusw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr113609-1.c b/gcc/testsuite/gcc.target/i386/pr113609-1.c new file mode 100644 index 00000000000..f0639b8500a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr113609-1.c @@ -0,0 +1,194 @@ +/* PR target/113609 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4" } */ +/* { dg-final { scan-assembler-not "^cmp" } } */ +/* { dg-final { scan-assembler-not "\[ \\t\]+sete" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "\[ \\t\]+setne" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "\[ \\t\]+je" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "\[ \\t\]+jne" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+sete" 1 { target { ia32 } } } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+setne" 1 { target { ia32 } } } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+je" 1 { target { ia32 } } } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+jne" 2 { target { ia32 } } } } */ +/* { dg-final { scan-assembler-times "kortest" 12 { target { ia32 } } } } */ +/* { dg-final { scan-assembler-times "kortest" 17 { target { ! ia32 } } } } */ + +#include + +unsigned int +cmp_vector_sete_mask8(__m128i a, __m128i b) +{ + __mmask8 k = _mm_cmpeq_epi16_mask (a, b); + if (k == (__mmask8) -1) + return 1; + else + return 0; +} + +unsigned int +cmp_vector_sete_mask16(__m128i a, __m128i b) +{ + __mmask16 k = _mm_cmpeq_epi8_mask (a, b); + if (k == (__mmask16) -1) + return 1; + else + return 0; +} + +unsigned int +cmp_vector_sete_mask32(__m256i a, __m256i b) +{ + __mmask32 k = _mm256_cmpeq_epi8_mask (a, b); + if (k == (__mmask32) -1) + return 1; + else + return 0; +} + +unsigned int +cmp_vector_sete_mask64(__m512i a, __m512i b) +{ + __mmask64 k = _mm512_cmpeq_epi8_mask (a, b); + if (k == (__mmask64) -1) + return 1; + else + return 0; +} + +unsigned int +cmp_vector_setne_mask8(__m128i a, __m128i b) +{ + __mmask8 k = _mm_cmpeq_epi16_mask (a, b); + if (k != (__mmask8) -1) + return 1; + else + return 0; +} + +unsigned int +cmp_vector_setne_mask16(__m128i a, __m128i b) +{ + __mmask16 k = _mm_cmpeq_epi8_mask (a, b); + if (k != (__mmask16) -1) + return 1; + else + return 0; +} + +unsigned int +cmp_vector_setne_mask32(__m256i a, __m256i b) +{ + __mmask32 k = _mm256_cmpeq_epi8_mask (a, b); + if (k != (__mmask32) -1) + return 1; + else + return 0; +} + +unsigned int +cmp_vector_setne_mask64(__m512i a, __m512i b) +{ + __mmask64 k = _mm512_cmpeq_epi8_mask (a, b); + if (k != (__mmask64) -1) + return 1; + else + return 0; +} + +__m128i +cmp_vector_je_mask8(__m128i a, __m128i b) { + __mmask8 k = _mm_cmpeq_epi16_mask (a, b); + if (k == (__mmask8) -1) { + a[0] = a[0] + 1; + } + else { + a[0] = a[0] - 1; + } + return a; +} + +__m128i +cmp_vector_je_mask16(__m128i a, __m128i b) { + __mmask16 k = _mm_cmpeq_epi8_mask (a, b); + if (k == (__mmask16) -1) { + a[0] = a[0] + 1; + } + else { + a[0] = a[0] - 1; + } + return a; +} + +__m256i +cmp_vector_je_mask32(__m256i a, __m256i b) { + __mmask32 k = _mm256_cmpeq_epi8_mask (a, b); + if (k == (__mmask32) -1) { + a[0] = a[0] + 1; + } + else { + a[0] = a[0] - 1; + } + return a; +} + +__m512i +cmp_vector_je_mask64(__m512i a, __m512i b) { + __mmask64 k = _mm512_cmpeq_epi8_mask (a, b); + if (k == (__mmask64) -1) { + a[0] = a[0] + 1; + } + else { + a[0] = a[0] - 5; + } + return a; +} + +__m128i +cmp_vector_jne_mask8(__m128i a, __m128i b) { + __mmask8 k = _mm_cmpeq_epi16_mask (a, b); + if (k == (__mmask8) -1) { + a[0] = a[0] + 1; + } + a[0] = a[0] - 4; + return a; +} + +__m128i +cmp_vector_jne_mask16(__m128i a, __m128i b) { + __mmask16 k = _mm_cmpeq_epi8_mask (a, b); + if (k == (__mmask16) -1) { + a[0] = a[0] + 1; + } + a[0] = a[0] - 4; + return a; +} + +__m256i +cmp_vector_jne_mask32(__m256i a, __m256i b) { + __mmask32 k = _mm256_cmpeq_epi8_mask (a, b); + if (k == (__mmask32) -1) { + a[0] = a[0] + 1; + } + a[0] = a[0] - 4; + return a; +} + +__m512i +cmp_vector_jne_mask64(__m512i a, __m512i b) { + __mmask64 k = _mm512_cmpeq_epi8_mask (a, b); + if (k == (__mmask64) -1) { + a[0] = a[0] + 1; + } + a[0] = a[0] - 4; + return a; +} + +__m512i +mask_cmp_vector_jne_mask64(__m512i a, __m512i b) { + __mmask64 k = _mm512_mask_cmpeq_epi8_mask ((__mmask64)0xffffffefffffffff, a, b); + if (k == (__mmask64) -1) { + a[0] = a[0] + 1; + } + a[0] = a[0] - 4; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/pr113609-2.c b/gcc/testsuite/gcc.target/i386/pr113609-2.c new file mode 100644 index 00000000000..e9503f51538 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr113609-2.c @@ -0,0 +1,161 @@ +/* PR target/113609 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4" } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+sete" 4 } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+setne" 4 } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+je" 4 } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+jne" 4 } } */ + +#include + +unsigned int +cmp_pi8_setcc(char a) +{ + if (a == -1) + return 1; + else + return 0; +} + +unsigned int +cmp_pi16_setcc(short a) +{ + if (a == -1) + return 1; + else + return 0; +} + +unsigned int +cmp_pi32_setcc(int a) +{ + if (a == -1) + return 1; + else + return 0; +} + +unsigned int +cmp_pi64_setcc(long long a) +{ + if (a == -1) + return 1; + else + return 0; +} + +unsigned int +cmp_pi8_setne(char a) +{ + if (a != -1) + return 1; + else + return 0; +} + +unsigned int +cmp_pi16_setne(short a) +{ + if (a != -1) + return 1; + else + return 0; +} + +unsigned int +cmp_pi32_setne(int a) +{ + if (a != -1) + return 1; + else + return 0; +} + +unsigned int +cmp_pi64_setne(long long a) +{ + if (a != -1) + return 1; + else + return 0; +} + +__m128i +cmp_pi8_je(__m128i a, char b) { + if (b == -1) { + a[0] = a[0] + 1; + } + else { + a[0] = a[0] - 1; + } + return a; +} + +__m128i +cmp_pi16_je(__m128i a, short b) { + if (b == -1) { + a[0] = a[0] + 1; + } + else { + a[0] = a[0] - 1; + } + return a; +} + +__m128i +cmp_pi32_je(__m128i a, int b) { + if (b == -1) { + a[0] = a[0] + 1; + } + else { + a[0] = a[0] - 1; + } + return a; +} + +__m128i +cmp_pi64_je(__m128i a, long long b) { + if (b == -1) { + a[0] = a[0] + 1; + } + else { + a[0] = a[0] - 1; + } + return a; +} + +__m128i +cmp_pi8_jne(__m128i a, char b) { + if (b == -1) { + a[0] = a[0] + 1; + } + a[0] = a[0] - 4; + return a; +} + +__m128i +cmp_pi16_jne(__m128i a, short b) { + if (b == -1) { + a[0] = a[0] + 1; + } + a[0] = a[0] - 4; + return a; +} + +__m128i +cmp_pi32_jne(__m128i a, int b) { + if (b == -1) { + a[0] = a[0] + 1; + } + a[0] = a[0] - 4; + return a; +} + +__m128i +cmp_pi64_jne(__m128i a, long long b) { + if (b == -1) { + a[0] = a[0] + 1; + } + a[0] = a[0] - 4; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/pr114428-1.c b/gcc/testsuite/gcc.target/i386/pr114428-1.c new file mode 100644 index 00000000000..927476f2269 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr114428-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2" } */ +/* { dg-final { scan-assembler-times "psrlw" 1 } } */ +/* { dg-final { scan-assembler-times "psrld" 1 } } */ +/* { dg-final { scan-assembler-times "psrlq" 1 { target { ! ia32 } } } } */ + + +#define SHIFTC 12 + +typedef int v4si __attribute__((vector_size(16))); +typedef short v8hi __attribute__((vector_size(16))); +typedef long long v2di __attribute__((vector_size(16))); + +v8hi +foo1 (v8hi a) +{ + return + (a >> (16 - SHIFTC)) & (__extension__(v8hi){(1<> (32 - SHIFTC)) & (__extension__(v4si){(1<> (long long)(64 - SHIFTC)) & (__extension__(v2di){(1ULL<> (short)8; +} + +void +foo3 (char* __restrict a, short* b) +{ + for (int i = 0; i != 16; i++) + a[i] = b[i] >> (short)8; +} + diff --git a/gcc/testsuite/gcc.target/i386/pr115299.c b/gcc/testsuite/gcc.target/i386/pr115299.c new file mode 100644 index 00000000000..53c5899136a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr115299.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -mno-sse4.1 -msse2" } */ + +void f(double*d,double*e){ + for(;d diff --git a/gcc/testsuite/gcc.target/riscv/sat_arith.h b/gcc/testsuite/gcc.target/riscv/sat_arith.h index 2ef9fd825f3..976ef1c44c1 100644 --- a/gcc/testsuite/gcc.target/riscv/sat_arith.h +++ b/gcc/testsuite/gcc.target/riscv/sat_arith.h @@ -10,6 +10,45 @@ sat_u_add_##T##_fmt_1 (T x, T y) \ return (x + y) | (-(T)((T)(x + y) < x)); \ } +#define DEF_SAT_U_ADD_FMT_2(T) \ +T __attribute__((noinline)) \ +sat_u_add_##T##_fmt_2 (T x, T y) \ +{ \ + return (T)(x + y) >= x ? (x + y) : -1; \ +} + +#define DEF_SAT_U_ADD_FMT_3(T) \ +T __attribute__((noinline)) \ +sat_u_add_##T##_fmt_3 (T x, T y) \ +{ \ + T ret; \ + T overflow = __builtin_add_overflow (x, y, &ret); \ + return (T)(-overflow) | ret; \ +} + +#define DEF_SAT_U_ADD_FMT_4(T) \ +T __attribute__((noinline)) \ +sat_u_add_##T##_fmt_4 (T x, T y) \ +{ \ + T ret; \ + return __builtin_add_overflow (x, y, &ret) ? -1 : ret; \ +} + +#define DEF_SAT_U_ADD_FMT_5(T) \ +T __attribute__((noinline)) \ +sat_u_add_##T##_fmt_5 (T x, T y) \ +{ \ + T ret; \ + return __builtin_add_overflow (x, y, &ret) == 0 ? ret : -1; \ +} + +#define DEF_SAT_U_ADD_FMT_6(T) \ +T __attribute__((noinline)) \ +sat_u_add_##T##_fmt_6 (T x, T y) \ +{ \ + return (T)(x + y) < x ? -1 : (x + y); \ +} + #define DEF_VEC_SAT_U_ADD_FMT_1(T) \ void __attribute__((noinline)) \ vec_sat_u_add_##T##_fmt_1 (T *out, T *op_1, T *op_2, unsigned limit) \ @@ -24,6 +63,11 @@ vec_sat_u_add_##T##_fmt_1 (T *out, T *op_1, T *op_2, unsigned limit) \ } #define RUN_SAT_U_ADD_FMT_1(T, x, y) sat_u_add_##T##_fmt_1(x, y) +#define RUN_SAT_U_ADD_FMT_2(T, x, y) sat_u_add_##T##_fmt_2(x, y) +#define RUN_SAT_U_ADD_FMT_3(T, x, y) sat_u_add_##T##_fmt_3(x, y) +#define RUN_SAT_U_ADD_FMT_4(T, x, y) sat_u_add_##T##_fmt_4(x, y) +#define RUN_SAT_U_ADD_FMT_5(T, x, y) sat_u_add_##T##_fmt_5(x, y) +#define RUN_SAT_U_ADD_FMT_6(T, x, y) sat_u_add_##T##_fmt_6(x, y) #define RUN_VEC_SAT_U_ADD_FMT_1(T, out, op_1, op_2, N) \ vec_sat_u_add_##T##_fmt_1(out, op_1, op_2, N) diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-10.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-10.c new file mode 100644 index 00000000000..3f627ef80b1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-10.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint16_t_fmt_3: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** slli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** slli\s+a0,\s*a0,\s*48 +** srli\s+a0,\s*a0,\s*48 +** ret +*/ +DEF_SAT_U_ADD_FMT_3(uint16_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-11.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-11.c new file mode 100644 index 00000000000..b6dc779b212 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-11.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint32_t_fmt_3: +** addw\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** sext.w\s+a0,\s*a0 +** ret +*/ +DEF_SAT_U_ADD_FMT_3(uint32_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-12.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-12.c new file mode 100644 index 00000000000..27b13a7f01f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-12.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint64_t_fmt_3: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+ +** ret +*/ +DEF_SAT_U_ADD_FMT_3(uint64_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-13.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-13.c new file mode 100644 index 00000000000..b2d93f29f48 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-13.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint8_t_fmt_4: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*0xff +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** andi\s+a0,\s*a0,\s*0xff +** ret +*/ +DEF_SAT_U_ADD_FMT_4(uint8_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-14.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-14.c new file mode 100644 index 00000000000..eafc578aafa --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-14.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint16_t_fmt_4: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** slli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** slli\s+a0,\s*a0,\s*48 +** srli\s+a0,\s*a0,\s*48 +** ret +*/ +DEF_SAT_U_ADD_FMT_4(uint16_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-15.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-15.c new file mode 100644 index 00000000000..27de543159d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-15.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint32_t_fmt_4: +** addw\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** sext.w\s+a0,\s*a0 +** ret +*/ +DEF_SAT_U_ADD_FMT_4(uint32_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-16.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-16.c new file mode 100644 index 00000000000..76e5f828ed9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-16.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint64_t_fmt_4: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+ +** ret +*/ +DEF_SAT_U_ADD_FMT_4(uint64_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-17.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-17.c new file mode 100644 index 00000000000..7085ac835f7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-17.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint8_t_fmt_5: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*0xff +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** andi\s+a0,\s*a0,\s*0xff +** ret +*/ +DEF_SAT_U_ADD_FMT_5(uint8_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-18.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-18.c new file mode 100644 index 00000000000..355ff8ba4ef --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-18.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint16_t_fmt_5: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** slli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** slli\s+a0,\s*a0,\s*48 +** srli\s+a0,\s*a0,\s*48 +** ret +*/ +DEF_SAT_U_ADD_FMT_5(uint16_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-19.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-19.c new file mode 100644 index 00000000000..491909165dc --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-19.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint32_t_fmt_5: +** addw\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** sext.w\s+a0,\s*a0 +** ret +*/ +DEF_SAT_U_ADD_FMT_5(uint32_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-20.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-20.c new file mode 100644 index 00000000000..c5f005cfe2f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-20.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint64_t_fmt_5: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+ +** ret +*/ +DEF_SAT_U_ADD_FMT_5(uint64_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-21.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-21.c new file mode 100644 index 00000000000..f75e35a5fa9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-21.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint8_t_fmt_6: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*0xff +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** andi\s+a0,\s*a0,\s*0xff +** ret +*/ +DEF_SAT_U_ADD_FMT_6(uint8_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-22.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-22.c new file mode 100644 index 00000000000..ad957a061f4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-22.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint16_t_fmt_6: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** slli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** slli\s+a0,\s*a0,\s*48 +** srli\s+a0,\s*a0,\s*48 +** ret +*/ +DEF_SAT_U_ADD_FMT_6(uint16_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-23.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-23.c new file mode 100644 index 00000000000..3b82bdffb59 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-23.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint32_t_fmt_6: +** addw\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** sext.w\s+a0,\s*a0 +** ret +*/ +DEF_SAT_U_ADD_FMT_6(uint32_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-24.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-24.c new file mode 100644 index 00000000000..6072d69b4dc --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-24.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint64_t_fmt_6: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+ +** ret +*/ +DEF_SAT_U_ADD_FMT_6(uint64_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-5.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-5.c new file mode 100644 index 00000000000..4c73c7f8a21 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-5.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint8_t_fmt_2: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*0xff +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** andi\s+a0,\s*a0,\s*0xff +** ret +*/ +DEF_SAT_U_ADD_FMT_2(uint8_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-6.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-6.c new file mode 100644 index 00000000000..0d64f5631bb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-6.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint16_t_fmt_2: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** slli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*48 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** slli\s+a0,\s*a0,\s*48 +** srli\s+a0,\s*a0,\s*48 +** ret +*/ +DEF_SAT_U_ADD_FMT_2(uint16_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-7.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-7.c new file mode 100644 index 00000000000..fe9dcd4f806 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-7.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint32_t_fmt_2: +** addw\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** sext.w\s+a0,\s*a0 +** ret +*/ +DEF_SAT_U_ADD_FMT_2(uint32_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-8.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-8.c new file mode 100644 index 00000000000..ebe2ad7b94b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-8.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint64_t_fmt_2: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+ +** ret +*/ +DEF_SAT_U_ADD_FMT_2(uint64_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-9.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-9.c new file mode 100644 index 00000000000..eac6707a407 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-9.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "sat_arith.h" + +/* +** sat_u_add_uint8_t_fmt_3: +** add\s+[atx][0-9]+,\s*a0,\s*a1 +** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*0xff +** sltu\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** neg\s+[atx][0-9]+,\s*[atx][0-9]+ +** or\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+ +** andi\s+a0,\s*a0,\s*0xff +** ret +*/ +DEF_SAT_U_ADD_FMT_3(uint8_t) + +/* { dg-final { scan-rtl-dump-times ".SAT_ADD " 2 "expand" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-10.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-10.c new file mode 100644 index 00000000000..bd935dcfd61 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-10.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint16_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_3 + +DEF_SAT_U_ADD_FMT_3(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 65534, 65534, }, + { 1, 65534, 65535, }, + { 2, 65534, 65535, }, + { 0, 65535, 65535, }, + { 1, 65535, 65535, }, + { 2, 65535, 65535, }, + { 65535, 65535, 65535, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-11.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-11.c new file mode 100644 index 00000000000..deccf9a7525 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-11.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint32_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_3 + +DEF_SAT_U_ADD_FMT_3(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 4294967294, 4294967294, }, + { 1, 4294967294, 4294967295, }, + { 2, 4294967294, 4294967295, }, + { 0, 4294967295, 4294967295, }, + { 1, 4294967295, 4294967295, }, + { 2, 4294967295, 4294967295, }, + { 4294967295, 4294967295, 4294967295, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-12.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-12.c new file mode 100644 index 00000000000..4f9936706a8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-12.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint64_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_3 + +DEF_SAT_U_ADD_FMT_3(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 18446744073709551614u, 18446744073709551614u, }, + { 1, 18446744073709551614u, 18446744073709551615u, }, + { 2, 18446744073709551614u, 18446744073709551615u, }, + { 0, 18446744073709551615u, 18446744073709551615u, }, + { 1, 18446744073709551615u, 18446744073709551615u, }, + { 2, 18446744073709551615u, 18446744073709551615u, }, + { 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-13.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-13.c new file mode 100644 index 00000000000..083d6e59a06 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-13.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint8_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_4 + +DEF_SAT_U_ADD_FMT_4(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 254, 254, }, + { 1, 254, 255, }, + { 2, 254, 255, }, + { 0, 255, 255, }, + { 1, 255, 255, }, + { 2, 255, 255, }, + { 255, 255, 255, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-14.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-14.c new file mode 100644 index 00000000000..33a595dad51 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-14.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint16_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_4 + +DEF_SAT_U_ADD_FMT_4(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 65534, 65534, }, + { 1, 65534, 65535, }, + { 2, 65534, 65535, }, + { 0, 65535, 65535, }, + { 1, 65535, 65535, }, + { 2, 65535, 65535, }, + { 65535, 65535, 65535, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-15.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-15.c new file mode 100644 index 00000000000..8a5b7c10600 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-15.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint32_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_4 + +DEF_SAT_U_ADD_FMT_4(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 4294967294, 4294967294, }, + { 1, 4294967294, 4294967295, }, + { 2, 4294967294, 4294967295, }, + { 0, 4294967295, 4294967295, }, + { 1, 4294967295, 4294967295, }, + { 2, 4294967295, 4294967295, }, + { 4294967295, 4294967295, 4294967295, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-16.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-16.c new file mode 100644 index 00000000000..fa20aae1d0b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-16.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint64_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_4 + +DEF_SAT_U_ADD_FMT_4(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 18446744073709551614u, 18446744073709551614u, }, + { 1, 18446744073709551614u, 18446744073709551615u, }, + { 2, 18446744073709551614u, 18446744073709551615u, }, + { 0, 18446744073709551615u, 18446744073709551615u, }, + { 1, 18446744073709551615u, 18446744073709551615u, }, + { 2, 18446744073709551615u, 18446744073709551615u, }, + { 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-17.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-17.c new file mode 100644 index 00000000000..936028cbe8b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-17.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint8_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_5 + +DEF_SAT_U_ADD_FMT_5(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 254, 254, }, + { 1, 254, 255, }, + { 2, 254, 255, }, + { 0, 255, 255, }, + { 1, 255, 255, }, + { 2, 255, 255, }, + { 255, 255, 255, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-18.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-18.c new file mode 100644 index 00000000000..a1d5d70b4ab --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-18.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint16_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_5 + +DEF_SAT_U_ADD_FMT_5(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 65534, 65534, }, + { 1, 65534, 65535, }, + { 2, 65534, 65535, }, + { 0, 65535, 65535, }, + { 1, 65535, 65535, }, + { 2, 65535, 65535, }, + { 65535, 65535, 65535, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-19.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-19.c new file mode 100644 index 00000000000..7608e71dd80 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-19.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint32_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_5 + +DEF_SAT_U_ADD_FMT_5(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 4294967294, 4294967294, }, + { 1, 4294967294, 4294967295, }, + { 2, 4294967294, 4294967295, }, + { 0, 4294967295, 4294967295, }, + { 1, 4294967295, 4294967295, }, + { 2, 4294967295, 4294967295, }, + { 4294967295, 4294967295, 4294967295, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-20.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-20.c new file mode 100644 index 00000000000..496ab58150b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-20.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint64_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_5 + +DEF_SAT_U_ADD_FMT_5(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 18446744073709551614u, 18446744073709551614u, }, + { 1, 18446744073709551614u, 18446744073709551615u, }, + { 2, 18446744073709551614u, 18446744073709551615u, }, + { 0, 18446744073709551615u, 18446744073709551615u, }, + { 1, 18446744073709551615u, 18446744073709551615u, }, + { 2, 18446744073709551615u, 18446744073709551615u, }, + { 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-21.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-21.c new file mode 100644 index 00000000000..8bc204ec74e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-21.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint8_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_6 + +DEF_SAT_U_ADD_FMT_6(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 254, 254, }, + { 1, 254, 255, }, + { 2, 254, 255, }, + { 0, 255, 255, }, + { 1, 255, 255, }, + { 2, 255, 255, }, + { 255, 255, 255, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-22.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-22.c new file mode 100644 index 00000000000..d304288d8b6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-22.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint16_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_6 + +DEF_SAT_U_ADD_FMT_6(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 65534, 65534, }, + { 1, 65534, 65535, }, + { 2, 65534, 65535, }, + { 0, 65535, 65535, }, + { 1, 65535, 65535, }, + { 2, 65535, 65535, }, + { 65535, 65535, 65535, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-23.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-23.c new file mode 100644 index 00000000000..1a1ea598133 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-23.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint32_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_6 + +DEF_SAT_U_ADD_FMT_6(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 4294967294, 4294967294, }, + { 1, 4294967294, 4294967295, }, + { 2, 4294967294, 4294967295, }, + { 0, 4294967295, 4294967295, }, + { 1, 4294967295, 4294967295, }, + { 2, 4294967295, 4294967295, }, + { 4294967295, 4294967295, 4294967295, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-24.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-24.c new file mode 100644 index 00000000000..dc977d5b3a5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-24.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint64_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_6 + +DEF_SAT_U_ADD_FMT_6(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 18446744073709551614u, 18446744073709551614u, }, + { 1, 18446744073709551614u, 18446744073709551615u, }, + { 2, 18446744073709551614u, 18446744073709551615u, }, + { 0, 18446744073709551615u, 18446744073709551615u, }, + { 1, 18446744073709551615u, 18446744073709551615u, }, + { 2, 18446744073709551615u, 18446744073709551615u, }, + { 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-5.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-5.c new file mode 100644 index 00000000000..508531c09d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-5.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint8_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_2 + +DEF_SAT_U_ADD_FMT_2(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 254, 254, }, + { 1, 254, 255, }, + { 2, 254, 255, }, + { 0, 255, 255, }, + { 1, 255, 255, }, + { 2, 255, 255, }, + { 255, 255, 255, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-6.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-6.c new file mode 100644 index 00000000000..99b5c3a39f0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-6.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint16_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_2 + +DEF_SAT_U_ADD_FMT_2(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 65534, 65534, }, + { 1, 65534, 65535, }, + { 2, 65534, 65535, }, + { 0, 65535, 65535, }, + { 1, 65535, 65535, }, + { 2, 65535, 65535, }, + { 65535, 65535, 65535, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-7.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-7.c new file mode 100644 index 00000000000..13f59548935 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-7.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint32_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_2 + +DEF_SAT_U_ADD_FMT_2(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 4294967294, 4294967294, }, + { 1, 4294967294, 4294967295, }, + { 2, 4294967294, 4294967295, }, + { 0, 4294967295, 4294967295, }, + { 1, 4294967295, 4294967295, }, + { 2, 4294967295, 4294967295, }, + { 4294967295, 4294967295, 4294967295, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-8.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-8.c new file mode 100644 index 00000000000..cdbea7b1b2c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-8.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint64_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_2 + +DEF_SAT_U_ADD_FMT_2(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 18446744073709551614u, 18446744073709551614u, }, + { 1, 18446744073709551614u, 18446744073709551615u, }, + { 2, 18446744073709551614u, 18446744073709551615u, }, + { 0, 18446744073709551615u, 18446744073709551615u, }, + { 1, 18446744073709551615u, 18446744073709551615u, }, + { 2, 18446744073709551615u, 18446744073709551615u, }, + { 18446744073709551615u, 18446744073709551615u, 18446744073709551615u, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/sat_u_add-run-9.c b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-9.c new file mode 100644 index 00000000000..670932fa910 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sat_u_add-run-9.c @@ -0,0 +1,25 @@ +/* { dg-do run { target { riscv_v } } } */ +/* { dg-additional-options "-std=c99" } */ + +#include "sat_arith.h" + +#define T uint8_t +#define RUN_SAT_BINARY RUN_SAT_U_ADD_FMT_3 + +DEF_SAT_U_ADD_FMT_3(T) + +T test_data[][3] = { + /* arg_0, arg_1, expect */ + { 0, 0, 0, }, + { 0, 1, 1, }, + { 1, 1, 2, }, + { 0, 254, 254, }, + { 1, 254, 255, }, + { 2, 254, 255, }, + { 0, 255, 255, }, + { 1, 255, 255, }, + { 2, 255, 255, }, + { 255, 255, 255, }, +}; + +#include "scalar_sat_binary.h" diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_arithmetic.c b/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_arithmetic.c new file mode 100644 index 00000000000..2ca170345af --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_arithmetic.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32i_zfbfmin -mabi=ilp32f -mcmodel=medany -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64i_zfbfmin -mabi=lp64f -mcmodel=medany -O" { target { rv64 } } } */ + +/* 1) bf -> sf fcvt.s.bf16 */ +/* 2) sf1 [+|-|*|/] sf2 f[add|sub|mul|div].s */ +/* 3) sf -> bf fcvt.bf16.s */ +extern __bf16 bf; +extern __bf16 bf1; +extern __bf16 bf2; + +void bf_add_bf () { bf = bf1 + bf2; } + +void bf_sub_bf () { bf = bf1 - bf2; } + +void bf_mul_bf () { bf = bf1 * bf2; } + +void bf_div_bf () { bf = bf1 / bf2; } + +void bf_add_const () { bf = bf1 + 3.14f; } + +void const_sub_bf () { bf = 3.14f - bf2; } + +void bf_mul_const () { bf = bf1 * 3.14f; } + +void const_div_bf () { bf = 3.14f / bf2; } + +void bf_inc () { ++bf; } + +void bf_dec () { --bf; } + +/* { dg-final { scan-assembler-times "fcvt.s.bf16" 14 } } */ +/* { dg-final { scan-assembler-times "fcvt.bf16.s" 10 } } */ + +/* { dg-final { scan-assembler-not "call" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_comparison.c b/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_comparison.c new file mode 100644 index 00000000000..62d532063c4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_comparison.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32i_zfbfmin -mabi=ilp32f -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64i_zfbfmin -mabi=lp64f -O" { target { rv64 } } } */ + +/* 1) bf -> sf fcvt.s.bf16 */ +/* 2) sf1 [<|<=|>|>=|==] sf2 f[lt|le|gt|ge|eq].s */ +extern __bf16 bf; +extern __bf16 bf1; +extern __bf16 bf2; + +void bf_lt_bf () { bf = (bf1 < bf2) ? bf1 : bf2; } + +void bf_le_bf () { bf = (bf1 <= bf2) ? bf1 : bf2; } + +void bf_gt_bf () { bf = (bf1 > bf2) ? bf1 : bf2; } + +void bf_ge_bf () { bf = (bf1 >= bf2) ? bf1 : bf2; } + +void bf_eq_bf () { bf = (bf1 == bf2) ? bf1 : bf2; } + +void bf_lt_const () { bf = (bf1 < 3.14f) ? bf1 : bf2; } + +void bf_le_const () { bf = (bf1 <= 3.14f) ? bf1 : bf2; } + +void const_gt_bf () { bf = (3.14f > bf2) ? bf1 : bf2; } + +void const_ge_bf () { bf = (3.14f >= bf2) ? bf1 : bf2; } + +void bf_eq_const () { bf = (bf1 == 3.14f) ? bf1 : bf2; } + +/* { dg-final { scan-assembler-times "fcvt.s.bf16" 15 } } */ + +/* { dg-final { scan-assembler-not "call" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_float_libcall_convert.c b/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_float_libcall_convert.c new file mode 100644 index 00000000000..95e65996e28 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_float_libcall_convert.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32i_zfbfmin -mabi=ilp32f -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64i_zfbfmin -mabi=lp64f -O" { target { rv64 } } } */ + + +/* 1) float -> BF16 + * hf -> bf == hf -> sf -> bf fcvt.h.s + fcvt.bf16.s + * sf -> bf == sf -> bf fcvt.bf16.s + * df -> bf == df -> sf -> bf __truncdfsf2 + fcvt.bf16.s + * tf -> bf == tf -> sf -> bf __trunctfsf2 + fcvt.bf16.s +*/ + +/* 2) BF16 -> float + * bf -> hf == bf -> sf -> hf fcvt.s.bf16 + fcvt.s.h + * bf -> sf == bf -> sf fcvt.s.bf16 + * bf -> df == bf -> sf -> df fcvt.s.bf16 + __extendsfdf2 + * bf -> tf == bf -> sf -> tf fcvt.s.bf16 + __extendsftf2 +*/ + +extern __bf16 bf; +extern _Float16 hf; +extern float sf; +extern double df; +extern long double tf; + +void hf_to_bf () { bf = hf; } +void bf_to_hf () { hf = bf; } + +void sf_to_bf () { bf = sf; } +void bf_to_sf () { sf = bf; } + +void df_to_bf () { bf = df; } +void bf_to_df () { df = bf; } + +void tf_to_bf () { bf = tf; } +void bf_to_tf () { tf = bf; } + +/* { dg-final { scan-assembler-times "fcvt.bf16.s" 4 } } */ +/* { dg-final { scan-assembler-times "fcvt.s.bf16" 4 } } */ +/* { dg-final { scan-assembler-times "fcvt.h.s" 1 } } */ +/* { dg-final { scan-assembler-times "fcvt.s.h" 1 } } */ +/* { dg-final { scan-assembler-times "call\t__truncdfsf2" 1 } } */ +/* { dg-final { scan-assembler-times "call\t__trunctfsf2" 1 } } */ +/* { dg-final { scan-assembler-times "call\t__extendsfdf2" 1 } } */ +/* { dg-final { scan-assembler-times "call\t__extendsftf2" 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_integer_libcall_convert.c b/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_integer_libcall_convert.c new file mode 100644 index 00000000000..1a998bfe2f8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin-bf16_integer_libcall_convert.c @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32i_zfbfmin -mabi=ilp32f -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64i_zfbfmin -mabi=lp64f -O" { target { rv64 } } } */ + +/* 1) Integer -> BF16 + * qi/hi -> bf fcvt.s.w + fcvt.bf16.s + * uqi/uhi -> bf fcvt.s.wu + fcvt.bf16.s + * + * si/di/ti -> bf __float[s|d|t]ibf + * usi/udi/uti -> bf __floatun[s|d|t]ibf +*/ + +/* 2) BF16 -> Integer + * bf -> qi/hi/si/di fcvt.s.bf16 + fcvt.[w|l].s + * bf -> uqi/uhi/usi/udi fcvt.s.bf16 + fcvt.[w|l]u.s + * bf -> ti/uti fcvt.s.bf16 + __fix[uns]sfti +*/ + +extern __bf16 bf; + +extern signed char qi; +extern unsigned char uqi; +extern signed short hi; +extern unsigned short uhi; +extern signed int si; +extern unsigned int usi; +extern signed long long di; +extern unsigned long long udi; + +void qi_to_bf () { bf = qi; } +void uqi_to_bf () { bf = uqi; } +void bf_to_qi () { qi = bf; } +void bf_to_uqi () { uqi = bf; } + +void hi_to_bf () { bf = hi; } +void uhi_to_bf () { bf = uhi; } +void bf_to_hi () { hi = bf; } +void bf_to_uhi () { uhi = bf; } + +void si_to_bf () { bf = si; } +void usi_to_bf () { bf = usi; } +void bf_to_si () { si = bf; } +void bf_to_usi () { usi = bf; } + +void di_to_bf () { bf = di; } +void udi_to_bf () { bf = udi; } +void bf_to_di () { di = bf; } +void bf_to_udi () { udi = bf; } + +#if __riscv_xlen == 64 +extern signed __int128 ti; +extern unsigned __int128 uti; +void ti_to_bf () { bf = ti; } /* { dg-final { scan-assembler-times "call\t__floattibf" 1 { target { rv64 } } } } */ +void uti_to_bf () { bf = uti; } /* { dg-final { scan-assembler-times "call\t__floatuntibf" 1 { target { rv64 } } } } */ +void bf_to_ti () { ti = bf; } /* { dg-final { scan-assembler-times "call\t__fixsfti" 1 { target { rv64 } } } } */ +void bf_to_uti () { uti = bf; } /* { dg-final { scan-assembler-times "call\t__fixunssfti" 1 { target { rv64 } } } } */ +#endif + +/* { dg-final { scan-assembler-times "fcvt.bf16.s" 4 } } */ +/* { dg-final { scan-assembler-times "fcvt.s.bf16" 8 { target { rv32 } } } } */ +/* { dg-final { scan-assembler-times "fcvt.s.bf16" 10 { target { rv64 } } } } */ + +/* { dg-final { scan-assembler-times "call\t__floatsibf" 1 } } */ +/* { dg-final { scan-assembler-times "call\t__floatunsibf" 1 } } */ +/* { dg-final { scan-assembler-times "call\t__floatdibf" 1 } } */ +/* { dg-final { scan-assembler-times "call\t__floatundibf" 1 } } */ diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 new file mode 100644 index 00000000000..4a9bd46da4d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 @@ -0,0 +1,33 @@ +! { dg-do run } +! +! PR fortran/83865 +! +! Test ALLOCATE with SOURCE= of deferred length character, where +! the source-expression is an array of character with length 0. + +program p + implicit none + character(:), allocatable :: z(:) + character(1) :: cc(4) = "" + allocate (z, source=['']) + if (len (z) /= 0 .or. size (z) /= 1) stop 1 + deallocate (z) + allocate (z, source=['','']) + if (len (z) /= 0 .or. size (z) /= 2) stop 2 + deallocate (z) + allocate (z, source=[ character(0) :: 'a','b','c']) + if (len (z) /= 0 .or. size (z) /= 3) stop 3 + deallocate (z) + allocate (z, source=[ character(0) :: cc ]) + if (len (z) /= 0 .or. size (z) /= 4) stop 4 + deallocate (z) + associate (x => f()) + if (len (x) /= 0 .or. size (x) /= 1) stop 5 + if (x(1) /= '') stop 6 + end associate +contains + function f() result(z) + character(:), allocatable :: z(:) + allocate (z, source=['']) + end function f +end diff --git a/gcc/testsuite/gfortran.dg/class_77.f90 b/gcc/testsuite/gfortran.dg/class_77.f90 new file mode 100644 index 00000000000..ef38dd67743 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/class_77.f90 @@ -0,0 +1,83 @@ +! { dg-do compile } +! { dg-additional-options "-fdump-tree-original" } +! +! PR fortran/90072 +! +! Contributed by Brad Richardson +! + +module types + implicit none + + type, abstract :: base_returned + end type base_returned + + type, extends(base_returned) :: first_returned + end type first_returned + + type, extends(base_returned) :: second_returned + end type second_returned + + type, abstract :: base_called + contains + procedure(get_), deferred :: get + end type base_called + + type, extends(base_called) :: first_extended + contains + procedure :: get => getFirst + end type first_extended + + type, extends(base_called) :: second_extended + contains + procedure :: get => getSecond + end type second_extended + + abstract interface + function get_(self) result(returned) + import base_called + import base_returned + class(base_called), intent(in) :: self + class(base_returned), allocatable :: returned + end function get_ + end interface +contains + function getFirst(self) result(returned) + class(first_extended), intent(in) :: self + class(base_returned), allocatable :: returned + + allocate(returned, source = first_returned()) + end function getFirst + + function getSecond(self) result(returned) + class(second_extended), intent(in) :: self + class(base_returned), allocatable :: returned + + allocate(returned, source = second_returned()) + end function getSecond +end module types + +program dispatch_memory_leak + implicit none + + call run() +contains + subroutine run() + use types, only: base_returned, base_called, first_extended + + class(base_called), allocatable :: to_call + class(base_returned), allocatable :: to_get + + allocate(to_call, source = first_extended()) + allocate(to_get, source = to_call%get()) + + deallocate(to_get) + select type(to_call) + type is (first_extended) + allocate(to_get, source = to_call%get()) + end select + end subroutine run +end program dispatch_memory_leak + +! { dg-final { scan-tree-dump-times "__builtin_free" 5 "original" } } + diff --git a/gcc/testsuite/gfortran.dg/finalize_57.f90 b/gcc/testsuite/gfortran.dg/finalize_57.f90 new file mode 100644 index 00000000000..b6257357c75 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_57.f90 @@ -0,0 +1,63 @@ +! { dg-do compile } +! { dg-additional-options "-fdump-tree-original" } +! +! PR fortran/90068 +! +! Contributed by Brad Richardson +! + +program array_memory_leak + implicit none + + type, abstract :: base + end type base + + type, extends(base) :: extended + end type extended + + type :: container + class(base), allocatable :: thing + end type + + type, extends(base) :: collection + type(container), allocatable :: stuff(:) + end type collection + + call run() + call bad() +contains + subroutine run() + type(collection) :: my_thing + type(container) :: a_container + + a_container = newContainer(newExtended()) ! This is fine + my_thing = newCollection([a_container]) + end subroutine run + + subroutine bad() + type(collection) :: my_thing + + my_thing = newCollection([newContainer(newExtended())]) ! This is a memory leak + end subroutine bad + + function newExtended() + type(extended) :: newExtended + end function newExtended + + function newContainer(thing) + class(base), intent(in) :: thing + type(container) :: newContainer + + allocate(newContainer%thing, source = thing) + end function newContainer + + function newCollection(things) + type(container), intent(in) :: things(:) + type(collection) :: newCollection + + newCollection%stuff = things + end function newCollection +end program array_memory_leak + +! { dg-final { scan-tree-dump-times "__builtin_free" 15 "original" } } + diff --git a/gcc/testsuite/gfortran.dg/gomp/inner-loops-1.f90 b/gcc/testsuite/gfortran.dg/gomp/inner-loops-1.f90 new file mode 100644 index 00000000000..00a2b8ac5e0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/inner-loops-1.f90 @@ -0,0 +1,60 @@ +subroutine test1 + !$omp parallel do collapse(2) + do i=0,100 + !$omp unroll partial(2) + do j=-300,100 + call dummy (j) + end do + end do +end subroutine test1 + +subroutine test3 + !$omp parallel do collapse(3) + do i=0,100 + do j=-300,100 + !$omp unroll partial(2) + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test3 + +subroutine test6 + !$omp parallel do collapse(3) + do i=0,100 + !$omp tile sizes(3,2) + do j=-300,100 + !$omp unroll partial(2) + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test6 + +subroutine test7 + !$omp parallel do collapse(3) + do i=0,100 + !$omp tile sizes(3,3) + do j=-300,100 + !$omp tile sizes(5) + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test7 + +subroutine test8 + !$omp parallel do collapse(1) + do i=0,100 + !$omp tile sizes(3,3) + do j=-300,100 + !$omp tile sizes(5) + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test8 diff --git a/gcc/testsuite/gfortran.dg/gomp/inner-loops-2.f90 b/gcc/testsuite/gfortran.dg/gomp/inner-loops-2.f90 new file mode 100644 index 00000000000..35f44db1c12 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/inner-loops-2.f90 @@ -0,0 +1,62 @@ +subroutine test2 + !$omp parallel do collapse(3) + do i=0,100 + !$omp unroll partial(2) ! { dg-error "UNROLL construct at \\\(1\\\) with PARTIAL clause generates just one loop with canonical form but 2 loops are needed" } + do j=-300,100 + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test2 + +subroutine test4 + !$omp parallel do collapse(3) + do i=0,100 + !$omp tile sizes(3) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + do j=-300,100 + !$omp unroll partial(2) + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test4 + +subroutine test5 + !$omp parallel do collapse(3) + !$omp tile sizes(3,2) ! { dg-error "TILE construct at \\\(1\\\) generates 2 loops with canonical form but 3 loops are needed" } + do i=0,100 + do j=-300,100 + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test5 + +subroutine test9 + !$omp parallel do collapse(3) + do i=0,100 + !$omp tile sizes(3,3,3) + do j=-300,100 + !$omp tile sizes(5) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test9 + +subroutine test10 + !$omp parallel do + do i=0,100 + !$omp tile sizes(3,3,3) + do j=-300,100 + !$omp tile sizes(5) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test10 diff --git a/gcc/testsuite/gfortran.dg/gomp/pure-1.f90 b/gcc/testsuite/gfortran.dg/gomp/pure-1.f90 index 598e455d2e9..cdbebe215db 100644 --- a/gcc/testsuite/gfortran.dg/gomp/pure-1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/pure-1.f90 @@ -86,3 +86,27 @@ pure integer function func_simd(n) end do func_simd = r end + +pure integer function func_unroll(n) + implicit none + integer, value :: n + integer :: j, r + r = 0 + !$omp unroll partial(2) + do j = 1, n + r = r + j + end do + func_unroll = r +end + +pure integer function func_tile(n) + implicit none + integer, value :: n + integer :: j, r + r = 0 + !$omp tile sizes(2) + do j = 1, n + r = r + j + end do + func_tile = r +end diff --git a/gcc/testsuite/gfortran.dg/gomp/pure-2.f90 b/gcc/testsuite/gfortran.dg/gomp/pure-2.f90 index 1e3cf8c9416..35503c6a284 100644 --- a/gcc/testsuite/gfortran.dg/gomp/pure-2.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/pure-2.f90 @@ -46,28 +46,3 @@ logical function func_reverse(n) end do end -!pure integer function func_unroll(n) -integer function func_unroll(n) - implicit none - integer, value :: n - integer :: j, r - r = 0 - !$omp unroll partial(2) ! { dg-error "Unclassifiable OpenMP directive" } - do j = 1, n - r = r + j - end do - func_unroll = r -end - -!pure integer function func_tile(n) -integer function func_tile(n) - implicit none - integer, value :: n - integer :: j, r - r = 0 - !$omp tile sizes(2) ! { dg-error "Unclassifiable OpenMP directive" } - do j = 1, n - r = r + j - end do - func_tile = r -end diff --git a/gcc/testsuite/gfortran.dg/gomp/scan-9.f90 b/gcc/testsuite/gfortran.dg/gomp/scan-9.f90 new file mode 100644 index 00000000000..64d17360217 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/scan-9.f90 @@ -0,0 +1,47 @@ +subroutine foo (c, d, a) + integer :: i, a, c(64), d(64) + !$omp do reduction (inscan, +: a) + !$omp tile sizes (2) + do i = 1, 64 + a = a + c(i) + !$omp scan inclusive (a) ! { dg-error "Unexpected !\\\$OMP SCAN at \\\(1\\\) outside loop construct with 'inscan' REDUCTION clause" } + d(i) = a + end do +end subroutine foo + +subroutine bar (c, d, a) + integer :: i, j, a, c(64, 64), d(64, 64) + !$omp do collapse (2) reduction (inscan, +: a) + do i = 1, 64 + !$omp tile sizes (2) + do j = 1, 64 + d(i, j) = a + !$omp scan exclusive (a) ! { dg-error "Unexpected !\\\$OMP SCAN at \\\(1\\\) outside loop construct with 'inscan' REDUCTION clause" } + a = a + c(i, j) + end do + end do +end subroutine bar + +subroutine baz (c, d, a) + integer :: i, a, c(64), d(64) + !$omp do reduction (inscan, +: a) + !$omp unroll partial (2) + do i = 1, 64 + d(i) = a + !$omp scan exclusive (a) ! { dg-error "Unexpected !\\\$OMP SCAN at \\\(1\\\) outside loop construct with 'inscan' REDUCTION clause" } + a = a + c(i) + end do +end subroutine baz + +subroutine qux (c, d, a) + integer :: i, j, a, c(64, 64), d(64, 64) + !$omp do collapse (2) reduction (inscan, +: a) + do i = 1, 64 + !$omp tile sizes (2) + do j = 1, 64 + a = a + c(i, j) + !$omp scan inclusive (a) ! { dg-error "Unexpected !\\\$OMP SCAN at \\\(1\\\) outside loop construct with 'inscan' REDUCTION clause" } + d(i, j) = a + end do + end do +end subroutine qux diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-1.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-1.f90 new file mode 100644 index 00000000000..a02d99a548f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-1.f90 @@ -0,0 +1,39 @@ +subroutine test + implicit none + integer :: i, j, k + + !$omp tile sizes ( 1 ) + do i = 1,100 + call dummy(i) + end do + + !$omp tile sizes(1) + do i = 1,100 + call dummy(i) + end do + !$omp end tile + + !$omp tile sizes(2+3) + do i = 1,100 + call dummy(i) + end do + !$omp end tile + + !$omp tile sizes(1,2) + do i = 1,100 + do j = 1,100 + call dummy(j) + end do + end do + !$omp end tile + + !$omp tile sizes(1,2,1) + do i = 1,100 + do j = 1,100 + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-10.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-10.f90 new file mode 100644 index 00000000000..43e1920b335 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-10.f90 @@ -0,0 +1,70 @@ +! It isn't really clear what is supposed to be valid and what isn't when mixing +! imperfectly nested loops with generated loops. Sorry for now until that is +! clarified. + +subroutine bar + integer :: i, j + !$omp do collapse(2) + do i = 0, 31 + call foo (i, -1) + !$omp tile sizes (2) ! { dg-message "Imperfectly nested loop using generated loops" } + do j = 0, 31 + call foo (i, j) + end do + call foo (i, -2) + end do +end subroutine bar + +subroutine baz + integer :: i, j, k, l + !$omp do collapse(2) + do i = 0, 31 + call foo (i, -1) + !$omp tile sizes (2, 2) ! { dg-message "Imperfectly nested loop using generated loops" } + do j = 0, 31 + !$omp tile sizes (2, 2) + do k = 0, 31 + do l = 0, 31 + call foo (i + k, j + l) + end do + end do + end do + call foo (i, -2) + end do +end subroutine baz + +subroutine qux + integer :: i, j, k, l, m + !$omp do collapse(2) + do i = 0, 31 + m = i + 6 + call foo (i, -1) + !$omp tile sizes (2) ! { dg-message "Imperfectly nested loop using generated loops" } + do j = m, 31 + call foo (i, j) + end do + call foo (i, -2) + end do +end subroutine qux + +subroutine freddy + integer :: i, j, k, l, m + !$omp do collapse(2) + do i = 0, 31 + block + integer :: m + m = i + 6 + call foo (i, -1) + !$omp tile sizes (2, 2) ! { dg-message "Imperfectly nested loop using generated loops" } + do j = 0, 31 + !$omp tile sizes (2, 2) + do k = 0, 31 + do l = m, 31 + call foo (i + k, j + l) + end do + end do + end do + call foo (i, -2) + end block + end do +end subroutine freddy diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-2.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-2.f90 new file mode 100644 index 00000000000..56d7e1d1b6c --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-2.f90 @@ -0,0 +1,61 @@ +subroutine test1 + implicit none + integer :: i, j, k + + !$omp tile sizes (1,2) + !$omp tile sizes (1,2) + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile + + !$omp tile sizes (8) + !$omp tile sizes (1,2) + !$omp tile sizes (1,2,3) + do i = 1,100 + do j = 1,100 + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test1 + +subroutine test2 + implicit none + integer :: i, j, k + + !$omp taskloop collapse(2) + !$omp tile sizes (3,4) + !$omp tile sizes (1,2) + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile + !$omp end taskloop + + !$omp taskloop simd + !$omp tile sizes (8) + !$omp tile sizes (1,2) + !$omp tile sizes (1,2,3) + do i = 1,100 + do j = 1,100 + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile + !$omp end taskloop simd +end subroutine test2 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-3.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-3.f90 new file mode 100644 index 00000000000..bd6b8b18c2e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-3.f90 @@ -0,0 +1,17 @@ +subroutine test + implicit none + integer :: i, j, k + + !$omp parallel do collapse(2) ordered(2) ! { dg-error "'ordered' clause used with generated loops" } + !$omp tile sizes (1,2) + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile + !$omp end parallel do +end subroutine test diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-4.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-4.f90 new file mode 100644 index 00000000000..51bf27e4f1d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-4.f90 @@ -0,0 +1,89 @@ +subroutine test1 + implicit none + integer :: i, j, k + + !$omp tile sizes (1,2) + !$omp tile sizes (1) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test1 + +subroutine test2 + implicit none + integer :: i, j, k + + !$omp tile sizes (1,2) + !$omp tile sizes (1) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test2 + +subroutine test3 + implicit none + integer :: i, j, k + + !$omp target teams distribute + !$omp tile sizes (1,2) + !$omp tile sizes (1) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test3 + +subroutine test4 + implicit none + integer :: i, j, k + + !$omp target teams distribute collapse(2) + !$omp tile sizes (8) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + !$omp tile sizes (1,2) + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test4 + +subroutine test5 + implicit none + integer :: i, j, k + + !$omp parallel do collapse(2) ordered(2) + !$omp tile sizes (8) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + !$omp tile sizes (1,2) + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile + !$omp end tile + !$omp end parallel do +end subroutine test5 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-5.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-5.f90 new file mode 100644 index 00000000000..ddeea0e3780 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-5.f90 @@ -0,0 +1,73 @@ +subroutine test + implicit none + integer :: i, j, k, l, m, n, o + !$omp do private (i, j, k, l) + !$omp tile sizes(2, 3) + !$omp tile sizes(3, 4, 5) + !$omp tile sizes(6, 7, 8, 9) + do i = 1, 100 + do j = 1, 100 + do k = 1, 100 + do l = 1, 100 + call dummy(i) + end do + end do + end do + end do + + !$omp do private (i, j, k, l, m, n) + !$omp tile sizes(2, 3) + do i = 1, 100 + !$omp tile sizes(3, 4, 5) + do j = 1, 100 + !$omp tile sizes(6, 7, 8, 9) + do k = 1, 100 + do l = 1, 100 + do m = 1, 100 + !$omp unroll partial(2) + do n = 1, 100 + call dummy(i) + end do + end do + end do + end do + end do + end do + + !$omp do collapse(2) private (i, j, k, l, m) + do i = 1, 100 + !$omp tile sizes(2, 3) + !$omp tile sizes(3, 4, 5) + !$omp tile sizes(6, 7, 8, 9) + do j = 1, 100 + do k = 1, 100 + do l = 1, 100 + do m = 1, 100 + call dummy(i) + end do + end do + end do + end do + end do + + !$omp do private (i, j, k, l, m, n, o) collapse(2) + do i = 1, 100 + !$omp tile sizes(2, 3) + do j = 1, 100 + !$omp tile sizes(3, 4, 5) + do k = 1, 100 + !$omp tile sizes(6, 7, 8, 9) + do l = 1, 100 + do m = 1, 100 + do n = 1, 100 + !$omp unroll partial(2) + do o = 1, 100 + call dummy(i) + end do + end do + end do + end do + end do + end do + end do +end subroutine test diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-6.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-6.f90 new file mode 100644 index 00000000000..8c5d94e8b92 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-6.f90 @@ -0,0 +1,9 @@ +subroutine test + !$omp tile sizes(1,2,1) ! { dg-error "not enough DO loops for collapsed !\\\$OMP TILE" } + do i = 1,100 + do j = 1,100 + call dummy(i) + end do + end do + !$omp end tile +end subroutine test diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-7.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-7.f90 new file mode 100644 index 00000000000..58559331c5f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-7.f90 @@ -0,0 +1,128 @@ +subroutine test + implicit none + integer :: i, j, k + + !$omp tile sizes(-21) ! { dg-error "INTEGER expression of SIZES clause at \\\(1\\\) must be positive" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile + + !$omp tile sizes(0) ! { dg-error "INTEGER expression of SIZES clause at \\\(1\\\) must be positive" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile + + !$omp tile sizes(i) ! { dg-error "SIZES requires constant expression" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile + + !$omp tile sizes ! { dg-error "Expected '\\\(' after 'sizes' at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile ! { dg-error "Unexpected !\\\$OMP END TILE statement at \\\(1\\\)" } + + !$omp tile sizes( ! { dg-error "Syntax error in OpenMP expression list at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile ! { dg-error "Unexpected !\\\$OMP END TILE statement at \\\(1\\\)" } + + !$omp tile sizes(2 ! { dg-error "Syntax error in OpenMP expression list at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile ! { dg-error "Unexpected !\\\$OMP END TILE statement at \\\(1\\\)" } + + !$omp tile sizes() ! { dg-error "Syntax error in OpenMP expression list at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile ! { dg-error "Unexpected !\\\$OMP END TILE statement at \\\(1\\\)" } + + !$omp tile sizes(2,) ! { dg-error "Syntax error in OpenMP expression list at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile ! { dg-error "Unexpected !\\\$OMP END TILE statement at \\\(1\\\)" } + + !$omp tile sizes(,2) ! { dg-error "Syntax error in OpenMP expression list at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile ! { dg-error "Unexpected !\\\$OMP END TILE statement at \\\(1\\\)" } + + !$omp tile sizes(,i) ! { dg-error "Syntax error in OpenMP expression list at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile ! { dg-error "Unexpected !\\\$OMP END TILE statement at \\\(1\\\)" } + + !$omp tile sizes(i,) ! { dg-error "Syntax error in OpenMP expression list at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile ! { dg-error "Unexpected !\\\$OMP END TILE statement at \\\(1\\\)" } + + !$omp tile sizes(1,2) ! { dg-error "not enough DO loops for collapsed !\\\$OMP TILE" } + do i = 1,100 + call dummy(i) + end do + !$omp end tile + + !$omp tile sizes(1,2,1) ! { dg-error "not enough DO loops for collapsed !\\\$OMP TILE" } + do i = 1,100 + do j = 1,100 + call dummy(i) + end do + end do + !$omp end tile + + !$omp tile sizes(1,2,1) ! { dg-error "!\\\$OMP TILE inner loops must be perfectly nested at \\\(1\\\)" } + do i = 1,100 + do j = 1,100 + do k = 1,100 + call dummy(i) + end do + end do + call dummy(i) + end do + !$omp end tile + + !$omp tile sizes(1,2,1) ! { dg-error "!\\\$OMP TILE inner loops must be perfectly nested at \\\(1\\\)" } + do i = 1,100 + do j = 1,100 + do k = 1,100 + call dummy(i) + end do + call dummy(j) + end do + end do + !$omp end tile + + !$omp tile sizes(1,2,1) ! { dg-error "!\\\$OMP TILE inner loops must be perfectly nested at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + do j = 1,100 + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile + + !$omp tile sizes(1,2,1) ! { dg-error "!\\\$OMP TILE inner loops must be perfectly nested at \\\(1\\\)" } + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-8.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-8.f90 new file mode 100644 index 00000000000..3acfd9687d0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-8.f90 @@ -0,0 +1,18 @@ +subroutine test3 + implicit none + integer :: i, j, k + + !$omp taskloop collapse(3) + !$omp tile sizes (1,2) ! { dg-error "TILE construct at \\\(1\\\) generates 2 loops with canonical form but 3 loops are needed" } + !$omp tile sizes (1,2) + do i = 1,100 + do j = 1,100 + call dummy(j) + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile + !$omp end taskloop +end subroutine test3 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-9.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-9.f90 new file mode 100644 index 00000000000..7bb6d732add --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-9.f90 @@ -0,0 +1,96 @@ +subroutine test1 + integer :: i, j, k, l + !$omp do collapse(4) private (i, j, k, l) + do i = 0, 1023 ! { dg-error "cannot be redefined inside loop" } + !$omp tile sizes (2, 2, 2) + do j = 0, 1023 + !$omp tile sizes (3, 3) + do k = 0, 1023 + !$omp tile sizes (4) + do i = 0, 1023 ! { dg-error "!\\\$OMP DO iteration variable used in more than one loop" } + end do ! { dg-error "cannot be redefined inside loop" "" { target *-*-* } .-1 } + end do + end do + end do +end subroutine test1 + +subroutine test2 + integer(kind=8) :: i + integer :: j, k, l + !$omp do collapse(4) private (i, j, k, l) + do i = 0, 1023 + !$omp tile sizes (2, 2, 2) + do j = 0, 1023 + !$omp tile sizes (3, 3) + do k = 0, 1023 + !$omp tile sizes (4) + do l = i, 1023 ! { dg-error "!\\\$OMP DO loop start expression not in canonical form" } + end do + end do + end do + end do +end subroutine test2 + +subroutine test3 + integer :: i, j, k, l + !$omp do collapse(4) private (i, j, k, l) + do i = 0, 1023 + !$omp tile sizes (2, 2, 2) + do j = 0, 1023 + !$omp tile sizes (3, 3) + do k = 0, 1023 + !$omp tile sizes (4) + do l = 0, 7 * i * i ! { dg-error "!\\\$OMP DO loop end expression not in canonical form" } + end do + end do + end do + end do +end subroutine test3 + +subroutine test4 + integer :: i, j, k, l + !$omp do collapse(4) private (i, j, k, l) + do i = 0, 1023 + !$omp tile sizes (2, 2, 2) + do j = 0, 1023 + !$omp tile sizes (3, 3) + do k = 0, 1023 + !$omp tile sizes (4) + do l = i * i, 1023 ! { dg-error "!\\\$OMP DO loop start expression not in canonical form" } + end do + end do + end do + end do +end subroutine test4 + +subroutine test5 + integer :: i, j, k, l + !$omp do collapse(4) private (i, j, k, l) + do i = 0, 1023 + !$omp tile sizes (2, 2, 2) + do j = 0, 1023 + !$omp tile sizes (3, 3) + do k = 0, 1023 + !$omp tile sizes (4) + do l = 0, 1023, j ! { dg-error "!\\\$OMP TILE loop increment not in canonical form" } + end do + end do + end do + end do +end subroutine test5 + +subroutine test6 + integer :: i, j, k, l + !$omp do collapse(4) private (i, j, k, l) + do i = 0, 1023 + !$omp tile sizes (2, 2, 2) + do j = 0, 1023 + !$omp tile sizes (3, 3) + do k = 0, 1023 + !$omp tile sizes (4) + do l = 0, i - 2 ! { dg-message "Non-rectangular loops from generated loops unsupported" } + end do + end do + end do + end do +end subroutine test6 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-imperfect-nest-1.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-imperfect-nest-1.f90 new file mode 100644 index 00000000000..f11cbbea5e3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-imperfect-nest-1.f90 @@ -0,0 +1,17 @@ +subroutine test0 + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + !$omp parallel do collapse(2) private(inner) + !$omp tile sizes (8, 1) + do i = 1,m + !$omp tile sizes (8, 1) + do j = 1,n + !$omp unroll partial(10) + do k = 1, n + if (k == 1) then + inner = 0 + endif + end do + end do + end do +end subroutine test0 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-imperfect-nest-2.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-imperfect-nest-2.f90 new file mode 100644 index 00000000000..829eeb9ec60 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-imperfect-nest-2.f90 @@ -0,0 +1,74 @@ +subroutine test0m + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + !$omp parallel do collapse(2) private(inner) + do i = 1,m + !$omp tile sizes (8, 1) ! { dg-error "!\\\$OMP TILE inner loops must be perfectly nested" } + do j = 1,n + do k = 1, n + if (k == 1) then + inner = 0 + endif + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do +end subroutine test0m + +subroutine test1 + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + !$omp parallel do collapse(2) private(inner) + !$omp tile sizes (8, 1) + do i = 1,m + !$omp tile sizes (8, 1) ! { dg-error "!\\\$OMP TILE inner loops must be perfectly nested" } + do j = 1,n + !$omp unroll partial(10) + do k = 1, n + if (k == 1) then + inner = 0 + endif + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do +end subroutine test1 + +subroutine test2 + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + !$omp parallel do collapse(2) private(inner) + !$omp tile sizes (8, 1) + do i = 1,m + !$omp tile sizes (8, 1) ! { dg-error "!\\\$OMP TILE inner loops must be perfectly nested" } + do j = 1,n + do k = 1, n + if (k == 1) then + inner = 0 + endif + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do +end subroutine test2 + +subroutine test3 + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + !$omp parallel do collapse(2) private(inner) + do i = 1,m + !$omp tile sizes (8, 1) ! { dg-error "!\\\$OMP TILE inner loops must be perfectly nested" } + do j = 1,n + do k = 1, n + if (k == 1) then + inner = 0 + endif + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do +end subroutine test3 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-1.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-1.f90 new file mode 100644 index 00000000000..6f6978c5085 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-1.f90 @@ -0,0 +1,16 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } + +subroutine test1 + !$omp parallel do collapse(2) + do i=0,100 + !$omp tile sizes(4) + do j=-300,100 + call dummy (j) + end do + end do +end subroutine test1 + +! Collapse of the gimple_omp_for should be unaffacted by the transformation +! { dg-final { scan-tree-dump-times "#pragma omp for nowait collapse\\\(2\\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp tile sizes\\\(4\\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp for nowait collapse\\\(2\\\)\[\n\r\]+ +for \\\(i = 0; i <= 100; i = i \\\+ 1\\\)\[\n\r\]+ +for \\\(j.\\\d = -300; j.\\\d <= 100; j.\\\d = j.\\\d \\\+ 4\\\)" 1 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-2.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-2.f90 new file mode 100644 index 00000000000..23e804bfdd1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-2.f90 @@ -0,0 +1,20 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } + +subroutine test2 + !$omp parallel do + !$omp tile sizes(3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(3,3) + do k=-300,100 + do l=0,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test2 + +! { dg-final { scan-tree-dump-times "#pragma omp for nowait" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp tile sizes\\\(3, 3\\\)" 2 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp for nowait\[\n\r\]+ +for \\\(i.\\\d = 0; i.\\\d <= 100; i.\\\d = i.\\\d \\\+ 3\\\)" 1 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-3.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-3.f90 new file mode 100644 index 00000000000..2e27730db90 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-3.f90 @@ -0,0 +1,22 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } + +subroutine test3 + !$omp parallel do + !$omp tile sizes(3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(3,3) + do k=-300,100 + do l=0,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test3 + +! { dg-final { scan-tree-dump-times "#pragma omp for nowait" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp tile sizes\\\(3, 3, 3\\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp tile sizes\\\(3, 3\\\)" 1 "original" } } +! { dg-final { scan-tree-dump-not "#pragma omp tile" "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp for nowait\[\n\r\]+ +for \\\(i.\\\d = 0; i.\\\d <= 100; i.\\\d = i.\\\d \\\+ 3\\\)" 1 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-4.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-4.f90 new file mode 100644 index 00000000000..fb252ed5659 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-4.f90 @@ -0,0 +1,14 @@ +subroutine test3 + !$omp parallel do + !$omp tile sizes(3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(3,3) + do k=-300,100 + do l=0,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test3 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-5.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-5.f90 new file mode 100644 index 00000000000..cb4337ea03d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-5.f90 @@ -0,0 +1,59 @@ +subroutine test1a + !$omp parallel do + !$omp tile sizes(3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(5) + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test1a + +subroutine test2a + !$omp parallel do + !$omp tile sizes(3,3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(5,5) + do k=-300,100 + do l=-300,100 + do m=-300,100 + call dummy (m) + end do + end do + end do + end do + end do +end subroutine test2a + +subroutine test1b + !$omp parallel do + !$omp tile sizes(3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(5) + do k=-300,100 + call dummy (k) + end do + end do + end do +end subroutine test1b + +subroutine test2b + !$omp parallel do + !$omp tile sizes(3,3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(5,5) + do k=-300,100 + do l=-300,100 + do m=-300,100 + call dummy (m) + end do + end do + end do + end do + end do +end subroutine test2b diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-6.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-6.f90 new file mode 100644 index 00000000000..da00a58a46b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-6.f90 @@ -0,0 +1,13 @@ +subroutine test + !$omp tile sizes(3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(3,3) + do k=-300,100 + do l=0,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-7.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-7.f90 new file mode 100644 index 00000000000..966d2d84e57 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-7.f90 @@ -0,0 +1,13 @@ +subroutine test3 + !$omp tile sizes(3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(3,3) + do k=-300,100 + do l=0,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test3 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-8.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-8.f90 new file mode 100644 index 00000000000..3d38a0eabfe --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-inner-loops-8.f90 @@ -0,0 +1,63 @@ +subroutine test3a + !$omp parallel do + !$omp tile sizes(3,3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(5) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + do k=-300,100 + do l=-300,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test3a + +subroutine test4a + !$omp parallel do + !$omp tile sizes(3,3,3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(5,5) ! { dg-error "TILE construct at \\\(1\\\) generates 2 loops with canonical form but 3 loops are needed" } + do k=-300,100 + do l=-300,100 + do m=-300,100 + call dummy (m) + end do + end do + end do + end do + end do +end subroutine test4a + +subroutine test3b + !$omp parallel do + !$omp tile sizes(3,3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(5) ! { dg-error "TILE construct at \\\(1\\\) generates 1 loops with canonical form but 2 loops are needed" } + do k=-300,100 + do l=-300,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test3b + +subroutine test4b + !$omp parallel do + !$omp tile sizes(3,3,3,3,3) + do i=0,100 + do j=-300,100 + !$omp tile sizes(5,5) ! { dg-error "TILE construct at \\\(1\\\) generates 2 loops with canonical form but 3 loops are needed" } + do k=-300,100 + do l=-300,100 + do m=-300,100 + call dummy (m) + end do + end do + end do + end do + end do +end subroutine test4b diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-non-rectangular-1.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-non-rectangular-1.f90 new file mode 100644 index 00000000000..4da9a2447b2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-non-rectangular-1.f90 @@ -0,0 +1,23 @@ +subroutine test1 + !$omp tile sizes(1) + do i = 1,100 + do j = 1,i + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test1 + +subroutine test5 + !$omp tile sizes(1,2) + do i = 1,100 + do j = 1,100 + do k = 1,j + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test5 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-non-rectangular-2.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-non-rectangular-2.f90 new file mode 100644 index 00000000000..dd78e0268e1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-non-rectangular-2.f90 @@ -0,0 +1,11 @@ +subroutine test + !$omp tile sizes(1,2,1) ! { dg-error "non-rectangular 'tile'" } + do i = 1,100 + do j = 1,100 + do k = 1,i + call dummy(i) + end do + end do + end do + !$end omp tile +end subroutine test diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-non-rectangular-3.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-non-rectangular-3.f90 new file mode 100644 index 00000000000..940d2bb8338 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-non-rectangular-3.f90 @@ -0,0 +1,47 @@ +subroutine test2 + !$omp tile sizes(1,2) ! { dg-error "non-rectangular 'tile'" } + do i = 1,100 + do j = 1,i + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test2 + +subroutine test3 + !$omp tile sizes(1,2,1) ! { dg-error "non-rectangular 'tile'" } + do i = 1,100 + do j = 1,i + do k = 1,100 + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test3 + +subroutine test4 + !$omp tile sizes(1,2,1) ! { dg-error "non-rectangular 'tile'" } + do i = 1,100 + do j = 1,100 + do k = 1,i + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test4 + +subroutine test6 + !$omp tile sizes(1,2,1) ! { dg-error "non-rectangular 'tile'" } + do i = 1,100 + do j = 1,100 + do k = 1,j + call dummy(i) + end do + end do + end do + !$omp end tile +end subroutine test6 diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-unroll-1.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-unroll-1.f90 new file mode 100644 index 00000000000..fa6395b24bb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-unroll-1.f90 @@ -0,0 +1,18 @@ +function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c( n, m )) + + !$omp tile sizes (8) + !$omp unroll partial(1) + do i = 1,m + do j = 1,n + inner = 0 + do k = 1, n + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do +end function mult diff --git a/gcc/testsuite/gfortran.dg/gomp/tile-unroll-2.f90 b/gcc/testsuite/gfortran.dg/gomp/tile-unroll-2.f90 new file mode 100644 index 00000000000..8f7327f0261 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/tile-unroll-2.f90 @@ -0,0 +1,44 @@ +function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c( n, m )) + + !$omp parallel do collapse(2) + !$omp tile sizes (8,8) + !$omp unroll partial(2) ! { dg-error "UNROLL construct at \\\(1\\\) with PARTIAL clause generates just one loop with canonical form but 2 loops are needed" } + do i = 1,m + do j = 1,n + inner = 0 + do k = 1, n + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do + + !$omp tile sizes (8,8) + !$omp unroll partial(2) ! { dg-error "UNROLL construct at \\\(1\\\) with PARTIAL clause generates just one loop with canonical form but 2 loops are needed" } + do i = 1,m + do j = 1,n + inner = 0 + do k = 1, n + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do + + !$omp parallel do collapse(2) + !$omp tile sizes (8,8) + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,m + do j = 1,n + inner = 0 + do k = 1, n + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do +end function mult diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-1.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-1.f90 new file mode 100644 index 00000000000..3badf870079 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-1.f90 @@ -0,0 +1,35 @@ +subroutine test16 + implicit none + integer :: i + + !$omp do + !$omp unroll partial(1) + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test16 + +subroutine test17 + implicit none + integer :: i + + !$omp do + !$omp unroll partial(2) + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test17 + +subroutine test20 + implicit none + integer :: i + + !$omp do + !$omp unroll partial + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test20 diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-10.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-10.f90 new file mode 100644 index 00000000000..d873b3dcfa2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-10.f90 @@ -0,0 +1,6 @@ +subroutine test(i) + !$omp unroll full + call dummy0 ! { dg-error "Unexpected CALL statement at \\\(1\\\)" } +end subroutine test ! { dg-error "Unexpected END statement at \\\(1\\\)" } + +! { dg-error "Unexpected end of file" "" { target "*-*-*" } 0 } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-11.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-11.f90 new file mode 100644 index 00000000000..93974b4089d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-11.f90 @@ -0,0 +1,75 @@ +subroutine test1(i) + implicit none + integer :: i + !$omp unroll + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,10 + call dummy(i) + end do +end subroutine test1 + +subroutine test2(i) + implicit none + integer :: i + !$omp unroll full + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,10 + call dummy(i) + end do +end subroutine test2 + +subroutine test3(i) + implicit none + integer :: i + !$omp unroll full + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,10 + call dummy(i) + end do +end subroutine test3 + +subroutine test4(i) + implicit none + integer :: i + !$omp do + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,10 + call dummy(i) + end do +end subroutine test4 + +subroutine test5(i) + implicit none + integer :: i + !$omp do + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,10 + call dummy(i) + end do +end subroutine test5 + +subroutine test6(i) + implicit none + integer :: i + !$omp do + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,10 + call dummy(i) + end do +end subroutine test6 + +subroutine test7(i) + implicit none + integer :: i + !$omp loop + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,10 + call dummy(i) + end do +end subroutine test7 diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-12.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-12.f90 new file mode 100644 index 00000000000..5ef640f8464 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-12.f90 @@ -0,0 +1,29 @@ +subroutine test1 + implicit none + integer :: i + !$omp unroll + do while (i < 10) ! { dg-error "!\\\$OMP UNROLL cannot be a DO WHILE or DO without loop control at \\\(1\\\)" } + call dummy(i) + i = i + 1 + end do +end subroutine test1 + +subroutine test2 + implicit none + integer :: i + !$omp unroll + do ! { dg-error "!\\\$OMP UNROLL cannot be a DO WHILE or DO without loop control at \\\(1\\\)" } + call dummy(i) + i = i + 1 + if (i >= 10) exit + end do +end subroutine test2 + +subroutine test3 + implicit none + integer :: i + !$omp unroll + do concurrent (i=1:10) ! { dg-error "!\\\$OMP UNROLL cannot be a DO CONCURRENT loop at \\\(1\\\)" } + call dummy(i) ! { dg-error "Subroutine call to 'dummy' in DO CONCURRENT block at \\\(1\\\) is not PURE" } + end do +end subroutine test3 diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-13.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-13.f90 new file mode 100644 index 00000000000..3d338d30af4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-13.f90 @@ -0,0 +1,43 @@ +subroutine foo + integer :: i, j + !$omp do collapse(2) + do i = 1, 512 + !$omp unroll partial (3) + do j = 1, 512 + end do + !$omp end unroll + end do + !$omp end do +end subroutine foo + +subroutine bar + integer :: i, j + !$omp do collapse(2) + do i = 1, 512 + !$omp unroll partial (3) + do j = 1, 512 + end do + end do + !$omp end do +end subroutine bar + +subroutine baz + integer :: i, j + !$omp do collapse(2) + do i = 1, 512 + !$omp unroll partial (3) + do j = 1, 512 + end do + !$omp end unroll + end do +end subroutine baz + +subroutine qux + integer :: i, j + !$omp do collapse(2) + do i = 1, 512 + !$omp unroll partial (3) + do j = 1, 512 + end do + end do +end subroutine qux diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-2.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-2.f90 new file mode 100644 index 00000000000..fa9316d1031 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-2.f90 @@ -0,0 +1,22 @@ +! { dg-additional-options "-fdump-tree-original" } + +subroutine test1 + implicit none + integer :: i + !$omp unroll + do i = 1,10 + call dummy(i) + end do +end subroutine test1 + +subroutine test2 + implicit none + integer :: i + !$omp unroll full + do i = 1,10 + call dummy(i) + end do +end subroutine test2 + +! { dg-final { scan-tree-dump-times "#pragma omp unroll" 2 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp unroll full" 1 "original" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-3.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-3.f90 new file mode 100644 index 00000000000..a649bc5edbe --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-3.f90 @@ -0,0 +1,15 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } + +subroutine test1 + implicit none + integer :: i + !$omp unroll full + do i = 1,10 + call dummy(i) + end do +end subroutine test1 + +! Loop should be removed with 10 copies of the body remaining +! { dg-final { scan-tree-dump "#pragma omp unroll full" "original" } } +! { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } +! { dg-final { scan-tree-dump "\.ANNOTATE \\\(\[^\n\r\]*, 1, 10\\\);" "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-4.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-4.f90 new file mode 100644 index 00000000000..96bc8da0783 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-4.f90 @@ -0,0 +1,15 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } + +subroutine test1 + implicit none + integer :: i + !$omp unroll + do i = 1,100 + call dummy(i) + end do +end subroutine test1 + +! { dg-final { scan-tree-dump "#pragma omp unroll" "original" } } +! { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } +! { dg-final { scan-tree-dump-times "dummy" 1 "gimple" } } +! { dg-final { scan-tree-dump "\.ANNOTATE \\\(\[^\n\r\]*, 1, 8\\\);" "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-5.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-5.f90 new file mode 100644 index 00000000000..7894304f7ac --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-5.f90 @@ -0,0 +1,14 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } + +subroutine test1 + implicit none + integer :: i + !$omp unroll partial + do i = 1,100 + call dummy(i) + end do +end subroutine test1 + +! { dg-final { scan-tree-dump "#pragma omp unroll partial" "original" } } +! { dg-final { scan-tree-dump-not "#pragma omp" "gimple" } } +! { dg-final { scan-tree-dump "\.ANNOTATE \\\(\[^\n\r\]*, 1, 8\\\);" "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-6.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-6.f90 new file mode 100644 index 00000000000..fb507b5164b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-6.f90 @@ -0,0 +1,241 @@ +subroutine test1 + implicit none + integer :: i + + !$omp do + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do +end subroutine test1 + +subroutine test2 + implicit none + integer :: i + + !$omp do + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test2 + +subroutine test3 + implicit none + integer :: i + + !$omp do + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end do +end subroutine test3 + +subroutine test4 + implicit none + integer :: i + + !$omp do + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll + !$omp end do +end subroutine test4 + +subroutine test5 + implicit none + integer :: i + + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do +end subroutine test5 + +subroutine test6 + implicit none + integer :: i + + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test6 + +subroutine test7 + implicit none + integer :: i + + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test7 + +subroutine test8 + implicit none + integer :: i + + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll + !$omp end unroll +end subroutine test8 + +subroutine test9 + implicit none + integer :: i + + !$omp do + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do +end subroutine test9 + +subroutine test10 + implicit none + integer :: i + + !$omp unroll full + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do +end subroutine test10 + +subroutine test11 + implicit none + integer :: i,j + + !$omp do + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + do j = 1,100 + call dummy2(i,j) + end do + end do +end subroutine test11 + +subroutine test12 + implicit none + integer :: i,j + + !$omp do + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + call dummy(i) ! { dg-error "Unexpected CALL statement at \\\(1\\\)" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do j = 1,100 + call dummy2(i,j) + end do + end do +end subroutine test12 + +subroutine test13 + implicit none + integer :: i,j + + !$omp do + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do j = 1,100 + call dummy2(i,j) + end do + call dummy(i) + end do +end subroutine test13 + +subroutine test14 + implicit none + integer :: i + + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll + !$omp end unroll + !$omp end unroll ! { dg-error "Unexpected !\\\$OMP END UNROLL statement at \\\(1\\\)" } +end subroutine test14 + +subroutine test15 + implicit none + integer :: i + + !$omp do + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll + !$omp end unroll + !$omp end unroll ! { dg-error "Unexpected !\\\$OMP END UNROLL statement at \\\(1\\\)" } +end subroutine test15 + +subroutine test18 + implicit none + integer :: i + + !$omp do + !$omp unroll partial(0) ! { dg-error "PARTIAL clause argument not constant positive integer at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test18 + +subroutine test19 + implicit none + integer :: i + + !$omp do + !$omp unroll partial(-10) ! { dg-error "PARTIAL clause argument not constant positive integer at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test19 + +subroutine test21 + implicit none + integer :: i + + !$omp unroll partial + do concurrent (i = 1:100) ! { dg-error "!\\\$OMP UNROLL cannot be a DO CONCURRENT loop at \\\(1\\\)" } + call dummy(i) ! { dg-error "Subroutine call to 'dummy' in DO CONCURRENT block at \\\(1\\\) is not PURE" } + end do + !$omp end unroll +end subroutine test21 + +subroutine test22 + implicit none + integer :: i + + !$omp do + !$omp unroll partial + do concurrent (i = 1:100) ! { dg-error "!\\\$OMP UNROLL cannot be a DO CONCURRENT loop at \\\(1\\\)" } + call dummy(i) ! { dg-error "Subroutine call to 'dummy' in DO CONCURRENT block at \\\(1\\\) is not PURE" } + end do + !$omp end unroll +end subroutine test22 diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-7.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-7.f90 new file mode 100644 index 00000000000..0a06dd2771b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-7.f90 @@ -0,0 +1,35 @@ +subroutine foo + integer :: i + !$omp do + !$omp unroll partial ( 3 ) + do i = 1, 512 + end do + !$omp end unroll + !$omp end do +end subroutine foo + +subroutine bar + integer :: i + !$omp do + !$omp unroll partial(3) + do i = 1, 512 + end do + !$omp end do +end subroutine bar + +subroutine baz + integer :: i + !$omp do + !$omp unroll partial (3) + do i = 1, 512 + end do +end subroutine baz + +subroutine qux + integer :: i + !$omp do + !$omp unroll partial (3) + do i = 1, 512 + end do + !$omp end unroll +end subroutine qux diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-8.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-8.f90 new file mode 100644 index 00000000000..c8fcfa17bb8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-8.f90 @@ -0,0 +1,26 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } */ + +subroutine test1 + implicit none + integer :: i + !$omp parallel do collapse(1) + !$omp unroll partial(4) + !$omp unroll partial(3) + !$omp unroll partial(2) + !$omp unroll partial(1) + do i = 1,100 + call dummy(i) + end do +end subroutine test1 + +! Loop should be unrolled 1 * 2 * 3 * 4 = 24 times +! { dg-final { scan-tree-dump "#pragma omp for nowait collapse\\\(1\\\)" "original" } } +! { dg-final { scan-tree-dump "#pragma omp unroll partial\\\(1\\\)" "original" } } +! { dg-final { scan-tree-dump "#pragma omp unroll partial\\\(2\\\)" "original" } } +! { dg-final { scan-tree-dump "#pragma omp unroll partial\\\(3\\\)" "original" } } +! { dg-final { scan-tree-dump "#pragma omp unroll partial\\\(4\\\)" "original" } } +! { dg-final { scan-tree-dump-not "#pragma omp unroll" "gimple" } } +! { dg-final { scan-tree-dump-times "\.ANNOTATE \\\(\[^\n\r\]*, 1, 2\\\);" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "\.ANNOTATE \\\(\[^\n\r\]*, 1, 3\\\);" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "\.ANNOTATE \\\(\[^\n\r\]*, 1, 4\\\);" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp for" 1 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-9.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-9.f90 new file mode 100644 index 00000000000..2223387a395 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-9.f90 @@ -0,0 +1,22 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } + +subroutine test1 + implicit none + integer :: i + !$omp unroll full + !$omp unroll partial(3) + !$omp unroll partial(2) + !$omp unroll partial(1) + do i = 1,100 + call dummy(i) + end do +end subroutine test1 + +! { dg-final { scan-tree-dump "#pragma omp unroll full" "original" } } +! { dg-final { scan-tree-dump "#pragma omp unroll partial\\\(1\\\)" "original" } } +! { dg-final { scan-tree-dump "#pragma omp unroll partial\\\(2\\\)" "original" } } +! { dg-final { scan-tree-dump "#pragma omp unroll partial\\\(3\\\)" "original" } } +! { dg-final { scan-tree-dump-not "#pragma omp unroll" "gimple" } } +! { dg-final { scan-tree-dump "\.ANNOTATE \\\(\[^\n\r]*, 1, 2\\\);" "gimple" } } +! { dg-final { scan-tree-dump "\.ANNOTATE \\\(\[^\n\r]*, 1, 3\\\);" "gimple" } } +! { dg-final { scan-tree-dump "\.ANNOTATE \\\(\[^\n\r]*, 1, 17\\\);" "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-inner-loop-1.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-inner-loop-1.f90 new file mode 100644 index 00000000000..c43314412e0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-inner-loop-1.f90 @@ -0,0 +1,28 @@ +subroutine test1a + !$omp parallel do + !$omp tile sizes(3,3,3) + do i=0,100 + do j=-300,100 + !$omp unroll partial(5) + do k=-300,100 + do l=0,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test1a + +subroutine test1b + !$omp tile sizes(3,3,3) + do i=0,100 + do j=-300,100 + !$omp unroll partial(5) + do k=-300,100 + do l=0,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test1b diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-inner-loop-2.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-inner-loop-2.f90 new file mode 100644 index 00000000000..89dc74d4e9e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-inner-loop-2.f90 @@ -0,0 +1,28 @@ +subroutine test2a + !$omp parallel do + !$omp tile sizes(3,3,3,3) + do i=0,100 + do j=-300,100 + !$omp unroll partial(5) ! { dg-error "UNROLL construct at \\\(1\\\) with PARTIAL clause generates just one loop with canonical form but 2 loops are needed" } + do k=-300,100 + do l=0,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test2a + +subroutine test2b + !$omp tile sizes(3,3,3,3) + do i=0,100 + do j=-300,100 + !$omp unroll partial(5) ! { dg-error "UNROLL construct at \\\(1\\\) with PARTIAL clause generates just one loop with canonical form but 2 loops are needed" } + do k=-300,100 + do l=0,100 + call dummy (l) + end do + end do + end do + end do +end subroutine test2b diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-no-clause-1.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-no-clause-1.f90 new file mode 100644 index 00000000000..7c5e1947a7d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-no-clause-1.f90 @@ -0,0 +1,21 @@ +! { dg-additional-options "-O2 -fdump-tree-gimple" } + +subroutine test + !$omp unroll + do i = 1,5 + do j = 1,10 + call dummy3(i,j) + end do + end do + !$omp end unroll + + !$omp unroll + do i = 1,6 + do j = 1,6 + call dummy3(i,j) + end do + end do + !$omp end unroll +end subroutine test + +! { dg-final { scan-tree-dump-times "\.ANNOTATE \\\(\[^\n\r\]*, 1, 8\\\);" 2 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-non-rect-1.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-non-rect-1.f90 new file mode 100644 index 00000000000..11e26a819a8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-non-rect-1.f90 @@ -0,0 +1,13 @@ +subroutine test + implicit none + + integer :: i, j, k + !$omp unroll full + do i = -3, 5 + do j = 1,10 + do k = j,j*2 + 1 + call dummy (i) + end do + end do + end do +end subroutine diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-non-rect-2.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-non-rect-2.f90 new file mode 100644 index 00000000000..d81256e28a1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-non-rect-2.f90 @@ -0,0 +1,22 @@ +subroutine test + implicit none + + integer :: i, j, k + !$omp target parallel do collapse(2) + do i = -300, 100 + !$omp unroll partial + do j = i,i*2 ! { dg-message "Non-rectangular loops from generated loops unsupported" } + call dummy (i) + end do + end do + + !$omp target parallel do collapse(3) + do i = -300, 100 + do j = 1,10 + !$omp unroll partial + do k = j,j*2 + 1 ! { dg-message "Non-rectangular loops from generated loops unsupported" } + call dummy (i) + end do + end do + end do +end subroutine diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-simd-1.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-simd-1.f90 new file mode 100644 index 00000000000..a6e7496fa0a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-simd-1.f90 @@ -0,0 +1,37 @@ +! { dg-options "-fno-openmp -fopenmp-simd" } + +subroutine test15 + implicit none + integer :: i + + !$omp simd + !$omp unroll partial(1) + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test15 + +subroutine test16 + implicit none + integer :: i + + !$omp simd + !$omp unroll partial(2) + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test16 + +subroutine test19 + implicit none + integer :: i + + !$omp simd + !$omp unroll partial + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test19 diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-simd-2.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-simd-2.f90 new file mode 100644 index 00000000000..06e712e16e9 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-simd-2.f90 @@ -0,0 +1,56 @@ +! { dg-do run } +! { dg-options "-O2 -fopenmp-simd -fdump-tree-original -fdump-tree-gimple" } + +module test_functions + contains + integer function compute_sum() result(sum) + implicit none + + integer :: i,j + + !$omp simd + do i = 1,10,3 + !$omp unroll full + do j = 1,10,3 + sum = sum + 1 + end do + end do + end function + + integer function compute_sum2() result(sum) + implicit none + + integer :: i,j + + !$omp simd + !$omp unroll partial(2) + do i = 1,10,3 + do j = 1,10,3 + sum = sum + 1 + end do + end do + end function +end module test_functions + +program test + use test_functions + implicit none + + integer :: result + + result = compute_sum () + write (*,*) result + if (result .ne. 16) then + call abort + end if + + result = compute_sum2 () + write (*,*) result + if (result .ne. 16) then + call abort + end if +end program + +! { dg-final { scan-tree-dump "omp unroll full" "original" } } +! { dg-final { scan-tree-dump "omp unroll partial\\\(2\\\)" "original" } } +! { dg-final { scan-tree-dump-not "omp unroll" "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-simd-3.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-simd-3.f90 new file mode 100644 index 00000000000..1c73c149fc8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-simd-3.f90 @@ -0,0 +1,208 @@ +! { dg-options "-fno-openmp -fopenmp-simd" } + +subroutine test1 + implicit none + integer :: i + + !$omp simd + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do +end subroutine test1 + +subroutine test2 + implicit none + integer :: i + + !$omp simd + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test2 + +subroutine test3 + implicit none + integer :: i + + !$omp simd + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end do +end subroutine test3 + +subroutine test4 + implicit none + integer :: i + + !$omp simd + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll + !$omp end do +end subroutine test4 + +subroutine test5 + implicit none + integer :: i + + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do +end subroutine test5 + +subroutine test6 + implicit none + integer :: i + + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test6 + +subroutine test7 + implicit none + integer :: i + + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll + !$omp end unroll +end subroutine test7 + +subroutine test8 + implicit none + integer :: i + + !$omp simd + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do +end subroutine test8 + +subroutine test9 + implicit none + integer :: i + + !$omp unroll full + !$omp unroll full ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do +end subroutine test9 + +subroutine test10 + implicit none + integer :: i,j + + !$omp simd + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + do j = 1,100 + call dummy2(i,j) + end do + end do +end subroutine test10 + +subroutine test11 + implicit none + integer :: i,j + + !$omp simd + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + call dummy(i) ! { dg-error "Unexpected CALL statement at \\\(1\\\)" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do j = 1,100 + call dummy2(i,j) + end do + end do +end subroutine test11 + +subroutine test12 + implicit none + integer :: i,j + + !$omp simd + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do j = 1,100 + call dummy2(i,j) + end do + call dummy(i) + end do +end subroutine test12 + +subroutine test13 + implicit none + integer :: i + + !$omp unroll + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll + !$omp end unroll + !$omp end unroll ! { dg-error "Unexpected !\\\$OMP END UNROLL statement at \\\(1\\\)" } +end subroutine test13 + +subroutine test14 + implicit none + integer :: i + + !$omp simd + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + !$omp unroll ! { dg-error "Generated loop of UNROLL construct at \\\(1\\\) without PARTIAL clause does not have canonical form" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll + !$omp end unroll + !$omp end unroll ! { dg-error "Unexpected !\\\$OMP END UNROLL statement at \\\(1\\\)" } +end subroutine test14 + +subroutine test17 + implicit none + integer :: i + + !$omp simd + !$omp unroll partial(0) ! { dg-error "PARTIAL clause argument not constant positive integer at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test17 + +subroutine test18 + implicit none + integer :: i + + !$omp simd + !$omp unroll partial(-10) ! { dg-error "PARTIAL clause argument not constant positive integer at \\\(1\\\)" } + do i = 1,100 + call dummy(i) + end do + !$omp end unroll +end subroutine test18 diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-tile-1.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-tile-1.f90 new file mode 100644 index 00000000000..ed7691be16e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-tile-1.f90 @@ -0,0 +1,35 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } + +function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c( n, m )) + + !$omp parallel do + !$omp unroll partial(1) + !$omp tile sizes (8,8) + do i = 1,m + do j = 1,n + inner = 0 + do k = 1, n + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do +end function mult + +! { dg-final { scan-tree-dump-times "#pragma omp for nowait" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp unroll partial\\\(1\\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp tile sizes\\\(8, 8\\\)" 1 "original" } } +! { dg-final { scan-tree-dump-not "#pragma omp unroll" "gimple" } } +! { dg-final { scan-tree-dump-not "#pragma omp tile" "gimple" } } + +! Tiling adds two floor and two tile loops. +! Unroll with partial(1) is effectively ignored and the innermost +! loop isn't associated with anything. So that means 5 loops, +! with the outermost associated with !$omp parallel do, where +! the innermost loop gimplifies condition into a boolean temporary. + +! { dg-final { scan-tree-dump-times "if \\\(\[A-Za-z0-9_.\]+ <" 3 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-tile-2.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-tile-2.f90 new file mode 100644 index 00000000000..d49e5ea08b7 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-tile-2.f90 @@ -0,0 +1,40 @@ +! { dg-additional-options "-O2 -fdump-tree-original -fdump-tree-gimple" } + +function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c( n, m )) + c = 0 + + !$omp target + !$omp parallel do + !$omp unroll partial(2) + !$omp tile sizes (8,8,4) + do i = 1,m + do j = 1,n + do k = 1, n + c(j,i) = c(j,i) + a(k, i) * b(j, k) + end do + end do + end do + !$omp end target +end function mult + +! { dg-final { scan-tree-dump-times "#pragma omp for nowait" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp unroll partial\\\(2\\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp tile sizes\\\(8, 8, 4\\\)" 1 "original" } } +! { dg-final { scan-tree-dump-not "#pragma omp unroll" "gimple" } } +! { dg-final { scan-tree-dump-not "#pragma omp tile" "gimple" } } + +! Check the number of loops + +! Tiling adds three tile and three floor loops. +! The outermost tile loop is then partially unrolled, turning it +! into one tile and one floor loop, so now 7 loops in total, one +! of them being fully unrolled. And finally the outermost loop is +! associated with the !$omp parallel do and so not lowered during +! gimplification. + +! { dg-final { scan-tree-dump-times "if \\\(\[A-Za-z0-9_.\]+ <" 5 "gimple" } } +! { dg-final { scan-tree-dump-times "\.ANNOTATE \\\(\[^\n\r\]*, 1, 2\\\);" 1 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/unroll-tile-inner-1.f90 b/gcc/testsuite/gfortran.dg/gomp/unroll-tile-inner-1.f90 new file mode 100644 index 00000000000..22e51cd6060 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/unroll-tile-inner-1.f90 @@ -0,0 +1,24 @@ +! { dg-additional-options "-fdump-tree-original -fdump-tree-gimple" } + +function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c( n, m )) + + !$omp parallel do collapse(2) + !$omp tile sizes (8,8) + do i = 1,m + do j = 1,n + inner = 0 + !$omp unroll partial(10) + do k = 1, n + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do +end function mult + +! { dg-final { scan-tree-dump-times "#pragma omp unroll partial" 1 "original" } } +! { dg-final { scan-tree-dump-not "#pragma omp unroll partial" "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/pr95690.f90 b/gcc/testsuite/gfortran.dg/pr95690.f90 index 807147f3a9a..1432937438a 100644 --- a/gcc/testsuite/gfortran.dg/pr95690.f90 +++ b/gcc/testsuite/gfortran.dg/pr95690.f90 @@ -2,8 +2,8 @@ module m contains subroutine s - print *, (erfc) ! { dg-error "not a floating constant" "" { target i?86-*-* x86_64-*-* sparc*-*-* cris-*-* hppa*-*-* aarch64-apple-darwin* } } - end ! { dg-error "not a floating constant" "" { target { ! "i?86-*-* x86_64-*-* sparc*-*-* cris-*-* hppa*-*-* aarch64-apple-darwin*" } } } + print *, (erfc) ! { dg-error "not a floating constant" "" { target i?86-*-* x86_64-*-* sparc*-*-* cris-*-* hppa*-*-* } } + end ! { dg-error "not a floating constant" "" { target { ! "i?86-*-* x86_64-*-* sparc*-*-* cris-*-* hppa*-*-*" } } } function erfc() end end diff --git a/gcc/testsuite/go.test/go-test.exp b/gcc/testsuite/go.test/go-test.exp index 8fdc7b420be..98317380746 100644 --- a/gcc/testsuite/go.test/go-test.exp +++ b/gcc/testsuite/go.test/go-test.exp @@ -477,7 +477,8 @@ proc go-gc-tests { } { if { ( [file tail $test] == "select2.go" \ || [file tail $test] == "stack.go" \ || [file tail $test] == "peano.go" \ - || [file tail $test] == "nilptr2.go" ) \ + || [file tail $test] == "nilptr2.go" \ + || [file tail $test] == "index0.go" ) \ && ! [check_effective_target_split_stack] } { # These tests fails on targets without split stack. untested $name diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index cee87e1d07f..42c719c512c 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -82,12 +82,8 @@ proc dg-scan { name positive testcase output_file orig_args } { if { [string compare -length 14 $name scan-assembler] == 0 } { # Remove LTO sections. # ??? Somehow, .*? is still greedy. - if { [istarget *-*-darwin*] } { - # Darwin/Mach-O LTO sections are in the __GNU_LTO segment. - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?__GNU_LTO(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } else { - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } + # regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_.*?\n(?=[[:space:]]*\.text\n)} $text {\1} text + regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text } set match [regexp -- $pattern $text] @@ -507,13 +503,7 @@ proc scan-assembler-times { args } { set fd [open $output_file r] set text [read $fd] close $fd - # Remove LTO sections. - if { [istarget *-*-darwin*] } { - # Darwin/Mach-O LTO sections are in the __GNU_LTO segment. - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?__GNU_LTO(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } else { - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } + regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text set result_count [regexp -all -- $pattern $text] if {$result_count == $times} { @@ -577,12 +567,7 @@ proc scan-assembler-bound { args } { set fd [open $output_file r] set text [read $fd] close $fd - if { [istarget *-*-darwin*] } { - # Darwin/Mach-O LTO sections are in the __GNU_LTO segment. - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?__GNU_LTO(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } else { - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } + regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text set result_count [regexp -all -- $pattern $text] if [expr $result_count $cmp $bound] { @@ -644,12 +629,7 @@ proc scan-assembler-dem { args } { set output [remote_exec host "$cxxfilt" "" "$output_file"] set text [lindex $output 1] - if { [istarget *-*-darwin*] } { - # Darwin/Mach-O LTO sections are in the __GNU_LTO segment. - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?__GNU_LTO(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } else { - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } + regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text if [regexp -- $pattern $text] { pass "$testcase scan-assembler-dem $pp_pattern" @@ -706,12 +686,7 @@ proc scan-assembler-dem-not { args } { set output [remote_exec host "$cxxfilt" "" "$output_file"] set text [lindex $output 1] - if { [istarget *-*-darwin*] } { - # Darwin/Mach-O LTO sections are in the __GNU_LTO segment. - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?__GNU_LTO(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } else { - regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - } + regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*"?\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text if ![regexp -- $pattern $text] { pass "$testcase scan-assembler-dem-not $pp_pattern" @@ -894,15 +869,15 @@ proc configure_check-function-bodies { config } { # Regexp for the start of a function definition (name in \1). if { [istarget nvptx*-*-*] } { set up_config(start) { - {^// BEGIN(?: GLOBAL|) FUNCTION DEF: ([a-zA-Z_]\S+)$} + {^// BEGIN(?: GLOBAL|) FUNCTION DEF: ([a-zA-Z_]\S*)$} } } elseif { [istarget *-*-darwin*] } { set up_config(start) { - {^_([a-zA-Z_]\S+):$} + {^_([a-zA-Z_]\S*):$} {^LFB[0-9]+:} } } else { - set up_config(start) {{^([a-zA-Z_]\S+):$}} + set up_config(start) {{^([a-zA-Z_]\S*):$}} } # Regexp for the end of a function definition. diff --git a/gcc/testsuite/lib/target-libpath.exp b/gcc/testsuite/lib/target-libpath.exp index e830046cd35..61408434145 100644 --- a/gcc/testsuite/lib/target-libpath.exp +++ b/gcc/testsuite/lib/target-libpath.exp @@ -86,32 +86,6 @@ proc set_ld_library_path_env_vars { } { return } - # Darwin's equivalent of LD_LIBRARY_PATH. - if { [istarget *-*-darwin\[89\]*] || [istarget *-*-darwin1\[0-4\]*] } { - if { $orig_environment_saved == 0 } { - set orig_environment_saved 1 - if [info exists env(DYLD_LIBRARY_PATH)] { - set orig_dyld_library_path "$env(DYLD_LIBRARY_PATH)" - set orig_dyld_library_path_saved 1 - } - if [info exists env(PATH)] { - set orig_path "$env(PATH)" - set orig_path_saved 1 - } - } - if { $orig_dyld_library_path_saved } { - setenv DYLD_LIBRARY_PATH "$ld_library_path:$orig_dyld_library_path" - } else { - setenv DYLD_LIBRARY_PATH "$ld_library_path" - } - verbose -log "DYLD_LIBRARY_PATH=[getenv DYLD_LIBRARY_PATH]" - return - } elseif { [istarget *-*-darwin*] } { - # Later versions exclude DYLD_* variables when calling via system apps - # which includes, for example, the shells - so this cannot work there. - return - } - if { $orig_environment_saved == 0 } { set orig_environment_saved 1 @@ -136,6 +110,10 @@ proc set_ld_library_path_env_vars { } { set orig_ld_library_path_64 "$env(LD_LIBRARY_PATH_64)" set orig_ld_library_path_64_saved 1 } + if [info exists env(DYLD_LIBRARY_PATH)] { + set orig_dyld_library_path "$env(DYLD_LIBRARY_PATH)" + set orig_dyld_library_path_saved 1 + } if [info exists env(PATH)] { set orig_path "$env(PATH)" set orig_path_saved 1 @@ -147,14 +125,16 @@ proc set_ld_library_path_env_vars { } { # It only sets SHLIB_PATH and LD_LIBRARY_PATH when it executes a # program. We also need the environment set for compilations, etc. # - # On Solaris, we have to set variables akin to LD_LIBRARY_PATH, but called - # LD_LIBRARY_PATH_32 (Solaris 32 bit) and LD_LIBRARY_PATH_32 (Solaris 64 bit). - # and, on HP-UX, (SHLIB_PATH). In some cases, the variables are independent - # of LD_LIBRARY_PATH, and in other cases LD_LIBRARY_PATH is used if the + # On Darwin, we have to set variables akin to LD_LIBRARY_PATH, but called + # DYLD_LIBRARY_PATH. The same applies to Solaris 32 bit + # (LD_LIBRARY_PATH_32), Solaris 64 bit (LD_LIBRARY_PATH_64), and HP-UX + # (SHLIB_PATH). In some cases, the variables are independent of + # LD_LIBRARY_PATH, and in other cases LD_LIBRARY_PATH is used if the # variable is not defined. # # Doing this is somewhat of a hack as ld_library_path gets repeated in # SHLIB_PATH and LD_LIBRARY_PATH when unix_load sets these variables. + if { ![istarget *-*-darwin*] } { if { $orig_ld_library_path_saved } { setenv LD_LIBRARY_PATH "$ld_library_path:$orig_ld_library_path" } else { @@ -188,7 +168,23 @@ proc set_ld_library_path_env_vars { } { } else { setenv LD_LIBRARY_PATH_64 "$ld_library_path" } - + } + if { [istarget *-*-darwin*] } { + if { [info exists ENABLE_DARWIN_AT_RPATH] || [istarget *-*-darwin1\[5-9\]*] + || [istarget *-*-darwin2*] } { + # Either we are not using DYLD_LIBRARY_PATH or we're on a version of the + # OS for which it is not passed through system exes. + if [info exists env(DYLD_LIBRARY_PATH)] { + unsetenv DYLD_LIBRARY_PATH + } + } else { + if { $orig_dyld_library_path_saved } { + setenv DYLD_LIBRARY_PATH "$ld_library_path:$orig_dyld_library_path" + } else { + setenv DYLD_LIBRARY_PATH "$ld_library_path" + } + } + } if { [istarget *-*-cygwin*] || [istarget *-*-mingw*] } { if { $orig_path_saved } { setenv PATH "$ld_library_path:$orig_path" @@ -203,6 +199,7 @@ proc set_ld_library_path_env_vars { } { verbose -log "SHLIB_PATH=[getenv SHLIB_PATH]" verbose -log "LD_LIBRARY_PATH_32=[getenv LD_LIBRARY_PATH_32]" verbose -log "LD_LIBRARY_PATH_64=[getenv LD_LIBRARY_PATH_64]" + verbose -log "DYLD_LIBRARY_PATH=[getenv DYLD_LIBRARY_PATH]" } ####################################### diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 6c57a08979b..5c0a3dade22 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -2044,7 +2044,7 @@ proc check_effective_target_riscv_zvfh_ok { } { # check if we can execute vector insns with the given hardware or # simulator set gcc_march [regsub {[[:alnum:]]*} [riscv_get_arch] &v] - if { [check_runtime ${gcc_march}_exec { + if { [check_runtime ${gcc_march}_zvfh_exec { int main() { asm ("vsetivli zero,8,e16,m1,ta,ma"); @@ -2057,6 +2057,8 @@ proc check_effective_target_riscv_zvfh_ok { } { return 0 } +# Return 1 if we can execute code when using dg-add-options riscv_zvbb + proc check_effective_target_riscv_zvbb_ok { } { # If the target already supports v without any added options, # we may assume we can execute just fine. @@ -2076,6 +2078,28 @@ proc check_effective_target_riscv_zvbb_ok { } { } } "-march=${gcc_march}"] } { return 1 } + return 0 +} + +# Return 1 if we can load a vector from a 1-byte aligned address. + +proc check_effective_target_riscv_v_misalign_ok { } { + + if { ![check_effective_target_riscv_v_ok] } { + return 0 + } + + set gcc_march [riscv_get_arch] + if { [check_runtime ${gcc_march}_misalign_exec { + int main() { + unsigned char a[16] + = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + asm ("vsetivli zero,7,e8,m1,ta,ma"); + asm ("addi a7,%0,1" : : "r" (a) : "a7" ); + asm ("vle8.v v8,0(a7)" : : : "v8"); + return 0; } } "-march=${gcc_march}"] } { + return 1 + } return 0 } @@ -8184,7 +8208,6 @@ proc check_effective_target_vect_hw_misalign { } { || ([istarget mips*-*-*] && [et-is-effective-target mips_msa]) || ([istarget s390*-*-*] && [check_effective_target_s390_vx]) - || ([istarget riscv*-*-*]) || ([istarget loongarch*-*-*]) || [istarget amdgcn*-*-*] } { return 1 @@ -8193,6 +8216,11 @@ proc check_effective_target_vect_hw_misalign { } { && ![check_effective_target_arm_vect_no_misalign] } { return 1 } + if { [istarget riscv*-*-*] + && [check_effective_target_riscv_v_misalign_ok] } { + return 1 + } + return 0 }] } @@ -9288,7 +9316,7 @@ proc check_effective_target_section_anchors { } { return [check_cached_effective_target section_anchors { expr { [istarget powerpc*-*-*] || [istarget arm*-*-*] - || ([istarget aarch64*-*-*] && ![istarget aarch64*-*-darwin*]) + || [istarget aarch64*-*-*] || [istarget loongarch*-*-*] }}] } @@ -10423,7 +10451,13 @@ proc check_effective_target_apxf { } { void foo () { - __asm__ volatile ("add\t%%r16, %%r31" ::); + __asm__ volatile ("movq\t%r16, %rax"); + __asm__ volatile ("push2p\t%r15, %r14"); + __asm__ volatile ("addq\t%r16, %r31, %r17"); + __asm__ volatile ("{nf} addq\t%r16, %r31"); + __asm__ volatile ("setzule\t%al"); + __asm__ volatile ("cfcmoveq\t%r16, %r31"); + __asm__ volatile ("ccmpleq\t{dfv=sf} %r16, %r31"); } } "-mapxf" ] } @@ -11610,6 +11644,9 @@ proc check_vect_support_and_set_flags { } { } elseif [istarget riscv*-*-*] { if [check_effective_target_riscv_v] { set dg-do-what-default run + if [check_effective_target_riscv_v_misalign_ok] { + lappend DEFAULT_VECTCFLAGS "-mno-vector-strict-align" + } } else { foreach item [add_options_for_riscv_v ""] { lappend DEFAULT_VECTCFLAGS $item @@ -12805,15 +12842,6 @@ proc check_effective_target_arm_thumb2_ok_no_arm_v8_1_lob { } { return 0 } -# Return 1 if this is an ARM target where -mabi=ilp32 can be used. - -proc check_effective_target_arm_mabi_ilp32 { } { - return [check_no_compiler_messages_nocache arm_mabi_ilp32 assembly { - int main() { return 0; } - } "-mabi=ilp32"] -} - - # Returns 1 if the target is using glibc, 0 otherwise. proc check_effective_target_glibc { } { diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-class-meta.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-class-meta.mm index e0974539ecf..92852c3ecea 100644 --- a/gcc/testsuite/obj-c++.dg/gnu-api-2-class-meta.mm +++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-class-meta.mm @@ -19,7 +19,6 @@ this behavior may be defined or documented (for example, if class /* { dg-do run } */ /* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */ -/* { dg-skip-if "API unsupported" { arm64*-*-darwin* aarch64*-*-darwin* } { "-fnext-runtime" } { "" } } */ /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ /* { dg-additional-options "-DOBJC_OLD_DISPATCH_PROTOTYPES" { target { *-*-darwin* } } } */ // { dg-additional-options "-Wno-objc-root-class" } diff --git a/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm b/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm index a23968a89b5..f6e3d8d22e0 100644 --- a/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm +++ b/gcc/testsuite/obj-c++.dg/gnu-api-2-class.mm @@ -6,7 +6,6 @@ /* { dg-do run } */ /* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */ -/* { dg-skip-if "API unsupported" { arm64*-*-darwin* aarch64*-*-darwin* } { "-fnext-runtime" } { "" } } */ /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ /* { dg-additional-options "-DOBJC_OLD_DISPATCH_PROTOTYPES" { target { *-*-darwin* } } } */ // { dg-additional-options "-Wno-objc-root-class" } diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-4.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-4.mm index e0dd8062373..1155db5f83f 100644 --- a/gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-4.mm +++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-4.mm @@ -18,4 +18,4 @@ /* { dg-final { scan-assembler ".section __DATA, __cfstring" } } */ /* { dg-final { scan-assembler ".long\t___CFConstantStringClassReference\n\t.long\t1992\n\t.long\t.*\n\t.long\t19\n" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t___CFConstantStringClassReference\n\t.(long|word)\t1992\n\t.space 4\n\t.(quad|xword)\t.*\n\t.(quad|xword)\t19\n} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t___CFConstantStringClassReference\n\t.long\t1992\n\t.space 4\n\t.quad\t.*\n\t.quad\t19\n" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm index eb89710d890..e1dad124cd6 100644 --- a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm +++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm @@ -33,4 +33,4 @@ @interface NSConstantString : NSSimpleCString /* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */ /* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */ /* { dg-final { scan-assembler ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t_OBJC_CLASS_._NSConstantString\n\t.(quad|xword)\t.*\n\t.(long|word)\t5\n\t.space} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._NSConstantString\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm index c1b58dc6cb8..30a9228a64e 100644 --- a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm +++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm @@ -33,4 +33,4 @@ @interface XStr : XString { /* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */ /* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */ /* { dg-final { scan-assembler ".long\t__XStrClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t_OBJC_CLASS_._XStr\n\t.(quad|xword)\t.*\n\t.(long|word)\t5\n\t.space} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._XStr\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm index 8457f46be53..a1a14295e90 100644 --- a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm +++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm @@ -25,4 +25,4 @@ @interface NSConstantString: NSObject { /* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */ /* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */ /* { dg-final { scan-assembler ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t_OBJC_CLASS_._NSConstantString\n\t.(quad|xword)\t.*\n\t.(long|word)\t5\n\t.space} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._NSConstantString\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/testsuite/objc.dg/gnu-api-2-class-meta.m b/gcc/testsuite/objc.dg/gnu-api-2-class-meta.m index 41a48f9c685..6c1c76a87a3 100644 --- a/gcc/testsuite/objc.dg/gnu-api-2-class-meta.m +++ b/gcc/testsuite/objc.dg/gnu-api-2-class-meta.m @@ -19,7 +19,6 @@ this behavior may be defined or documented (for example, if class /* { dg-do run } */ /* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */ -/* { dg-skip-if "API unsupported" { arm64*-*-darwin* aarch64*-*-darwin* } { "-fnext-runtime" } { "" } } */ /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ /* { dg-additional-options "-Wno-objc-root-class" } */ /* { dg-additional-options "-DOBJC_OLD_DISPATCH_PROTOTYPES" { target { *-*-darwin* } } } */ diff --git a/gcc/testsuite/objc.dg/gnu-api-2-class.m b/gcc/testsuite/objc.dg/gnu-api-2-class.m index 1386ebc2f99..d11dae0e6dc 100644 --- a/gcc/testsuite/objc.dg/gnu-api-2-class.m +++ b/gcc/testsuite/objc.dg/gnu-api-2-class.m @@ -6,7 +6,6 @@ /* { dg-do run } */ /* { dg-skip-if "No API#2 pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */ -/* { dg-skip-if "API unsupported" { arm64*-*-darwin* aarch64*-*-darwin* } { "-fnext-runtime" } { "" } } */ /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ /* { dg-additional-options "-Wno-objc-root-class" } */ /* { dg-additional-options "-DOBJC_OLD_DISPATCH_PROTOTYPES" { target { *-*-darwin* } } } */ diff --git a/gcc/testsuite/objc.dg/torture/strings/const-cfstring-4.m b/gcc/testsuite/objc.dg/torture/strings/const-cfstring-4.m index e0dd8062373..1155db5f83f 100644 --- a/gcc/testsuite/objc.dg/torture/strings/const-cfstring-4.m +++ b/gcc/testsuite/objc.dg/torture/strings/const-cfstring-4.m @@ -18,4 +18,4 @@ /* { dg-final { scan-assembler ".section __DATA, __cfstring" } } */ /* { dg-final { scan-assembler ".long\t___CFConstantStringClassReference\n\t.long\t1992\n\t.long\t.*\n\t.long\t19\n" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t___CFConstantStringClassReference\n\t.(long|word)\t1992\n\t.space 4\n\t.(quad|xword)\t.*\n\t.(quad|xword)\t19\n} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t___CFConstantStringClassReference\n\t.long\t1992\n\t.space 4\n\t.quad\t.*\n\t.quad\t19\n" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/testsuite/objc.dg/torture/strings/const-str-10.m b/gcc/testsuite/objc.dg/torture/strings/const-str-10.m index 81b0d326c56..6565dc20007 100644 --- a/gcc/testsuite/objc.dg/torture/strings/const-str-10.m +++ b/gcc/testsuite/objc.dg/torture/strings/const-str-10.m @@ -34,4 +34,4 @@ @interface NSConstantString : NSSimpleCString /* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */ /* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */ /* { dg-final { scan-assembler ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t_OBJC_CLASS_._NSConstantString\n\t.(quad|xword)\t.*\n\t.(long|word)\t5\n\t.space} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._NSConstantString\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/testsuite/objc.dg/torture/strings/const-str-11.m b/gcc/testsuite/objc.dg/torture/strings/const-str-11.m index b044b0fd8c7..2bdb1531e1d 100644 --- a/gcc/testsuite/objc.dg/torture/strings/const-str-11.m +++ b/gcc/testsuite/objc.dg/torture/strings/const-str-11.m @@ -33,4 +33,4 @@ @interface XStr : XString { /* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */ /* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */ /* { dg-final { scan-assembler ".long\t__XStrClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t_OBJC_CLASS_._XStr\n\t.(quad|xword)\t.*\n\t.(long|word)\t5\n\t.space} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._XStr\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/testsuite/objc.dg/torture/strings/const-str-9.m b/gcc/testsuite/objc.dg/torture/strings/const-str-9.m index d3d2916ed06..966ea5e498d 100644 --- a/gcc/testsuite/objc.dg/torture/strings/const-str-9.m +++ b/gcc/testsuite/objc.dg/torture/strings/const-str-9.m @@ -25,4 +25,4 @@ @interface NSConstantString: NSObject { /* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */ /* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */ /* { dg-final { scan-assembler ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */ -/* { dg-final { scan-assembler {.(quad|xword)\t_OBJC_CLASS_._NSConstantString\n\t.(quad|xword)\t.*\n\t.(long|word)\t5\n\t.space} { target { *-*-darwin* && { lp64 } } } } } */ +/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._NSConstantString\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */ diff --git a/gcc/tree-affine.cc b/gcc/tree-affine.cc index 3941a7700b1..d6309c43903 100644 --- a/gcc/tree-affine.cc +++ b/gcc/tree-affine.cc @@ -345,7 +345,7 @@ expr_to_aff_combination (aff_tree *comb, tree_code code, tree type, for below case: (T1)(X *+- CST) -> (T1)X *+- (T1)CST if X *+- CST doesn't overflow by range information. */ - value_range vr; + int_range_max vr; if (TYPE_UNSIGNED (itype) && TYPE_OVERFLOW_WRAPS (itype) && TREE_CODE (op1) == INTEGER_CST diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 9fa74342919..bb5a1303253 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -497,6 +497,15 @@ enum omp_clause_code { /* OpenMP clause: indirect [(constant-integer-expression)]. */ OMP_CLAUSE_INDIRECT, + /* OpenMP clause: partial (constant-integer-expression). */ + OMP_CLAUSE_PARTIAL, + + /* OpenMP clause: full. */ + OMP_CLAUSE_FULL, + + /* OpenMP clause: sizes (constant-integer-expression-list). */ + OMP_CLAUSE_SIZES, + /* Internally used only clause, holding SIMD uid. */ OMP_CLAUSE__SIMDUID_, diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc index 7c4049faf34..7b5f2d16238 100644 --- a/gcc/tree-data-ref.cc +++ b/gcc/tree-data-ref.cc @@ -588,9 +588,9 @@ debug_ddrs (vec ddrs) precision of A and B. */ static bool -compute_distributive_range (tree type, value_range &op0_range, - tree_code code, value_range &op1_range, - tree *off, value_range *result_range) +compute_distributive_range (tree type, irange &op0_range, + tree_code code, irange &op1_range, + tree *off, irange *result_range) { gcc_assert (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type)); if (result_range) @@ -641,7 +641,7 @@ compute_distributive_range (tree type, value_range &op0_range, but its range is more conducive to analysis. */ range_cast (op0_range, ssizetype); range_cast (op1_range, ssizetype); - value_range wide_range; + int_range_max wide_range; range_op_handler op (code); bool saved_flag_wrapv = flag_wrapv; flag_wrapv = 1; @@ -682,7 +682,7 @@ compute_distributive_range (tree type, value_range &op0_range, FROM_TYPE are integral types. */ static bool -nop_conversion_for_offset_p (tree to_type, tree from_type, value_range &range) +nop_conversion_for_offset_p (tree to_type, tree from_type, irange &range) { gcc_assert (INTEGRAL_TYPE_P (to_type) && INTEGRAL_TYPE_P (from_type) @@ -714,7 +714,7 @@ nop_conversion_for_offset_p (tree to_type, tree from_type, value_range &range) static void split_constant_offset (tree type, tree *var, tree *off, - value_range *result_range, + irange *result_range, hash_map > &cache, unsigned *limit); @@ -751,13 +751,13 @@ split_constant_offset (tree type, tree *var, tree *off, static bool split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, - tree *var, tree *off, value_range *result_range, + tree *var, tree *off, irange *result_range, hash_map > &cache, unsigned *limit) { tree var0, var1; tree off0, off1; - value_range op0_range, op1_range; + int_range_max op0_range, op1_range; *var = NULL_TREE; *off = NULL_TREE; @@ -1013,7 +1013,7 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, allowed to process before giving up. */ static void -split_constant_offset (tree exp, tree *var, tree *off, value_range *exp_range, +split_constant_offset (tree exp, tree *var, tree *off, irange *exp_range, hash_map > &cache, unsigned *limit) { @@ -1023,10 +1023,10 @@ split_constant_offset (tree exp, tree *var, tree *off, value_range *exp_range, code = TREE_CODE (exp); if (exp_range) { - *exp_range = type; + exp_range->set_varying (type); if (code == SSA_NAME) { - value_range vr; + int_range_max vr; get_range_query (cfun)->range_of_expr (vr, exp); if (vr.undefined_p ()) vr.set_varying (TREE_TYPE (exp)); @@ -1044,7 +1044,7 @@ split_constant_offset (tree exp, tree *var, tree *off, value_range *exp_range, domain, instead of VR_VARYING. The new code normalizes full-domain ranges to VR_VARYING. */ if (vr_kind == VR_RANGE || vr_kind == VR_VARYING) - *exp_range = value_range (type, var_min, var_max); + exp_range->set (type, var_min, var_max); } } @@ -1062,7 +1062,7 @@ split_constant_offset (tree exp, tree *var, tree *off, value_range *exp_range, *var = fold_convert (sizetype, *var); *off = ssize_int (0); - value_range r; + int_range_max r; if (exp_range && code != SSA_NAME && get_range_query (cfun)->range_of_expr (r, exp) && !r.undefined_p ()) @@ -6402,7 +6402,7 @@ dr_step_indicator (struct data_reference *dr, int useful_min) /* Get the range of values that the unconverted step actually has. */ wide_int step_min, step_max; - value_range vr; + int_range_max vr; if (TREE_CODE (step) != SSA_NAME || !get_range_query (cfun)->range_of_expr (vr, step) || vr.undefined_p ()) diff --git a/gcc/tree-dfa.cc b/gcc/tree-dfa.cc index 93e53b29a6d..77e119a6b1b 100644 --- a/gcc/tree-dfa.cc +++ b/gcc/tree-dfa.cc @@ -530,7 +530,7 @@ get_ref_base_and_extent (tree exp, poly_int64 *poffset, index. */ seen_variable_array_ref = true; - value_range vr; + int_range_max vr; range_query *query; query = get_range_query (cfun); diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index f9ad8562078..601cf215ca8 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -1461,6 +1461,25 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) spc, flags, false); pp_right_paren (pp); break; + case OMP_CLAUSE_PARTIAL: + pp_string (pp, "partial"); + if (OMP_CLAUSE_PARTIAL_EXPR (clause)) + { + pp_left_paren (pp); + dump_generic_node (pp, OMP_CLAUSE_PARTIAL_EXPR (clause), + spc, flags, false); + pp_right_paren (pp); + } + break; + case OMP_CLAUSE_FULL: + pp_string (pp, "full"); + break; + case OMP_CLAUSE_SIZES: + pp_string (pp, "sizes("); + dump_generic_node (pp, OMP_CLAUSE_SIZES_LIST (clause), + spc, flags, false); + pp_right_paren (pp); + break; case OMP_CLAUSE_IF_PRESENT: pp_string (pp, "if_present"); @@ -3796,6 +3815,14 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, pp_string (pp, "#pragma omp loop"); goto dump_omp_loop; + case OMP_TILE: + pp_string (pp, "#pragma omp tile"); + goto dump_omp_loop; + + case OMP_UNROLL: + pp_string (pp, "#pragma omp unroll"); + goto dump_omp_loop; + case OACC_LOOP: pp_string (pp, "#pragma acc loop"); goto dump_omp_loop; @@ -3853,6 +3880,8 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, spc -= 2; for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (node)); i++) { + if (TREE_VEC_ELT (OMP_FOR_INIT (node), i) == NULL_TREE) + continue; spc += 2; newline_and_indent (pp, spc); pp_string (pp, "for ("); diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc index 622c7246c1b..5aa95a2497a 100644 --- a/gcc/tree-scalar-evolution.cc +++ b/gcc/tree-scalar-evolution.cc @@ -3057,7 +3057,7 @@ iv_can_overflow_p (class loop *loop, tree type, tree base, tree step) widest_int nit; wide_int base_min, base_max, step_min, step_max, type_min, type_max; signop sgn = TYPE_SIGN (type); - value_range r; + int_range_max r; if (integer_zerop (step)) return false; diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc index 62da1c5ee08..173b0366f5e 100644 --- a/gcc/tree-ssa-math-opts.cc +++ b/gcc/tree-ssa-math-opts.cc @@ -4087,33 +4087,103 @@ arith_overflow_check_p (gimple *stmt, gimple *cast_stmt, gimple *&use_stmt, } extern bool gimple_unsigned_integer_sat_add (tree, tree*, tree (*)(tree)); +extern bool gimple_unsigned_integer_sat_sub (tree, tree*, tree (*)(tree)); + +static void +build_saturation_binary_arith_call (gimple_stmt_iterator *gsi, internal_fn fn, + tree lhs, tree op_0, tree op_1) +{ + if (direct_internal_fn_supported_p (fn, TREE_TYPE (lhs), OPTIMIZE_FOR_BOTH)) + { + gcall *call = gimple_build_call_internal (fn, 2, op_0, op_1); + gimple_call_set_lhs (call, lhs); + gsi_replace (gsi, call, /* update_eh_info */ true); + } +} + +static void +build_saturation_binary_arith_call (gimple_stmt_iterator *gsi, gphi *phi, + internal_fn fn, tree lhs, tree op_0, + tree op_1) +{ + if (direct_internal_fn_supported_p (fn, TREE_TYPE (lhs), OPTIMIZE_FOR_BOTH)) + { + gcall *call = gimple_build_call_internal (fn, 2, op_0, op_1); + gimple_call_set_lhs (call, lhs); + gsi_insert_before (gsi, call, GSI_SAME_STMT); + + gimple_stmt_iterator psi = gsi_for_stmt (phi); + remove_phi_node (&psi, /* release_lhs_p */ false); + } +} + +/* + * Try to match saturation unsigned add with assign. + * _7 = _4 + _6; + * _8 = _4 > _7; + * _9 = (long unsigned int) _8; + * _10 = -_9; + * _12 = _7 | _10; + * => + * _12 = .SAT_ADD (_4, _6); */ + +static void +match_unsigned_saturation_add (gimple_stmt_iterator *gsi, gassign *stmt) +{ + tree ops[2]; + tree lhs = gimple_assign_lhs (stmt); + + if (gimple_unsigned_integer_sat_add (lhs, ops, NULL)) + build_saturation_binary_arith_call (gsi, IFN_SAT_ADD, lhs, ops[0], ops[1]); +} /* - * Try to match saturation arith pattern(s). - * 1. SAT_ADD (unsigned) - * _7 = _4 + _6; - * _8 = _4 > _7; - * _9 = (long unsigned int) _8; - * _10 = -_9; - * _12 = _7 | _10; - * => - * _12 = .SAT_ADD (_4, _6); */ + * Try to match saturation unsigned add with PHI. + * : + * _1 = x_3(D) + y_4(D); + * if (_1 >= x_3(D)) + * goto ; [INV] + * else + * goto ; [INV] + * + * : + * + * : + * # _2 = PHI <255(2), _1(3)> + * => + * [local count: 1073741824]: + * _2 = .SAT_ADD (x_4(D), y_5(D)); */ + static void -match_saturation_arith (gimple_stmt_iterator *gsi, gassign *stmt) +match_unsigned_saturation_add (gimple_stmt_iterator *gsi, gphi *phi) { - gcall *call = NULL; + if (gimple_phi_num_args (phi) != 2) + return; + tree ops[2]; + tree phi_result = gimple_phi_result (phi); + + if (gimple_unsigned_integer_sat_add (phi_result, ops, NULL)) + build_saturation_binary_arith_call (gsi, phi, IFN_SAT_ADD, phi_result, + ops[0], ops[1]); +} + +/* + * Try to match saturation unsigned sub. + * _1 = _4 >= _5; + * _3 = _4 - _5; + * _6 = _1 ? _3 : 0; + * => + * _6 = .SAT_SUB (_4, _5); */ + +static void +match_unsigned_saturation_sub (gimple_stmt_iterator *gsi, gassign *stmt) +{ tree ops[2]; tree lhs = gimple_assign_lhs (stmt); - if (gimple_unsigned_integer_sat_add (lhs, ops, NULL) - && direct_internal_fn_supported_p (IFN_SAT_ADD, TREE_TYPE (lhs), - OPTIMIZE_FOR_BOTH)) - { - call = gimple_build_call_internal (IFN_SAT_ADD, 2, ops[0], ops[1]); - gimple_call_set_lhs (call, lhs); - gsi_replace (gsi, call, true); - } + if (gimple_unsigned_integer_sat_sub (lhs, ops, NULL)) + build_saturation_binary_arith_call (gsi, IFN_SAT_SUB, lhs, ops[0], ops[1]); } /* Recognize for unsigned x @@ -5956,7 +6026,7 @@ optimize_spaceship (gcond *stmt) wide_int wm1 = wi::minus_one (TYPE_PRECISION (integer_type_node)); wide_int w2 = wi::two (TYPE_PRECISION (integer_type_node)); - value_range vr (TREE_TYPE (lhs), wm1, w2); + int_range<1> vr (TREE_TYPE (lhs), wm1, w2); set_range_info (lhs, vr); } @@ -6029,6 +6099,13 @@ math_opts_dom_walker::after_dom_children (basic_block bb) fma_deferring_state fma_state (param_avoid_fma_max_bits > 0); + for (gphi_iterator psi = gsi_start_phis (bb); !gsi_end_p (psi); + gsi_next (&psi)) + { + gimple_stmt_iterator gsi = gsi_last_bb (bb); + match_unsigned_saturation_add (&gsi, psi.phi ()); + } + for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi);) { gimple *stmt = gsi_stmt (gsi); @@ -6078,7 +6155,7 @@ math_opts_dom_walker::after_dom_children (basic_block bb) break; case BIT_IOR_EXPR: - match_saturation_arith (&gsi, as_a (stmt)); + match_unsigned_saturation_add (&gsi, as_a (stmt)); /* fall-through */ case BIT_XOR_EXPR: match_uaddc_usubc (&gsi, stmt, code); @@ -6089,6 +6166,10 @@ math_opts_dom_walker::after_dom_children (basic_block bb) match_single_bit_test (&gsi, stmt); break; + case COND_EXPR: + match_unsigned_saturation_sub (&gsi, as_a (stmt)); + break; + default:; } } diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc index 5cf1968bc26..6c0436b8b15 100644 --- a/gcc/tree-ssa-pre.cc +++ b/gcc/tree-ssa-pre.cc @@ -3251,7 +3251,7 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum, >= TYPE_PRECISION (TREE_TYPE (expr->u.nary->op[0]))) && SSA_NAME_RANGE_INFO (expr->u.nary->op[0])) { - value_range r; + int_range_max r; if (get_range_query (cfun)->range_of_expr (r, expr->u.nary->op[0]) && !r.undefined_p () && !r.varying_p () diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc index 556ecdebe2d..4d9f5216d4c 100644 --- a/gcc/tree-ssa-reassoc.cc +++ b/gcc/tree-ssa-reassoc.cc @@ -3377,7 +3377,7 @@ optimize_range_tests_to_bit_test (enum tree_code opcode, int first, int length, case, if we would need otherwise 2 or more comparisons, then use the bit test; in the other cases, the threshold is 3 comparisons. */ bool entry_test_needed; - value_range r; + int_range_max r; if (TREE_CODE (exp) == SSA_NAME && get_range_query (cfun)->range_of_expr (r, exp) && !r.undefined_p () diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc index c43a2da2836..d3c7dc3a80f 100644 --- a/gcc/tree-ssa-strlen.cc +++ b/gcc/tree-ssa-strlen.cc @@ -347,7 +347,7 @@ compare_nonzero_chars (strinfo *si, gimple *stmt, if (!rvals || TREE_CODE (si->nonzero_chars) != SSA_NAME) return -1; - value_range vr; + int_range_max vr; if (!rvals->range_of_expr (vr, si->nonzero_chars, stmt) || vr.varying_p () || vr.undefined_p ()) @@ -980,7 +980,7 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals) print_generic_expr (fp, si->nonzero_chars); if (TREE_CODE (si->nonzero_chars) == SSA_NAME) { - value_range vr; + int_range_max vr; if (rvals) rvals->range_of_expr (vr, si->nonzero_chars, si->stmt); @@ -1218,7 +1218,7 @@ get_range_strlen_dynamic (tree src, gimple *stmt, pdata->minlen = si->nonzero_chars; else if (TREE_CODE (si->nonzero_chars) == SSA_NAME) { - value_range vr; + int_range_max vr; ptr_qry->rvals->range_of_expr (vr, si->nonzero_chars, si->stmt); if (vr.undefined_p () || vr.varying_p ()) pdata->minlen = build_zero_cst (size_type_node); @@ -1274,7 +1274,7 @@ get_range_strlen_dynamic (tree src, gimple *stmt, } else if (pdata->minlen && TREE_CODE (pdata->minlen) == SSA_NAME) { - value_range vr; + int_range_max vr; ptr_qry->rvals->range_of_expr (vr, si->nonzero_chars, stmt); if (vr.varying_p () || vr.undefined_p ()) { @@ -1919,7 +1919,7 @@ set_strlen_range (tree lhs, wide_int min, wide_int max, } else if (TREE_CODE (bound) == SSA_NAME) { - value_range r; + int_range_max r; get_range_query (cfun)->range_of_expr (r, bound); if (!r.undefined_p ()) { @@ -1937,7 +1937,7 @@ set_strlen_range (tree lhs, wide_int min, wide_int max, if (min == max) return wide_int_to_tree (size_type_node, min); - value_range vr (TREE_TYPE (lhs), min, max); + int_range_max vr (TREE_TYPE (lhs), min, max); set_range_info (lhs, vr); return lhs; } @@ -2900,7 +2900,7 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt, return false; wide_int cntrange[2]; - value_range r; + int_range_max r; if (!get_range_query (cfun)->range_of_expr (r, cnt) || r.varying_p () || r.undefined_p ()) @@ -4075,7 +4075,7 @@ strlen_pass::get_len_or_size (gimple *stmt, tree arg, int idx, } else if (TREE_CODE (si->nonzero_chars) == SSA_NAME) { - value_range r; + int_range_max r; if (get_range_query (cfun)->range_of_expr (r, si->nonzero_chars) && !r.undefined_p () && !r.varying_p ()) @@ -4370,7 +4370,7 @@ strlen_pass::handle_builtin_string_cmp () known to be unequal set the range of the result to non-zero. This allows the call to be eliminated if its result is only used in tests for equality to zero. */ - value_range nz; + int_range_max nz; nz.set_nonzero (TREE_TYPE (lhs)); set_range_info (lhs, nz); return false; @@ -4807,7 +4807,7 @@ strlen_pass::count_nonzero_bytes_addr (tree exp, tree vuse, gimple *stmt, else if (si->nonzero_chars && TREE_CODE (si->nonzero_chars) == SSA_NAME) { - value_range vr; + int_range_max vr; if (!ptr_qry.rvals->range_of_expr (vr, si->nonzero_chars, stmt) || vr.undefined_p () || vr.varying_p ()) @@ -5567,7 +5567,7 @@ strlen_pass::handle_integral_assign (bool *cleanup_eh) /* Reading a character before the final '\0' character. Just set the value range to ~[0, 0] if we don't have anything better. */ - value_range r; + int_range_max r; if (!get_range_query (cfun)->range_of_expr (r, lhs) || r.varying_p ()) { diff --git a/gcc/tree-switch-conversion.cc b/gcc/tree-switch-conversion.cc index 3a5b84c09e2..64629122ec6 100644 --- a/gcc/tree-switch-conversion.cc +++ b/gcc/tree-switch-conversion.cc @@ -1662,7 +1662,7 @@ bit_test_cluster::emit (tree index_expr, tree index_type, /* If every possible relative value of the index expression is a valid shift amount, then we can merge the entry test in the bit test. */ bool entry_test_needed; - value_range r; + int_range_max r; if (TREE_CODE (index_expr) == SSA_NAME && get_range_query (cfun)->range_of_expr (r, index_expr) && !r.undefined_p () diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index 43c7881c640..ac13873cd88 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -2845,25 +2845,25 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters, { if (niters_no_overflow) { - value_range vr (type, - wi::one (TYPE_PRECISION (type)), - wi::rshift (wi::max_value (TYPE_PRECISION (type), - TYPE_SIGN (type)), - exact_log2 (const_vf), - TYPE_SIGN (type))); + int_range<1> vr (type, + wi::one (TYPE_PRECISION (type)), + wi::rshift (wi::max_value (TYPE_PRECISION (type), + TYPE_SIGN (type)), + exact_log2 (const_vf), + TYPE_SIGN (type))); set_range_info (niters_vector, vr); } /* For VF == 1 the vector IV might also overflow so we cannot assert a minimum value of 1. */ else if (const_vf > 1) { - value_range vr (type, - wi::one (TYPE_PRECISION (type)), - wi::rshift (wi::max_value (TYPE_PRECISION (type), - TYPE_SIGN (type)) - - (const_vf - 1), - exact_log2 (const_vf), TYPE_SIGN (type)) - + 1); + int_range<1> vr (type, + wi::one (TYPE_PRECISION (type)), + wi::rshift (wi::max_value (TYPE_PRECISION (type), + TYPE_SIGN (type)) + - (const_vf - 1), + exact_log2 (const_vf), TYPE_SIGN (type)) + + 1); set_range_info (niters_vector, vr); } } @@ -3408,9 +3408,9 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1, least VF, so set range information for newly generated var. */ if (new_var_p) { - value_range vr (type, - wi::to_wide (build_int_cst (type, lowest_vf)), - wi::to_wide (TYPE_MAX_VALUE (type))); + int_range<1> vr (type, + wi::to_wide (build_int_cst (type, lowest_vf)), + wi::to_wide (TYPE_MAX_VALUE (type))); set_range_info (niters, vr); } diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 5b85cffb37f..028692614bb 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -685,6 +685,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, class loop *loop, STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_double_reduction_def; STMT_VINFO_DEF_TYPE (reduc_stmt_info) = vect_double_reduction_def; + /* Make it accessible for SLP vectorization. */ + LOOP_VINFO_REDUCTIONS (loop_vinfo).safe_push (reduc_stmt_info); } else { @@ -3485,7 +3487,7 @@ vect_analyze_loop_1 (class loop *loop, vec_info_shared *shared, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "***** Analysis %s with vector mode %s\n", - res ? "succeeded" : " failed", + res ? "succeeded" : "failed", GET_MODE_NAME (loop_vinfo->vector_mode)); if (res && !main_loop_vinfo && suggested_unroll_factor > 1) @@ -5606,6 +5608,12 @@ get_initial_defs_for_reduction (loop_vec_info loop_vinfo, tree_vector_builder elts (vector_type, nunits, 1); elts.quick_grow (nunits); gimple_seq ctor_seq = NULL; + if (neutral_op + && !useless_type_conversion_p (TREE_TYPE (vector_type), + TREE_TYPE (neutral_op))) + neutral_op = gimple_convert (&ctor_seq, + TREE_TYPE (vector_type), + neutral_op); for (j = 0; j < nunits * number_of_vectors; ++j) { tree op; @@ -5614,14 +5622,7 @@ get_initial_defs_for_reduction (loop_vec_info loop_vinfo, /* Get the def before the loop. In reduction chain we have only one initial value. Else we have as many as PHIs in the group. */ if (i >= initial_values.length () || (j > i && neutral_op)) - { - if (!useless_type_conversion_p (TREE_TYPE (vector_type), - TREE_TYPE (neutral_op))) - neutral_op = gimple_convert (&ctor_seq, - TREE_TYPE (vector_type), - neutral_op); - op = neutral_op; - } + op = neutral_op; else { if (!useless_type_conversion_p (TREE_TYPE (vector_type), @@ -5976,7 +5977,6 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, stmt_vec_info rdef_info = stmt_info; if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def) { - gcc_assert (!slp_node); double_reduc = true; stmt_info = loop_vinfo->lookup_def (gimple_phi_arg_def (stmt_info->stmt, 0)); @@ -6021,7 +6021,7 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, { outer_loop = loop; loop = loop->inner; - gcc_assert (!slp_node && double_reduc); + gcc_assert (double_reduc); } vectype = STMT_VINFO_REDUC_VECTYPE (reduc_info); @@ -6031,7 +6031,13 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, tree induc_val = NULL_TREE; tree adjustment_def = NULL; if (slp_node) - ; + { + /* Optimize: for induction condition reduction, if we can't use zero + for induc_val, use initial_def. */ + if (STMT_VINFO_REDUC_TYPE (reduc_info) == INTEGER_INDUC_COND_REDUCTION) + induc_val = STMT_VINFO_VEC_INDUC_COND_INITIAL_VAL (reduc_info); + /* ??? Coverage for 'else' isn't clear. */ + } else { /* Optimize: for induction condition reduction, if we can't use zero @@ -6076,23 +6082,46 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, if (STMT_VINFO_REDUC_TYPE (reduc_info) == COND_REDUCTION) { auto_vec, 2> ccompares; - stmt_vec_info cond_info = STMT_VINFO_REDUC_DEF (reduc_info); - cond_info = vect_stmt_to_vectorize (cond_info); - while (cond_info != reduc_info) + if (slp_node) { - if (gimple_assign_rhs_code (cond_info->stmt) == COND_EXPR) + slp_tree cond_node = slp_node_instance->root; + while (cond_node != slp_node_instance->reduc_phis) { - gimple *vec_stmt = STMT_VINFO_VEC_STMTS (cond_info)[0]; - gcc_assert (gimple_assign_rhs_code (vec_stmt) == VEC_COND_EXPR); - ccompares.safe_push - (std::make_pair (unshare_expr (gimple_assign_rhs1 (vec_stmt)), - STMT_VINFO_REDUC_IDX (cond_info) == 2)); + stmt_vec_info cond_info = SLP_TREE_REPRESENTATIVE (cond_node); + if (gimple_assign_rhs_code (cond_info->stmt) == COND_EXPR) + { + gimple *vec_stmt + = SSA_NAME_DEF_STMT (SLP_TREE_VEC_DEFS (cond_node)[0]); + gcc_assert (gimple_assign_rhs_code (vec_stmt) == VEC_COND_EXPR); + ccompares.safe_push + (std::make_pair (gimple_assign_rhs1 (vec_stmt), + STMT_VINFO_REDUC_IDX (cond_info) == 2)); + } + /* ??? We probably want to have REDUC_IDX on the SLP node? */ + cond_node = SLP_TREE_CHILDREN + (cond_node)[STMT_VINFO_REDUC_IDX (cond_info)]; } - cond_info - = loop_vinfo->lookup_def (gimple_op (cond_info->stmt, - 1 + STMT_VINFO_REDUC_IDX - (cond_info))); + } + else + { + stmt_vec_info cond_info = STMT_VINFO_REDUC_DEF (reduc_info); cond_info = vect_stmt_to_vectorize (cond_info); + while (cond_info != reduc_info) + { + if (gimple_assign_rhs_code (cond_info->stmt) == COND_EXPR) + { + gimple *vec_stmt = STMT_VINFO_VEC_STMTS (cond_info)[0]; + gcc_assert (gimple_assign_rhs_code (vec_stmt) == VEC_COND_EXPR); + ccompares.safe_push + (std::make_pair (gimple_assign_rhs1 (vec_stmt), + STMT_VINFO_REDUC_IDX (cond_info) == 2)); + } + cond_info + = loop_vinfo->lookup_def (gimple_op (cond_info->stmt, + 1 + STMT_VINFO_REDUC_IDX + (cond_info))); + cond_info = vect_stmt_to_vectorize (cond_info); + } } gcc_assert (ccompares.length () != 0); @@ -6505,7 +6534,7 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, /* 2.3 Create the reduction code, using one of the three schemes described above. In SLP we simply need to extract all the elements from the vector (without reducing them), so we use scalar shifts. */ - else if (reduc_fn != IFN_LAST && !slp_reduc) + else if (reduc_fn != IFN_LAST && (!slp_reduc || group_size == 1)) { tree tmp; tree vec_elem_type; @@ -6675,7 +6704,7 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, gsi_insert_seq_before (&exit_gsi, stmts, GSI_SAME_STMT); reduc_inputs[0] = new_temp; - if (reduce_with_shift && !slp_reduc) + if (reduce_with_shift && (!slp_reduc || group_size == 1)) { int element_bitsize = tree_to_uhwi (bitsize); /* Enforced by vectorizable_reduction, which disallows SLP reductions @@ -7110,56 +7139,46 @@ vectorize_fold_left_reduction (loop_vec_info loop_vinfo, gcc_assert (TREE_CODE_LENGTH (tree_code (code)) == binary_op); if (slp_node) - { - if (is_cond_op) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "fold-left reduction on SLP not supported.\n"); - return false; - } - - gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (vectype_out), - TYPE_VECTOR_SUBPARTS (vectype_in))); - } + gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (vectype_out), + TYPE_VECTOR_SUBPARTS (vectype_in))); /* The operands either come from a binary operation or an IFN_COND operation. The former is a gimple assign with binary rhs and the latter is a gimple call with four arguments. */ gcc_assert (num_ops == 2 || num_ops == 4); - tree op0, opmask; - if (!is_cond_op) - op0 = ops[1 - reduc_index]; - else - { - op0 = ops[2 + (1 - reduc_index)]; - opmask = ops[0]; - gcc_assert (!slp_node); - } int group_size = 1; stmt_vec_info scalar_dest_def_info; auto_vec vec_oprnds0, vec_opmask; if (slp_node) { - auto_vec > vec_defs (2); - vect_get_slp_defs (loop_vinfo, slp_node, &vec_defs); - vec_oprnds0.safe_splice (vec_defs[1 - reduc_index]); - vec_defs[0].release (); - vec_defs[1].release (); + vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[(is_cond_op ? 2 : 0) + + (1 - reduc_index)], + &vec_oprnds0); group_size = SLP_TREE_SCALAR_STMTS (slp_node).length (); scalar_dest_def_info = SLP_TREE_SCALAR_STMTS (slp_node)[group_size - 1]; + /* For an IFN_COND_OP we also need the vector mask operand. */ + if (is_cond_op) + vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[0], &vec_opmask); } else { + tree op0, opmask; + if (!is_cond_op) + op0 = ops[1 - reduc_index]; + else + { + op0 = ops[2 + (1 - reduc_index)]; + opmask = ops[0]; + } vect_get_vec_defs_for_operand (loop_vinfo, stmt_info, 1, op0, &vec_oprnds0); scalar_dest_def_info = stmt_info; /* For an IFN_COND_OP we also need the vector mask operand. */ if (is_cond_op) - vect_get_vec_defs_for_operand (loop_vinfo, stmt_info, 1, - opmask, &vec_opmask); + vect_get_vec_defs_for_operand (loop_vinfo, stmt_info, 1, + opmask, &vec_opmask); } gimple *sdef = vect_orig_stmt (scalar_dest_def_info)->stmt; @@ -7198,7 +7217,7 @@ vectorize_fold_left_reduction (loop_vec_info loop_vinfo, if (LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)) mask = vect_get_loop_mask (loop_vinfo, gsi, masks, vec_num, vectype_in, i); else if (is_cond_op) - mask = vec_opmask[0]; + mask = vec_opmask[i]; if (LOOP_VINFO_FULLY_WITH_LENGTH_P (loop_vinfo)) { len = vect_get_loop_len (loop_vinfo, gsi, lens, vec_num, vectype_in, @@ -7577,15 +7596,16 @@ vectorizable_reduction (loop_vec_info loop_vinfo, STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type; return true; } - if (slp_node) - { - slp_node_instance->reduc_phis = slp_node; - /* ??? We're leaving slp_node to point to the PHIs, we only - need it to get at the number of vector stmts which wasn't - yet initialized for the instance root. */ - } if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def) { + if (gimple_bb (stmt_info->stmt) != loop->header) + { + /* For SLP we arrive here for both the inner loop LC PHI and + the outer loop PHI. The latter is what we want to analyze + the reduction with. */ + gcc_assert (slp_node); + return true; + } use_operand_p use_p; gimple *use_stmt; bool res = single_imm_use (gimple_phi_result (stmt_info->stmt), @@ -7594,6 +7614,14 @@ vectorizable_reduction (loop_vec_info loop_vinfo, phi_info = loop_vinfo->lookup_stmt (use_stmt); } + if (slp_node) + { + slp_node_instance->reduc_phis = slp_node; + /* ??? We're leaving slp_node to point to the PHIs, we only + need it to get at the number of vector stmts which wasn't + yet initialized for the instance root. */ + } + /* PHIs should not participate in patterns. */ gcc_assert (!STMT_VINFO_RELATED_STMT (phi_info)); gphi *reduc_def_phi = as_a (phi_info->stmt); @@ -7609,6 +7637,11 @@ vectorizable_reduction (loop_vec_info loop_vinfo, bool only_slp_reduc_chain = true; stmt_info = NULL; slp_tree slp_for_stmt_info = slp_node ? slp_node_instance->root : NULL; + /* For double-reductions we start SLP analysis at the inner loop LC PHI + which is the def of the outer loop live stmt. */ + if (STMT_VINFO_DEF_TYPE (reduc_info) == vect_double_reduction_def + && slp_node) + slp_for_stmt_info = SLP_TREE_CHILDREN (slp_for_stmt_info)[0]; while (reduc_def != PHI_RESULT (reduc_def_phi)) { stmt_vec_info def = loop_vinfo->lookup_def (reduc_def); @@ -7845,7 +7878,7 @@ vectorizable_reduction (loop_vec_info loop_vinfo, /* If we have a condition reduction, see if we can simplify it further. */ if (v_reduc_type == COND_REDUCTION) { - if (slp_node) + if (slp_node && SLP_TREE_LANES (slp_node) != 1) return false; /* When the condition uses the reduction value in the condition, fail. */ @@ -8051,6 +8084,18 @@ vectorizable_reduction (loop_vec_info loop_vinfo, } } + if ((reduction_type == COND_REDUCTION + || reduction_type == INTEGER_INDUC_COND_REDUCTION + || reduction_type == CONST_COND_REDUCTION) + && slp_node + && SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) > 1) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "multiple types in condition reduction reduction.\n"); + return false; + } + if ((double_reduc || reduction_type != TREE_CODE_REDUCTION) && ncopies > 1) { @@ -8155,7 +8200,7 @@ vectorizable_reduction (loop_vec_info loop_vinfo, } if (reduction_type == FOLD_LEFT_REDUCTION - && slp_node + && (slp_node && SLP_TREE_LANES (slp_node) > 1) && !REDUC_GROUP_FIRST_ELEMENT (stmt_info)) { /* We cannot use in-order reductions in this case because there is @@ -8766,7 +8811,31 @@ vect_transform_cycle_phi (loop_vec_info loop_vinfo, if (slp_node) { vec_initial_defs.reserve (vec_num); - if (nested_cycle) + /* Optimize: if initial_def is for REDUC_MAX smaller than the base + and we can't use zero for induc_val, use initial_def. Similarly + for REDUC_MIN and initial_def larger than the base. */ + if (STMT_VINFO_REDUC_TYPE (reduc_info) == INTEGER_INDUC_COND_REDUCTION) + { + gcc_assert (SLP_TREE_LANES (slp_node) == 1); + tree initial_def = vect_phi_initial_value (phi); + reduc_info->reduc_initial_values.safe_push (initial_def); + tree induc_val = STMT_VINFO_VEC_INDUC_COND_INITIAL_VAL (reduc_info); + if (TREE_CODE (initial_def) == INTEGER_CST + && !integer_zerop (induc_val) + && ((STMT_VINFO_REDUC_CODE (reduc_info) == MAX_EXPR + && tree_int_cst_lt (initial_def, induc_val)) + || (STMT_VINFO_REDUC_CODE (reduc_info) == MIN_EXPR + && tree_int_cst_lt (induc_val, initial_def)))) + { + induc_val = initial_def; + /* Communicate we used the initial_def to epilouge + generation. */ + STMT_VINFO_VEC_INDUC_COND_INITIAL_VAL (reduc_info) = NULL_TREE; + } + vec_initial_defs.quick_push + (build_vector_from_val (vectype_out, induc_val)); + } + else if (nested_cycle) { unsigned phi_idx = loop_preheader_edge (loop)->dest_idx; vect_get_slp_defs (SLP_TREE_CHILDREN (slp_node)[phi_idx], diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 88e7e34d78d..cef901808eb 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -66,7 +66,7 @@ along with GCC; see the file COPYING3. If not see bool vect_get_range_info (tree var, wide_int *min_value, wide_int *max_value) { - value_range vr; + int_range_max vr; tree vr_min, vr_max; get_range_query (cfun)->range_of_expr (vr, var); if (vr.undefined_p ()) @@ -4488,6 +4488,32 @@ vect_recog_mult_pattern (vec_info *vinfo, } extern bool gimple_unsigned_integer_sat_add (tree, tree*, tree (*)(tree)); +extern bool gimple_unsigned_integer_sat_sub (tree, tree*, tree (*)(tree)); + +static gcall * +vect_recog_build_binary_gimple_call (vec_info *vinfo, gimple *stmt, + internal_fn fn, tree *type_out, + tree op_0, tree op_1) +{ + tree itype = TREE_TYPE (op_0); + tree vtype = get_vectype_for_scalar_type (vinfo, itype); + + if (vtype != NULL_TREE + && direct_internal_fn_supported_p (fn, vtype, OPTIMIZE_FOR_BOTH)) + { + gcall *call = gimple_build_call_internal (fn, 2, op_0, op_1); + + gimple_call_set_lhs (call, vect_recog_temp_ssa_var (itype, NULL)); + gimple_call_set_nothrow (call, /* nothrow_p */ false); + gimple_set_location (call, gimple_location (stmt)); + + *type_out = vtype; + + return call; + } + + return NULL; +} /* * Try to detect saturation add pattern (SAT_ADD), aka below gimple: @@ -4510,27 +4536,55 @@ vect_recog_sat_add_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo, if (!is_gimple_assign (last_stmt)) return NULL; - tree res_ops[2]; + tree ops[2]; tree lhs = gimple_assign_lhs (last_stmt); - if (gimple_unsigned_integer_sat_add (lhs, res_ops, NULL)) + if (gimple_unsigned_integer_sat_add (lhs, ops, NULL)) { - tree itype = TREE_TYPE (res_ops[0]); - tree vtype = get_vectype_for_scalar_type (vinfo, itype); - - if (vtype != NULL_TREE - && direct_internal_fn_supported_p (IFN_SAT_ADD, vtype, - OPTIMIZE_FOR_BOTH)) + gcall *call = vect_recog_build_binary_gimple_call (vinfo, last_stmt, + IFN_SAT_ADD, type_out, + ops[0], ops[1]); + if (call) { - *type_out = vtype; - gcall *call = gimple_build_call_internal (IFN_SAT_ADD, 2, res_ops[0], - res_ops[1]); + vect_pattern_detected ("vect_recog_sat_add_pattern", last_stmt); + return call; + } + } + + return NULL; +} - gimple_call_set_lhs (call, vect_recog_temp_ssa_var (itype, NULL)); - gimple_call_set_nothrow (call, /* nothrow_p */ false); - gimple_set_location (call, gimple_location (last_stmt)); +/* + * Try to detect saturation sub pattern (SAT_ADD), aka below gimple: + * _7 = _1 >= _2; + * _8 = _1 - _2; + * _10 = (long unsigned int) _7; + * _9 = _8 * _10; + * + * And then simplied to + * _9 = .SAT_SUB (_1, _2); + */ - vect_pattern_detected ("vect_recog_sat_add_pattern", last_stmt); +static gimple * +vect_recog_sat_sub_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo, + tree *type_out) +{ + gimple *last_stmt = STMT_VINFO_STMT (stmt_vinfo); + + if (!is_gimple_assign (last_stmt)) + return NULL; + + tree ops[2]; + tree lhs = gimple_assign_lhs (last_stmt); + + if (gimple_unsigned_integer_sat_sub (lhs, ops, NULL)) + { + gcall *call = vect_recog_build_binary_gimple_call (vinfo, last_stmt, + IFN_SAT_SUB, type_out, + ops[0], ops[1]); + if (call) + { + vect_pattern_detected ("vect_recog_sat_sub_pattern", last_stmt); return call; } } @@ -5011,7 +5065,7 @@ vect_recog_divmod_pattern (vec_info *vinfo, t3 = t2; int msb = 1; - value_range r; + int_range_max r; get_range_query (cfun)->range_of_expr (r, oprnd0); if (!r.varying_p () && !r.undefined_p ()) { @@ -6999,6 +7053,7 @@ static vect_recog_func vect_vect_recog_func_ptrs[] = { { vect_recog_divmod_pattern, "divmod" }, { vect_recog_mult_pattern, "mult" }, { vect_recog_sat_add_pattern, "sat_add" }, + { vect_recog_sat_sub_pattern, "sat_sub" }, { vect_recog_mixed_size_cond_pattern, "mixed_size_cond" }, { vect_recog_gcond_pattern, "gcond" }, { vect_recog_bool_pattern, "bool" }, diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index bf1f467f53f..7e3d0107b4e 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -778,6 +778,7 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap, case vect_constant_def: case vect_internal_def: case vect_reduction_def: + case vect_double_reduction_def: case vect_induction_def: case vect_nested_cycle: case vect_first_order_recurrence: @@ -1906,12 +1907,13 @@ vect_build_slp_tree_2 (vec_info *vinfo, slp_tree node, class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); /* Reduction initial values are not explicitely represented. */ if (def_type != vect_first_order_recurrence - && !nested_in_vect_loop_p (loop, stmt_info)) + && gimple_bb (stmt_info->stmt) == loop->header) skip_args[loop_preheader_edge (loop)->dest_idx] = true; /* Reduction chain backedge defs are filled manually. ??? Need a better way to identify a SLP reduction chain PHI. Or a better overall way to SLP match those. */ - if (all_same && def_type == vect_reduction_def) + if (stmts.length () > 1 + && all_same && def_type == vect_reduction_def) skip_args[loop_latch_edge (loop)->dest_idx] = true; } else if (def_type != vect_internal_def) @@ -3909,9 +3911,10 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) } /* Find SLP sequences starting from groups of reductions. */ - if (loop_vinfo->reductions.length () > 1) + if (loop_vinfo->reductions.length () > 0) { - /* Collect reduction statements. */ + /* Collect reduction statements we can combine into + a SLP reduction. */ vec scalar_stmts; scalar_stmts.create (loop_vinfo->reductions.length ()); for (auto next_info : loop_vinfo->reductions) @@ -3924,23 +3927,58 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) reduction path. In that case we'd have to reverse engineer that conversion stmt following the chain using reduc_idx and from the PHI using reduc_def. */ - && STMT_VINFO_DEF_TYPE (next_info) == vect_reduction_def - /* Do not discover SLP reductions for lane-reducing ops, that - will fail later. */ - && (!(g = dyn_cast (STMT_VINFO_STMT (next_info))) - || !lane_reducing_op_p (gimple_assign_rhs_code (g)))) - scalar_stmts.quick_push (next_info); + && STMT_VINFO_DEF_TYPE (next_info) == vect_reduction_def) + { + /* Do not discover SLP reductions combining lane-reducing + ops, that will fail later. */ + if (!(g = dyn_cast (STMT_VINFO_STMT (next_info))) + || !lane_reducing_op_p (gimple_assign_rhs_code (g))) + scalar_stmts.quick_push (next_info); + else + { + /* Do SLP discovery for single-lane reductions. */ + vec stmts; + vec roots = vNULL; + vec remain = vNULL; + stmts.create (1); + stmts.quick_push (next_info); + vect_build_slp_instance (vinfo, + slp_inst_kind_reduc_group, + stmts, roots, remain, + max_tree_size, &limit, + bst_map, NULL); + } + } } - if (scalar_stmts.length () > 1) + /* Save for re-processing on failure. */ + vec saved_stmts = scalar_stmts.copy (); + vec roots = vNULL; + vec remain = vNULL; + if (scalar_stmts.length () <= 1 + || !vect_build_slp_instance (loop_vinfo, + slp_inst_kind_reduc_group, + scalar_stmts, roots, remain, + max_tree_size, &limit, bst_map, + NULL)) { - vec roots = vNULL; - vec remain = vNULL; - vect_build_slp_instance (loop_vinfo, slp_inst_kind_reduc_group, - scalar_stmts, roots, remain, - max_tree_size, &limit, bst_map, NULL); + if (scalar_stmts.length () <= 1) + scalar_stmts.release (); + /* Do SLP discovery for single-lane reductions. */ + for (auto stmt_info : saved_stmts) + { + vec stmts; + vec roots = vNULL; + vec remain = vNULL; + stmts.create (1); + stmts.quick_push (vect_stmt_to_vectorize (stmt_info)); + vect_build_slp_instance (vinfo, + slp_inst_kind_reduc_group, + stmts, roots, remain, + max_tree_size, &limit, + bst_map, NULL); + } + saved_stmts.release (); } - else - scalar_stmts.release (); } } @@ -9650,7 +9688,12 @@ vect_schedule_slp_node (vec_info *vinfo, else { si = gsi_for_stmt (last_stmt); - gsi_next (&si); + /* When we're getting gsi_after_labels from the starting + condition of a fully masked/len loop avoid insertion + after a GIMPLE_COND that can appear as the only header + stmt with early break vectorization. */ + if (gimple_code (last_stmt) != GIMPLE_COND) + gsi_next (&si); } } diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 935d80f0e1b..5098b7fab6a 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -2160,6 +2160,23 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, } overrun_p = true; } + + /* If this is single-element interleaving with an element + distance that leaves unused vector loads around punt - we + at least create very sub-optimal code in that case (and + blow up memory, see PR65518). */ + if (loop_vinfo + && *memory_access_type == VMAT_CONTIGUOUS + && SLP_TREE_LOAD_PERMUTATION (slp_node).exists () + && single_element_p + && maybe_gt (group_size, TYPE_VECTOR_SUBPARTS (vectype))) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "single-element interleaving not supported " + "for not adjacent vector loads\n"); + return false; + } } } else @@ -8202,7 +8219,9 @@ vectorizable_store (vec_info *vinfo, gcc_assert (ncopies >= 1); /* FORNOW. This restriction should be relaxed. */ - if (loop && nested_in_vect_loop_p (loop, stmt_info) && ncopies > 1) + if (loop + && nested_in_vect_loop_p (loop, stmt_info) + && (ncopies > 1 || (slp && SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) > 1))) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -9945,7 +9964,8 @@ vectorizable_load (vec_info *vinfo, gcc_assert (ncopies >= 1); /* FORNOW. This restriction should be relaxed. */ - if (nested_in_vect_loop && ncopies > 1) + if (nested_in_vect_loop + && (ncopies > 1 || (slp && SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node) > 1))) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -12096,7 +12116,7 @@ vectorizable_condition (vec_info *vinfo, = STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info)) != NULL; if (for_reduction) { - if (slp_node) + if (slp_node && SLP_TREE_LANES (slp_node) > 1) return false; reduc_info = info_for_reduction (vinfo, stmt_info); reduction_type = STMT_VINFO_REDUC_TYPE (reduc_info); @@ -12185,6 +12205,10 @@ vectorizable_condition (vec_info *vinfo, cond_expr = NULL_TREE; } } + /* ??? The vectorized operand query below doesn't allow swapping + this way for SLP. */ + if (slp_node) + return false; std::swap (then_clause, else_clause); } @@ -13236,6 +13260,10 @@ vect_analyze_stmt (vec_info *vinfo, || relevance == vect_used_only_live)); break; + case vect_double_reduction_def: + gcc_assert (!bb_vinfo && node); + break; + case vect_induction_def: case vect_first_order_recurrence: gcc_assert (!bb_vinfo); diff --git a/gcc/tree.cc b/gcc/tree.cc index 01572fe70f7..5a31fae3125 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -316,6 +316,9 @@ unsigned const char omp_clause_num_ops[] = 0, /* OMP_CLAUSE_BIND */ 1, /* OMP_CLAUSE_FILTER */ 1, /* OMP_CLAUSE_INDIRECT */ + 1, /* OMP_CLAUSE_PARTIAL */ + 0, /* OMP_CLAUSE_FULL */ + 1, /* OMP_CLAUSE_SIZES */ 1, /* OMP_CLAUSE__SIMDUID_ */ 0, /* OMP_CLAUSE__SIMT_ */ 0, /* OMP_CLAUSE_INDEPENDENT */ @@ -409,6 +412,9 @@ const char * const omp_clause_code_name[] = "bind", "filter", "indirect", + "partial", + "full", + "sizes", "_simduid_", "_simt_", "independent", @@ -14495,7 +14501,7 @@ get_range_pos_neg (tree arg) if (TREE_CODE (arg) != SSA_NAME) return 3; - value_range r; + int_range_max r; while (!get_global_range_query ()->range_of_expr (r, arg) || r.undefined_p () || r.varying_p ()) { diff --git a/gcc/tree.def b/gcc/tree.def index 24128e1e039..85ab182c6f5 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -1230,6 +1230,14 @@ DEFTREECODE (OMP_TASKLOOP, "omp_taskloop", tcc_statement, 7) Operands like for OMP_FOR. */ DEFTREECODE (OMP_LOOP, "omp_loop", tcc_statement, 7) +/* OpenMP - #pragma omp tile [clause1 ... clauseN] + Operands like for OMP_FOR. */ +DEFTREECODE (OMP_TILE, "omp_tile", tcc_statement, 7) + +/* OpenMP - #pragma omp unroll [clause1 ... clauseN] + Operands like for OMP_FOR. */ +DEFTREECODE (OMP_UNROLL, "omp_unroll", tcc_statement, 7) + /* OpenMP - #pragma acc loop [clause1 ... clauseN] Operands like for OMP_FOR. */ DEFTREECODE (OACC_LOOP, "oacc_loop", tcc_statement, 7) diff --git a/gcc/tree.h b/gcc/tree.h index 60488564118..28e8e71b036 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1546,6 +1546,10 @@ class auto_suppress_location_wrappers #define OMP_FOR_PRE_BODY(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 5) #define OMP_FOR_ORIG_DECLS(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 6) +#define OMP_LOOPXFORM_CHECK(NODE) TREE_RANGE_CHECK (NODE, OMP_TILE, OMP_UNROLL) +#define OMP_LOOPXFORM_LOWERED(NODE) \ + (OMP_LOOPXFORM_CHECK (NODE)->base.public_flag) + #define OMP_SECTIONS_BODY(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 0) #define OMP_SECTIONS_CLAUSES(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 1) @@ -1742,6 +1746,10 @@ class auto_suppress_location_wrappers OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_HINT), 0) #define OMP_CLAUSE_FILTER_EXPR(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FILTER), 0) +#define OMP_CLAUSE_PARTIAL_EXPR(NODE) \ + OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PARTIAL), 0) +#define OMP_CLAUSE_SIZES_LIST(NODE) \ + OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SIZES), 0) #define OMP_CLAUSE_GRAINSIZE_EXPR(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_GRAINSIZE),0) diff --git a/gcc/value-range.cc b/gcc/value-range.cc index b38d6159a85..dbb4f81ae3c 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -2506,20 +2506,6 @@ debug (const vrange &vr) debug (&vr); } -DEBUG_FUNCTION void -debug (const value_range *vr) -{ - dump_value_range (stderr, vr); - fprintf (stderr, "\n"); -} - -DEBUG_FUNCTION void -debug (const value_range &vr) -{ - dump_value_range (stderr, &vr); - fprintf (stderr, "\n"); -} - /* Return true, if VAL1 and VAL2 are equal values for VRP purposes. */ bool diff --git a/gcc/value-range.h b/gcc/value-range.h index 44cdbd717f4..3cc15d51516 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -739,8 +739,6 @@ public: virtual void visit (const unsupported_range &) const { } }; -typedef int_range<2> value_range; - // This is an "infinite" precision range object for use in temporary // calculations for any of the handled types. The object can be // transparently used as a vrange. diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc index e6ea9592574..470e3145787 100644 --- a/gcc/vr-values.cc +++ b/gcc/vr-values.cc @@ -69,7 +69,7 @@ simplify_using_ranges::op_with_boolean_value_range_p (tree op, gimple *s) /* ?? Errr, this should probably check for [0,0] and [1,1] as well as [0,1]. */ - value_range vr; + int_range_max vr; return (query->range_of_expr (vr, op, s) && vr == range_true_and_false (TREE_TYPE (op))); } @@ -85,7 +85,7 @@ check_for_binary_op_overflow (range_query *query, enum tree_code subcode, tree type, tree op0, tree op1, bool *ovf, gimple *s = NULL) { - value_range vr0, vr1; + int_range_max vr0, vr1; if (!query->range_of_expr (vr0, op0, s) || vr0.undefined_p ()) vr0.set_varying (TREE_TYPE (op0)); if (!query->range_of_expr (vr1, op1, s) || vr1.undefined_p ()) @@ -376,7 +376,7 @@ simplify_using_ranges::legacy_fold_cond_overflow (gimple *stmt) } else { - value_range vro, vri; + int_range_max vro, vri; tree type = TREE_TYPE (op0); if (code == GT_EXPR || code == GE_EXPR) { @@ -399,7 +399,7 @@ simplify_using_ranges::legacy_fold_cond_overflow (gimple *stmt) } else gcc_unreachable (); - value_range vr0; + int_range_max vr0; if (!query->range_of_expr (vr0, op0, stmt)) vr0.set_varying (TREE_TYPE (op0)); /* If vro, the range for OP0 to pass the overflow test, has @@ -479,7 +479,7 @@ simplify_using_ranges::legacy_fold_cond (gcond *stmt, edge *taken_edge_p) Returns true if the default label is not needed. */ static bool -find_case_label_ranges (gswitch *stmt, const value_range *vr, +find_case_label_ranges (gswitch *stmt, const irange *vr, size_t *min_idx1, size_t *max_idx1, size_t *min_idx2, size_t *max_idx2) { @@ -611,9 +611,9 @@ simplify_using_ranges::simplify_truth_ops_using_ranges if (INTEGRAL_TYPE_P (TREE_TYPE (tem)) && TYPE_PRECISION (TREE_TYPE (tem)) > 1) { - value_range vr (TREE_TYPE (tem), - wi::zero (TYPE_PRECISION (TREE_TYPE (tem))), - wi::one (TYPE_PRECISION (TREE_TYPE (tem)))); + int_range<1> vr (TREE_TYPE (tem), + wi::zero (TYPE_PRECISION (TREE_TYPE (tem))), + wi::one (TYPE_PRECISION (TREE_TYPE (tem)))); set_range_info (tem, vr); } gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem); @@ -646,7 +646,7 @@ simplify_using_ranges::simplify_div_or_mod_using_ranges tree op1 = gimple_assign_rhs2 (stmt); tree op0min = NULL_TREE, op0max = NULL_TREE; tree op1min = op1; - value_range vr; + int_range_max vr; if (TREE_CODE (op0) == INTEGER_CST) { @@ -668,7 +668,7 @@ simplify_using_ranges::simplify_div_or_mod_using_ranges if (rhs_code == TRUNC_MOD_EXPR && TREE_CODE (op1) == SSA_NAME) { - value_range vr1; + int_range_max vr1; if (!query->range_of_expr (vr1, op1, stmt)) vr1.set_varying (TREE_TYPE (op1)); if (!vr1.varying_p () && !vr1.undefined_p ()) @@ -806,7 +806,7 @@ simplify_using_ranges::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, return false; } -/* value_range wrapper for wi_set_zero_nonzero_bits. +/* irange wrapper for wi_set_zero_nonzero_bits. Return TRUE if VR was a constant range and we were able to compute the bit masks. */ @@ -842,7 +842,7 @@ simplify_using_ranges::simplify_bit_ops_using_ranges tree op0 = gimple_assign_rhs1 (stmt); tree op1 = gimple_assign_rhs2 (stmt); tree op = NULL_TREE; - value_range vr0, vr1; + int_range_max vr0, vr1; wide_int may_be_nonzero0, may_be_nonzero1; wide_int must_be_nonzero0, must_be_nonzero1; wide_int mask; @@ -914,7 +914,7 @@ simplify_using_ranges::simplify_bit_ops_using_ranges static tree test_for_singularity (enum tree_code cond_code, tree op0, - tree op1, const value_range *vr) + tree op1, const irange *vr) { tree min = NULL; tree max = NULL; @@ -1226,7 +1226,7 @@ simplify_using_ranges::simplify_compare_using_ranges_1 (tree_code &cond_code, tr && INTEGRAL_TYPE_P (TREE_TYPE (op0)) && is_gimple_min_invariant (op1)) { - value_range vr; + int_range_max vr; if (!query->range_of_expr (vr, op0, stmt)) vr.set_undefined (); @@ -1307,7 +1307,7 @@ simplify_using_ranges::simplify_casted_compare (tree_code &, tree &op0, tree &op && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop) && desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0))) { - value_range vr; + int_range_max vr; if (query->range_of_expr (vr, innerop) && !vr.varying_p () @@ -1334,7 +1334,7 @@ bool simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt) { tree op = gimple_switch_index (stmt); - value_range vr; + int_range_max vr; bool take_default; edge e; edge_iterator ei; @@ -1582,7 +1582,7 @@ simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) /* Get the value-range of the inner operand. Use global ranges in case innerop was created during substitute-and-fold. */ wide_int imin, imax; - value_range vr; + int_range_max vr; if (!INTEGRAL_TYPE_P (TREE_TYPE (innerop))) return false; get_range_query (cfun)->range_of_expr (vr, innerop, stmt); @@ -1643,7 +1643,7 @@ simplify_using_ranges::simplify_float_conversion_using_ranges gimple *stmt) { tree rhs1 = gimple_assign_rhs1 (stmt); - value_range vr; + int_range_max vr; scalar_float_mode fltmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))); scalar_int_mode mode; @@ -1814,7 +1814,7 @@ bool simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b, gimple *s) { - value_range vr; + int_range_max vr; if (!query->range_of_expr (vr, var, s)) return false; if (vr.varying_p () || vr.undefined_p ()) diff --git a/libcpp/files.cc b/libcpp/files.cc index c61df339e20..78f56e30bde 100644 --- a/libcpp/files.cc +++ b/libcpp/files.cc @@ -1008,7 +1008,10 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type, if (decrement) pfile->line_table->highest_location--; - if (file->header_unit <= 0) + /* Normally a header unit becomes an __import directive in the current file, + but with -include we need something to LC_LEAVE to trigger the file_change + hook and continue to the next -include or the main source file. */ + if (file->header_unit <= 0 || type == IT_CMDLINE) /* Add line map and do callbacks. */ _cpp_do_file_change (pfile, LC_ENTER, file->path, /* With preamble injection, start on line zero, diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 48f3ee4f388..bf1ff5198e6 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,32 @@ +2024-06-06 Andre Vieira + + PR target/115360 + * config/arm/cmse_nonsecure_call.S: Add .type and .size directives. + +2024-06-06 Thomas Schwinge + Andrew Stubbs + + * config/nvptx/t-nvptx: Add unwind-nvptx.c. + * config/nvptx/unwind-nvptx.c: New file. + +2024-06-06 Thomas Schwinge + + * config/nvptx/gbl-ctors.c ["mgomp"] + (__do_global_ctors__entry__mgomp) + (__do_global_dtors__entry__mgomp): New. + [!"mgomp"] (__do_global_ctors__entry, __do_global_dtors__entry): + New. + +2024-06-05 Wilco Dijkstra + + PR target/115342 + * config/aarch64/cpuinfo.c (__init_cpu_features_constructor): + Use HWCAP where possible. Use atomic write for initialization. + Fix FEAT_PREDRES comparison. + (__init_cpu_features_resolver): Use atomic load for correct + initialization. + (__init_cpu_features): Likewise. + 2024-05-31 Thomas Schwinge * config/nvptx/crt0.c (__gbl_ctors): New weak function. diff --git a/libgcc/config.host b/libgcc/config.host index a29e0c64ff7..9fae51d4ce7 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -82,7 +82,7 @@ m32c*-*-*) cpu_type=m32c tmake_file=t-fdpbit ;; -aarch64*-*-* | arm64*-*-*) +aarch64*-*-*) cpu_type=aarch64 ;; alpha*-*-*) @@ -236,10 +236,7 @@ case ${host} in esac tmake_file="$tmake_file t-slibgcc-darwin" case ${host} in - *-*-darwin2*) - tmake_file="t-darwin-min-11 $tmake_file" - ;; - *-*-darwin1[89]*) + *-*-darwin1[89]* | *-*-darwin2* ) tmake_file="t-darwin-min-8 $tmake_file" ;; *-*-darwin9* | *-*-darwin1[0-7]*) @@ -277,7 +274,7 @@ case ${host} in if test "x$enable_darwin_at_rpath" = "xyes"; then tmake_file="$tmake_file t-darwin-rpath " fi - extra_parts="crt3.o crttms.o crttme.o libemutls_w.a " + extra_parts="crt3.o libd10-uwfef.a crttms.o crttme.o libemutls_w.a" ;; *-*-dragonfly*) tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip" @@ -408,15 +405,6 @@ aarch64*-*-elf | aarch64*-*-rtems*) tmake_file="${tmake_file} t-dfprules" md_unwind_header=aarch64/aarch64-unwind.h ;; -aarch64*-*-darwin*) - extra_parts="$extra_parts crtfastmath.o libheapt_w.a" - tmake_file="${tmake_file} ${cpu_type}/t-aarch64" - tmake_file="${tmake_file} ${cpu_type}/t-lse" - tmake_file="${tmake_file} t-crtfm t-dfprules" - tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp" - tmake_file="${tmake_file} ${cpu_type}/t-heap-trampoline" - md_unwind_header=aarch64/aarch64-unwind.h - ;; aarch64*-*-freebsd*) extra_parts="$extra_parts crtfastmath.o" tmake_file="${tmake_file} ${cpu_type}/t-aarch64" @@ -739,14 +727,14 @@ i[34567]86-*-darwin*) tmake_file="$tmake_file i386/t-crtpc t-crtfm i386/t-msabi" tm_file="$tm_file i386/darwin-lib.h" extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o" - extra_parts="$extra_parts crtfastmath.o libd10-uwfef.a libheapt_w.a" + extra_parts="$extra_parts crtfastmath.o libheapt_w.a" tmake_file="${tmake_file} i386/t-heap-trampoline" ;; x86_64-*-darwin*) tmake_file="$tmake_file i386/t-crtpc t-crtfm i386/t-msabi" tm_file="$tm_file i386/darwin-lib.h" extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o" - extra_parts="$extra_parts crtfastmath.o libd10-uwfef.a libheapt_w.a" + extra_parts="$extra_parts crtfastmath.o libheapt_w.a" tmake_file="${tmake_file} i386/t-heap-trampoline" ;; i[34567]86-*-elfiamcu) @@ -1229,14 +1217,12 @@ powerpc-*-darwin*) # We build the darwin10 EH shim for Rosetta (running on x86 machines). tm_file="$tm_file i386/darwin-lib.h" tmake_file="$tmake_file rs6000/t-ppc64-fp rs6000/t-ibm-ldouble" - extra_parts="$extra_parts libd10-uwfef.a " extra_parts="$extra_parts crt2.o crt3_2.o libef_ppc.a dw_ppc.o" ;; powerpc64-*-darwin*) # We build the darwin10 EH shim for Rosetta (running on x86 machines). tm_file="$tm_file i386/darwin-lib.h" tmake_file="$tmake_file rs6000/t-darwin64 rs6000/t-ibm-ldouble" - extra_parts="$extra_parts libd10-uwfef.a " extra_parts="$extra_parts crt2.o crt3_2.o libef_ppc.a dw_ppc.o" ;; powerpc*-*-freebsd*) diff --git a/libgcc/config/aarch64/__arm_sme_state.S b/libgcc/config/aarch64/__arm_sme_state.S index b665769004f..1fbb8c1ff53 100644 --- a/libgcc/config/aarch64/__arm_sme_state.S +++ b/libgcc/config/aarch64/__arm_sme_state.S @@ -30,19 +30,14 @@ - Takes no argument. - Returns SME state in x0 and TPIDR2_EL0 in x1. */ -HIDDEN (ASMNAME (__aarch64_have_sme)) +HIDDEN (__aarch64_have_sme) -variant_pcs (ASMNAME (__arm_sme_state)) +variant_pcs (__arm_sme_state) -ENTRY (ASMNAME (__arm_sme_state)) +ENTRY (__arm_sme_state) /* Check if SME is available. */ -#ifdef __APPLE__ - adrp x1, ASMNAME (__aarch64_have_sme)@PAGE - ldrb w1, [x1, ASMNAME (__aarch64_have_sme)@PAGEOFF] -#else - adrp x1, ASMNAME (__aarch64_have_sme) - ldrb w1, [x1, :lo12:ASMNAME (__aarch64_have_sme)] -#endif + adrp x1, __aarch64_have_sme + ldrb w1, [x1, :lo12:__aarch64_have_sme] cbz w1, L(nosme) /* Expose the bottom 2 bits of svcr (SM, ZA) in x0 and set the @@ -57,4 +52,4 @@ L(nosme): mov x0, 0 mov x1, 0 ret -ENDm ASMNAME(__arm_sme_state) +END (__arm_sme_state) diff --git a/libgcc/config/aarch64/__arm_tpidr2_restore.S b/libgcc/config/aarch64/__arm_tpidr2_restore.S index bcfb935bc96..5088c86df32 100644 --- a/libgcc/config/aarch64/__arm_tpidr2_restore.S +++ b/libgcc/config/aarch64/__arm_tpidr2_restore.S @@ -31,9 +31,9 @@ - Does not return a value. - Can abort on failure (then registers are not preserved). */ -variant_pcs (ASMNAME (__arm_tpidr2_restore)) +variant_pcs (__arm_tpidr2_restore) -ENTRY (ASMNAME (__arm_tpidr2_restore)) +ENTRY (__arm_tpidr2_restore) .inst 0xd53bd0ae /* mrs x14, tpidr2_el0 */ cbnz x14, L(fail) @@ -85,5 +85,5 @@ L(fail): str x16, [sp, 16] .cfi_rel_offset 46, 16 .inst 0xd503467f /* smstop */ - bl ASMNAME (abort) -ENDm ASMNAME (__arm_tpidr2_restore) + bl abort +END (__arm_tpidr2_restore) diff --git a/libgcc/config/aarch64/__arm_tpidr2_save.S b/libgcc/config/aarch64/__arm_tpidr2_save.S index 28e75ade2d0..2466b5863e4 100644 --- a/libgcc/config/aarch64/__arm_tpidr2_save.S +++ b/libgcc/config/aarch64/__arm_tpidr2_save.S @@ -35,15 +35,10 @@ HIDDEN (__aarch64_have_sme) variant_pcs (__arm_tpidr2_save) -ENTRY (ASMNAME (__arm_tpidr2_save)) +ENTRY (__arm_tpidr2_save) /* Check if SME is available. */ -#if __APPLE__ - adrp x14, ASMNAME (__aarch64_have_sme)@PAGE - ldrb w14, [x14, ASMNAME (__aarch64_have_sme)@PAGEOFF] -#else - adrp x14, ASMNAME (__aarch64_have_sme) - ldrb w14, [x14, :lo12:ASMNAME (__aarch64_have_sme)] -#endif + adrp x14, __aarch64_have_sme + ldrb w14, [x14, :lo12:__aarch64_have_sme] cbz w14, L(end) .inst 0xd53bd0ae /* mrs x14, tpidr2_el0 */ @@ -97,18 +92,10 @@ L(fail): str x16, [sp, 16] .cfi_rel_offset 46, 16 .inst 0xd503467f /* smstop */ - bl ASMNAME (abort) -ENDm ASMNAME (__arm_tpidr2_save) - - GLOBAL(ASMNAME (__libgcc_arm_tpidr2_save)) - HIDDEN (ASMNAME (__libgcc_arm_tpidr2_save)) -#if __APPLE__ - .text - .p2align 4 -ASMNAME (__libgcc_arm_tpidr2_save): - b ASMNAME (__arm_tpidr2_save) -#else -/* Hidden alias used by __arm_za_disable. */ -.set ASMNAME (__libgcc_arm_tpidr2_save), ASMNAME (__arm_tpidr2_save) -#endif + bl abort +END (__arm_tpidr2_save) +/* Hidden alias used by __arm_za_disable. */ +.global __libgcc_arm_tpidr2_save +HIDDEN (__libgcc_arm_tpidr2_save) +.set __libgcc_arm_tpidr2_save, __arm_tpidr2_save diff --git a/libgcc/config/aarch64/__arm_za_disable.S b/libgcc/config/aarch64/__arm_za_disable.S index 9aefed6cde7..c372fcffe18 100644 --- a/libgcc/config/aarch64/__arm_za_disable.S +++ b/libgcc/config/aarch64/__arm_za_disable.S @@ -31,33 +31,16 @@ - Does not return a value. - Can abort on failure (then registers are not preserved). */ -HIDDEN (ASMNAME(__aarch64_have_sme)) +HIDDEN (__aarch64_have_sme) -HIDDEN (ASMNAME(__libgcc_arm_tpidr2_save)) +HIDDEN (__libgcc_arm_tpidr2_save) -variant_pcs (ASMNAME(__arm_za_disable)) +variant_pcs (__arm_za_disable) -GLOBAL (ASMNAME (__libgcc_arm_za_disable)) -HIDDEN (ASMNAME (__libgcc_arm_za_disable)) -#if __APPLE__ - .text - .p2align 4 -ASMNAME (__libgcc_arm_za_disable): - b ASMNAME (__arm_za_disable) -#else -/* Hidden alias used by the unwinder. */ -.set ASMNAME (__libgcc_arm_za_disable), ASMNAME (__arm_za_disable) -#endif - -ENTRY (ASMNAME (__arm_za_disable)) +ENTRY (__arm_za_disable) /* Check if SME is available. */ -#if __APPLE__ - adrp x14, ASMNAME (__aarch64_have_sme)@PAGE - ldrb w14, [x14, ASMNAME (__aarch64_have_sme)@PAGEOFF] -#else - adrp x14, ASMNAME (__aarch64_have_sme) - ldrb w14, [x14, :lo12:ASMNAME (__aarch64_have_sme)] -#endif + adrp x14, __aarch64_have_sme + ldrb w14, [x14, :lo12:__aarch64_have_sme] cbz w14, L(end) .inst 0xd53bd0ae /* mrs x14, tpidr2_el0 */ @@ -69,7 +52,7 @@ ENTRY (ASMNAME (__arm_za_disable)) .cfi_rel_offset x29, 0 .cfi_rel_offset x30, 8 mov x29, sp - bl ASMNAME (__libgcc_arm_tpidr2_save) + bl __libgcc_arm_tpidr2_save .inst 0xd51bd0bf /* msr tpidr2_el0, xzr */ .inst 0xd503447f /* smstop za */ ldp x29, x30, [sp], 16 @@ -79,5 +62,9 @@ ENTRY (ASMNAME (__arm_za_disable)) AUTIASP L(end): ret -ENDm ASMNAME(__arm_za_disable) +END (__arm_za_disable) +/* Hidden alias used by the unwinder. */ +.global __libgcc_arm_za_disable +HIDDEN (__libgcc_arm_za_disable) +.set __libgcc_arm_za_disable, __arm_za_disable diff --git a/libgcc/config/aarch64/aarch64-asm.h b/libgcc/config/aarch64/aarch64-asm.h index 7e41e6eb082..83c2e5944b3 100644 --- a/libgcc/config/aarch64/aarch64-asm.h +++ b/libgcc/config/aarch64/aarch64-asm.h @@ -24,6 +24,8 @@ #include "auto-target.h" +#define L(label) .L ## label + /* Marking variant PCS symbol references is important for PLT calls otherwise it is for documenting the PCS in the symbol table. */ #ifdef HAVE_AS_VARIANT_PCS @@ -56,31 +58,12 @@ # define AUTIASP #endif -#define PASTE2(a, b) PASTE2a(a, b) -#define PASTE2a(a, b) a ## b - -#ifdef __USER_LABEL_PREFIX__ -# define ASMNAME(name) PASTE2(__USER_LABEL_PREFIX__, name) -#else -# define ASMNAME(name) name -#endif - #ifdef __ELF__ -#define L(label) .L ## label #define HIDDEN(name) .hidden name -#define GLOBAL(name) .global name #define SYMBOL_SIZE(name) .size name, .-name #define SYMBOL_TYPE(name, _type) .type name, _type -#elif __APPLE__ -#define L(label) L ## label -#define HIDDEN(name) .private_extern name -#define GLOBAL(name) .globl name -#define SYMBOL_SIZE(name) -#define SYMBOL_TYPE(name, _type) #else -#define L(label) .L ## label #define HIDDEN(name) -#define GLOBAL(name) .global name #define SYMBOL_SIZE(name) #define SYMBOL_TYPE(name, _type) #endif @@ -110,19 +93,16 @@ GNU_PROPERTY (FEATURE_1_AND, BTI_FLAG|PAC_FLAG) # endif #endif -.macro ENTRY_ALIGNP2m, name, align - .text - .p2align \align - GLOBAL (\name) - SYMBOL_TYPE(\name, %function) -\name: - .cfi_startproc - BTI_C -.endm - -#define ENTRY(name) ENTRY_ALIGNP2m name, 4 - -.macro ENDm, name - .cfi_endproc - SYMBOL_SIZE (\name) -.endm +#define ENTRY_ALIGN(name, align) \ + .global name; \ + SYMBOL_TYPE(name, %function); \ + .balign align; \ + name: \ + .cfi_startproc; \ + BTI_C + +#define ENTRY(name) ENTRY_ALIGN(name, 16) + +#define END(name) \ + .cfi_endproc; \ + SYMBOL_SIZE(name) diff --git a/libgcc/config/aarch64/cpuinfo.c b/libgcc/config/aarch64/cpuinfo.c index 4b94fca8695..544c5516133 100644 --- a/libgcc/config/aarch64/cpuinfo.c +++ b/libgcc/config/aarch64/cpuinfo.c @@ -227,14 +227,22 @@ struct { #ifndef HWCAP2_SVE_EBF16 #define HWCAP2_SVE_EBF16 (1UL << 33) #endif +#ifndef HWCAP2_SME2 +#define HWCAP2_SME2 (1UL << 37) +#endif +#ifndef HWCAP2_LRCPC3 +#define HWCAP2_LRCPC3 (1UL << 46) +#endif static void -__init_cpu_features_constructor(unsigned long hwcap, - const __ifunc_arg_t *arg) { -#define setCPUFeature(F) __aarch64_cpu_features.features |= 1ULL << F +__init_cpu_features_constructor (unsigned long hwcap, + const __ifunc_arg_t *arg) +{ + unsigned long feat = 0; +#define setCPUFeature(F) feat |= 1UL << F #define getCPUFeature(id, ftr) __asm__("mrs %0, " #id : "=r"(ftr)) #define extractBits(val, start, number) \ - (val & ((1ULL << number) - 1ULL) << start) >> start + (val & ((1UL << number) - 1UL) << start) >> start unsigned long hwcap2 = 0; if (hwcap & _IFUNC_ARG_HWCAP) hwcap2 = arg->_hwcap2; @@ -244,26 +252,20 @@ __init_cpu_features_constructor(unsigned long hwcap, setCPUFeature(FEAT_PMULL); if (hwcap & HWCAP_FLAGM) setCPUFeature(FEAT_FLAGM); - if (hwcap2 & HWCAP2_FLAGM2) { - setCPUFeature(FEAT_FLAGM); + if (hwcap2 & HWCAP2_FLAGM2) setCPUFeature(FEAT_FLAGM2); - } - if (hwcap & HWCAP_SM3 && hwcap & HWCAP_SM4) + if (hwcap & HWCAP_SM4) setCPUFeature(FEAT_SM4); if (hwcap & HWCAP_ASIMDDP) setCPUFeature(FEAT_DOTPROD); if (hwcap & HWCAP_ASIMDFHM) setCPUFeature(FEAT_FP16FML); - if (hwcap & HWCAP_FPHP) { + if (hwcap & HWCAP_FPHP) setCPUFeature(FEAT_FP16); - setCPUFeature(FEAT_FP); - } if (hwcap & HWCAP_DIT) setCPUFeature(FEAT_DIT); if (hwcap & HWCAP_ASIMDRDM) setCPUFeature(FEAT_RDM); - if (hwcap & HWCAP_ILRCPC) - setCPUFeature(FEAT_RCPC2); if (hwcap & HWCAP_AES) setCPUFeature(FEAT_AES); if (hwcap & HWCAP_SHA1) @@ -277,22 +279,21 @@ __init_cpu_features_constructor(unsigned long hwcap, if (hwcap & HWCAP_SB) setCPUFeature(FEAT_SB); if (hwcap & HWCAP_SSBS) - setCPUFeature(FEAT_SSBS2); - if (hwcap2 & HWCAP2_MTE) { - setCPUFeature(FEAT_MEMTAG); - setCPUFeature(FEAT_MEMTAG2); - } - if (hwcap2 & HWCAP2_MTE3) { - setCPUFeature(FEAT_MEMTAG); - setCPUFeature(FEAT_MEMTAG2); + { + setCPUFeature(FEAT_SSBS); + setCPUFeature(FEAT_SSBS2); + } + if (hwcap2 & HWCAP2_MTE) + { + setCPUFeature(FEAT_MEMTAG); + setCPUFeature(FEAT_MEMTAG2); + } + if (hwcap2 & HWCAP2_MTE3) setCPUFeature(FEAT_MEMTAG3); - } if (hwcap2 & HWCAP2_SVEAES) setCPUFeature(FEAT_SVE_AES); - if (hwcap2 & HWCAP2_SVEPMULL) { - setCPUFeature(FEAT_SVE_AES); + if (hwcap2 & HWCAP2_SVEPMULL) setCPUFeature(FEAT_SVE_PMULL128); - } if (hwcap2 & HWCAP2_SVEBITPERM) setCPUFeature(FEAT_SVE_BITPERM); if (hwcap2 & HWCAP2_SVESHA3) @@ -329,108 +330,76 @@ __init_cpu_features_constructor(unsigned long hwcap, setCPUFeature(FEAT_WFXT); if (hwcap2 & HWCAP2_SME) setCPUFeature(FEAT_SME); + if (hwcap2 & HWCAP2_SME2) + setCPUFeature(FEAT_SME2); if (hwcap2 & HWCAP2_SME_I16I64) setCPUFeature(FEAT_SME_I64); if (hwcap2 & HWCAP2_SME_F64F64) setCPUFeature(FEAT_SME_F64); - if (hwcap & HWCAP_CPUID) { - unsigned long ftr; - getCPUFeature(ID_AA64PFR1_EL1, ftr); - /* ID_AA64PFR1_EL1.MTE >= 0b0001 */ - if (extractBits(ftr, 8, 4) >= 0x1) - setCPUFeature(FEAT_MEMTAG); - /* ID_AA64PFR1_EL1.SSBS == 0b0001 */ - if (extractBits(ftr, 4, 4) == 0x1) - setCPUFeature(FEAT_SSBS); - /* ID_AA64PFR1_EL1.SME == 0b0010 */ - if (extractBits(ftr, 24, 4) == 0x2) - setCPUFeature(FEAT_SME2); - getCPUFeature(ID_AA64PFR0_EL1, ftr); - /* ID_AA64PFR0_EL1.FP != 0b1111 */ - if (extractBits(ftr, 16, 4) != 0xF) { - setCPUFeature(FEAT_FP); - /* ID_AA64PFR0_EL1.AdvSIMD has the same value as ID_AA64PFR0_EL1.FP */ - setCPUFeature(FEAT_SIMD); - } - /* ID_AA64PFR0_EL1.SVE != 0b0000 */ - if (extractBits(ftr, 32, 4) != 0x0) { - /* get ID_AA64ZFR0_EL1, that name supported if sve enabled only */ - getCPUFeature(S3_0_C0_C4_4, ftr); - /* ID_AA64ZFR0_EL1.SVEver == 0b0000 */ - if (extractBits(ftr, 0, 4) == 0x0) - setCPUFeature(FEAT_SVE); - /* ID_AA64ZFR0_EL1.SVEver == 0b0001 */ - if (extractBits(ftr, 0, 4) == 0x1) - setCPUFeature(FEAT_SVE2); - /* ID_AA64ZFR0_EL1.BF16 != 0b0000 */ - if (extractBits(ftr, 20, 4) != 0x0) - setCPUFeature(FEAT_SVE_BF16); + if (hwcap & HWCAP_CPUID) + { + unsigned long ftr; + + getCPUFeature(ID_AA64ISAR1_EL1, ftr); + /* ID_AA64ISAR1_EL1.SPECRES >= 0b0001 */ + if (extractBits(ftr, 40, 4) >= 0x1) + setCPUFeature(FEAT_PREDRES); + /* ID_AA64ISAR1_EL1.LS64 >= 0b0001 */ + if (extractBits(ftr, 60, 4) >= 0x1) + setCPUFeature(FEAT_LS64); + /* ID_AA64ISAR1_EL1.LS64 >= 0b0010 */ + if (extractBits(ftr, 60, 4) >= 0x2) + setCPUFeature(FEAT_LS64_V); + /* ID_AA64ISAR1_EL1.LS64 >= 0b0011 */ + if (extractBits(ftr, 60, 4) >= 0x3) + setCPUFeature(FEAT_LS64_ACCDATA); } - getCPUFeature(ID_AA64ISAR0_EL1, ftr); - /* ID_AA64ISAR0_EL1.SHA3 != 0b0000 */ - if (extractBits(ftr, 32, 4) != 0x0) - setCPUFeature(FEAT_SHA3); - getCPUFeature(ID_AA64ISAR1_EL1, ftr); - /* ID_AA64ISAR1_EL1.DPB >= 0b0001 */ - if (extractBits(ftr, 0, 4) >= 0x1) - setCPUFeature(FEAT_DPB); - /* ID_AA64ISAR1_EL1.LRCPC != 0b0000 */ - if (extractBits(ftr, 20, 4) != 0x0) - setCPUFeature(FEAT_RCPC); - /* ID_AA64ISAR1_EL1.LRCPC == 0b0011 */ - if (extractBits(ftr, 20, 4) == 0x3) - setCPUFeature(FEAT_RCPC3); - /* ID_AA64ISAR1_EL1.SPECRES == 0b0001 */ - if (extractBits(ftr, 40, 4) == 0x2) - setCPUFeature(FEAT_PREDRES); - /* ID_AA64ISAR1_EL1.BF16 != 0b0000 */ - if (extractBits(ftr, 44, 4) != 0x0) - setCPUFeature(FEAT_BF16); - /* ID_AA64ISAR1_EL1.LS64 >= 0b0001 */ - if (extractBits(ftr, 60, 4) >= 0x1) - setCPUFeature(FEAT_LS64); - /* ID_AA64ISAR1_EL1.LS64 >= 0b0010 */ - if (extractBits(ftr, 60, 4) >= 0x2) - setCPUFeature(FEAT_LS64_V); - /* ID_AA64ISAR1_EL1.LS64 >= 0b0011 */ - if (extractBits(ftr, 60, 4) >= 0x3) - setCPUFeature(FEAT_LS64_ACCDATA); - } else { - /* Set some features in case of no CPUID support. */ - if (hwcap & (HWCAP_FP | HWCAP_FPHP)) { + + if (hwcap & HWCAP_FP) + { setCPUFeature(FEAT_FP); /* FP and AdvSIMD fields have the same value. */ setCPUFeature(FEAT_SIMD); } - if (hwcap & HWCAP_DCPOP || hwcap2 & HWCAP2_DCPODP) - setCPUFeature(FEAT_DPB); - if (hwcap & HWCAP_LRCPC || hwcap & HWCAP_ILRCPC) - setCPUFeature(FEAT_RCPC); - if (hwcap2 & HWCAP2_BF16 || hwcap2 & HWCAP2_EBF16) - setCPUFeature(FEAT_BF16); - if (hwcap2 & HWCAP2_SVEBF16) - setCPUFeature(FEAT_SVE_BF16); - if (hwcap2 & HWCAP2_SVE2 && hwcap & HWCAP_SVE) - setCPUFeature(FEAT_SVE2); - if (hwcap & HWCAP_SHA3) - setCPUFeature(FEAT_SHA3); - } + if (hwcap & HWCAP_DCPOP) + setCPUFeature(FEAT_DPB); + if (hwcap & HWCAP_LRCPC) + setCPUFeature(FEAT_RCPC); + if (hwcap & HWCAP_ILRCPC) + setCPUFeature(FEAT_RCPC2); + if (hwcap2 & HWCAP2_LRCPC3) + setCPUFeature(FEAT_RCPC3); + if (hwcap2 & HWCAP2_BF16) + setCPUFeature(FEAT_BF16); + if (hwcap2 & HWCAP2_SVEBF16) + setCPUFeature(FEAT_SVE_BF16); + if (hwcap & HWCAP_SVE) + setCPUFeature(FEAT_SVE); + if (hwcap2 & HWCAP2_SVE2) + setCPUFeature(FEAT_SVE2); + if (hwcap & HWCAP_SHA3) + setCPUFeature(FEAT_SHA3); setCPUFeature(FEAT_INIT); + + __atomic_store_n (&__aarch64_cpu_features.features, feat, __ATOMIC_RELAXED); } void -__init_cpu_features_resolver(unsigned long hwcap, const __ifunc_arg_t *arg) { - if (__aarch64_cpu_features.features) +__init_cpu_features_resolver(unsigned long hwcap, const __ifunc_arg_t *arg) +{ + if (__atomic_load_n (&__aarch64_cpu_features.features, __ATOMIC_RELAXED)) return; __init_cpu_features_constructor(hwcap, arg); } void __attribute__ ((constructor)) -__init_cpu_features(void) { +__init_cpu_features(void) +{ unsigned long hwcap; unsigned long hwcap2; + /* CPU features already initialized. */ - if (__aarch64_cpu_features.features) + if (__atomic_load_n (&__aarch64_cpu_features.features, __ATOMIC_RELAXED)) return; hwcap = getauxval(AT_HWCAP); hwcap2 = getauxval(AT_HWCAP2); diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S index 54b85b5ad2a..ecef47086c6 100644 --- a/libgcc/config/aarch64/lse.S +++ b/libgcc/config/aarch64/lse.S @@ -62,7 +62,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #endif /* Declare the symbol gating the LSE implementations. */ - HIDDEN (ASMNAME (__aarch64_have_lse_atomics)) + HIDDEN(__aarch64_have_lse_atomics) /* Turn size and memory model defines into mnemonic fragments. */ #if SIZE == 1 @@ -85,7 +85,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see # error #endif -#undef L #if MODEL == 1 # define SUFF _relax # define A @@ -168,21 +167,32 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define tmp3 14 #define tmp4 13 +/* Start and end a function. */ +.macro STARTFN name + .text + .balign 16 + .globl \name + HIDDEN(\name) + SYMBOL_TYPE(\name, %function) + .cfi_startproc +\name: +.endm + +.macro ENDFN name + .cfi_endproc + SYMBOL_SIZE(\name) +.endm + /* Branch to LABEL if LSE is disabled. */ .macro JUMP_IF_NOT_LSE label -#if __APPLE__ - adrp x(tmp0), ASMNAME (__aarch64_have_lse_atomics)@PAGE - ldrb w(tmp0), [x(tmp0), ASMNAME (__aarch64_have_lse_atomics)@PAGEOFF] -#else - adrp x(tmp0), ASMNAME (__aarch64_have_lse_atomics) - ldrb w(tmp0), [x(tmp0), :lo12:ASMNAME (__aarch64_have_lse_atomics)] -#endif + adrp x(tmp0), __aarch64_have_lse_atomics + ldrb w(tmp0), [x(tmp0), :lo12:__aarch64_have_lse_atomics] cbz w(tmp0), \label .endm #ifdef L_cas -ENTRY (ASMNAME (NAME(cas))) +STARTFN NAME(cas) JUMP_IF_NOT_LSE 8f #if SIZE < 16 @@ -235,7 +245,7 @@ ENTRY (ASMNAME (NAME(cas))) #endif -ENDm ASMNAME (NAME(cas)) +ENDFN NAME(cas) #endif #ifdef L_swp @@ -245,7 +255,7 @@ ENDm ASMNAME (NAME(cas)) # define SWP .inst 0x38208020 + B + N #endif -ENTRY (ASMNAME (NAME (swp))) +STARTFN NAME(swp) JUMP_IF_NOT_LSE 8f SWP /* s(0), s(0), [x1] */ @@ -258,7 +268,7 @@ ENTRY (ASMNAME (NAME (swp))) BARRIER ret -ENDm ASMNAME (NAME (swp)) +ENDFN NAME(swp) #endif #if defined(L_ldadd) || defined(L_ldclr) \ @@ -289,7 +299,7 @@ ENDm ASMNAME (NAME (swp)) # define LDOP .inst 0x38200020 + OPN + B + N #endif -ENTRY (ASMNAME (NAME (LDNM))) +STARTFN NAME(LDNM) JUMP_IF_NOT_LSE 8f LDOP /* s(0), s(0), [x1] */ @@ -303,5 +313,5 @@ ENTRY (ASMNAME (NAME (LDNM))) BARRIER ret -ENDm ASMNAME (NAME (LDNM)) +ENDFN NAME(LDNM) #endif diff --git a/libgcc/config/aarch64/sfp-machine.h b/libgcc/config/aarch64/sfp-machine.h index 3ebc1d5fe44..7fbb2a4288a 100644 --- a/libgcc/config/aarch64/sfp-machine.h +++ b/libgcc/config/aarch64/sfp-machine.h @@ -124,27 +124,6 @@ void __sfp_handle_exceptions (int); /* Define ALIASNAME as a strong alias for NAME. */ -#if defined __APPLE__ -/* Mach-O doesn't support aliasing, so we build a secondary function for - the alias - we need to do a bit of a dance to find out what the type of - the arguments is and then apply that to the secondary function. - If these functions ever return anything but CMPtype we need to revisit - this... */ -typedef float alias_HFtype __attribute__ ((mode (HF))); -typedef float alias_SFtype __attribute__ ((mode (SF))); -typedef float alias_DFtype __attribute__ ((mode (DF))); -typedef float alias_TFtype __attribute__ ((mode (TF))); -#define ALIAS_SELECTOR \ - CMPtype (*) (alias_HFtype, alias_HFtype): (alias_HFtype) 0, \ - CMPtype (*) (alias_SFtype, alias_SFtype): (alias_SFtype) 0, \ - CMPtype (*) (alias_DFtype, alias_DFtype): (alias_DFtype) 0, \ - CMPtype (*) (alias_TFtype, alias_TFtype): (alias_TFtype) 0 -#define strong_alias(name, aliasname) \ - CMPtype aliasname (__typeof (_Generic (name, ALIAS_SELECTOR)) a, \ - __typeof (_Generic (name, ALIAS_SELECTOR)) b) \ - { return name (a, b); } -#else # define strong_alias(name, aliasname) _strong_alias(name, aliasname) # define _strong_alias(name, aliasname) \ extern __typeof (name) aliasname __attribute__ ((alias (#name))); -#endif diff --git a/libgcc/config/aarch64/t-darwin b/libgcc/config/aarch64/t-darwin deleted file mode 100644 index f6ecda7b608..00000000000 --- a/libgcc/config/aarch64/t-darwin +++ /dev/null @@ -1,7 +0,0 @@ -# Ensure we have a suitable minimum OS version. - -HOST_LIBGCC2_CFLAGS += -mmacosx-version-min=11.0 - -LIB2_SIDITI_CONV_FUNCS = yes - -BUILD_LIBGCCS1 = diff --git a/libgcc/config/arm/cmse_nonsecure_call.S b/libgcc/config/arm/cmse_nonsecure_call.S index f93ce6bb4f9..fef37b955af 100644 --- a/libgcc/config/arm/cmse_nonsecure_call.S +++ b/libgcc/config/arm/cmse_nonsecure_call.S @@ -33,6 +33,7 @@ #endif .thumb +.type __gnu_cmse_nonsecure_call, %function .global __gnu_cmse_nonsecure_call __gnu_cmse_nonsecure_call: #if defined(__ARM_ARCH_8M_MAIN__) @@ -142,3 +143,4 @@ pop {r5-r7, pc} #else #error "This should only be used for armv8-m base- and mainline." #endif +.size __gnu_cmse_nonsecure_call, .-__gnu_cmse_nonsecure_call diff --git a/libgcc/config/avr/libf7/ChangeLog b/libgcc/config/avr/libf7/ChangeLog index 0351fae9c91..d5ce1fe9ab1 100644 --- a/libgcc/config/avr/libf7/ChangeLog +++ b/libgcc/config/avr/libf7/ChangeLog @@ -1,3 +1,8 @@ +2024-06-01 Georg-Johann Lay + + PR target/115317 + * libf7-asm.sx (__isinf): Map -Inf to -1. + 2024-05-08 Georg-Johann Lay PR target/114981 diff --git a/libgcc/config/avr/libf7/libf7-asm.sx b/libgcc/config/avr/libf7/libf7-asm.sx index 1f8f60ab282..bef62f3a46a 100644 --- a/libgcc/config/avr/libf7/libf7-asm.sx +++ b/libgcc/config/avr/libf7/libf7-asm.sx @@ -1639,19 +1639,24 @@ _ENDF __copysign #ifdef F7MOD_D_isinf_ +;;; +Inf -> +1 +;;; -Inf -> -1 _DEFUN __isinf DALIAS isinf LALIAS isinfl + ;; Save sign for later + push R25 F7call class_D + pop TMP + ldi R24, 0 + ldi R25, 0 ;; Inf: T = Z = 1. - brtc 0f + brtc 0f ; ordinary number + brne 0f ; Nan ldi R24, 1 - breq 1f -0: - clr R24 -1: - clr R25 - ret + sbrc TMP, 7 + sbiw R24, 2 +0: ret _ENDF __isinf #endif /* F7MOD_D_isinf_ */ diff --git a/libgcc/config/nvptx/gbl-ctors.c b/libgcc/config/nvptx/gbl-ctors.c index a2ca053e5e3..a56d64f8ef8 100644 --- a/libgcc/config/nvptx/gbl-ctors.c +++ b/libgcc/config/nvptx/gbl-ctors.c @@ -68,6 +68,61 @@ __gbl_ctors (void) } +/* For nvptx offloading configurations, need '.entry' wrappers. */ + +# if defined(__nvptx_softstack__) && defined(__nvptx_unisimt__) + +/* OpenMP */ + +/* See 'crt0.c', 'mgomp.c'. */ +extern void *__nvptx_stacks[32] __attribute__((shared,nocommon)); +extern unsigned __nvptx_uni[32] __attribute__((shared,nocommon)); + +__attribute__((kernel)) void __do_global_ctors__entry__mgomp (void *); + +void +__do_global_ctors__entry__mgomp (void *nvptx_stacks_0) +{ + __nvptx_stacks[0] = nvptx_stacks_0; + __nvptx_uni[0] = 0; + + __static_do_global_ctors (); +} + +__attribute__((kernel)) void __do_global_dtors__entry__mgomp (void *); + +void +__do_global_dtors__entry__mgomp (void *nvptx_stacks_0) +{ + __nvptx_stacks[0] = nvptx_stacks_0; + __nvptx_uni[0] = 0; + + __static_do_global_dtors (); +} + +# else + +/* OpenACC */ + +__attribute__((kernel)) void __do_global_ctors__entry (void); + +void +__do_global_ctors__entry (void) +{ + __static_do_global_ctors (); +} + +__attribute__((kernel)) void __do_global_dtors__entry (void); + +void +__do_global_dtors__entry (void) +{ + __static_do_global_dtors (); +} + +# endif + + /* The following symbol just provides a means for the nvptx-tools 'ld' to trigger linking in this file. */ diff --git a/libgcc/config/nvptx/t-nvptx b/libgcc/config/nvptx/t-nvptx index 260ed6334db..1ff574c2982 100644 --- a/libgcc/config/nvptx/t-nvptx +++ b/libgcc/config/nvptx/t-nvptx @@ -1,6 +1,7 @@ LIB2ADD=$(srcdir)/config/nvptx/reduction.c \ $(srcdir)/config/nvptx/mgomp.c \ - $(srcdir)/config/nvptx/atomic.c + $(srcdir)/config/nvptx/atomic.c \ + $(srcdir)/config/nvptx/unwind-nvptx.c # Until we have libstdc++-v3/libsupc++ proper. LIB2ADD += $(srcdir)/c++-minimal/guard.c diff --git a/libgcc/config/nvptx/unwind-nvptx.c b/libgcc/config/nvptx/unwind-nvptx.c new file mode 100644 index 00000000000..d08ba266be1 --- /dev/null +++ b/libgcc/config/nvptx/unwind-nvptx.c @@ -0,0 +1,37 @@ +/* Stub unwinding implementation. + + Copyright (C) 2019-2024 Free Software Foundation, Inc. + Contributed by Mentor Graphics + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#include "unwind.h" + +_Unwind_Reason_Code +_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument) +{ + return 0; +} + +_Unwind_Ptr +_Unwind_GetIPInfo (struct _Unwind_Context *c, int *ip_before_insn) +{ + return 0; +} diff --git a/libgcc/config/t-darwin-min-11 b/libgcc/config/t-darwin-min-11 deleted file mode 100644 index 4009d41addb..00000000000 --- a/libgcc/config/t-darwin-min-11 +++ /dev/null @@ -1,3 +0,0 @@ -# Support building with -mmacosx-version-min back to macOS 11. -DARWIN_MIN_LIB_VERSION = -mmacosx-version-min=11 -DARWIN_MIN_CRT_VERSION = -mmacosx-version-min=11 diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 79147b12f14..44a55ee16c3 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,14 @@ +2024-06-06 Thomas Schwinge + Andrew Stubbs + + * configure.ac: No longer set 'LIBGFOR_MINIMAL' for nvptx. + * configure: Regenerate. + +2024-06-06 Thomas Schwinge + + PR target/85463 + * runtime/minimal.c [__nvptx__] (exit): Don't override. + 2024-05-07 Rainer Orth * Makefile.am [LIBGFOR_USE_SYMVER_SUN} (gfortran.ver-sun): Pass diff --git a/libgfortran/configure b/libgfortran/configure index 774dd52fc95..11a1bc5f070 100755 --- a/libgfortran/configure +++ b/libgfortran/configure @@ -6207,17 +6207,12 @@ else fi -# For GPU offloading, not everything in libfortran can be supported. -# Currently, the only target that has this problem is nvptx. The -# following is a (partial) list of features that are unsupportable on -# this particular target: -# * Constructors -# * alloca -# * C library support for I/O, with printf as the one notable exception -# * C library support for other features such as signal, environment -# variables, time functions - - if test "x${target_cpu}" = xnvptx; then +# "Minimal" mode is for targets that cannot (yet) support all features of +# libgfortran. It avoids the need for working constructors, alloca, and C +# library support for I/O, signals, environment variables, time functions, etc. +# At present there are no targets that require this mode. + + if false; then LIBGFOR_MINIMAL_TRUE= LIBGFOR_MINIMAL_FALSE='#' else @@ -12852,7 +12847,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12855 "configure" +#line 12850 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12958,7 +12953,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12961 "configure" +#line 12956 "configure" #include "confdefs.h" #if HAVE_DLFCN_H diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac index 46585a3ee14..cca1ea0ea97 100644 --- a/libgfortran/configure.ac +++ b/libgfortran/configure.ac @@ -209,17 +209,12 @@ AM_CONDITIONAL(LIBGFOR_USE_SYMVER, [test "x$gfortran_use_symver" != xno]) AM_CONDITIONAL(LIBGFOR_USE_SYMVER_GNU, [test "x$gfortran_use_symver" = xgnu]) AM_CONDITIONAL(LIBGFOR_USE_SYMVER_SUN, [test "x$gfortran_use_symver" = xsun]) -# For GPU offloading, not everything in libfortran can be supported. -# Currently, the only target that has this problem is nvptx. The -# following is a (partial) list of features that are unsupportable on -# this particular target: -# * Constructors -# * alloca -# * C library support for I/O, with printf as the one notable exception -# * C library support for other features such as signal, environment -# variables, time functions - -AM_CONDITIONAL(LIBGFOR_MINIMAL, [test "x${target_cpu}" = xnvptx]) +# "Minimal" mode is for targets that cannot (yet) support all features of +# libgfortran. It avoids the need for working constructors, alloca, and C +# library support for I/O, signals, environment variables, time functions, etc. +# At present there are no targets that require this mode. + +AM_CONDITIONAL(LIBGFOR_MINIMAL, false) # Some compiler target support may have limited support for integer # or floating point numbers – or may want to reduce the libgfortran size diff --git a/libgfortran/runtime/minimal.c b/libgfortran/runtime/minimal.c index f13b3a4bf90..619f818c844 100644 --- a/libgfortran/runtime/minimal.c +++ b/libgfortran/runtime/minimal.c @@ -31,14 +31,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #endif -#if __nvptx__ -/* Map "exit" to "abort"; see PR85463 '[nvptx] "exit" in offloaded region - doesn't terminate process'. */ -# undef exit -# define exit(status) do { (void) (status); abort (); } while (0) -#endif - - #if __nvptx__ /* 'printf' is all we have. */ # undef estr_vprintf diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index df78e2c3754..8c685f633c3 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,119 @@ +2024-06-06 Tobias Burnus + + * libgomp.texi (nvptx): Add missing preposition. + +2024-06-06 Thomas Schwinge + Andrew Stubbs + + * libgomp.texi (nvptx): Update. + * testsuite/libgomp.fortran/target-print-1-nvptx.f90: Remove. + * testsuite/libgomp.fortran/target-print-1.f90: Adjust. + * testsuite/libgomp.oacc-fortran/error_stop-2-nvptx.f: New. + * testsuite/libgomp.oacc-fortran/error_stop-2.f: Adjust. + * testsuite/libgomp.oacc-fortran/print-1-nvptx.f90: Adjust. + * testsuite/libgomp.oacc-fortran/print-1.f90: Adjust. + * testsuite/libgomp.oacc-fortran/stop-2-nvptx.f: New. + * testsuite/libgomp.oacc-fortran/stop-2.f: Adjust. + +2024-06-06 Thomas Schwinge + + PR libgomp/97384 + PR libgomp/105274 + * plugin/cuda-lib.def (cuCtxSetLimit): Add. + * plugin/plugin-nvptx.c (nvptx_open_device): Handle + 'GOMP_NVPTX_NATIVE_GPU_THREAD_STACK_SIZE' environment variable. + +2024-06-06 Thomas Schwinge + + * plugin/plugin-nvptx.c (nvptx_do_global_cdtors): New. + (nvptx_close_device, GOMP_OFFLOAD_load_image) + (GOMP_OFFLOAD_unload_image): Call it. + +2024-06-06 Thomas Schwinge + + PR target/85463 + * config/nvptx/error.c (exit): Don't override. + * testsuite/libgomp.oacc-fortran/error_stop-1.f: Update. + * testsuite/libgomp.oacc-fortran/error_stop-2.f: Likewise. + * testsuite/libgomp.oacc-fortran/error_stop-3.f: Likewise. + * testsuite/libgomp.oacc-fortran/stop-1.f: Likewise. + * testsuite/libgomp.oacc-fortran/stop-2.f: Likewise. + * testsuite/libgomp.oacc-fortran/stop-3.f: Likewise. + +2024-06-06 Jakub Jelinek + + * libgomp.texi (OpenMP 5.1 status): Mark Loop transformation constructs + as implemented. + +2024-06-05 Jakub Jelinek + Frederik Harwath + Sandra Loosemore + + * testsuite/libgomp.c-c++-common/imperfect-transform-1.c: New test. + * testsuite/libgomp.c-c++-common/imperfect-transform-2.c: New test. + * testsuite/libgomp.c-c++-common/matrix-1.h: New test. + * testsuite/libgomp.c-c++-common/matrix-constant-iter.h: New test. + * testsuite/libgomp.c-c++-common/matrix-helper.h: New test. + * testsuite/libgomp.c-c++-common/matrix-no-directive-1.c: New test. + * testsuite/libgomp.c-c++-common/matrix-no-directive-unroll-full-1.c: + New test. + * testsuite/libgomp.c-c++-common/matrix-omp-distribute-parallel-for-1.c: + New test. + * testsuite/libgomp.c-c++-common/matrix-omp-for-1.c: New test. + * testsuite/libgomp.c-c++-common/matrix-omp-parallel-for-1.c: New test. + * testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-1.c: + New test. + * testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-simd-1.c: + New test. + * testsuite/libgomp.c-c++-common/matrix-omp-target-parallel-for-1.c: + New test. + * testsuite/libgomp.c-c++-common/matrix-omp-target-teams-distribute-parallel-for-1.c: + New test. + * testsuite/libgomp.c-c++-common/matrix-omp-taskloop-1.c: New test. + * testsuite/libgomp.c-c++-common/matrix-omp-teams-distribute-parallel-for-1.c: + New test. + * testsuite/libgomp.c-c++-common/matrix-simd-1.c: New test. + * testsuite/libgomp.c-c++-common/matrix-transform-variants-1.h: + New test. + * testsuite/libgomp.c-c++-common/target-imperfect-transform-1.c: + New test. + * testsuite/libgomp.c-c++-common/target-imperfect-transform-2.c: + New test. + * testsuite/libgomp.c-c++-common/unroll-1.c: New test. + * testsuite/libgomp.c-c++-common/unroll-non-rect-1.c: New test. + * testsuite/libgomp.c++/matrix-no-directive-unroll-full-1.C: New test. + * testsuite/libgomp.c++/tile-2.C: New test. + * testsuite/libgomp.c++/tile-3.C: New test. + * testsuite/libgomp.c++/unroll-1.C: New test. + * testsuite/libgomp.c++/unroll-2.C: New test. + * testsuite/libgomp.c++/unroll-full-tile.C: New test. + * testsuite/libgomp.fortran/imperfect-transform-1.f90: New test. + * testsuite/libgomp.fortran/imperfect-transform-2.f90: New test. + * testsuite/libgomp.fortran/inner-1.f90: New test. + * testsuite/libgomp.fortran/nested-fn.f90: New test. + * testsuite/libgomp.fortran/target-imperfect-transform-1.f90: New test. + * testsuite/libgomp.fortran/target-imperfect-transform-2.f90: New test. + * testsuite/libgomp.fortran/tile-1.f90: New test. + * testsuite/libgomp.fortran/tile-2.f90: New test. + * testsuite/libgomp.fortran/tile-unroll-1.f90: New test. + * testsuite/libgomp.fortran/tile-unroll-2.f90: New test. + * testsuite/libgomp.fortran/tile-unroll-3.f90: New test. + * testsuite/libgomp.fortran/tile-unroll-4.f90: New test. + * testsuite/libgomp.fortran/unroll-1.f90: New test. + * testsuite/libgomp.fortran/unroll-2.f90: New test. + * testsuite/libgomp.fortran/unroll-3.f90: New test. + * testsuite/libgomp.fortran/unroll-4.f90: New test. + * testsuite/libgomp.fortran/unroll-5.f90: New test. + * testsuite/libgomp.fortran/unroll-6.f90: New test. + * testsuite/libgomp.fortran/unroll-7a.f90: New test. + * testsuite/libgomp.fortran/unroll-7b.f90: New test. + * testsuite/libgomp.fortran/unroll-7c.f90: New test. + * testsuite/libgomp.fortran/unroll-7.f90: New test. + * testsuite/libgomp.fortran/unroll-8.f90: New test. + * testsuite/libgomp.fortran/unroll-simd-1.f90: New test. + * testsuite/libgomp.fortran/unroll-tile-1.f90: New test. + * testsuite/libgomp.fortran/unroll-tile-2.f90: New test. + 2024-05-31 Rainer Orth PR testsuite/115294 diff --git a/libgomp/config/nvptx/error.c b/libgomp/config/nvptx/error.c index 7e668276004..f7a2536c29b 100644 --- a/libgomp/config/nvptx/error.c +++ b/libgomp/config/nvptx/error.c @@ -58,11 +58,4 @@ #endif -/* The 'exit (EXIT_FAILURE);' of an Fortran (only, huh?) OpenMP 'error' - directive with 'severity (fatal)' causes a hang, so 'abort' instead of - 'exit'. */ -#undef exit -#define exit(status) abort () - - #include "../../error.c" diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index d612488ad10..73e8e39ca42 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -302,7 +302,7 @@ The OpenMP 4.5 specification is fully supported. @item @code{error} directive @tab Y @tab @item @code{masked} construct @tab Y @tab @item @code{scope} directive @tab Y @tab -@item Loop transformation constructs @tab N @tab +@item Loop transformation constructs @tab Y @tab @item @code{strict} modifier in the @code{grainsize} and @code{num_tasks} clauses of the @code{taskloop} construct @tab Y @tab @item @code{align} clause in @code{allocate} directive @tab P @@ -6354,7 +6354,7 @@ The used sizes are The implementation remark: @itemize -@item I/O within OpenMP target regions and OpenACC parallel/kernels is supported +@item I/O within OpenMP target regions and OpenACC compute regions is supported using the C library @code{printf} functions and the Fortran @code{print}/@code{write} statements. @item Reverse offload regions (i.e. @code{target} regions with @@ -6429,9 +6429,11 @@ CUDA version and hardware. The implementation remark: @itemize -@item I/O within OpenMP target regions and OpenACC parallel/kernels is supported - using the C library @code{printf} functions. Note that the Fortran - @code{print}/@code{write} statements are not supported, yet. +@item I/O within OpenMP target regions and OpenACC compute regions is supported + using the C library @code{printf} functions. + Additionally, the Fortran @code{print}/@code{write} statements are + supported within OpenMP target regions, but not yet within OpenACC compute + regions. @c The latter needs 'GOMP_NVPTX_NATIVE_GPU_THREAD_STACK_SIZE'. @item Compilation OpenMP code that contains @code{requires reverse_offload} requires at least @code{-march=sm_35}, compiling for @code{-march=sm_30} is not supported. diff --git a/libgomp/plugin/cuda-lib.def b/libgomp/plugin/cuda-lib.def index 007c6e0f4df..9255c1cff68 100644 --- a/libgomp/plugin/cuda-lib.def +++ b/libgomp/plugin/cuda-lib.def @@ -4,6 +4,7 @@ CUDA_ONE_CALL (cuCtxGetCurrent) CUDA_ONE_CALL (cuCtxGetDevice) CUDA_ONE_CALL (cuCtxPopCurrent) CUDA_ONE_CALL (cuCtxPushCurrent) +CUDA_ONE_CALL (cuCtxSetLimit) CUDA_ONE_CALL (cuCtxSynchronize) CUDA_ONE_CALL (cuDeviceGet) CUDA_ONE_CALL (cuDeviceGetAttribute) diff --git a/libgomp/plugin/plugin-nvptx.c b/libgomp/plugin/plugin-nvptx.c index 4cedc5390a3..99cbcb699b3 100644 --- a/libgomp/plugin/plugin-nvptx.c +++ b/libgomp/plugin/plugin-nvptx.c @@ -150,6 +150,8 @@ init_cuda_lib (void) #include "secure_getenv.h" +static void notify_var (const char *, const char *); + #undef MIN #undef MAX #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) @@ -341,11 +343,19 @@ struct ptx_device static struct ptx_device **ptx_devices; +/* "Native" GPU thread stack size. */ +static unsigned native_gpu_thread_stack_size = 0; + /* OpenMP kernels reserve a small amount of ".shared" space for use by omp_alloc. The size is configured using GOMP_NVPTX_LOWLAT_POOL, but the default is set here. */ static unsigned lowlat_pool_size = 8 * 1024; +static bool nvptx_do_global_cdtors (CUmodule, struct ptx_device *, + const char *); +static size_t nvptx_stacks_size (); +static void *nvptx_stacks_acquire (struct ptx_device *, size_t, int); + static inline struct nvptx_thread * nvptx_thread (void) { @@ -550,6 +560,46 @@ nvptx_open_device (int n) ptx_dev->free_blocks = NULL; pthread_mutex_init (&ptx_dev->free_blocks_lock, NULL); + /* "Native" GPU thread stack size. */ + { + /* This is intentionally undocumented, until we work out a proper, common + scheme (as much as makes sense) between all offload plugins as well + as between nvptx offloading use of "native" stacks for OpenACC vs. + OpenMP "soft stacks" vs. OpenMP '-msoft-stack-reserve-local=[...]'. + + GCN offloading has a 'GCN_STACK_SIZE' environment variable (without + 'GOMP_' prefix): documented; presumably used for all things OpenACC and + OpenMP? Based on GCN command-line option '-mstack-size=[...]' (marked + "obsolete"), that one may be set via a GCN 'mkoffload'-synthesized + 'constructor' function. */ + const char *var_name = "GOMP_NVPTX_NATIVE_GPU_THREAD_STACK_SIZE"; + const char *env_var = secure_getenv (var_name); + notify_var (var_name, env_var); + + if (env_var != NULL) + { + char *endptr; + unsigned long val = strtoul (env_var, &endptr, 10); + if (endptr == NULL || *endptr != '\0' + || errno == ERANGE || errno == EINVAL + || val > UINT_MAX) + GOMP_PLUGIN_error ("Error parsing %s", var_name); + else + native_gpu_thread_stack_size = val; + } + } + if (native_gpu_thread_stack_size == 0) + ; /* Zero means use default. */ + else + { + GOMP_PLUGIN_debug (0, "Setting \"native\" GPU thread stack size" + " ('CU_LIMIT_STACK_SIZE') to %u bytes\n", + native_gpu_thread_stack_size); + CUDA_CALL (cuCtxSetLimit, + CU_LIMIT_STACK_SIZE, (size_t) native_gpu_thread_stack_size); + } + + /* OpenMP "soft stacks". */ ptx_dev->omp_stacks.ptr = 0; ptx_dev->omp_stacks.size = 0; pthread_mutex_init (&ptx_dev->omp_stacks.lock, NULL); @@ -565,6 +615,18 @@ nvptx_close_device (struct ptx_device *ptx_dev) if (!ptx_dev) return true; + bool ret = true; + + for (struct ptx_image_data *image = ptx_dev->images; + image != NULL; + image = image->next) + { + if (!nvptx_do_global_cdtors (image->module, ptx_dev, + "__do_global_dtors__entry" + /* or "__do_global_dtors__entry__mgomp" */)) + ret = false; + } + for (struct ptx_free_block *b = ptx_dev->free_blocks; b;) { struct ptx_free_block *b_next = b->next; @@ -585,7 +647,8 @@ nvptx_close_device (struct ptx_device *ptx_dev) CUDA_CALL (cuCtxDestroy, ptx_dev->ctx); free (ptx_dev); - return true; + + return ret; } static int @@ -1317,6 +1380,93 @@ nvptx_set_clocktick (CUmodule module, struct ptx_device *dev) GOMP_PLUGIN_fatal ("cuMemcpyHtoD error: %s", cuda_error (r)); } +/* Invoke MODULE's global constructors/destructors. */ + +static bool +nvptx_do_global_cdtors (CUmodule module, struct ptx_device *ptx_dev, + const char *funcname) +{ + bool ret = true; + char *funcname_mgomp = NULL; + CUresult r; + CUfunction funcptr; + r = CUDA_CALL_NOCHECK (cuModuleGetFunction, + &funcptr, module, funcname); + GOMP_PLUGIN_debug (0, "cuModuleGetFunction (%s): %s\n", + funcname, cuda_error (r)); + if (r == CUDA_ERROR_NOT_FOUND) + { + /* Try '[funcname]__mgomp'. */ + + size_t funcname_len = strlen (funcname); + const char *mgomp_suffix = "__mgomp"; + size_t mgomp_suffix_len = strlen (mgomp_suffix); + funcname_mgomp + = GOMP_PLUGIN_malloc (funcname_len + mgomp_suffix_len + 1); + memcpy (funcname_mgomp, funcname, funcname_len); + memcpy (funcname_mgomp + funcname_len, + mgomp_suffix, mgomp_suffix_len + 1); + funcname = funcname_mgomp; + + r = CUDA_CALL_NOCHECK (cuModuleGetFunction, + &funcptr, module, funcname); + GOMP_PLUGIN_debug (0, "cuModuleGetFunction (%s): %s\n", + funcname, cuda_error (r)); + } + if (r == CUDA_ERROR_NOT_FOUND) + ; + else if (r != CUDA_SUCCESS) + { + GOMP_PLUGIN_error ("cuModuleGetFunction (%s) error: %s", + funcname, cuda_error (r)); + ret = false; + } + else + { + /* If necessary, set up soft stack. */ + void *nvptx_stacks_0; + void *kargs[1]; + if (funcname_mgomp) + { + size_t stack_size = nvptx_stacks_size (); + pthread_mutex_lock (&ptx_dev->omp_stacks.lock); + nvptx_stacks_0 = nvptx_stacks_acquire (ptx_dev, stack_size, 1); + nvptx_stacks_0 += stack_size; + kargs[0] = &nvptx_stacks_0; + } + r = CUDA_CALL_NOCHECK (cuLaunchKernel, + funcptr, + 1, 1, 1, 1, 1, 1, + /* sharedMemBytes */ 0, + /* hStream */ NULL, + /* kernelParams */ funcname_mgomp ? kargs : NULL, + /* extra */ NULL); + if (r != CUDA_SUCCESS) + { + GOMP_PLUGIN_error ("cuLaunchKernel (%s) error: %s", + funcname, cuda_error (r)); + ret = false; + } + + r = CUDA_CALL_NOCHECK (cuStreamSynchronize, + NULL); + if (r != CUDA_SUCCESS) + { + GOMP_PLUGIN_error ("cuStreamSynchronize (%s) error: %s", + funcname, cuda_error (r)); + ret = false; + } + + if (funcname_mgomp) + pthread_mutex_unlock (&ptx_dev->omp_stacks.lock); + } + + if (funcname_mgomp) + free (funcname_mgomp); + + return ret; +} + /* Load the (partial) program described by TARGET_DATA to device number ORD. Allocate and return TARGET_TABLE. If not NULL, REV_FN_TABLE will contain the on-device addresses of the functions for reverse offload. @@ -1546,6 +1696,11 @@ GOMP_OFFLOAD_load_image (int ord, unsigned version, const void *target_data, nvptx_set_clocktick (module, dev); + if (!nvptx_do_global_cdtors (module, dev, + "__do_global_ctors__entry" + /* or "__do_global_ctors__entry__mgomp" */)) + return -1; + return fn_entries + var_entries + other_entries; } @@ -1571,6 +1726,11 @@ GOMP_OFFLOAD_unload_image (int ord, unsigned version, const void *target_data) for (prev_p = &dev->images; (image = *prev_p) != 0; prev_p = &image->next) if (image->target_data == target_data) { + if (!nvptx_do_global_cdtors (image->module, dev, + "__do_global_dtors__entry" + /* or "__do_global_dtors__entry__mgomp" */)) + ret = false; + *prev_p = image->next; if (CUDA_CALL_NOCHECK (cuModuleUnload, image->module) != CUDA_SUCCESS) ret = false; diff --git a/libgomp/testsuite/libgomp.c++/matrix-no-directive-unroll-full-1.C b/libgomp/testsuite/libgomp.c++/matrix-no-directive-unroll-full-1.C new file mode 100644 index 00000000000..ef9469bfaaf --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/matrix-no-directive-unroll-full-1.C @@ -0,0 +1,13 @@ +/* { dg-additional-options "-O0 -fdump-tree-original -Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE +#define COMMON_TOP_TRANSFORM omp unroll full +#define COLLAPSE_1 +#define COLLAPSE_2 +#define COLLAPSE_3 +#define IMPLEMENTATION_FILE "../libgomp.c-c++-common/matrix-constant-iter.h" + +#include "../libgomp.c-c++-common/matrix-transform-variants-1.h" + +/* A consistency check to prevent broken macro usage. */ +/* { dg-final { scan-tree-dump-times "unroll full" 13 "original" } } */ diff --git a/libgomp/testsuite/libgomp.c++/tile-2.C b/libgomp/testsuite/libgomp.c++/tile-2.C new file mode 100644 index 00000000000..6bb635bf9ea --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/tile-2.C @@ -0,0 +1,57 @@ +// { dg-additional-options "-std=c++11 -O0" } + +#include + +constexpr unsigned +fib (unsigned n) +{ + return n <= 2 ? 1 : fib (n-1) + fib (n-2); +} + +int +test1 () +{ + std::vector v; + + for (unsigned i = 0; i <= 9; i++) + v.push_back (1); + + int sum = 0; + for (int k = 0; k < 10; k++) + #pragma omp tile sizes(fib(4)) + for (int i : v) { + for (int j = 8; j != -2; --j) + sum = sum + i; + } + + return sum; +} + +int +test2 () +{ + std::vector v; + + for (unsigned i = 0; i <= 10; i++) + v.push_back (i); + + int sum = 0; + for (int k = 0; k < 10; k++) + #pragma omp parallel for collapse(2) reduction(+:sum) + #pragma omp tile sizes(fib(4), 1) + for (int i : v) + for (int j = 8; j > -2; --j) + sum = sum + i; + + return sum; +} + +int +main () +{ + if (test1 () != 1000) + __builtin_abort (); + + if (test2 () != 5500) + __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c++/tile-3.C b/libgomp/testsuite/libgomp.c++/tile-3.C new file mode 100644 index 00000000000..2bf9a79d18d --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/tile-3.C @@ -0,0 +1,26 @@ +// { dg-additional-options "-std=c++11 -O0" } + +#include + +int +main () +{ + std::vector v; + std::vector w; + + for (unsigned i = 0; i <= 9; i++) + v.push_back (i); + + int iter = 0; + #pragma omp for + #pragma omp tile sizes(5) + for (int i : v) + { + w.push_back (iter); + iter++; + } + + for (int i = 0; i < w.size (); i++) + if (w[i] != i) + __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c++/unroll-1.C b/libgomp/testsuite/libgomp.c++/unroll-1.C new file mode 100644 index 00000000000..84b6c62cbf6 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/unroll-1.C @@ -0,0 +1,63 @@ +// { dg-additional-options "-std=c++11 -O0" } + +#include +#include + +constexpr unsigned +fib (unsigned n) +{ + return n <= 2 ? 1 : fib (n-1) + fib (n-2); +} + +int +test1 () +{ + std::vector v; + + for (unsigned i = 0; i <= 9; i++) + v.push_back (1); + + int sum = 0; + for (int k = 0; k < 10; k++) + #pragma omp unroll partial(fib(3)) + for (int i : v) + { + for (int j = 8; j != -2; --j) + sum = sum + i; + } + + return sum; +} + +int +test2 () +{ + std::vector v; + + for (unsigned i = 0; i <= 10; i++) + v.push_back (i); + + int sum = 0; + #pragma omp parallel for reduction(+:sum) + for (int k = 0; k < 10; k++) + #pragma omp unroll + #pragma omp unroll partial(fib(4)) + for (int i : v) + { + #pragma omp unroll full + for (int j = 8; j != -2; --j) + sum = sum + i; + } + + return sum; +} + +int +main () +{ + if (test1 () != 1000) + __builtin_abort (); + + if (test2 () != 5500) + __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c++/unroll-2.C b/libgomp/testsuite/libgomp.c++/unroll-2.C new file mode 100644 index 00000000000..592dbfee099 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/unroll-2.C @@ -0,0 +1,31 @@ +// { dg-do run } +// { dg-additional-options "-std=c++11" } + +#include +#include + +int +main () +{ + std::vector> v; + std::vector w; + + for (unsigned i = 0; i < 10; i++) + { + std::vector u; + for (unsigned j = 0; j < 10; j++) + u.push_back (j); + v.push_back (u); + } + + #pragma omp for + #pragma omp unroll partial(7) + for (auto u : v) + for (int x : u) + w.push_back (x); + + std::size_t l = w.size (); + for (std::size_t i = 0; i < l; i++) + if (w[i] != i % 10) + __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c++/unroll-full-tile.C b/libgomp/testsuite/libgomp.c++/unroll-full-tile.C new file mode 100644 index 00000000000..19633a8bb8b --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/unroll-full-tile.C @@ -0,0 +1,81 @@ +template +int sum () +{ + int sum = 0; + #pragma omp unroll full + #pragma omp tile sizes (dim0, dim1) + for (unsigned i = 0; i < 4; i++) + for (unsigned j = 0; j < 5; j++) + sum++; + + return sum; +} + +int main () +{ + if (sum <1,1> () != 20) + __builtin_abort (); + if (sum <1,2> () != 20) + __builtin_abort (); + if (sum <1,3> () != 20) + __builtin_abort (); + if (sum <1,4> () != 20) + __builtin_abort (); + if (sum <1,5> () != 20) + __builtin_abort (); + + if (sum <2,1> () != 20) + __builtin_abort (); + if (sum <2,2> () != 20) + __builtin_abort (); + if (sum <2,3> () != 20) + __builtin_abort (); + if (sum <2,4> () != 20) + __builtin_abort (); + if (sum <2,5> () != 20) + __builtin_abort (); + + if (sum <3,1> () != 20) + __builtin_abort (); + if (sum <3,2> () != 20) + __builtin_abort (); + if (sum <3,3> () != 20) + __builtin_abort (); + if (sum <3,4> () != 20) + __builtin_abort (); + if (sum <3,5> () != 20) + __builtin_abort (); + + if (sum <4,1> () != 20) + __builtin_abort (); + if (sum <4,2> () != 20) + __builtin_abort (); + if (sum <4,3> () != 20) + __builtin_abort (); + if (sum <4,4> () != 20) + __builtin_abort (); + if (sum <4,5> () != 20) + __builtin_abort (); + + if (sum <5,1> () != 20) + __builtin_abort (); + if (sum <5,2> () != 20) + __builtin_abort (); + if (sum <5,3> () != 20) + __builtin_abort (); + if (sum <5,4> () != 20) + __builtin_abort (); + if (sum <5,5> () != 20) + __builtin_abort (); + + if (sum <6,1> () != 20) + __builtin_abort (); + if (sum <6,2> () != 20) + __builtin_abort (); + if (sum <6,3> () != 20) + __builtin_abort (); + if (sum <6,4> () != 20) + __builtin_abort (); + if (sum <6,5> () != 20) + __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/imperfect-transform-1.c b/libgomp/testsuite/libgomp.c-c++-common/imperfect-transform-1.c new file mode 100644 index 00000000000..2eafe04077c --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/imperfect-transform-1.c @@ -0,0 +1,76 @@ +/* { dg-do run } */ + +/* Like imperfect1.c, but also includes loop transforms. */ + +static int f1count[3], f2count[3]; + +int +f1 (int depth, int iter) +{ + f1count[depth]++; + return iter; +} + +int +f2 (int depth, int iter) +{ + f2count[depth]++; + return iter; +} + +void +s1 (int a1, int a2, int a3) +{ + int i, j, k; + + #pragma omp for collapse(2) private (j, k) + for (i = 0; i < a1; i++) + { + f1 (0, i); + for (j = 0; j < a2; j++) + { + f1 (1, j); + #pragma omp unroll partial + for (k = 0; k < a3; k++) + { + f1 (2, k); + f2 (2, k); + } + f2 (1, j); + } + f2 (0, i); + } +} + +int +main () +{ + f1count[0] = 0; + f1count[1] = 0; + f1count[2] = 0; + f2count[0] = 0; + f2count[1] = 0; + f2count[2] = 0; + + s1 (3, 4, 5); + + /* All intervening code at the same depth must be executed the same + number of times. */ + if (f1count[0] != f2count[0]) __builtin_abort (); + if (f1count[1] != f2count[1]) __builtin_abort (); + if (f1count[2] != f2count[2]) __builtin_abort (); + + /* Intervening code must be executed at least as many times as the loop + that encloses it. */ + if (f1count[0] < 3) __builtin_abort (); + if (f1count[1] < 3 * 4) __builtin_abort (); + + /* Intervening code must not be executed more times than the number + of logical iterations. */ + if (f1count[0] > 3 * 4 * 5) __builtin_abort (); + if (f1count[1] > 3 * 4 * 5) __builtin_abort (); + + /* Check that the innermost loop body is executed exactly the number + of logical iterations expected. */ + if (f1count[2] != 3 * 4 * 5) __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/imperfect-transform-2.c b/libgomp/testsuite/libgomp.c-c++-common/imperfect-transform-2.c new file mode 100644 index 00000000000..0d5e0b419b1 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/imperfect-transform-2.c @@ -0,0 +1,76 @@ +/* { dg-do run } */ + +/* Like imperfect1.c, but also includes loop transforms. */ + +static int f1count[3], f2count[3]; + +int +f1 (int depth, int iter) +{ + f1count[depth]++; + return iter; +} + +int +f2 (int depth, int iter) +{ + f2count[depth]++; + return iter; +} + +void +s1 (int a1, int a2, int a3) +{ + int i, j, k; + + #pragma omp for collapse(2) private (j, k) + for (i = 0; i < a1; i++) + { + f1 (0, i); + for (j = 0; j < a2; j++) + { + f1 (1, j); + #pragma omp tile sizes(5) + for (k = 0; k < a3; k++) + { + f1 (2, k); + f2 (2, k); + } + f2 (1, j); + } + f2 (0, i); + } +} + +int +main () +{ + f1count[0] = 0; + f1count[1] = 0; + f1count[2] = 0; + f2count[0] = 0; + f2count[1] = 0; + f2count[2] = 0; + + s1 (3, 4, 5); + + /* All intervening code at the same depth must be executed the same + number of times. */ + if (f1count[0] != f2count[0]) __builtin_abort (); + if (f1count[1] != f2count[1]) __builtin_abort (); + if (f1count[2] != f2count[2]) __builtin_abort (); + + /* Intervening code must be executed at least as many times as the loop + that encloses it. */ + if (f1count[0] < 3) __builtin_abort (); + if (f1count[1] < 3 * 4) __builtin_abort (); + + /* Intervening code must not be executed more times than the number + of logical iterations. */ + if (f1count[0] > 3 * 4 * 5) __builtin_abort (); + if (f1count[1] > 3 * 4 * 5) __builtin_abort (); + + /* Check that the innermost loop body is executed exactly the number + of logical iterations expected. */ + if (f1count[2] != 3 * 4 * 5) __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-1.h b/libgomp/testsuite/libgomp.c-c++-common/matrix-1.h new file mode 100644 index 00000000000..b2e9273c51c --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-1.h @@ -0,0 +1,82 @@ +#include +#include +#include +#include + +#ifndef FUN_NAME_SUFFIX +#define FUN_NAME_SUFFIX +#endif + +#ifdef MULT +#undef MULT +#endif +#define MULT CAT(mult, FUN_NAME_SUFFIX) + +#ifdef MAIN +#undef MAIN +#endif +#define MAIN CAT(main, FUN_NAME_SUFFIX) + +void +MULT (float *matrix1, float *matrix2, float *result, + unsigned dim0, unsigned dim1) +{ + memset (result, 0, sizeof (float) * dim0 * dim1); + DIRECTIVE + TRANSFORMATION1 + for (unsigned i = 0; i < dim0; i++) + TRANSFORMATION2 + for (unsigned j = 0; j < dim1; j++) + TRANSFORMATION3 + for (unsigned k = 0; k < dim1; k++) + result[i * dim1 + j] += matrix1[i * dim1 + k] * matrix2[k * dim0 + j]; +} + +int +MAIN () +{ + unsigned dim0 = 20; + unsigned dim1 = 20; + + float *result = (float *) malloc (sizeof (float) * dim0 * dim1); + float *matrix1 = (float *) malloc (sizeof (float) * dim0 * dim1); + float *matrix2 = (float *) malloc (sizeof (float) * dim0 * dim1); + + for (unsigned i = 0; i < dim0; i++) + for (unsigned j = 0; j < dim1; j++) + matrix1[i * dim1 + j] = j; + + for (unsigned i = 0; i < dim0; i++) + for (unsigned j = 0; j < dim1; j++) + if (i == j) + matrix2[i * dim1 + j] = 1; + else + matrix2[i * dim1 + j] = 0; + + MULT (matrix1, matrix2, result, dim0, dim1); + + for (unsigned i = 0; i < dim0; i++) + for (unsigned j = 0; j < dim1; j++) + { + if (matrix1[i * dim1 + j] != result[i * dim1 + j]) + { + print_matrix (matrix1, dim0, dim1); + print_matrix (matrix2, dim0, dim1); + print_matrix (result, dim0, dim1); + fprintf (stderr, "%s: ERROR at %d, %d\n", __FUNCTION__, i, j); + abort (); + } + } + + free (matrix2); + free (matrix1); + free (result); + + return 0; +} + +#undef DIRECTIVE +#undef TRANSFORMATION1 +#undef TRANSFORMATION2 +#undef TRANSFORMATION3 +#undef FUN_NAME_SUFFIX diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-constant-iter.h b/libgomp/testsuite/libgomp.c-c++-common/matrix-constant-iter.h new file mode 100644 index 00000000000..8769e737284 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-constant-iter.h @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +#ifndef FUN_NAME_SUFFIX +#define FUN_NAME_SUFFIX +#endif + +#ifdef MULT +#undef MULT +#endif +#define MULT CAT(mult, FUN_NAME_SUFFIX) + +#ifdef MAIN +#undef MAIN +#endif +#define MAIN CAT(main, FUN_NAME_SUFFIX) + +void +MULT (float *matrix1, float *matrix2, float *result) +{ + const unsigned dim0 = 20; + const unsigned dim1 = 20; + + memset (result, 0, sizeof (float) * dim0 * dim1); + DIRECTIVE + TRANSFORMATION1 + for (unsigned i = 0; i < dim0; i++) + TRANSFORMATION2 + for (unsigned j = 0; j < dim1; j++) + TRANSFORMATION3 + for (unsigned k = 0; k < dim1; k++) + result[i * dim1 + j] += matrix1[i * dim1 + k] * matrix2[k * dim0 + j]; +} + +int +MAIN () +{ + const unsigned dim0 = 20; + const unsigned dim1 = 20; + + float *result = (float *) malloc (sizeof (float) * dim0 * dim1); + float *matrix1 = (float *) malloc (sizeof (float) * dim0 * dim1); + float *matrix2 = (float *) malloc (sizeof (float) * dim0 * dim1); + + for (unsigned i = 0; i < dim0; i++) + for (unsigned j = 0; j < dim1; j++) + matrix1[i * dim1 + j] = j; + + for (unsigned i = 0; i < dim0; i++) + for (unsigned j = 0; j < dim1; j++) + if (i == j) + matrix2[i * dim1 + j] = 1; + else + matrix2[i * dim1 + j] = 0; + + MULT (matrix1, matrix2, result); + + for (unsigned i = 0; i < dim0; i++) + for (unsigned j = 0; j < dim1; j++) + { + if (matrix1[i * dim1 + j] != result[i * dim1 + j]) + { + printf ("%s: error at %d, %d\n", __FUNCTION__, i, j); + print_matrix (matrix1, dim0, dim1); + print_matrix (matrix2, dim0, dim1); + print_matrix (result, dim0, dim1); + printf ("\n"); + abort (); + } + } + + free (matrix2); + free (matrix1); + free (result); + + return 0; +} + +#undef DIRECTIVE +#undef TRANSFORMATION1 +#undef TRANSFORMATION2 +#undef TRANSFORMATION3 +#undef FUN_NAME_SUFFIX diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-helper.h b/libgomp/testsuite/libgomp.c-c++-common/matrix-helper.h new file mode 100644 index 00000000000..168a1328795 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-helper.h @@ -0,0 +1,19 @@ +#include +#include + +#define CAT(x,y) XCAT(x,y) +#define XCAT(x,y) x ## y +#define DO_PRAGMA(x) XDO_PRAGMA(x) +#define XDO_PRAGMA(x) _Pragma (#x) + +void +print_matrix (float *matrix, unsigned dim0, unsigned dim1) +{ + for (unsigned i = 0; i < dim0; i++) + { + for (unsigned j = 0; j < dim1; j++) + fprintf (stderr, "%f ", matrix[i * dim1 + j]); + fprintf (stderr, "\n"); + } + fprintf (stderr, "\n"); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-no-directive-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-no-directive-1.c new file mode 100644 index 00000000000..7405ab883b9 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-no-directive-1.c @@ -0,0 +1,11 @@ +/* { dg-additional-options "-fdump-tree-original -Wall -Wno-unknown-pragmas" } */ + +#undef COMMON_DIRECTIVE +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 collapse(3) + +#include "matrix-transform-variants-1.h" + +/* A consistency check to prevent broken macro usage. */ +/* { dg-final { scan-tree-dump-times "unroll partial" 12 "original" } } */ diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-no-directive-unroll-full-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-no-directive-unroll-full-1.c new file mode 100644 index 00000000000..d8ef67f1854 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-no-directive-unroll-full-1.c @@ -0,0 +1,13 @@ +/* { dg-additional-options "-O2 -fdump-tree-original -Wall -Wno-unknown-pragmas" } */ + +#undef COMMON_DIRECTIVE +#define COMMON_TOP_TRANSFORM omp unroll full +#define COLLAPSE_1 +#define COLLAPSE_2 +#define COLLAPSE_3 +#define IMPLEMENTATION_FILE "matrix-constant-iter.h" + +#include "matrix-transform-variants-1.h" + +/* A consistency check to prevent broken macro usage. */ +/* { dg-final { scan-tree-dump-times "unroll full" 13 "original" } } */ diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-distribute-parallel-for-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-distribute-parallel-for-1.c new file mode 100644 index 00000000000..27e313672d8 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-distribute-parallel-for-1.c @@ -0,0 +1,8 @@ +/* { dg-additional-options "-Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE "omp teams distribute parallel for" +#define COLLAPSE_1 "collapse(1)" +#define COLLAPSE_2 "collapse(2)" +#define COLLAPSE_3 "collapse(3)" + +#include "matrix-transform-variants-1.h" diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-for-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-for-1.c new file mode 100644 index 00000000000..c91ae4d8e04 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-for-1.c @@ -0,0 +1,13 @@ +/* { dg-additional-options "-fdump-tree-original -Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE omp for +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 collapse(3) + +#include "matrix-transform-variants-1.h" + + +/* A consistency check to prevent broken macro usage. */ +/* { dg-final { scan-tree-dump-times "omp for" 13 "original" } } */ +/* { dg-final { scan-tree-dump-times "collapse" 12 "original" } } */ diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-parallel-for-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-parallel-for-1.c new file mode 100644 index 00000000000..cb4cd1cce2d --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-parallel-for-1.c @@ -0,0 +1,13 @@ +/* { dg-additional-options "-fdump-tree-original -Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE omp parallel for +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 + +#include "matrix-transform-variants-1.h" + + +/* A consistency check to prevent broken macro usage. */ +/* { dg-final { scan-tree-dump-times "omp parallel" 13 "original" } } */ +/* { dg-final { scan-tree-dump-times "collapse" 9 "original" } } */ diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-1.c new file mode 100644 index 00000000000..5b88fa5d662 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-1.c @@ -0,0 +1,8 @@ +/* { dg-additional-options "-Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE omp parallel masked taskloop +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 + +#include "matrix-transform-variants-1.h" diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-simd-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-simd-1.c new file mode 100644 index 00000000000..ad7b838aee2 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-parallel-masked-taskloop-simd-1.c @@ -0,0 +1,8 @@ +/* { dg-additional-options "-Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE omp parallel masked taskloop simd +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 + +#include "matrix-transform-variants-1.h" diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-target-parallel-for-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-target-parallel-for-1.c new file mode 100644 index 00000000000..7d0968e82cf --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-target-parallel-for-1.c @@ -0,0 +1,15 @@ +/* This test appears to have too much parallelism to run without a GPU. */ +/* { dg-do run { target { offload_device } } } */ +/* { dg-additional-options "-fdump-tree-original -Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE omp target parallel for map(tofrom:result[0:dim0 * dim1]) map(to:matrix1[0:dim0 * dim1], matrix2[0:dim0 * dim1]) +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 + +#include "matrix-transform-variants-1.h" + +/* A consistency check to prevent broken macro usage. */ +/* { dg-final { scan-tree-dump-times "omp target" 13 "original" } } */ +/* { dg-final { scan-tree-dump-times "collapse" 9 "original" } } */ +/* { dg-final { scan-tree-dump-times "unroll partial" 12 "original" } } */ diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-target-teams-distribute-parallel-for-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-target-teams-distribute-parallel-for-1.c new file mode 100644 index 00000000000..c86050e2f9c --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-target-teams-distribute-parallel-for-1.c @@ -0,0 +1,10 @@ +/* This test appears to have too much parallelism to run without a GPU. */ +/* { dg-do run { target { offload_device } } } */ +/* { dg-additional-options "-Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE omp target teams distribute parallel for map(tofrom:result[:dim0 * dim1]) map(to:matrix1[0:dim0 * dim1], matrix2[0:dim0 * dim1]) +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 + +#include "matrix-transform-variants-1.h" diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-taskloop-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-taskloop-1.c new file mode 100644 index 00000000000..53d49b40d5f --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-taskloop-1.c @@ -0,0 +1,8 @@ +/* { dg-additional-options "-Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE omp taskloop +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 collapse(3) + +#include "matrix-transform-variants-1.h" diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-teams-distribute-parallel-for-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-teams-distribute-parallel-for-1.c new file mode 100644 index 00000000000..7f61dab8976 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-omp-teams-distribute-parallel-for-1.c @@ -0,0 +1,8 @@ +/* { dg-additional-options "-Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE omp teams distribute parallel for +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 + +#include "matrix-transform-variants-1.h" diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-simd-1.c b/libgomp/testsuite/libgomp.c-c++-common/matrix-simd-1.c new file mode 100644 index 00000000000..4c4bc367041 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-simd-1.c @@ -0,0 +1,8 @@ +/* { dg-additional-options "-Wall -Wno-unknown-pragmas" } */ + +#define COMMON_DIRECTIVE omp simd +#define COLLAPSE_1 collapse(1) +#define COLLAPSE_2 collapse(2) +#define COLLAPSE_3 collapse(3) + +#include "matrix-transform-variants-1.h" diff --git a/libgomp/testsuite/libgomp.c-c++-common/matrix-transform-variants-1.h b/libgomp/testsuite/libgomp.c-c++-common/matrix-transform-variants-1.h new file mode 100644 index 00000000000..6b5241f6b08 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/matrix-transform-variants-1.h @@ -0,0 +1,171 @@ +#include "matrix-helper.h" + +#ifndef COMMON_TOP_TRANSFORM +#define COMMON_TOP_TRANSFORM +#endif + +#ifndef IMPLEMENTATION_FILE +#define IMPLEMENTATION_FILE "matrix-1.h" +#endif + +#define FUN_NAME_SUFFIX 1 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp unroll partial(2)") _Pragma("omp tile sizes(10)") +#define TRANSFORMATION2 +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 2 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_3) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp tile sizes(8,16,4)") +#define TRANSFORMATION2 +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 3 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_2) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp tile sizes(8, 8)") +#define TRANSFORMATION2 +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 4 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_1) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp tile sizes(8, 8)") +#define TRANSFORMATION2 +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 5 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_1) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp tile sizes(8, 8, 8)") +#define TRANSFORMATION2 +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 6 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_1) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp tile sizes(10)") _Pragma("omp unroll partial(2)") +#define TRANSFORMATION2 +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 7 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_2) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp tile sizes(7, 11)") +#define TRANSFORMATION2 _Pragma("omp unroll partial(7)") +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 8 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_2) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp tile sizes(7, 11)") +#define TRANSFORMATION2 _Pragma("omp tile sizes(7)") _Pragma("omp unroll partial(7)") +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 9 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_2) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp tile sizes(7, 11)") +#define TRANSFORMATION2 _Pragma("omp tile sizes(7)") _Pragma("omp unroll partial(3)") _Pragma("omp tile sizes(7)") +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 10 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_1) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) _Pragma("omp unroll partial(5)") _Pragma("omp tile sizes(7)") _Pragma("omp unroll partial(3)") _Pragma("omp tile sizes(7)") +#define TRANSFORMATION2 +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 11 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_2) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) +#define TRANSFORMATION2 _Pragma("omp unroll partial(5)") _Pragma("omp tile sizes(7)") _Pragma("omp unroll partial(3)") _Pragma("omp tile sizes(7)") +#define TRANSFORMATION3 +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 12 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_3) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) +#define TRANSFORMATION2 +#define TRANSFORMATION3 _Pragma("omp unroll partial(5)") _Pragma("omp tile sizes(7)") _Pragma("omp unroll partial(3)") _Pragma("omp tile sizes(7)") +#include IMPLEMENTATION_FILE + +#define FUN_NAME_SUFFIX 13 +#ifdef COMMON_DIRECTIVE +#define DIRECTIVE DO_PRAGMA(COMMON_DIRECTIVE COLLAPSE_3) +#else +#define DIRECTIVE +#endif +#define TRANSFORMATION1 DO_PRAGMA(COMMON_TOP_TRANSFORM) +#define TRANSFORMATION2 _Pragma("omp tile sizes(7,8)") +#define TRANSFORMATION3 _Pragma("omp unroll partial(3)") _Pragma("omp tile sizes(7)") +#include IMPLEMENTATION_FILE + +int +main () +{ + main1 (); + main2 (); + main3 (); + main4 (); + main5 (); + main6 (); + main7 (); + main8 (); + main9 (); + main10 (); + main11 (); + main12 (); + main13 (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-imperfect-transform-1.c b/libgomp/testsuite/libgomp.c-c++-common/target-imperfect-transform-1.c new file mode 100644 index 00000000000..2dc1e91ee0e --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/target-imperfect-transform-1.c @@ -0,0 +1,79 @@ +/* { dg-do run } */ + +/* Like imperfect-transform.c, but enables offloading. */ + +static int f1count[3], f2count[3]; +#pragma omp declare target enter (f1count, f2count) + +int +f1 (int depth, int iter) +{ + #pragma omp atomic + f1count[depth]++; + return iter; +} + +int +f2 (int depth, int iter) +{ + #pragma omp atomic + f2count[depth]++; + return iter; +} + +void +s1 (int a1, int a2, int a3) +{ + int i, j, k; + + #pragma omp target parallel for collapse(2) map(always, tofrom:f1count, f2count) private (j, k) + for (i = 0; i < a1; i++) + { + f1 (0, i); + for (j = 0; j < a2; j++) + { + f1 (1, j); + #pragma omp unroll partial + for (k = 0; k < a3; k++) + { + f1 (2, k); + f2 (2, k); + } + f2 (1, j); + } + f2 (0, i); + } +} + +int +main () +{ + f1count[0] = 0; + f1count[1] = 0; + f1count[2] = 0; + f2count[0] = 0; + f2count[1] = 0; + f2count[2] = 0; + + s1 (3, 4, 5); + + /* All intervening code at the same depth must be executed the same + number of times. */ + if (f1count[0] != f2count[0]) __builtin_abort (); + if (f1count[1] != f2count[1]) __builtin_abort (); + if (f1count[2] != f2count[2]) __builtin_abort (); + + /* Intervening code must be executed at least as many times as the loop + that encloses it. */ + if (f1count[0] < 3) __builtin_abort (); + if (f1count[1] < 3 * 4) __builtin_abort (); + + /* Intervening code must not be executed more times than the number + of logical iterations. */ + if (f1count[0] > 3 * 4 * 5) __builtin_abort (); + if (f1count[1] > 3 * 4 * 5) __builtin_abort (); + + /* Check that the innermost loop body is executed exactly the number + of logical iterations expected. */ + if (f1count[2] != 3 * 4 * 5) __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-imperfect-transform-2.c b/libgomp/testsuite/libgomp.c-c++-common/target-imperfect-transform-2.c new file mode 100644 index 00000000000..ea5a9293836 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/target-imperfect-transform-2.c @@ -0,0 +1,79 @@ +/* { dg-do run } */ + +/* Like imperfect-transform.c, but enables offloading. */ + +static int f1count[3], f2count[3]; +#pragma omp declare target enter (f1count, f2count) + +int +f1 (int depth, int iter) +{ + #pragma omp atomic + f1count[depth]++; + return iter; +} + +int +f2 (int depth, int iter) +{ + #pragma omp atomic + f2count[depth]++; + return iter; +} + +void +s1 (int a1, int a2, int a3) +{ + int i, j, k; + + #pragma omp target parallel for collapse(2) map(always, tofrom:f1count, f2count) private (j, k) + for (i = 0; i < a1; i++) + { + f1 (0, i); + for (j = 0; j < a2; j++) + { + f1 (1, j); + #pragma omp tile sizes(5) + for (k = 0; k < a3; k++) + { + f1 (2, k); + f2 (2, k); + } + f2 (1, j); + } + f2 (0, i); + } +} + +int +main () +{ + f1count[0] = 0; + f1count[1] = 0; + f1count[2] = 0; + f2count[0] = 0; + f2count[1] = 0; + f2count[2] = 0; + + s1 (3, 4, 5); + + /* All intervening code at the same depth must be executed the same + number of times. */ + if (f1count[0] != f2count[0]) __builtin_abort (); + if (f1count[1] != f2count[1]) __builtin_abort (); + if (f1count[2] != f2count[2]) __builtin_abort (); + + /* Intervening code must be executed at least as many times as the loop + that encloses it. */ + if (f1count[0] < 3) __builtin_abort (); + if (f1count[1] < 3 * 4) __builtin_abort (); + + /* Intervening code must not be executed more times than the number + of logical iterations. */ + if (f1count[0] > 3 * 4 * 5) __builtin_abort (); + if (f1count[1] > 3 * 4 * 5) __builtin_abort (); + + /* Check that the innermost loop body is executed exactly the number + of logical iterations expected. */ + if (f1count[2] != 3 * 4 * 5) __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/unroll-1.c b/libgomp/testsuite/libgomp.c-c++-common/unroll-1.c new file mode 100644 index 00000000000..81fcf4ad2fa --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/unroll-1.c @@ -0,0 +1,70 @@ +/* { dg-additional-options "-Wall -Wno-unknown-pragmas" } */ + +int +compute_sum1 (void) +{ + int sum = 0; + int i, j; + + #pragma omp parallel for reduction(+:sum) lastprivate(j) + #pragma omp unroll partial + for (i = 3; i < 10; ++i) + for (j = -2; j < 7; ++j) + sum++; + + if (j != 7) + __builtin_abort (); + + return sum; +} + +int +compute_sum2 (void) +{ + int sum = 0; + int i, j; + + #pragma omp parallel for reduction(+:sum) lastprivate(j) + #pragma omp unroll partial(5) + for (i = 3; i < 10; ++i) + for (j = -2; j < 7; ++j) + sum++; + + if (j != 7) + __builtin_abort (); + + return sum; +} + +int +compute_sum3 (void) +{ + int sum = 0; + int i, j; + + #pragma omp parallel for reduction(+:sum) lastprivate(j) + #pragma omp unroll partial(1) + for (i = 3; i < 10; ++i) + for (j = -2; j < 7; ++j) + sum++; + + if (j != 7) + __builtin_abort (); + + return sum; +} + +int +main () +{ + if (compute_sum1 () != 7 * 9) + __builtin_abort (); + + if (compute_sum2 () != 7 * 9) + __builtin_abort (); + + if (compute_sum3 () != 7 * 9) + __builtin_abort (); + + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/unroll-non-rect-1.c b/libgomp/testsuite/libgomp.c-c++-common/unroll-non-rect-1.c new file mode 100644 index 00000000000..d2515b0e9e7 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/unroll-non-rect-1.c @@ -0,0 +1,118 @@ +/* { dg-additional-options "-Wall -Wno-unknown-pragmas" } */ + +void +test1 (void) +{ + int sum = 0; + + for (int i = -3; i != 1; ++i) + for (int j = -2; j < i * -1; ++j) + sum++; + + if (sum != 14) + __builtin_abort (); +} + +void +test2 (void) +{ + int sum = 0; + + #pragma omp unroll partial + for (int i = -3; i != 1; ++i) + for (int j = -2; j < i * -1; ++j) + sum++; + + if (sum != 14) + __builtin_abort (); +} + +void +test3 (void) +{ + int sum = 0; + + #pragma omp unroll partial + for (int i = -3; i != 1; ++i) + #pragma omp unroll partial + for (int j = -2; j < i * -1; ++j) + sum++; + + if (sum != 14) + __builtin_abort (); +} + +int sum; + +void +test4 (void) +{ + #pragma omp for reduction(+:sum) + #pragma omp unroll partial(5) + for (int i = -3; i != 1; ++i) + #pragma omp unroll partial(2) + for (int j = -2; j < i * -1; ++j) + sum++; + + if (sum != 14) + __builtin_abort (); +} + +void +test5 (void) +{ + int sum = 0; + + #pragma omp parallel for reduction(+:sum) + #pragma omp unroll partial(2) + for (int i = -3; i != 1; ++i) + #pragma omp unroll partial(2) + for (int j = -2; j < i * -1; ++j) + sum++; + + if (sum != 14) + __builtin_abort (); +} + +void +test6 (void) +{ + int sum = 0; + #pragma omp target parallel for reduction(+:sum) + #pragma omp unroll partial(7) + for (int i = -3; i != 1; ++i) + #pragma omp unroll partial(2) + for (int j = -2; j < i * -1; ++j) + sum++; + + if (sum != 14) + __builtin_abort (); +} + +void +test7 (void) +{ + int sum = 0; +#pragma omp target teams distribute parallel for reduction(+:sum) +#pragma omp unroll partial(7) + for (int i = -3; i != 1; ++i) +#pragma omp unroll partial(2) + for (int j = -2; j < i * -1; ++j) + sum++; + + if (sum != 14) + __builtin_abort (); +} + +int +main () +{ + test1 (); + test2 (); + test3 (); + test4 (); + test5 (); + test6 (); + test7 (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.fortran/imperfect-transform-1.f90 b/libgomp/testsuite/libgomp.fortran/imperfect-transform-1.f90 new file mode 100644 index 00000000000..3e0e4f7934c --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/imperfect-transform-1.f90 @@ -0,0 +1,70 @@ +! { dg-do run } + +! Like imperfect1.f90, but also includes loop transforms. + +program foo + integer, save :: f1count(3), f2count(3) + + f1count(1) = 0 + f1count(2) = 0 + f1count(3) = 0 + f2count(1) = 0 + f2count(2) = 0 + f2count(3) = 0 + + call s1 (3, 4, 5) + + ! All intervening code at the same depth must be executed the same + ! number of times. + if (f1count(1) /= f2count(1)) error stop 101 + if (f1count(2) /= f2count(2)) error stop 102 + if (f1count(3) /= f2count(3)) error stop 103 + + ! Intervening code must be executed at least as many times as the loop + ! that encloses it. + if (f1count(1) < 3) error stop 111 + if (f1count(2) < 3 * 4) error stop 112 + + ! Intervening code must not be executed more times than the number + ! of logical iterations. + if (f1count(1) > 3 * 4 * 5) error stop 121 + if (f1count(2) > 3 * 4 * 5) error stop 122 + + ! Check that the innermost loop body is executed exactly the number + ! of logical iterations expected. + if (f1count(3) /= 3 * 4 * 5) error stop 131 + +contains + +subroutine f1 (depth, iter) + integer :: depth, iter + f1count(depth) = f1count(depth) + 1 +end subroutine + +subroutine f2 (depth, iter) + integer :: depth, iter + f2count(depth) = f2count(depth) + 1 +end subroutine + +subroutine s1 (a1, a2, a3) + integer :: a1, a2, a3 + integer :: i, j, k + + !$omp do collapse(2) private (j, k) + do i = 1, a1 + call f1 (1, i) + do j = 1, a2 + call f1 (2, j) + !$omp unroll partial + do k = 1, a3 + call f1 (3, k) + call f2 (3, k) + end do + call f2 (2, j) + end do + call f2 (1, i) + end do + +end subroutine + +end program diff --git a/libgomp/testsuite/libgomp.fortran/imperfect-transform-2.f90 b/libgomp/testsuite/libgomp.fortran/imperfect-transform-2.f90 new file mode 100644 index 00000000000..61f403436f1 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/imperfect-transform-2.f90 @@ -0,0 +1,70 @@ +! { dg-do run } + +! Like imperfect1.f90, but also includes loop transforms. + +program foo + integer, save :: f1count(3), f2count(3) + + f1count(1) = 0 + f1count(2) = 0 + f1count(3) = 0 + f2count(1) = 0 + f2count(2) = 0 + f2count(3) = 0 + + call s1 (3, 4, 5) + + ! All intervening code at the same depth must be executed the same + ! number of times. + if (f1count(1) /= f2count(1)) error stop 101 + if (f1count(2) /= f2count(2)) error stop 102 + if (f1count(3) /= f2count(3)) error stop 103 + + ! Intervening code must be executed at least as many times as the loop + ! that encloses it. + if (f1count(1) < 3) error stop 111 + if (f1count(2) < 3 * 4) error stop 112 + + ! Intervening code must not be executed more times than the number + ! of logical iterations. + if (f1count(1) > 3 * 4 * 5) error stop 121 + if (f1count(2) > 3 * 4 * 5) error stop 122 + + ! Check that the innermost loop body is executed exactly the number + ! of logical iterations expected. + if (f1count(3) /= 3 * 4 * 5) error stop 131 + +contains + +subroutine f1 (depth, iter) + integer :: depth, iter + f1count(depth) = f1count(depth) + 1 +end subroutine + +subroutine f2 (depth, iter) + integer :: depth, iter + f2count(depth) = f2count(depth) + 1 +end subroutine + +subroutine s1 (a1, a2, a3) + integer :: a1, a2, a3 + integer :: i, j, k + + !$omp do collapse(2) private (j, k) + do i = 1, a1 + call f1 (1, i) + do j = 1, a2 + call f1 (2, j) + !$omp tile sizes(5) + do k = 1, a3 + call f1 (3, k) + call f2 (3, k) + end do + call f2 (2, j) + end do + call f2 (1, i) + end do + +end subroutine + +end program diff --git a/libgomp/testsuite/libgomp.fortran/inner-1.f90 b/libgomp/testsuite/libgomp.fortran/inner-1.f90 new file mode 100644 index 00000000000..a72e5de33a6 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/inner-1.f90 @@ -0,0 +1,77 @@ +module matrix + implicit none + integer :: n = 10 + integer :: m = 10 + +contains + function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c( n, m )) + !$omp target parallel do collapse(2) & + !$omp & private(inner, i, j, k) map(to:a,b) map(from:c) + !$omp tile sizes (8, 1) + do i = 1,m + !$omp tile sizes (8) + do j = 1,n + !$omp unroll partial(10) + do k = 1, n + if (k == 1) then + inner = 0 + endif + inner = inner + a(k, i) * b(j, k) + if (k == n) then + c(j, i) = inner + endif + end do + end do + end do + end function mult + + subroutine print_matrix (m) + integer, allocatable :: m(:,:) + integer :: i, j, n + + n = size (m, 1) + do i = 1,n + do j = 1,n + write (*, fmt="(i4)", advance='no') m(j, i) + end do + write (*, *) "" + end do + write (*, *) "" + end subroutine + +end module matrix + +program main + use matrix + implicit none + + integer, allocatable :: a(:,:),b(:,:),c(:,:) + integer :: i,j + + allocate(a( n, m )) + allocate(b( n, m )) + + do i = 1,n + do j = 1,m + a(j,i) = merge(1,0, i.eq.j) + b(j,i) = j + end do + end do + + c = mult (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (c) + + do i = 1,n + do j = 1,m + if (b(i,j) .ne. c(i,j)) stop 1 + end do + end do + +end program main diff --git a/libgomp/testsuite/libgomp.fortran/nested-fn.f90 b/libgomp/testsuite/libgomp.fortran/nested-fn.f90 new file mode 100644 index 00000000000..db269643807 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/nested-fn.f90 @@ -0,0 +1,23 @@ +! { dg-do run } + +program foo + integer :: count + call s1 +contains + + subroutine s1 () + integer :: i, count + + count = 0 + + !$omp target parallel do map(tofrom:count) reduction(+:count) private(i) + !$omp unroll partial + do i = 1, 100 + count = count + 1 + end do + + if (count .ne. 100) stop 1 + + end subroutine + +end program diff --git a/libgomp/testsuite/libgomp.fortran/target-imperfect-transform-1.f90 b/libgomp/testsuite/libgomp.fortran/target-imperfect-transform-1.f90 new file mode 100644 index 00000000000..d260ee5f490 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/target-imperfect-transform-1.f90 @@ -0,0 +1,74 @@ +! { dg-do run } + +! Like imperfect-transform.f90, but enables offloading. + +program foo + integer, save :: f1count(3), f2count(3) + !$omp declare target enter (f1count, f2count) + + f1count(1) = 0 + f1count(2) = 0 + f1count(3) = 0 + f2count(1) = 0 + f2count(2) = 0 + f2count(3) = 0 + + call s1 (3, 4, 5) + + ! All intervening code at the same depth must be executed the same + ! number of times. + if (f1count(1) /= f2count(1)) error stop 101 + if (f1count(2) /= f2count(2)) error stop 102 + if (f1count(3) /= f2count(3)) error stop 103 + + ! Intervening code must be executed at least as many times as the loop + ! that encloses it. + if (f1count(1) < 3) error stop 111 + if (f1count(2) < 3 * 4) error stop 112 + + ! Intervening code must not be executed more times than the number + ! of logical iterations. + if (f1count(1) > 3 * 4 * 5) error stop 121 + if (f1count(2) > 3 * 4 * 5) error stop 122 + + ! Check that the innermost loop body is executed exactly the number + ! of logical iterations expected. + if (f1count(3) /= 3 * 4 * 5) error stop 131 + +contains + +subroutine f1 (depth, iter) + integer :: depth, iter + !$omp atomic + f1count(depth) = f1count(depth) + 1 +end subroutine + +subroutine f2 (depth, iter) + integer :: depth, iter + !$omp atomic + f2count(depth) = f2count(depth) + 1 +end subroutine + +subroutine s1 (a1, a2, a3) + integer :: a1, a2, a3 + integer :: i, j, k + + !$omp target parallel do collapse(2) map(always, tofrom:f1count, f2count) & + !$omp & private (j, k) + do i = 1, a1 + call f1 (1, i) + do j = 1, a2 + call f1 (2, j) + !$omp unroll partial + do k = 1, a3 + call f1 (3, k) + call f2 (3, k) + end do + call f2 (2, j) + end do + call f2 (1, i) + end do + +end subroutine + +end program diff --git a/libgomp/testsuite/libgomp.fortran/target-imperfect-transform-2.f90 b/libgomp/testsuite/libgomp.fortran/target-imperfect-transform-2.f90 new file mode 100644 index 00000000000..738be8e2e92 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/target-imperfect-transform-2.f90 @@ -0,0 +1,74 @@ +! { dg-do run } + +! Like imperfect-transform.f90, but enables offloading. + +program foo + integer, save :: f1count(3), f2count(3) + !$omp declare target enter (f1count, f2count) + + f1count(1) = 0 + f1count(2) = 0 + f1count(3) = 0 + f2count(1) = 0 + f2count(2) = 0 + f2count(3) = 0 + + call s1 (3, 4, 5) + + ! All intervening code at the same depth must be executed the same + ! number of times. + if (f1count(1) /= f2count(1)) error stop 101 + if (f1count(2) /= f2count(2)) error stop 102 + if (f1count(3) /= f2count(3)) error stop 103 + + ! Intervening code must be executed at least as many times as the loop + ! that encloses it. + if (f1count(1) < 3) error stop 111 + if (f1count(2) < 3 * 4) error stop 112 + + ! Intervening code must not be executed more times than the number + ! of logical iterations. + if (f1count(1) > 3 * 4 * 5) error stop 121 + if (f1count(2) > 3 * 4 * 5) error stop 122 + + ! Check that the innermost loop body is executed exactly the number + ! of logical iterations expected. + if (f1count(3) /= 3 * 4 * 5) error stop 131 + +contains + +subroutine f1 (depth, iter) + integer :: depth, iter + !$omp atomic + f1count(depth) = f1count(depth) + 1 +end subroutine + +subroutine f2 (depth, iter) + integer :: depth, iter + !$omp atomic + f2count(depth) = f2count(depth) + 1 +end subroutine + +subroutine s1 (a1, a2, a3) + integer :: a1, a2, a3 + integer :: i, j, k + + !$omp target parallel do collapse(2) map(always, tofrom:f1count, f2count) & + !$omp & private(j, k) + do i = 1, a1 + call f1 (1, i) + do j = 1, a2 + call f1 (2, j) + !$omp tile sizes(5) + do k = 1, a3 + call f1 (3, k) + call f2 (3, k) + end do + call f2 (2, j) + end do + call f2 (1, i) + end do + +end subroutine + +end program diff --git a/libgomp/testsuite/libgomp.fortran/target-print-1-nvptx.f90 b/libgomp/testsuite/libgomp.fortran/target-print-1-nvptx.f90 deleted file mode 100644 index a89c9c33484..00000000000 --- a/libgomp/testsuite/libgomp.fortran/target-print-1-nvptx.f90 +++ /dev/null @@ -1,11 +0,0 @@ -! Ensure that write on the offload device works, nvptx offloading variant. - -! This doesn't compile: for nvptx offloading we're using a minimal libgfortran -! configuration. -! { dg-do link } ! ..., but still apply 'dg-do run' options. -! { dg-xfail-if "minimal libgfortran" { offload_target_nvptx } } - -! Skip duplicated testing. -! { dg-skip-if "separate file" { ! offload_target_nvptx } } - -include 'target-print-1.f90' diff --git a/libgomp/testsuite/libgomp.fortran/target-print-1.f90 b/libgomp/testsuite/libgomp.fortran/target-print-1.f90 index 327bb22cb6d..9ac70e5a85f 100644 --- a/libgomp/testsuite/libgomp.fortran/target-print-1.f90 +++ b/libgomp/testsuite/libgomp.fortran/target-print-1.f90 @@ -3,9 +3,6 @@ ! { dg-do run } ! { dg-output "The answer is 42(\n|\r\n|\r)+" } -! Separate file 'target-print-1-nvptx.f90' for nvptx offloading. -! { dg-skip-if "separate file" { offload_target_nvptx } } - program main implicit none integer :: var = 42 diff --git a/libgomp/testsuite/libgomp.fortran/tile-1.f90 b/libgomp/testsuite/libgomp.fortran/tile-1.f90 new file mode 100644 index 00000000000..f4be10e37cc --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/tile-1.f90 @@ -0,0 +1,70 @@ +module matrix + implicit none + integer :: n = 10 + integer :: m = 10 + +contains + function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c( n, m )) + !$omp parallel do collapse(2) private(inner, i, j, k) + !$omp tile sizes (8, 1) + do i = 1,m + do j = 1,n + inner = 0 + do k = 1, n + inner = inner + a(k, i) * b(j, k) + end do + c(j, i) = inner + end do + end do + end function mult + + subroutine print_matrix (m) + integer, allocatable :: m(:,:) + integer :: i, j, n + + n = size (m, 1) + do i = 1,n + do j = 1,n + write (*, fmt="(i4)", advance='no') m(j, i) + end do + write (*, *) "" + end do + write (*, *) "" + end subroutine + +end module matrix + +program main + use matrix + implicit none + + integer, allocatable :: a(:,:),b(:,:),c(:,:) + integer :: i,j + + allocate(a( n, m )) + allocate(b( n, m )) + + do i = 1,n + do j = 1,m + a(j,i) = merge(1,0, i.eq.j) + b(j,i) = j + end do + end do + + c = mult (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (c) + + do i = 1,n + do j = 1,m + if (b(i,j) .ne. c(i,j)) stop 1 + end do + end do + +end program main diff --git a/libgomp/testsuite/libgomp.fortran/tile-2.f90 b/libgomp/testsuite/libgomp.fortran/tile-2.f90 new file mode 100644 index 00000000000..9fdcdedb008 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/tile-2.f90 @@ -0,0 +1,107 @@ +! { dg-do run } + +module test_functions + contains + integer function compute_sum1() result(sum) + implicit none + integer :: i,j + + sum = 0 + !$omp parallel do reduction(+:sum) private(j) + do i = 1,10,3 + !$omp tile sizes(2) + do j = 1,10,3 + sum = sum + 1 + end do + end do + end function + + integer function compute_sum2() result(sum) + implicit none + integer :: i,j + + sum = 0 + !$omp parallel do reduction(+:sum) private(j) + do i = 1,10,3 + !$omp tile sizes(16) + do j = 1,10,3 + sum = sum + 1 + end do + end do + end function + + integer function compute_sum3() result(sum) + implicit none + integer :: i,j + + sum = 0 + !$omp parallel do reduction(+:sum) private(j) + do i = 1,10,3 + !$omp tile sizes(100) + do j = 1,10,3 + sum = sum + 1 + end do + end do + end function + + integer function compute_sum4() result(sum) + implicit none + integer :: i,j + + sum = 0 + !$omp parallel do reduction(+:sum) private(i, j) + !$omp tile sizes(6,10) + do i = 1,10,3 + do j = 1,10,3 + sum = sum + 1 + end do + end do + end function + + integer function compute_sum5() result(sum) + implicit none + integer :: i,j + + sum = 0 + !$omp parallel do collapse(2) reduction(+:sum) private(i, j) + !$omp tile sizes(6,10) + do i = 1,10,3 + do j = 1,10,3 + sum = sum + 1 + end do + end do + !$omp end tile + !$omp end parallel do + end function +end module test_functions + +program test + use test_functions + implicit none + integer :: result + + result = compute_sum1 () + if (result .ne. 16) then + stop 1 + end if + + result = compute_sum2 () + if (result .ne. 16) then + stop 2 + end if + + result = compute_sum3 () + if (result .ne. 16) then + stop 3 + end if + + result = compute_sum4 () + if (result .ne. 16) then + stop 4 + end if + + result = compute_sum5 () + if (result .ne. 16) then + stop 5 + end if +end program diff --git a/libgomp/testsuite/libgomp.fortran/tile-unroll-1.f90 b/libgomp/testsuite/libgomp.fortran/tile-unroll-1.f90 new file mode 100644 index 00000000000..db10486e8a0 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/tile-unroll-1.f90 @@ -0,0 +1,108 @@ +module matrix + implicit none + integer :: n = 10 + integer :: m = 10 + +contains + + function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c(n, m)) + do i = 1,10 + do j = 1,n + c(j,i) = 0 + end do + end do + + !$omp unroll partial(10) + !$omp tile sizes(1, 3) + do i = 1,10 + do j = 1,n + do k = 1, n + c(j,i) = c(j,i) + a(k, i) * b(j, k) + end do + end do + end do + end function mult + + function mult2 (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c(n, m)) + do i = 1,10 + do j = 1,n + c(j,i) = 0 + end do + end do + + !$omp unroll partial(2) + !$omp tile sizes(1,2) + do i = 1,10 + do j = 1,n + do k = 1, n + c(j,i) = c(j,i) + a(k, i) * b(j, k) + end do + end do + end do + end function mult2 + + subroutine print_matrix (m) + integer, allocatable :: m(:,:) + integer :: i, j, n + + n = size (m, 1) + do i = 1,n + do j = 1,n + write (*, fmt="(i4)", advance='no') m(j, i) + end do + write (*, *) "" + end do + write (*, *) "" + end subroutine + +end module matrix + +program main + use matrix + implicit none + integer, allocatable :: a(:,:), b(:,:), c(:,:), d(:, :) + integer :: i, j + + allocate(a(n, m)) + allocate(b(n, m)) + + do i = 1,n + do j = 1,m + a(j,i) = merge(1,0, i.eq.j) + b(j,i) = j + end do + end do + + d = mult (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (d) + + do i = 1,n + do j = 1,m + if (b(i,j) .ne. d(i,j)) stop 1 + end do + end do + + c = mult2 (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (c) + + do i = 1,n + do j = 1,m + if (b(i,j) .ne. c(i,j)) stop 2 + end do + end do + +end program main diff --git a/libgomp/testsuite/libgomp.fortran/tile-unroll-2.f90 b/libgomp/testsuite/libgomp.fortran/tile-unroll-2.f90 new file mode 100644 index 00000000000..3a78b422670 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/tile-unroll-2.f90 @@ -0,0 +1,71 @@ +module matrix + implicit none + integer :: n = 10 + integer :: m = 10 + +contains + + function copy (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c(n, m)) + do i = 1,10 + do j = 1,n + c(j,i) = 0 + end do + end do + + !$omp unroll partial(2) + !$omp tile sizes (1,5) + do i = 1,10 + do j = 1,n + c(j,i) = c(j,i) + a(j, i) + end do + end do + end function copy + + subroutine print_matrix (m) + integer, allocatable :: m(:,:) + integer :: i, j, n + + n = size (m, 1) + do i = 1,n + do j = 1,n + write (*, fmt="(i4)", advance='no') m(j, i) + end do + write (*, *) "" + end do + write (*, *) "" + end subroutine +end module matrix + +program main + use matrix + implicit none + + integer, allocatable :: a(:,:),b(:,:),c(:,:) + integer :: i,j + + allocate(a(n, m)) + allocate(b(n, m)) + + do i = 1,n + do j = 1,m + a(j,i) = 1 + end do + end do + + c = copy (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (c) + + do i = 1,n + do j = 1,m + if (c(i,j) .ne. a(i,j)) stop 1 + end do + end do + +end program main diff --git a/libgomp/testsuite/libgomp.fortran/tile-unroll-3.f90 b/libgomp/testsuite/libgomp.fortran/tile-unroll-3.f90 new file mode 100644 index 00000000000..8a11f91caaf --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/tile-unroll-3.f90 @@ -0,0 +1,75 @@ +module matrix + implicit none + integer :: n = 4 + integer :: m = 4 + +contains + function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c(n, m)) + !$omp parallel do private(inner, j, k) + do i = 1,m + !$omp unroll partial(4) + !$omp tile sizes (5) + do j = 1,n + do k = 1, n + if (k == 1) then + inner = 0 + endif + inner = inner + a(k, i) * b(j, k) + if (k == n) then + c(j, i) = inner + endif + end do + end do + end do + end function mult + + subroutine print_matrix (m) + integer, allocatable :: m(:,:) + integer :: i, j, n + + n = size (m, 1) + do i = 1,n + do j = 1,n + write (*, fmt="(i4)", advance='no') m(j, i) + end do + write (*, *) "" + end do + write (*, *) "" + end subroutine + +end module matrix + +program main + use matrix + implicit none + + integer, allocatable :: a(:,:),b(:,:),c(:,:) + integer :: i,j + + allocate(a(n, m)) + allocate(b(n, m)) + + do i = 1,n + do j = 1,m + a(j,i) = merge(1,0, i.eq.j) + b(j,i) = j + end do + end do + + c = mult (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (c) + + do i = 1,n + do j = 1,m + if (b(i,j) .ne. c(i,j)) stop 1 + end do + end do + +end program main diff --git a/libgomp/testsuite/libgomp.fortran/tile-unroll-4.f90 b/libgomp/testsuite/libgomp.fortran/tile-unroll-4.f90 new file mode 100644 index 00000000000..6e148b22fbd --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/tile-unroll-4.f90 @@ -0,0 +1,74 @@ +module matrix + implicit none + integer :: n = 4 + integer :: m = 4 + +contains + function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c(n, m)) + do i = 1,m + do j = 1,n + c(j, i) = 0 + end do + end do + + !$omp parallel do private(j, k) + do i = 1,m + !$omp tile sizes (5,2) + do j = 1,n + do k = 1, n + c(j,i) = c(j,i) + a(k, i) * b(j, k) + end do + end do + end do + end function mult + + subroutine print_matrix (m) + integer, allocatable :: m(:,:) + integer :: i, j, n + + n = size (m, 1) + do i = 1,n + do j = 1,n + write (*, fmt="(i4)", advance='no') m(j, i) + end do + write (*, *) "" + end do + write (*, *) "" + end subroutine + +end module matrix + +program main + use matrix + implicit none + + integer, allocatable :: a(:,:),b(:,:),c(:,:) + integer :: i,j + + allocate(a(n, m)) + allocate(b(n, m)) + + do i = 1,n + do j = 1,m + a(j,i) = merge(1,0, i.eq.j) + b(j,i) = j + end do + end do + + c = mult (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (c) + + do i = 1,n + do j = 1,m + if (b(i,j) .ne. c(i,j)) stop 1 + end do + end do + +end program main diff --git a/libgomp/testsuite/libgomp.fortran/unroll-1.f90 b/libgomp/testsuite/libgomp.fortran/unroll-1.f90 new file mode 100644 index 00000000000..1674755b55d --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-1.f90 @@ -0,0 +1,49 @@ +! { dg-do run } + +module test_functions + contains + integer function compute_sum() result(sum) + implicit none + integer :: i,j + + sum = 0 + !$omp parallel do reduction(+:sum) private(j) + do i = 1,10,3 + !$omp unroll full + do j = 1,10,3 + sum = sum + 1 + end do + end do + end function + + integer function compute_sum2() result(sum) + implicit none + integer :: i,j + + sum = 0 + !$omp parallel do reduction(+:sum) private(i, j) + !$omp unroll partial(2) + do i = 1,10,3 + do j = 1,10,3 + sum = sum + 1 + end do + end do + end function +end module test_functions + +program test + use test_functions + implicit none + + integer :: result + + result = compute_sum () + if (result .ne. 16) then + stop 1 + end if + + result = compute_sum2 () + if (result .ne. 16) then + stop 2 + end if +end program diff --git a/libgomp/testsuite/libgomp.fortran/unroll-2.f90 b/libgomp/testsuite/libgomp.fortran/unroll-2.f90 new file mode 100644 index 00000000000..d60f97e5648 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-2.f90 @@ -0,0 +1,76 @@ +! { dg-do run } +! { dg-additional-options "-g" } + +module test_functions +contains + integer function compute_sum1 () result(sum) + implicit none + integer :: i + + sum = 0 + !$omp unroll full + do i = 1,10,3 + sum = sum + 1 + end do + end function compute_sum1 + + integer function compute_sum2() result(sum) + implicit none + integer :: i + + sum = 0 + !$omp unroll full + do i = -20,1,3 + sum = sum + 1 + end do + end function compute_sum2 + + integer function compute_sum3() result(sum) + implicit none + integer :: i + + sum = 0 + !$omp unroll full + do i = 30,1,-3 + sum = sum + 1 + end do + end function compute_sum3 + + integer function compute_sum4() result(sum) + implicit none + integer :: i + + sum = 0 + !$omp unroll full + do i = 50,-60,-10 + sum = sum + 1 + end do + end function compute_sum4 + +end module test_functions + +program test + use test_functions + implicit none + integer :: result + + result = compute_sum1 () + if (result .ne. 4) then + stop 1 + end if + + result = compute_sum2 () + if (result .ne. 8) then + stop 2 + end if + + result = compute_sum3 () + if (result .ne. 10) then + stop 3 + end if + + result = compute_sum4 () + if (result .ne. 12) then + stop 4 + end if +end program diff --git a/libgomp/testsuite/libgomp.fortran/unroll-3.f90 b/libgomp/testsuite/libgomp.fortran/unroll-3.f90 new file mode 100644 index 00000000000..7aad03ce1a8 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-3.f90 @@ -0,0 +1,56 @@ +! Test lowering of the internal representation of "omp unroll" loops +! which are not unrolled. + +! { dg-do run } + +module test_functions +contains + integer function compute_sum1 () result(sum) + implicit none + integer :: i + + sum = 0 + !$omp unroll + do i = 0,50 + sum = sum + 1 + end do + end function compute_sum1 + + integer function compute_sum3 (step,n) result(sum) + implicit none + integer :: i, step, n + + sum = 0 + !$omp unroll + do i = 0,n,step + sum = sum + 1 + end do + end function compute_sum3 +end module test_functions + +program test + use test_functions + implicit none + + integer :: result + + result = compute_sum1 () + if (result .ne. 51) then + stop 1 + end if + + result = compute_sum3 (1, 100) + if (result .ne. 101) then + stop 2 + end if + + result = compute_sum3 (2, 100) + if (result .ne. 51) then + stop 3 + end if + + result = compute_sum3 (-2, -100) + if (result .ne. 51) then + stop 4 + end if +end program diff --git a/libgomp/testsuite/libgomp.fortran/unroll-4.f90 b/libgomp/testsuite/libgomp.fortran/unroll-4.f90 new file mode 100644 index 00000000000..3472dd71213 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-4.f90 @@ -0,0 +1,63 @@ +! { dg-do run } +! { dg-additional-options "-g" } + +module test_functions +contains + integer function compute_sum1 () result(sum) + implicit none + integer :: i + + sum = 0 + !$omp unroll partial(2) + do i = 1,50 + sum = sum + 1 + end do + end function compute_sum1 + + integer function compute_sum3 (step,n) result(sum) + implicit none + integer :: i, step, n + + sum = 0 + !$omp unroll partial(5) + do i = 1,n,step + sum = sum + 1 + end do + end function compute_sum3 +end module test_functions + +program test + use test_functions + implicit none + integer :: result + + result = compute_sum1 () + if (result .ne. 50) then + stop 1 + end if + + result = compute_sum3 (1, 100) + if (result .ne. 100) then + stop 2 + end if + + result = compute_sum3 (1, 9) + if (result .ne. 9) then + stop 3 + end if + + result = compute_sum3 (2, 96) + if (result .ne. 48) then + stop 4 + end if + + result = compute_sum3 (-2, -98) + if (result .ne. 50) then + stop 5 + end if + + result = compute_sum3 (-2, -100) + if (result .ne. 51) then + stop 6 + end if +end program diff --git a/libgomp/testsuite/libgomp.fortran/unroll-5.f90 b/libgomp/testsuite/libgomp.fortran/unroll-5.f90 new file mode 100644 index 00000000000..39285512099 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-5.f90 @@ -0,0 +1,48 @@ +! { dg-do run } +! { dg-additional-options "-g" } + +module test_functions +contains + integer function compute_sum4 (step,n) result(sum) + implicit none + integer :: i, step, n + + sum = 0 + !$omp parallel do reduction(+:sum) private(i) + !$omp unroll partial(5) + do i = 1,n,step + sum = sum + 1 + end do + end function compute_sum4 +end module test_functions + +program test + use test_functions + implicit none + integer :: result + + result = compute_sum4 (1, 100) + if (result .ne. 100) then + stop 1 + end if + + result = compute_sum4 (1, 9) + if (result .ne. 9) then + stop 2 + end if + + result = compute_sum4 (2, 96) + if (result .ne. 48) then + stop 3 + end if + + result = compute_sum4 (-2, -98) + if (result .ne. 50) then + stop 4 + end if + + result = compute_sum4 (-2, -100) + if (result .ne. 51) then + stop 5 + end if +end program diff --git a/libgomp/testsuite/libgomp.fortran/unroll-6.f90 b/libgomp/testsuite/libgomp.fortran/unroll-6.f90 new file mode 100644 index 00000000000..f6ee57b79a0 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-6.f90 @@ -0,0 +1,102 @@ +! { dg-do run } +! { dg-additional-options "-g" } + +module test_functions +contains + integer function compute_sum4 (step,n) result(sum) + implicit none + integer :: i, step, n + + sum = 0 + !$omp parallel do reduction(+:sum) lastprivate(i) + !$omp unroll partial(5) + do i = 1,n,step + sum = sum + 1 + end do + end function compute_sum4 + + integer function compute_sum5 (step,n) result(sum) + implicit none + integer :: i, step, n + + sum = 0 + !$omp parallel do reduction(+:sum) lastprivate(i) + !$omp unroll partial(5) + !$omp unroll partial(10) + do i = 1,n,step + sum = sum + 1 + end do + end function compute_sum5 + + integer function compute_sum6 (step,n) result(sum) + implicit none + integer :: i, j, step, n + + sum = 0 + !$omp parallel do reduction(+:sum) lastprivate(i) & + !$omp & private(j) + do i = 1,n,step + !$omp unroll full + !$omp unroll partial(10) + do j = 1, 1000 + sum = sum + 1 + end do + end do + end function compute_sum6 +end module test_functions + +program test + use test_functions + implicit none + integer :: result + + result = compute_sum4 (1, 100) + if (result .ne. 100) then + stop 1 + end if + + result = compute_sum4 (1, 9) + if (result .ne. 9) then + stop 2 + end if + + result = compute_sum4 (2, 96) + if (result .ne. 48) then + stop 3 + end if + + result = compute_sum4 (-2, -98) + if (result .ne. 50) then + stop 4 + end if + + result = compute_sum4 (-2, -100) + if (result .ne. 51) then + stop 5 + end if + + result = compute_sum5 (1, 100) + if (result .ne. 100) then + stop 6 + end if + + result = compute_sum5 (1, 9) + if (result .ne. 9) then + stop 7 + end if + + result = compute_sum5 (2, 96) + if (result .ne. 48) then + stop 8 + end if + + result = compute_sum5 (-2, -98) + if (result .ne. 50) then + stop 9 + end if + + result = compute_sum5 (-2, -100) + if (result .ne. 51) then + stop 10 + end if +end program diff --git a/libgomp/testsuite/libgomp.fortran/unroll-7.f90 b/libgomp/testsuite/libgomp.fortran/unroll-7.f90 new file mode 100644 index 00000000000..3b114788608 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-7.f90 @@ -0,0 +1,186 @@ +! { dg-do run } +! { dg-additional-options "-cpp" } + +#ifndef UNROLL_FACTOR +#define UNROLL_FACTOR 1 +#endif +module test_functions +contains + subroutine copy (array1, array2) + implicit none + integer :: array1(:) + integer :: array2(:) + integer :: i + + !$omp parallel do private(i) + !$omp unroll partial(UNROLL_FACTOR) + do i = 1, 100 + array1(i) = array2(i) + end do + end subroutine + + subroutine copy2 (array1, array2) + implicit none + + integer :: array1(100) + integer :: array2(100) + integer :: i + + !$omp parallel do private(i) + !$omp unroll partial(UNROLL_FACTOR) + do i = 0,99 + array1(i+1) = array2(i+1) + end do + end subroutine copy2 + + subroutine copy3 (array1, array2) + implicit none + + integer :: array1(100) + integer :: array2(100) + integer :: i + + !$omp parallel do lastprivate(i) + !$omp unroll partial(UNROLL_FACTOR) + do i = -49,50 + if (i < 0) then + array1((-1)*i) = array2((-1)*i) + else + array1(50+i) = array2(50+i) + endif + end do + end subroutine copy3 + + subroutine copy4 (array1, array2) + implicit none + integer :: array1(:) + integer :: array2(:) + integer :: i + + !$omp parallel do private(i) + !$omp unroll partial(UNROLL_FACTOR) + do i = 2, 200, 2 + array1(i/2) = array2(i/2) + end do + end subroutine copy4 + + subroutine copy5 (array1, array2) + implicit none + integer :: array1(:) + integer :: array2(:) + integer :: i + + !$omp parallel do private(i) + !$omp unroll partial(UNROLL_FACTOR) + do i = 200, 2, -2 + array1(i/2) = array2(i/2) + end do + end subroutine + + subroutine copy6 (array1, array2, lower, upper, step) + implicit none + integer :: array1(:) + integer :: array2(:) + integer :: lower, upper, step + integer :: i + + !$omp parallel do private(i) + !$omp unroll partial(UNROLL_FACTOR) + do i = lower, upper, step + array1 (i) = array2(i) + end do + end subroutine + + subroutine prepare (array1, array2) + implicit none + integer :: array1(:) + integer :: array2(:) + + array1 = 2 + array2 = 0 + end subroutine + + subroutine check_equal (array1, array2) + implicit none + integer :: array1(:) + integer :: array2(:) + integer :: i + + do i=1,100 + if (array1(i) /= array2(i)) then + stop 1 + end if + end do + end subroutine + + subroutine check_equal_at_steps (array1, array2, lower, upper, step) + implicit none + integer :: array1(:) + integer :: array2(:) + integer :: lower, upper, step + integer :: i + + do i=lower, upper, step + if (array1(i) /= array2(i)) then + stop 2 + end if + end do + end subroutine + + subroutine check_unchanged_at_non_steps (array1, array2, lower, upper, step) + implicit none + integer :: array1(:) + integer :: array2(:) + integer :: lower, upper, step + integer :: i, j + + do i=lower, upper,step + do j=i,i+step-1 + if (array2(j) /= 0) then + stop 3 + end if + end do + end do + end subroutine +end module test_functions + +program test + use test_functions + implicit none + integer :: array1(100), array2(100) + + call prepare (array1, array2) + call copy (array1, array2) + call check_equal (array1, array2) + + call prepare (array1, array2) + call copy2 (array1, array2) + call check_equal (array1, array2) + + call prepare (array1, array2) + call copy3 (array1, array2) + call check_equal (array1, array2) + + call prepare (array1, array2) + call copy4 (array1, array2) + call check_equal (array1, array2) + + call prepare (array1, array2) + call copy5 (array1, array2) + call check_equal (array1, array2) + + call prepare (array1, array2) + call copy6 (array1, array2, 1, 100, 5) + call check_equal_at_steps (array1, array2, 1, 100, 5) + call check_unchanged_at_non_steps (array1, array2, 1, 100, 5) + + call prepare (array1, array2) + call copy6 (array1, array2, 1, 50, 5) + call check_equal_at_steps (array1, array2, 1, 50, 5) + call check_unchanged_at_non_steps (array1, array2, 1, 50, 5) + + call prepare (array1, array2) + call copy6 (array1, array2, 3, 18, 7) + call check_equal_at_steps (array1, array2, 3 , 18, 7) + call check_unchanged_at_non_steps (array1, array2, 3, 18, 7) +end program diff --git a/libgomp/testsuite/libgomp.fortran/unroll-7a.f90 b/libgomp/testsuite/libgomp.fortran/unroll-7a.f90 new file mode 100644 index 00000000000..1fbfa7051df --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-7a.f90 @@ -0,0 +1,7 @@ +! { dg-do run } +! { dg-additional-options "-g -cpp" } + +! Check an unroll factor that divides the number of iterations +! of the loops in the test implementation. +#define UNROLL_FACTOR 5 +#include "unroll-7.f90" diff --git a/libgomp/testsuite/libgomp.fortran/unroll-7b.f90 b/libgomp/testsuite/libgomp.fortran/unroll-7b.f90 new file mode 100644 index 00000000000..d78a5a1d926 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-7b.f90 @@ -0,0 +1,7 @@ +! { dg-do run } +! { dg-additional-options "-g -cpp" } + +! Check an unroll factor that does not divide the number of iterations +! of the loops in the test implementation. +#define UNROLL_FACTOR 3 +#include "unroll-7.f90" diff --git a/libgomp/testsuite/libgomp.fortran/unroll-7c.f90 b/libgomp/testsuite/libgomp.fortran/unroll-7c.f90 new file mode 100644 index 00000000000..0b3d91cdba3 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-7c.f90 @@ -0,0 +1,7 @@ +! { dg-do run } +! { dg-additional-options "-g -cpp" } + +! Check an unroll factor that is larger than the number of iterations +! of the loops in the test implementation. +#define UNROLL_FACTOR 113 +#include "unroll-7.f90" diff --git a/libgomp/testsuite/libgomp.fortran/unroll-8.f90 b/libgomp/testsuite/libgomp.fortran/unroll-8.f90 new file mode 100644 index 00000000000..1ff7a13dc13 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-8.f90 @@ -0,0 +1,35 @@ +! { dg-do run } +! { dg-additional-options "-g" } + +module test_functions +contains + subroutine copy (array1, array2, step, n) + implicit none + integer :: array1(n) + integer :: array2(n) + integer :: i, step, n + + call omp_set_num_threads (4) + !$omp parallel do shared(array1) shared(array2) schedule(static, 4) & + !$omp & private(i) + !$omp unroll partial(2) + do i = 1,n + array1(i) = array2(i) + end do + end subroutine +end module test_functions + +program test + use test_functions + implicit none + integer :: array1(100), array2(100) + integer :: i + + array1 = 2 + call copy(array1, array2, 1, 100) + do i=1,100 + if (array1(i) /= array2(i)) then + stop 1 + end if + end do +end program diff --git a/libgomp/testsuite/libgomp.fortran/unroll-simd-1.f90 b/libgomp/testsuite/libgomp.fortran/unroll-simd-1.f90 new file mode 100644 index 00000000000..3e1834620e1 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-simd-1.f90 @@ -0,0 +1,30 @@ +! { dg-do run } +! { dg-options "-fno-openmp -fopenmp-simd" } + +module test_functions + contains + integer function compute_sum() result(sum) + implicit none + integer :: i,j + + sum = 0 + !$omp simd reduction(+:sum) + do i = 1,10,3 + !$omp unroll full + do j = 1,10,3 + sum = sum + 1 + end do + end do + end function compute_sum +end module test_functions + +program test + use test_functions + implicit none + integer :: result + + result = compute_sum () + if (result .ne. 16) then + stop 1 + end if +end program diff --git a/libgomp/testsuite/libgomp.fortran/unroll-tile-1.f90 b/libgomp/testsuite/libgomp.fortran/unroll-tile-1.f90 new file mode 100644 index 00000000000..3d2c088a49b --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-tile-1.f90 @@ -0,0 +1,108 @@ +module matrix + implicit none + integer :: n = 10 + integer :: m = 10 + +contains + + function mult (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c( n, m )) + do i = 1,10 + do j = 1,n + c(j,i) = 0 + end do + end do + + !$omp unroll partial(10) + !$omp tile sizes(1, 3) + do i = 1,10 + do j = 1,n + do k = 1, n + c(j,i) = c(j,i) + a(k, i) * b(j, k) + end do + end do + end do + end function mult + + function mult2 (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c(n, m)) + do i = 1,10 + do j = 1,n + c(j,i) = 0 + end do + end do + + !$omp unroll partial(2) + !$omp tile sizes(1,2) + do i = 1,10 + do j = 1,n + do k = 1, n + c(j,i) = c(j,i) + a(k, i) * b(j, k) + end do + end do + end do + end function mult2 + + subroutine print_matrix (m) + integer, allocatable :: m(:,:) + integer :: i, j, n + + n = size (m, 1) + do i = 1,n + do j = 1,n + write (*, fmt="(i4)", advance='no') m(j, i) + end do + write (*, *) "" + end do + write (*, *) "" + end subroutine + +end module matrix + +program main + use matrix + implicit none + integer, allocatable :: a(:,:),b(:,:),c(:,:),d(:,:) + integer :: i,j + + allocate(a( n, m )) + allocate(b( n, m )) + + do i = 1,n + do j = 1,m + a(j,i) = merge(1,0, i.eq.j) + b(j,i) = j + end do + end do + + d = mult (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (d) + + do i = 1,n + do j = 1,m + if (b(i,j) .ne. d(i,j)) stop 1 + end do + end do + + c = mult2 (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (c) + + do i = 1,n + do j = 1,m + if (b(i,j) .ne. c(i,j)) stop 2 + end do + end do + +end program main diff --git a/libgomp/testsuite/libgomp.fortran/unroll-tile-2.f90 b/libgomp/testsuite/libgomp.fortran/unroll-tile-2.f90 new file mode 100644 index 00000000000..7453288b544 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/unroll-tile-2.f90 @@ -0,0 +1,70 @@ +module matrix + implicit none + integer :: n = 10 + integer :: m = 10 + +contains + + function copy (a, b) result (c) + integer, allocatable, dimension (:,:) :: a,b,c + integer :: i, j, k, inner + + allocate(c(n, m)) + do i = 1,10 + do j = 1,n + c(j,i) = 0 + end do + end do + + !$omp unroll partial(2) + !$omp tile sizes (1,5) + do i = 1,10 + do j = 1,n + c(j,i) = c(j,i) + a(j, i) + end do + end do + end function copy + + subroutine print_matrix (m) + integer, allocatable :: m(:,:) + integer :: i, j, n + + n = size (m, 1) + do i = 1,n + do j = 1,n + write (*, fmt="(i4)", advance='no') m(j, i) + end do + write (*, *) "" + end do + write (*, *) "" + end subroutine +end module matrix + +program main + use matrix + implicit none + integer, allocatable :: a(:,:),b(:,:),c(:,:) + integer :: i,j + + allocate(a(n, m)) + allocate(b(n, m)) + + do i = 1,n + do j = 1,m + a(j,i) = 1 + end do + end do + + c = copy (a, b) + + call print_matrix (a) + call print_matrix (b) + call print_matrix (c) + + do i = 1,n + do j = 1,m + if (c(i,j) .ne. a(i,j)) stop 1 + end do + end do + +end program main diff --git a/libgomp/testsuite/libgomp.oacc-fortran/error_stop-1.f b/libgomp/testsuite/libgomp.oacc-fortran/error_stop-1.f index de727749a53..3918d6853f6 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/error_stop-1.f +++ b/libgomp/testsuite/libgomp.oacc-fortran/error_stop-1.f @@ -16,14 +16,16 @@ END PROGRAM MAIN ! { dg-output "CheCKpOInT(\n|\r\n|\r)+" } + ! { dg-output "ERROR STOP (\n|\r\n|\r)+" } ! ! In gfortran's main program, libfortran's set_options is called - which sets ! compiler_options.backtrace = 1 by default. For an offload libgfortran, this ! is never called and, hence, "Error termination." is never printed. Thus: ! { dg-output "Error termination.*" { target { ! { openacc_nvidia_accel_selected || openacc_radeon_accel_selected } } } } -! -! PR85463: + +! PR85463. The 'exit' implementation used with nvptx +! offloading is a little bit different. ! { dg-output "libgomp: cuStreamSynchronize error.*" { target openacc_nvidia_accel_selected } } -! + ! { dg-shouldfail "" } diff --git a/libgomp/testsuite/libgomp.oacc-fortran/error_stop-2-nvptx.f b/libgomp/testsuite/libgomp.oacc-fortran/error_stop-2-nvptx.f new file mode 100644 index 00000000000..ef93e80d9d4 --- /dev/null +++ b/libgomp/testsuite/libgomp.oacc-fortran/error_stop-2-nvptx.f @@ -0,0 +1,39 @@ +! 'error_stop-2.f' nvptx offloading variant + +! { dg-do run { target openacc_nvidia_accel_selected } } +! +! The PTX JIT doesn't understand the 'ERROR STOP' call graph, and therefore: +! warning : Stack size for entry function 'main$_omp_fn$0' cannot be statically determined +! Running with default 1024-bytes GPU thread stack size overflows the stack, +! so raise it to an arbitrarily higher value: +! { dg-set-target-env-var GOMP_NVPTX_NATIVE_GPU_THREAD_STACK_SIZE 3333 } + + PROGRAM MAIN + IMPLICIT NONE + +! Initialize before the checkpoint, in case this produces any output. +!$ACC PARALLEL +!$ACC END PARALLEL + + PRINT *, "CheCKpOInT" +!$ACC PARALLEL + ERROR STOP 35 +!$ACC END PARALLEL + PRINT *, "WrONg WAy" + + END PROGRAM MAIN + +! { dg-output "CheCKpOInT(\n|\r\n|\r)+" } + +! { dg-output "ERROR STOP 35(\n|\r\n|\r)+" } +! +! In gfortran's main program, libfortran's set_options is called - which sets +! compiler_options.backtrace = 1 by default. For an offload libgfortran, this +! is never called and, hence, "Error termination." is never printed. Thus: +! { dg-output "Error termination.*" { target { ! { openacc_nvidia_accel_selected || openacc_radeon_accel_selected } } } } + +! PR85463. The 'exit' implementation used with nvptx +! offloading is a little bit different. +! { dg-output "libgomp: cuStreamSynchronize error.*" { target openacc_nvidia_accel_selected } } + +! { dg-shouldfail "" } diff --git a/libgomp/testsuite/libgomp.oacc-fortran/error_stop-2.f b/libgomp/testsuite/libgomp.oacc-fortran/error_stop-2.f index 475c9cb5850..c0762835faa 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/error_stop-2.f +++ b/libgomp/testsuite/libgomp.oacc-fortran/error_stop-2.f @@ -16,14 +16,17 @@ END PROGRAM MAIN ! { dg-output "CheCKpOInT(\n|\r\n|\r)+" } -! { dg-output "ERROR STOP 35(\n|\r\n|\r)+" } + +! See 'error_stop-2-nvptx.f' regarding the nvptx offloading XFAIL. +! { dg-output "ERROR STOP 35(\n|\r\n|\r)+" { xfail openacc_nvidia_accel_selected } } ! ! In gfortran's main program, libfortran's set_options is called - which sets ! compiler_options.backtrace = 1 by default. For an offload libgfortran, this ! is never called and, hence, "Error termination." is never printed. Thus: ! { dg-output "Error termination.*" { target { ! { openacc_nvidia_accel_selected || openacc_radeon_accel_selected } } } } -! -! PR85463: + +! PR85463. The 'exit' implementation used with nvptx +! offloading is a little bit different. ! { dg-output "libgomp: cuStreamSynchronize error.*" { target openacc_nvidia_accel_selected } } -! + ! { dg-shouldfail "" } diff --git a/libgomp/testsuite/libgomp.oacc-fortran/error_stop-3.f b/libgomp/testsuite/libgomp.oacc-fortran/error_stop-3.f index ab63444ce34..15e02d8b744 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/error_stop-3.f +++ b/libgomp/testsuite/libgomp.oacc-fortran/error_stop-3.f @@ -16,14 +16,16 @@ END PROGRAM MAIN ! { dg-output "CheCKpOInT(\n|\r\n|\r)+" } + ! { dg-output "ERROR STOP SiGN(\n|\r\n|\r)+" } ! ! In gfortran's main program, libfortran's set_options is called - which sets ! compiler_options.backtrace = 1 by default. For an offload libgfortran, this ! is never called and, hence, "Error termination." is never printed. Thus: ! { dg-output "Error termination.*" { target { ! { openacc_nvidia_accel_selected || openacc_radeon_accel_selected } } } } -! -! PR85463: + +! PR85463. The 'exit' implementation used with nvptx +! offloading is a little bit different. ! { dg-output "libgomp: cuStreamSynchronize error.*" { target openacc_nvidia_accel_selected } } -! + ! { dg-shouldfail "" } diff --git a/libgomp/testsuite/libgomp.oacc-fortran/print-1-nvptx.f90 b/libgomp/testsuite/libgomp.oacc-fortran/print-1-nvptx.f90 index 866c8654355..e8080e6c8ac 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/print-1-nvptx.f90 +++ b/libgomp/testsuite/libgomp.oacc-fortran/print-1-nvptx.f90 @@ -1,11 +1,37 @@ ! Ensure that write on the offload device works, nvptx offloading variant. -! This doesn't compile: for nvptx offloading we're using a minimal libgfortran -! configuration. -! { dg-do link } ! ..., but still apply 'dg-do run' options. -! { dg-xfail-if "minimal libgfortran" { offload_target_nvptx } } +! { dg-do run { target openacc_nvidia_accel_selected } } +! { dg-output "The answer is 42(\n|\r\n|\r)+" } +! +! The PTX JIT doesn't understand the 'write' call graph, and therefore: +! warning : Stack size for entry function 'main$_omp_fn$0' cannot be statically determined +! Running with default 1024-bytes GPU thread stack size overflows the stack, +! so raise it to an arbitrarily higher value: +! { dg-set-target-env-var GOMP_NVPTX_NATIVE_GPU_THREAD_STACK_SIZE 3333 } -! Skip duplicated testing. -! { dg-skip-if "separate file" { ! offload_target_nvptx } } +! { dg-additional-options "-fopt-info-note-omp" } +! { dg-additional-options "-foffload=-fopt-info-note-omp" } -include 'print-1.f90' +! { dg-additional-options "--param=openacc-privatization=noisy" } +! { dg-additional-options "-foffload=--param=openacc-privatization=noisy" } +! Prune a few: uninteresting, and potentially varying depending on GCC configuration (data types): +! { dg-prune-output {note: variable 'D\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: not addressable} } */ + +! It's only with Tcl 8.5 (released in 2007) that "the variable 'varName' +! passed to 'incr' may be unset, and in that case, it will be set to [...]", +! so to maintain compatibility with earlier Tcl releases, we manually +! initialize counter variables: +! { dg-line l_dummy[variable c_compute 0] } +! { dg-message dummy {} { target iN-VAl-Id } l_dummy } to avoid +! "WARNING: dg-line var l_dummy defined, but not used". + +program main + implicit none + integer :: var = 42 + +!$acc parallel ! { dg-line l_compute[incr c_compute] } + ! { dg-note {variable 'dt_parm\.[0-9]+' declared in block isn't candidate for adjusting OpenACC privatization level: artificial} {} { target *-*-* } l_compute$c_compute } + write (0, '("The answer is ", I2)') var +!$acc end parallel + +end program main diff --git a/libgomp/testsuite/libgomp.oacc-fortran/print-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/print-1.f90 index d2f89d915f8..00f5c634a20 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/print-1.f90 +++ b/libgomp/testsuite/libgomp.oacc-fortran/print-1.f90 @@ -3,8 +3,8 @@ ! { dg-do run } ! { dg-output "The answer is 42(\n|\r\n|\r)+" } -! Separate file 'print-1-nvptx.f90' for nvptx offloading. -! { dg-skip-if "separate file" { offload_target_nvptx } } +! See 'print-1-nvptx.f90' regarding the nvptx offloading XFAIL. +! { dg-xfail-run-if TODO { openacc_nvidia_accel_selected } } ! { dg-additional-options "-fopt-info-note-omp" } ! { dg-additional-options "-foffload=-fopt-info-note-omp" } diff --git a/libgomp/testsuite/libgomp.oacc-fortran/stop-1.f b/libgomp/testsuite/libgomp.oacc-fortran/stop-1.f index 2c00d2e5bf8..590b3c97da4 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/stop-1.f +++ b/libgomp/testsuite/libgomp.oacc-fortran/stop-1.f @@ -16,11 +16,16 @@ END PROGRAM MAIN ! { dg-output "CheCKpOInT(\n|\r\n|\r)+" } -! PR85463. The "minimal" libgfortran implementation used with nvptx + +! { dg-output "" } +! +! PR85463. The 'exit' implementation used with nvptx ! offloading is a little bit different. ! { dg-output "libgomp: cuStreamSynchronize error.*" { target openacc_nvidia_accel_selected } } + ! { dg-output "$" } + ! PR85463. STOP with code zero (as implied here) should actually -! terminate the process normally, but doesn't in the "minimal" -! libgfortran implementation used with nvptx offloading. -! { dg-shouldfail "" { openacc_nvidia_accel_selected } } +! terminate the process normally, but doesn't with the 'exit' +! implementation used with nvptx offloading. +! { dg-shouldfail PR85463 { openacc_nvidia_accel_selected } } diff --git a/libgomp/testsuite/libgomp.oacc-fortran/stop-2-nvptx.f b/libgomp/testsuite/libgomp.oacc-fortran/stop-2-nvptx.f new file mode 100644 index 00000000000..3c8b45c102f --- /dev/null +++ b/libgomp/testsuite/libgomp.oacc-fortran/stop-2-nvptx.f @@ -0,0 +1,36 @@ +! 'stop-2.f' nvptx offloading variant + +! { dg-do run { target openacc_nvidia_accel_selected } } +! +! The PTX JIT doesn't understand the 'STOP' call graph, and therefore: +! warning : Stack size for entry function 'main$_omp_fn$0' cannot be statically determined +! Running with default 1024-bytes GPU thread stack size overflows the stack, +! so raise it to an arbitrarily higher value: +! { dg-set-target-env-var GOMP_NVPTX_NATIVE_GPU_THREAD_STACK_SIZE 3333 } + + PROGRAM MAIN + IMPLICIT NONE + +! Initialize before the checkpoint, in case this produces any output. +!$ACC PARALLEL +!$ACC END PARALLEL + + PRINT *, "CheCKpOInT" +!$ACC PARALLEL + STOP 35 +!$ACC END PARALLEL + PRINT *, "WrONg WAy" + + END PROGRAM MAIN + +! { dg-output "CheCKpOInT(\n|\r\n|\r)+" } + +! { dg-output "STOP 35(\n|\r\n|\r)+" } +! +! PR85463. The 'exit' implementation used with nvptx +! offloading is a little bit different. +! { dg-output "libgomp: cuStreamSynchronize error.*" { target openacc_nvidia_accel_selected } } + +! { dg-output "$" } + +! { dg-shouldfail "" } diff --git a/libgomp/testsuite/libgomp.oacc-fortran/stop-2.f b/libgomp/testsuite/libgomp.oacc-fortran/stop-2.f index adade54557c..e08297eda5d 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/stop-2.f +++ b/libgomp/testsuite/libgomp.oacc-fortran/stop-2.f @@ -16,9 +16,14 @@ END PROGRAM MAIN ! { dg-output "CheCKpOInT(\n|\r\n|\r)+" } -! { dg-output "STOP 35(\n|\r\n|\r)+" } -! PR85463. The "minimal" libgfortran implementation used with nvptx + +! See 'stop-2-nvptx.f' regarding the nvptx offloading XFAIL. +! { dg-output "STOP 35(\n|\r\n|\r)+" { xfail openacc_nvidia_accel_selected } } +! +! PR85463. The 'exit' implementation used with nvptx ! offloading is a little bit different. ! { dg-output "libgomp: cuStreamSynchronize error.*" { target openacc_nvidia_accel_selected } } + ! { dg-output "$" } + ! { dg-shouldfail "" } diff --git a/libgomp/testsuite/libgomp.oacc-fortran/stop-3.f b/libgomp/testsuite/libgomp.oacc-fortran/stop-3.f index 157e369d4e7..b28989895b5 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/stop-3.f +++ b/libgomp/testsuite/libgomp.oacc-fortran/stop-3.f @@ -16,12 +16,16 @@ END PROGRAM MAIN ! { dg-output "CheCKpOInT(\n|\r\n|\r)+" } + ! { dg-output "STOP SiGN(\n|\r\n|\r)+" } -! PR85463. The "minimal" libgfortran implementation used with nvptx +! +! PR85463. The 'exit' implementation used with nvptx ! offloading is a little bit different. ! { dg-output "libgomp: cuStreamSynchronize error.*" { target openacc_nvidia_accel_selected } } + ! { dg-output "$" } + ! PR85463. STOP with code zero (as implied here) should actually -! terminate the process normally, but doesn't in the "minimal" -! libgfortran implementation used with nvptx offloading. -! { dg-shouldfail "" { openacc_nvidia_accel_selected } } +! terminate the process normally, but doesn't with the 'exit' +! implementation used with nvptx offloading. +! { dg-shouldfail PR85463 { openacc_nvidia_accel_selected } } diff --git a/libitm/config/aarch64/sjlj.S b/libitm/config/aarch64/sjlj.S index dd844e8c9d8..6b248f7c040 100644 --- a/libitm/config/aarch64/sjlj.S +++ b/libitm/config/aarch64/sjlj.S @@ -57,19 +57,10 @@ .text .align 2 -#if __ELF__ .global _ITM_beginTransaction .type _ITM_beginTransaction, %function _ITM_beginTransaction: - -#elif __MACH__ - .global __ITM_beginTransaction - -__ITM_beginTransaction: - -#endif - cfi_startproc CFI_PAC_KEY PAC_AND_BTI @@ -93,13 +84,8 @@ __ITM_beginTransaction: /* Invoke GTM_begin_transaction with the struct we just built. */ mov x1, sp -#if __ELF__ bl GTM_begin_transaction -#elif __MACH__ - bl _GTM_begin_transaction -#else -#error "unexpected object format" -#endif + /* Return; we don't need to restore any of the call-saved regs. */ ldp x29, x30, [sp], 11*16 cfi_adjust_cfa_offset(-11*16) @@ -109,23 +95,14 @@ __ITM_beginTransaction: CFI_PAC_TOGGLE ret cfi_endproc -#if __ELF__ .size _ITM_beginTransaction, . - _ITM_beginTransaction -#endif .align 2 -#if __ELF__ .global GTM_longjmp .hidden GTM_longjmp .type GTM_longjmp, %function GTM_longjmp: - -#elif __MACH__ - .private_extern _GTM_longjmp - -_GTM_longjmp: -#endif /* The first parameter becomes the return value (x0). The third parameter is ignored for now. */ cfi_startproc @@ -149,9 +126,7 @@ _GTM_longjmp: CFI_PAC_TOGGLE br x30 cfi_endproc -#if __ELF__ .size GTM_longjmp, . - GTM_longjmp -#endif /* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code. */ #define FEATURE_1_AND 0xc0000000 diff --git a/libitm/configure.tgt b/libitm/configure.tgt index 6fad8534372..a8276f05d9b 100644 --- a/libitm/configure.tgt +++ b/libitm/configure.tgt @@ -50,7 +50,7 @@ fi # Map the target cpu to an ARCH sub-directory. At the same time, # work out any special compilation flags as necessary. case "${target_cpu}" in - aarch64* | arm64*) ARCH=aarch64 ;; + aarch64*) ARCH=aarch64 ;; alpha*) ARCH=alpha ;; rs6000 | powerpc*) XCFLAGS="${XCFLAGS} -mhtm" diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d index 2b70a8cca2b..cb8df47507f 100644 --- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d +++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d @@ -30,13 +30,8 @@ module core.internal.gc.impl.conservative.gc; /***************************************************/ version = COLLECT_PARALLEL; // parallel scanning -version (GNU) -{ - version (linux) - version = COLLECT_FORK; // uses clone(), battle tested and reliable -} -else version (Posix) - version = COLLECT_FORK; +version (Posix) + version = COLLECT_FORK; import core.internal.gc.bits; import core.internal.gc.os; diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 538fb6b82b2..acbd7165d5f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,91 @@ +2024-06-06 Alexandre Oliva + + * include/bits/c++config (_GLIBCXX_CLANG): Define or undefine. + * include/bits/locale_facets_nonio.tcc: Test for it. + * include/bits/stl_bvector.h: Likewise. + * include/c_compatibility/stdatomic.h: Likewise. + * include/experimental/bits/simd.h: Likewise. + * include/experimental/bits/simd_builtin.h: Likewise. + * include/experimental/bits/simd_detail.h: Likewise. + * include/experimental/bits/simd_x86.h: Likewise. + * include/experimental/simd: Likewise. + * include/std/complex: Likewise. + * include/std/ranges: Likewise. + * include/std/variant: Likewise. + * include/pstl/pstl_config.h: Likewise. + +2024-06-05 Gerald Pfeifer + + * doc/xml/faq.xml: Move gcc.gnu.org to https. + * doc/html/faq.html: Regenerate. + +2024-06-04 Jonathan Wakely + + PR libstdc++/115335 + * include/std/span (span::at): Guard with feature test macro. + +2024-06-04 Matthias Kretz + + PR libstdc++/115308 + * include/experimental/bits/simd.h (__int_for_sizeof): Remove + special cases for __clang__. + (_SimdWrapper): Change constructor overload set to allow + conversion from vector types with integral conversions via bit + reinterpretation. + +2024-06-03 Jonathan Wakely + + * include/std/stacktrace (basic_stacktrace::_Impl::_M_allocate): + Use __detail::__get_temporary_buffer. + (basic_stacktrace::_Impl::_M_deallocate): Use + __detail::__return_temporary_buffer. + +2024-06-03 Jonathan Wakely + + PR libstdc++/105258 + * include/bits/stl_tempbuf.h (__detail::__get_temporary_buffer): + New function to do allocation for get_temporary_buffer, with + extended alignment support. + (__detail::__return_temporary_buffer): Support extended + alignment. + (get_temporary_buffer): Use __get_temporary_buffer. + (return_temporary_buffer): Support extended alignment. Add + deprecated attribute. + (_Temporary_buffer): Move allocation and deallocation into a + subobject and remove try-catch block in constructor. + (__uninitialized_construct_buf): Use argument deduction for + value type. + * testsuite/20_util/temporary_buffer.cc: Add dg-warning for new + deprecated warning. + * testsuite/25_algorithms/stable_sort/overaligned.cc: New test. + +2024-06-03 François Dumont + + PR libstdc++/109849 + * include/bits/vector.tcc + (std::vector<>::_M_range_insert(iterator, _FwdIt, _FwdIt, + forward_iterator_tag))[__cplusplus < 201103L]: Add __builtin_unreachable + expression to tell the compiler that the allocated buffer is large enough to + receive current elements plus the elements of the range to insert. + +2024-06-03 Jonathan Wakely + + * include/std/string_view (starts_with(basic_string_view)): + Compare lengths first and then call traits_type::compare + directly. + +2024-06-02 Gerald Pfeifer + + * doc/xml/api.xml: Move gcc.gnu.org links to https. + * doc/html/api.html: Regenerate. + +2024-06-01 Jonathan Wakely + + PR libstdc++/115269 + * doc/xml/manual/using.xml: Replace link to gcc-4.3.2 docs. + Replace list of -std=... options with a single entry for -std. + * doc/html/manual/using.html: Regenerate. + 2024-05-30 Alexandre Oliva * configure.ac [*-*-rtems*]: Set chdir, chmod and mkdir as diff --git a/libstdc++-v3/doc/html/api.html b/libstdc++-v3/doc/html/api.html index fc27b5f98ae..b494d91f9af 100644 --- a/libstdc++-v3/doc/html/api.html +++ b/libstdc++-v3/doc/html/api.html @@ -21,9 +21,9 @@ particular include file, looking at inheritance diagrams, etc.

The API documentation, rendered into HTML, can be viewed online - for each GCC release + for each GCC release and - + for the main development tree (see the date on the first page). @@ -32,10 +32,10 @@ gcc.gnu.org site in a directory located at <URL:https://gcc.gnu.org/pub/gcc/libstdc++/doxygen/>. You will almost certainly need to use one of the - mirror sites to download + mirror sites to download the tarball. After unpacking, simply load libstdc++-html-*/index.html into a browser.

In addition, a rendered set of man pages are available in the same location specified above. Start with C++Intro(3). -

\ No newline at end of file +

diff --git a/libstdc++-v3/doc/html/faq.html b/libstdc++-v3/doc/html/faq.html index e84e455c4e9..dcb94ba67dc 100644 --- a/libstdc++-v3/doc/html/faq.html +++ b/libstdc++-v3/doc/html/faq.html @@ -268,7 +268,7 @@ Libstdc++ comes with its own validation testsuite, which includes conformance testing, regression testing, ABI testing, and performance testing. Please consult the - testing + testing documentation for GCC and Testing in the libstdc++ manual for more details. @@ -458,14 +458,14 @@ g++ -E -dM -x c++ /dev/null to display a list of predefined macros for any particular installation.

This has been discussed on the mailing lists - quite a bit. + quite a bit.

This method is something of a wart. We'd like to find a cleaner solution, but nobody yet has contributed the time.

4.4.

Mac OS X ctype.h is broken! How can I fix it?

Note

This answer is old and probably no longer be relevant.

This was a long-standing bug in the OS X support. Fortunately, the - patch + patch was quite simple, and well-known.

4.5.

Threading is broken on i386? @@ -636,7 +636,7 @@ <iterator> header), then you will suddenly be faced with huge numbers of ambiguity errors. This was discussed on the mailing list; Nathan Myers - sums + sums things up here. The collisions with vector/string iterator types have been fixed for 3.1.

6.4.

@@ -729,7 +729,7 @@

If you have found a bug in the library and you think you have a working fix, then send it in! The main GCC site has a page - on submitting + on submitting patches that covers the procedure, but for libstdc++ you should also send the patch to our mailing list in addition to the GCC patches mailing list. The libstdc++ diff --git a/libstdc++-v3/doc/html/manual/using.html b/libstdc++-v3/doc/html/manual/using.html index d663660b3a4..fcd1b96de0d 100644 --- a/libstdc++-v3/doc/html/manual/using.html +++ b/libstdc++-v3/doc/html/manual/using.html @@ -4,7 +4,7 @@  Next


Chapter 3. Using

Command Options

The set of features available in the GNU C++ library is shaped by - several GCC + several GCC Command Options. Options that impact libstdc++ are enumerated and detailed in the table below.

@@ -14,9 +14,11 @@ g++ -std=gnu++17 since GCC 11, and g++ -std=gnu++14 in GCC 6, 7, 8, 9, and 10, and g++ -std=gnu++98 for older releases. -

Table 3.1. C++ Command Options

Option FlagsDescription
-std=c++98 or -std=c++03 - Use the 1998 ISO C++ standard plus amendments.
-std=gnu++98 or -std=gnu++03 - As directly above, with GNU extensions.
-std=c++11Use the 2011 ISO C++ standard.
-std=gnu++11As directly above, with GNU extensions.
-std=c++14Use the 2014 ISO C++ standard.
-std=gnu++14As directly above, with GNU extensions.
+

Table 3.1. C++ Command Options

- -std=c++98 or -std=c++03 + -std - Use the 1998 ISO C++ standard plus amendments. - - - - -std=gnu++98 or -std=gnu++03 + + Select the C++ standard, and whether to use the base standard + or GNU dialect. - As directly above, with GNU extensions. - - - - -std=c++11 - Use the 2011 ISO C++ standard. - - - - -std=gnu++11 - As directly above, with GNU extensions. - - - - -std=c++14 - Use the 2014 ISO C++ standard. - - - - -std=gnu++14 - As directly above, with GNU extensions. diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index b57e3f338e9..6dca2d9467a 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -481,9 +481,20 @@ _GLIBCXX_END_NAMESPACE_VERSION // Define if compatibility should be provided for -mlong-double-64. #undef _GLIBCXX_LONG_DOUBLE_COMPAT +// Use an alternate macro to test for clang, so as to provide an easy +// workaround for systems (such as vxworks) whose headers require +// __clang__ to be defined, even when compiling with GCC. +#if !defined _GLIBCXX_CLANG && defined __clang__ +# define _GLIBCXX_CLANG __clang__ +// Turn -D_GLIBCXX_CLANG=0 into -U_GLIBCXX_CLANG, so that +// _GLIBCXX_CLANG can be tested as defined, just like __clang__. +#elif !_GLIBCXX_CLANG +# undef _GLIBCXX_CLANG +#endif + // Define if compatibility should be provided for alternative 128-bit long // double formats. Not possible for Clang until __ibm128 is supported. -#ifndef __clang__ +#ifndef _GLIBCXX_CLANG #undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT #endif diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc index 8f67be5a614..72136f42f08 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc +++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc @@ -1465,7 +1465,7 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 ctype<_CharT> const& __ctype = use_facet >(__loc); __err = ios_base::goodbit; bool __use_state = false; -#if __GNUC__ >= 5 && !defined(__clang__) +#if __GNUC__ >= 5 && !defined(_GLIBCXX_CLANG) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpmf-conversions" // Nasty hack. The C++ standard mandates that get invokes the do_get diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index 6c65001cb74..ca67feecca3 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -200,36 +200,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; +#ifndef __glibcxx_to_address // C++ < 20 template + [[__gnu__::__always_inline__]] constexpr _Tp* __to_address(_Tp* __ptr) noexcept { - static_assert(!std::is_function<_Tp>::value, "not a function pointer"); + static_assert(!std::is_function<_Tp>::value, "std::to_address argument " + "must not be a function pointer"); return __ptr; } -#ifndef __glibcxx_to_address // C++ < 20 template constexpr typename std::pointer_traits<_Ptr>::element_type* __to_address(const _Ptr& __ptr) { return std::__to_address(__ptr.operator->()); } #else - template - constexpr auto - __to_address(const _Ptr& __ptr) noexcept - -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) - { return std::pointer_traits<_Ptr>::to_address(__ptr); } - - template - constexpr auto - __to_address(const _Ptr& __ptr, _None...) noexcept - { - if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>) - return std::__to_address(__ptr.base().operator->()); - else - return std::__to_address(__ptr.operator->()); - } - /** * @brief Obtain address referenced by a pointer to an object * @param __ptr A pointer to an object @@ -237,9 +223,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @ingroup pointer_abstractions */ template + [[__gnu__::__always_inline__]] constexpr _Tp* to_address(_Tp* __ptr) noexcept - { return std::__to_address(__ptr); } + { + static_assert(!is_function_v<_Tp>, "std::to_address argument " + "must not be a function pointer"); + return __ptr; + } /** * @brief Obtain address referenced by a pointer to an object @@ -251,7 +242,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template constexpr auto to_address(const _Ptr& __ptr) noexcept - { return std::__to_address(__ptr); } + { + if constexpr (requires { pointer_traits<_Ptr>::to_address(__ptr); }) + return pointer_traits<_Ptr>::to_address(__ptr); + else if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>) + return std::to_address(__ptr.base().operator->()); + else + return std::to_address(__ptr.operator->()); + } + + /// @cond undocumented + /// Compatibility for use in code that is also compiled as pre-C++20. + template + [[__gnu__::__always_inline__]] + constexpr auto + __to_address(const _Ptr& __ptr) noexcept + { return std::to_address(__ptr); } + /// @endcond #endif // __glibcxx_to_address _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index e26a73a27d6..e1f00838818 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -38,6 +38,7 @@ #include // ranges::begin, ranges::range etc. #include // __invoke #include // __is_byte +#include // __memcmp #if __cpp_lib_concepts namespace std _GLIBCXX_VISIBILITY(default) diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index d567e26f4e4..52153cadf8f 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -185,7 +185,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_assume_normalized() const { -#if __has_attribute(__assume__) && !defined(__clang__) +#if __has_attribute(__assume__) && !defined(_GLIBCXX_CLANG) unsigned int __ofst = _M_offset; __attribute__ ((__assume__ (__ofst < unsigned(_S_word_bit)))); #endif diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h b/libstdc++-v3/include/bits/stl_tempbuf.h index 77b121460f9..fa03fd27704 100644 --- a/libstdc++-v3/include/bits/stl_tempbuf.h +++ b/libstdc++-v3/include/bits/stl_tempbuf.h @@ -66,19 +66,58 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION +#if __has_builtin(__builtin_operator_new) >= 201802L +# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new +# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete +#else +# define _GLIBCXX_OPERATOR_NEW ::operator new +# define _GLIBCXX_OPERATOR_DELETE ::operator delete +#endif + namespace __detail { + // Equivalent to std::get_temporary_buffer but won't return a smaller size. + // It either returns a buffer of __len elements, or a null pointer. + template + inline _Tp* + __get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOTHROW + { + if (__builtin_expect(__len > (size_t(-1) / sizeof(_Tp)), 0)) + return 0; + +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + return (_Tp*) _GLIBCXX_OPERATOR_NEW(__len * sizeof(_Tp), + align_val_t(alignof(_Tp)), + nothrow_t()); +#endif + return (_Tp*) _GLIBCXX_OPERATOR_NEW(__len * sizeof(_Tp), nothrow_t()); + } + + // Equivalent to std::return_temporary_buffer but with a size argument. + // The size is the number of elements, not the number of bytes. template inline void __return_temporary_buffer(_Tp* __p, size_t __len __attribute__((__unused__))) { #if __cpp_sized_deallocation - ::operator delete(__p, __len * sizeof(_Tp)); +# define _GLIBCXX_SIZED_DEALLOC(T, p, n) (p), (n) * sizeof(T) #else - ::operator delete(__p); +# define _GLIBCXX_SIZED_DEALLOC(T, p, n) (p) #endif + +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(_Tp, __p, __len), + align_val_t(alignof(_Tp))); + return; + } +#endif + _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(_Tp, __p, __len)); } +#undef _GLIBCXX_SIZED_DEALLOC } /** @@ -90,7 +129,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * This function tries to obtain storage for @c __len adjacent Tp * objects. The objects themselves are not constructed, of course. - * A pair<> is returned containing the buffer s address and + * A pair<> is returned containing the buffer's address and * capacity (in the units of sizeof(_Tp)), or a pair of 0 values if * no storage can be obtained. Note that the capacity obtained * may be less than that requested if the memory is unavailable; @@ -110,13 +149,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION while (__len > 0) { - _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp), - std::nothrow)); - if (__tmp != 0) - return std::pair<_Tp*, ptrdiff_t>(__tmp, __len); + if (_Tp* __tmp = __detail::__get_temporary_buffer<_Tp>(__len)) + return pair<_Tp*, ptrdiff_t>(__tmp, __len); __len = __len == 1 ? 0 : ((__len + 1) / 2); } - return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0); + return pair<_Tp*, ptrdiff_t>(); } /** @@ -127,9 +164,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * Frees the memory pointed to by __p. */ template + _GLIBCXX17_DEPRECATED inline void return_temporary_buffer(_Tp* __p) - { ::operator delete(__p); } + { +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + _GLIBCXX_OPERATOR_DELETE(__p, align_val_t(alignof(_Tp))); + else +#endif + _GLIBCXX_OPERATOR_DELETE(__p); + } + +#undef _GLIBCXX_OPERATOR_DELETE +#undef _GLIBCXX_OPERATOR_NEW /** * This class is used in two places: stl_algo.h and ext/memory, @@ -150,14 +198,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION protected: size_type _M_original_len; - size_type _M_len; - pointer _M_buffer; + struct _Impl + { + explicit + _Impl(ptrdiff_t __original_len) + { + pair __p( + std::get_temporary_buffer(__original_len)); + _M_len = __p.second; + _M_buffer = __p.first; + } + + ~_Impl() + { std::__detail::__return_temporary_buffer(_M_buffer, _M_len); } + + size_type _M_len; + pointer _M_buffer; + } _M_impl; public: /// As per Table mumble. size_type size() const - { return _M_len; } + { return _M_impl._M_len; } /// Returns the size requested by the constructor; may be >size(). size_type @@ -167,12 +230,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// As per Table mumble. iterator begin() - { return _M_buffer; } + { return _M_impl._M_buffer; } /// As per Table mumble. iterator end() - { return _M_buffer + _M_len; } + { return _M_impl._M_buffer + _M_impl._M_len; } /** * Constructs a temporary buffer of a size somewhere between @@ -181,10 +244,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Temporary_buffer(_ForwardIterator __seed, size_type __original_len); ~_Temporary_buffer() - { - std::_Destroy(_M_buffer, _M_buffer + _M_len); - std::__detail::__return_temporary_buffer(_M_buffer, _M_len); - } + { std::_Destroy(_M_impl._M_buffer, _M_impl._M_buffer + _M_impl._M_len); } private: // Disable copy constructor and assignment operator. @@ -203,7 +263,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __ucr(_Pointer __first, _Pointer __last, _ForwardIterator __seed) { - if (__first == __last) + if (__builtin_expect(__first == __last, 0)) return; _Pointer __cur = __first; @@ -243,17 +303,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // the same value when the algorithm finishes, unless one of the // constructions throws. // - // Requirements: _Pointer::value_type(_Tp&&) is valid. - template + // Requirements: + // _Tp is move constructible and constructible from std::move(*__seed). + template inline void - __uninitialized_construct_buf(_Pointer __first, _Pointer __last, + __uninitialized_construct_buf(_Tp* __first, _Tp* __last, _ForwardIterator __seed) { - typedef typename std::iterator_traits<_Pointer>::value_type - _ValueType; - std::__uninitialized_construct_buf_dispatch< - __has_trivial_constructor(_ValueType)>:: + __has_trivial_constructor(_Tp)>:: __ucr(__first, __last, __seed); } @@ -262,26 +320,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template _Temporary_buffer<_ForwardIterator, _Tp>:: _Temporary_buffer(_ForwardIterator __seed, size_type __original_len) - : _M_original_len(__original_len), _M_len(0), _M_buffer(0) + : _M_original_len(__original_len), _M_impl(__original_len) { - std::pair __p( - std::get_temporary_buffer(_M_original_len)); - - if (__p.first) - { - __try - { - std::__uninitialized_construct_buf(__p.first, __p.first + __p.second, - __seed); - _M_buffer = __p.first; - _M_len = __p.second; - } - __catch(...) - { - std::__detail::__return_temporary_buffer(__p.first, __p.second); - __throw_exception_again; - } - } + std::__uninitialized_construct_buf(begin(), end(), __seed); } #pragma GCC diagnostic pop diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index 36b27dce7b9..c500aab9e56 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -933,6 +933,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const size_type __len = _M_check_len(__n, "vector::_M_range_insert"); +#if __cplusplus < 201103LL + if (__len < (__n + (__old_start - __old_finish))) + __builtin_unreachable(); +#endif + pointer __new_start(this->_M_allocate(__len)); pointer __new_finish(__new_start); __try diff --git a/libstdc++-v3/include/c_compatibility/stdatomic.h b/libstdc++-v3/include/c_compatibility/stdatomic.h index 52daa16c9b1..5403b52a036 100644 --- a/libstdc++-v3/include/c_compatibility/stdatomic.h +++ b/libstdc++-v3/include/c_compatibility/stdatomic.h @@ -125,7 +125,7 @@ using std::atomic_flag_clear_explicit; using std::atomic_thread_fence; using std::atomic_signal_fence; -#elif defined __clang__ +#elif defined _GLIBCXX_CLANG # include_next #endif // __cpp_lib_stdatomic_h #endif // _GLIBCXX_STDATOMIC_H diff --git a/libstdc++-v3/include/experimental/bits/simd.h b/libstdc++-v3/include/experimental/bits/simd.h index 7c524625719..ca1cf181482 100644 --- a/libstdc++-v3/include/experimental/bits/simd.h +++ b/libstdc++-v3/include/experimental/bits/simd.h @@ -606,19 +606,12 @@ template static_assert(_Bytes > 0); if constexpr (_Bytes == sizeof(int)) return int(); - #ifdef __clang__ - else if constexpr (_Bytes == sizeof(char)) - return char(); - #else else if constexpr (_Bytes == sizeof(_SChar)) return _SChar(); - #endif else if constexpr (_Bytes == sizeof(short)) return short(); - #ifndef __clang__ else if constexpr (_Bytes == sizeof(long)) return long(); - #endif else if constexpr (_Bytes == sizeof(_LLong)) return _LLong(); #ifdef __SIZEOF_INT128__ @@ -1720,7 +1713,7 @@ template __builtin_memcpy(&__r, &__v, sizeof(_To)); return __r; } -#if _GLIBCXX_SIMD_X86INTRIN && !defined __clang__ +#if _GLIBCXX_SIMD_X86INTRIN && !defined _GLIBCXX_CLANG else if constexpr (__have_avx && sizeof(_From) == 16 && sizeof(_To) == 32) return reinterpret_cast<_To>(__builtin_ia32_ps256_ps( reinterpret_cast<__vector_type_t>(__v))); @@ -1975,7 +1968,7 @@ template // }}} // __andnot{{{ -#if _GLIBCXX_SIMD_X86INTRIN && !defined __clang__ +#if _GLIBCXX_SIMD_X86INTRIN && !defined _GLIBCXX_CLANG static constexpr struct { _GLIBCXX_SIMD_INTRINSIC __v4sf @@ -2035,7 +2028,7 @@ static constexpr struct operator()(__v8di __a, __v8di __b) const noexcept { return _mm512_andnot_si512(__a, __b); } } _S_x86_andnot; -#endif // _GLIBCXX_SIMD_X86INTRIN && !__clang__ +#endif // _GLIBCXX_SIMD_X86INTRIN && !_GLIBCXX_CLANG template _GLIBCXX_SIMD_INTRINSIC constexpr _TW @@ -2046,7 +2039,7 @@ template using _TVT = conditional_t<__is_simd_wrapper_v<_TW>, _TW, _VectorTraitsImpl<_TW>>; using _Tp = typename _TVT::value_type; -#if _GLIBCXX_SIMD_X86INTRIN && !defined __clang__ +#if _GLIBCXX_SIMD_X86INTRIN && !defined _GLIBCXX_CLANG if constexpr (sizeof(_TW) >= 16) { const auto __ai = __to_intrin(__a); @@ -2095,7 +2088,7 @@ template using _Tp = remove_reference_t()[0])>; using _RV [[maybe_unused]] = __vector_type_t<_Tp, sizeof...(_Is)>; #if __has_builtin(__builtin_shufflevector) -#ifdef __clang__ +#ifdef _GLIBCXX_CLANG // Clang requires _T0 == _T1 if constexpr (sizeof(__x) > sizeof(__y) and _N1 == 1) return __vec_shuffle(__x, _T0{__y[0]}, __seq, __idx_perm); @@ -2747,6 +2740,8 @@ template // }}} // _SimdWrapper{{{ +struct _DisabledSimdWrapper; + template struct _SimdWrapper< _Tp, _Width, @@ -2756,16 +2751,17 @@ template == sizeof(__vector_type_t<_Tp, _Width>), __vector_type_t<_Tp, _Width>> { - using _Base - = _SimdWrapperBase<__has_iec559_behavior<__signaling_NaN, _Tp>::value - && sizeof(_Tp) * _Width - == sizeof(__vector_type_t<_Tp, _Width>), - __vector_type_t<_Tp, _Width>>; + static constexpr bool _S_need_default_init + = __has_iec559_behavior<__signaling_NaN, _Tp>::value + and sizeof(_Tp) * _Width == sizeof(__vector_type_t<_Tp, _Width>); + + using _BuiltinType = __vector_type_t<_Tp, _Width>; + + using _Base = _SimdWrapperBase<_S_need_default_init, _BuiltinType>; static_assert(__is_vectorizable_v<_Tp>); static_assert(_Width >= 2); // 1 doesn't make sense, use _Tp directly then - using _BuiltinType = __vector_type_t<_Tp, _Width>; using value_type = _Tp; static inline constexpr size_t _S_full_size @@ -2801,13 +2797,26 @@ template _GLIBCXX_SIMD_INTRINSIC constexpr _SimdWrapper& operator=(_SimdWrapper&&) = default; - template >, - is_same<_V, __intrinsic_type_t<_Tp, _Width>>>>> + // Convert from exactly matching __vector_type_t + using _SimdWrapperBase<_S_need_default_init, _BuiltinType>::_SimdWrapperBase; + + // Convert from __intrinsic_type_t if __intrinsic_type_t and __vector_type_t differ, otherwise + // this ctor should not exist. Making the argument type unusable is our next best solution. + _GLIBCXX_SIMD_INTRINSIC constexpr + _SimdWrapper(conditional_t>, + _DisabledSimdWrapper, __intrinsic_type_t<_Tp, _Width>> __x) + : _Base(__vector_bitcast<_Tp, _Width>(__x)) {} + + // Convert from different __vector_type_t, but only if bit reinterpretation is a correct + // conversion of the value_type + template , + typename = enable_if_t + and is_integral_v>> _GLIBCXX_SIMD_INTRINSIC constexpr _SimdWrapper(_V __x) - // __vector_bitcast can convert e.g. __m128 to __vector(2) float - : _Base(__vector_bitcast<_Tp, _Width>(__x)) {} + : _Base(reinterpret_cast<_BuiltinType>(__x)) {} template && ...) diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h b/libstdc++-v3/include/experimental/bits/simd_builtin.h index 505f8083794..4abc750cfa1 100644 --- a/libstdc++-v3/include/experimental/bits/simd_builtin.h +++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h @@ -1177,7 +1177,7 @@ struct _CommonImplBuiltin constexpr size_t _Bytes = _ReqBytes == 0 ? sizeof(__x) : _ReqBytes; static_assert(sizeof(__x) >= _Bytes); -#if !defined __clang__ && _GLIBCXX_SIMD_WORKAROUND_PR90424 +#if !defined _GLIBCXX_CLANG && _GLIBCXX_SIMD_WORKAROUND_PR90424 if constexpr (__is_vector_type_v<_TV>) _S_memcpy<_Bytes>(reinterpret_cast(__addr), reinterpret_cast(&__x)); else @@ -2022,7 +2022,7 @@ template return __vector_bitcast(_S_plus_minus(__x4, __y)); } #endif -#if !defined __clang__ && __GCC_IEC_559 == 0 +#if !defined _GLIBCXX_CLANG && __GCC_IEC_559 == 0 if (__builtin_is_constant_evaluated() || (__builtin_constant_p(__x) && __builtin_constant_p(__y))) return (__x + __y) - __y; diff --git a/libstdc++-v3/include/experimental/bits/simd_detail.h b/libstdc++-v3/include/experimental/bits/simd_detail.h index 51e130bd36a..9ddf912a62b 100644 --- a/libstdc++-v3/include/experimental/bits/simd_detail.h +++ b/libstdc++-v3/include/experimental/bits/simd_detail.h @@ -262,7 +262,7 @@ #endif //}}} -#ifdef __clang__ +#ifdef _GLIBCXX_CLANG #define _GLIBCXX_SIMD_NORMAL_MATH #define _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA #else @@ -277,7 +277,7 @@ #define _GLIBCXX_SIMD_IS_UNLIKELY(__x) __builtin_expect(__x, 0) #define _GLIBCXX_SIMD_IS_LIKELY(__x) __builtin_expect(__x, 1) -#if _GLIBCXX_SIMD_HAVE_SVE || __STRICT_ANSI__ || defined __clang__ +#if _GLIBCXX_SIMD_HAVE_SVE || __STRICT_ANSI__ || defined _GLIBCXX_CLANG #define _GLIBCXX_SIMD_CONSTEXPR #define _GLIBCXX_SIMD_USE_CONSTEXPR_API const #else @@ -285,7 +285,7 @@ #define _GLIBCXX_SIMD_USE_CONSTEXPR_API constexpr #endif -#if defined __clang__ +#if defined _GLIBCXX_CLANG #define _GLIBCXX_SIMD_USE_CONSTEXPR const #else #define _GLIBCXX_SIMD_USE_CONSTEXPR constexpr @@ -330,7 +330,7 @@ #endif // integer division not optimized -#ifndef __clang__ +#ifndef _GLIBCXX_CLANG #define _GLIBCXX_SIMD_WORKAROUND_PR90993 1 #endif diff --git a/libstdc++-v3/include/experimental/bits/simd_x86.h b/libstdc++-v3/include/experimental/bits/simd_x86.h index 517c4b4a5be..4ab933b573c 100644 --- a/libstdc++-v3/include/experimental/bits/simd_x86.h +++ b/libstdc++-v3/include/experimental/bits/simd_x86.h @@ -363,7 +363,7 @@ template // }}} -#ifdef __clang__ +#ifdef _GLIBCXX_CLANG template _GLIBCXX_SIMD_INTRINSIC constexpr auto __movm(_Kp __k) noexcept @@ -408,7 +408,7 @@ template else __assert_unreachable<_Tp>(); } -#endif // __clang__ +#endif // _GLIBCXX_CLANG #ifdef _GLIBCXX_SIMD_WORKAROUND_PR85048 #include "simd_x86_conversions.h" @@ -674,7 +674,7 @@ struct _CommonImplX86 : _CommonImplBuiltin using _Tp = typename _VectorTraits<_TV>::value_type; static_assert(sizeof(_TV) >= 16); static_assert(sizeof(_Tp) <= 8); -#ifdef __clang__ +#ifdef _GLIBCXX_CLANG return __movm<_VectorTraits<_TV>::_S_full_size, _Tp>(__k) ? __b : __a; #else using _IntT @@ -3505,9 +3505,9 @@ template // optimize masked unary increment and decrement as masked sub +/-1 constexpr int __pm_one = is_same_v<_Op, __increment> ? -1 : 1; -#ifdef __clang__ +#ifdef _GLIBCXX_CLANG return __movm<_Np, _Tp>(__k._M_data) ? __v._M_data - __pm_one : __v._M_data; -#else // __clang__ +#else // _GLIBCXX_CLANG using _TV = __vector_type_t<_Tp, _Np>; constexpr size_t __bytes = sizeof(__v) < 16 ? 16 : sizeof(__v); constexpr size_t __width = __bytes / sizeof(_Tp); @@ -3561,7 +3561,7 @@ template #undef _GLIBCXX_SIMD_MASK_SUB_512 #undef _GLIBCXX_SIMD_MASK_SUB } -#endif // __clang__ +#endif // _GLIBCXX_CLANG } else return _Base::template _S_masked_unary<_Op>(__k, __v); diff --git a/libstdc++-v3/include/experimental/simd b/libstdc++-v3/include/experimental/simd index f45ad4ed2e6..d2d081e0d1a 100644 --- a/libstdc++-v3/include/experimental/simd +++ b/libstdc++-v3/include/experimental/simd @@ -59,7 +59,7 @@ #pragma GCC diagnostic push // Many [[gnu::vector_size(N)]] types might lead to a -Wpsabi warning which is // irrelevant as those functions never appear on ABI borders -#ifndef __clang__ +#ifndef _GLIBCXX_CLANG #pragma GCC diagnostic ignored "-Wpsabi" #endif diff --git a/libstdc++-v3/include/pstl/pstl_config.h b/libstdc++-v3/include/pstl/pstl_config.h index ccb9dd32838..7157a8a492e 100644 --- a/libstdc++-v3/include/pstl/pstl_config.h +++ b/libstdc++-v3/include/pstl/pstl_config.h @@ -53,7 +53,7 @@ // the actual GCC version on the system. #define _PSTL_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#if defined(__clang__) +#if defined(_GLIBCXX_CLANG) // according to clang documentation, version can be vendor specific # define _PSTL_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) #endif @@ -62,7 +62,7 @@ #if (defined(_OPENMP) && _OPENMP >= 201307) || \ (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1600) || \ (!defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900) || \ - defined(__clang__) + defined(_GLIBCXX_CLANG) # define _PSTL_PRAGMA_SIMD _PSTL_PRAGMA(omp simd) # define _PSTL_PRAGMA_DECLARE_SIMD _PSTL_PRAGMA(omp declare simd) # define _PSTL_PRAGMA_SIMD_REDUCTION(PRM) _PSTL_PRAGMA(omp simd reduction(PRM)) diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index 415c735665c..be810b6d05d 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -47,7 +47,7 @@ // Get rid of a macro possibly defined in #undef complex -#ifdef __clang__ +#ifdef _GLIBCXX_CLANG #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wc99-extensions" #endif @@ -2646,7 +2646,7 @@ _GLIBCXX_END_NAMESPACE_VERSION #endif // C++11 -#ifdef __clang__ +#ifdef _GLIBCXX_CLANG #pragma clang diagnostic pop #endif diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index b1e827c9a72..3f335b95a08 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -4687,7 +4687,7 @@ namespace views::__adaptor class zip_view<_Vs...>::_Iterator : public __detail::__zip_view_iter_cat<_Const, _Vs...> { -#ifdef __clang__ // LLVM-61763 workaround +#ifdef _GLIBCXX_CLANG // LLVM-61763 workaround public: #endif tuple>...> _M_current; @@ -4710,7 +4710,7 @@ namespace views::__adaptor return input_iterator_tag{}; } -#ifndef __clang__ // LLVM-61763 workaround +#ifndef _GLIBCXX_CLANG // LLVM-61763 workaround template requires (view<_Ws> && ...) && (sizeof...(_Ws) > 0) && is_object_v<_Fp> && regular_invocable<_Fp&, range_reference_t<_Ws>...> @@ -5387,7 +5387,7 @@ namespace views::__adaptor template class adjacent_view<_Vp, _Nm>::_Iterator { -#ifdef __clang__ // LLVM-61763 workaround +#ifdef _GLIBCXX_CLANG // LLVM-61763 workaround public: #endif using _Base = __detail::__maybe_const_t<_Const, _Vp>; @@ -5430,7 +5430,7 @@ namespace views::__adaptor friend class adjacent_view; -#ifndef __clang__ // LLVM-61763 workaround +#ifndef _GLIBCXX_CLANG // LLVM-61763 workaround template requires view<_Wp> && (_Mm > 0) && is_object_v<_Fp> && regular_invocable<__detail::__unarize<_Fp&, _Mm>, range_reference_t<_Wp>> diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span index 43e9cf82a54..00fc5279152 100644 --- a/libstdc++-v3/include/std/span +++ b/libstdc++-v3/include/std/span @@ -287,6 +287,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_ptr + __idx); } +#if __cpp_lib_span >= 202311L // >= C++26 [[nodiscard]] constexpr reference at(size_type __idx) const @@ -296,6 +297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "of size %zu"), __idx, this->size()); return *(this->_M_ptr + __idx); } +#endif [[nodiscard]] constexpr pointer diff --git a/libstdc++-v3/include/std/stacktrace b/libstdc++-v3/include/std/stacktrace index 962dbed7a41..e0a543920bc 100644 --- a/libstdc++-v3/include/std/stacktrace +++ b/libstdc++-v3/include/std/stacktrace @@ -45,6 +45,7 @@ #include #include #include +#include // __get_temporary_buffer #include namespace std _GLIBCXX_VISIBILITY(default) @@ -545,21 +546,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::min(__size_max, __alloc_max); } -#if __has_builtin(__builtin_operator_new) >= 201802L -# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new -# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete -#else -# define _GLIBCXX_OPERATOR_NEW ::operator new -# define _GLIBCXX_OPERATOR_DELETE ::operator delete -#endif - -#if __cpp_sized_deallocation -# define _GLIBCXX_SIZED_DELETE(T, p, n) \ - _GLIBCXX_OPERATOR_DELETE((p), (n) * sizeof(T)) -#else -# define _GLIBCXX_SIZED_DELETE(T, p, n) _GLIBCXX_OPERATOR_DELETE(p) -#endif - // Precondition: _M_frames == nullptr && __n != 0 pointer _M_allocate(allocator_type& __alloc, size_type __n) noexcept @@ -570,11 +556,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { // For std::allocator we use nothrow-new directly so we // don't need to handle bad_alloc exceptions. - size_t __nb = __n * sizeof(value_type); - void* const __p = _GLIBCXX_OPERATOR_NEW (__nb, nothrow_t{}); + auto __p = __detail::__get_temporary_buffer(__n); if (__p == nullptr) [[unlikely]] return nullptr; - _M_frames = static_cast(__p); + _M_frames = __p; } else { @@ -599,9 +584,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (_M_capacity) { if constexpr (is_same_v>) - _GLIBCXX_SIZED_DELETE(value_type, - static_cast(_M_frames), - _M_capacity); + __detail::__return_temporary_buffer(_M_frames, _M_capacity); else __alloc.deallocate(_M_frames, _M_capacity); _M_frames = nullptr; @@ -609,10 +592,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } -#undef _GLIBCXX_SIZED_DELETE -#undef _GLIBCXX_OPERATOR_DELETE -#undef _GLIBCXX_OPERATOR_NEW - // Precondition: __n <= _M_size void _M_resize(size_type __n, allocator_type& __alloc) noexcept diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index a7c5a126461..740aa9344f0 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -385,7 +385,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION [[nodiscard]] constexpr bool starts_with(basic_string_view __x) const noexcept - { return this->substr(0, __x.size()) == __x; } + { + return _M_len >= __x._M_len + && traits_type::compare(_M_str, __x._M_str, __x._M_len) == 0; + } [[nodiscard]] constexpr bool diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 371cbb90f54..13ea1dd3849 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -1758,11 +1758,6 @@ namespace __detail::__variant }, __rhs); } -#if defined(__clang__) && __clang_major__ <= 7 - public: - using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852 -#endif - private: template friend constexpr decltype(auto) diff --git a/libstdc++-v3/testsuite/20_util/temporary_buffer.cc b/libstdc++-v3/testsuite/20_util/temporary_buffer.cc index 155d19034e5..065739be29d 100644 --- a/libstdc++-v3/testsuite/20_util/temporary_buffer.cc +++ b/libstdc++-v3/testsuite/20_util/temporary_buffer.cc @@ -44,7 +44,7 @@ int main(void) VERIFY( results.first == 0 ); } - std::return_temporary_buffer(results.first); + std::return_temporary_buffer(results.first); // { dg-warning "deprecated" "" { target c++17 } } return 0; } diff --git a/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc b/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc index 7385f0f335c..10e919757bb 100644 --- a/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc +++ b/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc @@ -16,7 +16,7 @@ // . // { dg-do compile { target c++20 } } -// { dg-error "not a function pointer" "" { target *-*-* } 0 } +// { dg-error "must not be a function pointer" "" { target *-*-* } 0 } #include diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_sort/overaligned.cc b/libstdc++-v3/testsuite/25_algorithms/stable_sort/overaligned.cc new file mode 100644 index 00000000000..3c200624617 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/stable_sort/overaligned.cc @@ -0,0 +1,29 @@ +// { dg-do run { target c++17 } } +// PR libstdc++/105258 std::get_temporary_buffer() does not respect alignment + +#include +#include +#include + +struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) Overaligned +{ + ~Overaligned() + { + auto alignment = reinterpret_cast(this); + VERIFY( (alignment % alignof(Overaligned)) == 0 ); + } + + bool operator<(const Overaligned&) const { return false; } +}; + +void +test_pr105258() +{ + Overaligned o[2]; + std::stable_sort(o, o+2); +} + +int main() +{ + test_pr105258(); +}
Option FlagsDescription
-std + + Select the C++ standard, and whether to use the base standard + or GNU dialect. +
-fno-exceptions See exception-free dialect
-fno-rtti diff --git a/libstdc++-v3/doc/xml/api.xml b/libstdc++-v3/doc/xml/api.xml index 1b011aa2e23..9aee3484e27 100644 --- a/libstdc++-v3/doc/xml/api.xml +++ b/libstdc++-v3/doc/xml/api.xml @@ -41,9 +41,9 @@ The API documentation, rendered into HTML, can be viewed online - for each GCC release + for each GCC release and - + for the main development tree (see the date on the first page). @@ -54,7 +54,7 @@ gcc.gnu.org site in a directory located at <URL:https://gcc.gnu.org/pub/gcc/libstdc++/doxygen/>. You will almost certainly need to use one of the - mirror sites to download + mirror sites to download the tarball. After unpacking, simply load libstdc++-html-*/index.html into a browser. diff --git a/libstdc++-v3/doc/xml/faq.xml b/libstdc++-v3/doc/xml/faq.xml index 79edb02bec4..4888fa93ae9 100644 --- a/libstdc++-v3/doc/xml/faq.xml +++ b/libstdc++-v3/doc/xml/faq.xml @@ -313,7 +313,7 @@ Libstdc++ comes with its own validation testsuite, which includes conformance testing, regression testing, ABI testing, and performance testing. Please consult the - testing + testing documentation for GCC and Testing in the libstdc++ manual for more details. @@ -583,7 +583,7 @@ a list of predefined macros for any particular installation. This has been discussed on the mailing lists - quite a bit. + quite a bit. This method is something of a wart. We'd like to find a cleaner solution, but nobody yet has contributed the time. @@ -604,7 +604,7 @@ This was a long-standing bug in the OS X support. Fortunately, the - patch + patch was quite simple, and well-known. @@ -885,7 +885,7 @@ <iterator> header), then you will suddenly be faced with huge numbers of ambiguity errors. This was discussed on the mailing list; Nathan Myers - sums + sums things up here. The collisions with vector/string iterator types have been fixed for 3.1. @@ -1041,7 +1041,7 @@ If you have found a bug in the library and you think you have a working fix, then send it in! The main GCC site has a page - on submitting + on submitting patches that covers the procedure, but for libstdc++ you should also send the patch to our mailing list in addition to the GCC patches mailing list. The libstdc++ diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml index 8ac7e74034c..74321733e8f 100644 --- a/libstdc++-v3/doc/xml/manual/using.xml +++ b/libstdc++-v3/doc/xml/manual/using.xml @@ -7,7 +7,7 @@ The set of features available in the GNU C++ library is shaped by - several GCC + several GCC Command Options. Options that impact libstdc++ are enumerated and detailed in the table below. @@ -37,35 +37,12 @@