Skip to content

Commit

Permalink
take the fast path for Regexp.new with non-default options (#4731)
Browse files Browse the repository at this point in the history
  • Loading branch information
froydnj committed Oct 15, 2021
1 parent 5c0704c commit ab2ddc2
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 8 deletions.
8 changes: 3 additions & 5 deletions ast/desugar/Desugar.cc
Expand Up @@ -1691,7 +1691,7 @@ ExpressionPtr node2TreeImpl(DesugarContext dctx, unique_ptr<parser::Node> what)
result = std::move(send);
},
[&](parser::Regopt *regopt) {
ExpressionPtr acc = MK::Int(loc, 0);
int flags = 0;
for (auto &chr : regopt->opts) {
int flag = 0;
switch (chr) {
Expand All @@ -1714,11 +1714,9 @@ ExpressionPtr node2TreeImpl(DesugarContext dctx, unique_ptr<parser::Node> what)
// The parser already yelled about this
break;
}
if (flag != 0) {
acc = MK::Send1(loc, std::move(acc), core::Names::orOp(), MK::Int(loc, flag));
}
flags |= flag;
}
result = std::move(acc);
result = MK::Int(loc, flags);
},
[&](parser::Return *ret) {
if (ret->exprs.size() > 1) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/IREmitter/Payload.cc
Expand Up @@ -71,7 +71,7 @@ llvm::Value *Payload::doubleToRubyValue(CompilerState &cs, llvm::IRBuilderBase &
llvm::Value *Payload::cPtrToRubyRegexp(CompilerState &cs, llvm::IRBuilderBase &builder, std::string_view str,
int options) {
// all regexp are frozen. We'll allocate it at load time and share it.
string rawName = "rubyRegexpFrozen_" + string(str);
auto rawName = fmt::format("rubyRegexpFrozen_{}_{}", str, options);
auto tp = llvm::Type::getInt64Ty(cs);
auto zero = llvm::ConstantInt::get(cs, llvm::APInt(64, 0));
llvm::Constant *indices[] = {zero};
Expand Down
4 changes: 4 additions & 0 deletions test/testdata/compiler/Regexp.rb
Expand Up @@ -5,5 +5,9 @@
puts (/cat/.match("CAT"))
puts (/cat/i.match("cat"))
puts (/cat/i.match("CAT"))
puts (/cat # Comment/ix.match("CAT"))
puts (/abc # Comment/.match("abc"))
puts (/abc # Comment/x.match("abc"))
puts (/abc.abc/m.match("abc\nabc"))
puts (/abc.abc # Comment/mx.match("abc\nabc"))
puts (/abc.abc # Comment/mxi.match("ABC\nABC"))
118 changes: 118 additions & 0 deletions test/testdata/compiler/regexp_flags.rb
@@ -0,0 +1,118 @@
# frozen_string_literal: true
# typed: true
# compiled: true
# run_filecheck: INITIAL OPT

def noflags(x)
x.match(/pattern/)
end

# INITIAL-LABEL: define i64 @"func_Object#7noflags"(
# INITIAL: load i64, i64* @rubyRegexpFrozen_pattern_0
# INITIAL-LITERAL: }

# OPT-LABEL: define i64 @"func_Object#7noflags"(
# OPT-NOT: ic_new
# OPT: load i64, i64* @rubyRegexpFrozen_pattern_0
# OPT-NOT: ic_new
# OPT-LITERAL: }

def i_flag(x)
x.match(/pattern/i)
end

# INITIAL-LABEL: define i64 @"func_Object#6i_flag"(
# INITIAL: load i64, i64* @rubyRegexpFrozen_pattern_1
# INITIAL-LITERAL: }

# OPT-LABEL: define i64 @"func_Object#6i_flag"(
# OPT-NOT: ic_new
# OPT: load i64, i64* @rubyRegexpFrozen_pattern_1
# OPT-NOT: ic_new
# OPT-LITERAL: }

def ix_flag(x)
x.match(/pattern # Comment/ix)
end

# INITIAL-LABEL: define i64 @"func_Object#7ix_flag"(
# INITIAL: load i64, i64* @"rubyRegexpFrozen_pattern # Comment_3"
# INITIAL-LITERAL: }

# OPT-LABEL: define i64 @"func_Object#7ix_flag"(
# OPT-NOT: ic_new
# OPT: load i64, i64* @"rubyRegexpFrozen_pattern # Comment_3"
# OPT-NOT: ic_new
# OPT-LITERAL: }

def ixm_flag(x)
x.match(/pattern.more # Comment/ixm)
end

# INITIAL-LABEL: define i64 @"func_Object#8ixm_flag"(
# INITIAL: load i64, i64* @"rubyRegexpFrozen_pattern.more # Comment_7"
# INITIAL-LITERAL: }

# OPT-LABEL: define i64 @"func_Object#8ixm_flag"(
# OPT-NOT: ic_new
# OPT: load i64, i64* @"rubyRegexpFrozen_pattern.more # Comment_7"
# OPT-NOT: ic_new
# OPT-LITERAL: }

def x_flag(x)
x.match(/pattern # Comment/x)
end

# INITIAL-LABEL: define i64 @"func_Object#6x_flag"(
# INITIAL: load i64, i64* @"rubyRegexpFrozen_pattern # Comment_2"
# INITIAL-LITERAL: }

# OPT-LABEL: define i64 @"func_Object#6x_flag"(
# OPT-NOT: ic_new
# OPT: load i64, i64* @"rubyRegexpFrozen_pattern # Comment_2"
# OPT-NOT: ic_new
# OPT-LITERAL: }

def xm_flag(x)
x.match(/pattern.still more # Comment/xm)
end

# INITIAL-LABEL: define i64 @"func_Object#7xm_flag"(
# INITIAL: load i64, i64* @"rubyRegexpFrozen_pattern.still more # Comment_6"
# INITIAL-LITERAL: }

# OPT-LABEL: define i64 @"func_Object#7xm_flag"(
# OPT-NOT: ic_new
# OPT: load i64, i64* @"rubyRegexpFrozen_pattern.still more # Comment__6
# OPT-NOT: ic_new
# OPT-LITERAL: }

def m_flag(x)
x.match(/pattern.mflag/m)
end

# INITIAL-LABEL: define i64 @"func_Object#6m_flag"(
# INITIAL: load i64, i64* @rubyRegexpFrozen_pattern.mflag_4
# INITIAL-LITERAL: }

# OPT-LABEL: define i64 @"func_Object#6m_flag"(
# OPT-NOT: ic_new
# OPT: load i64, i64* @rubyRegexpFrozen_pattern.mflag_4
# OPT-NOT: ic_new
# OPT-LITERAL: }

# Run some execution tests, too.
p noflags("pattern")
p noflags("PATTERN")
p i_flag("pattern")
p i_flag("PATTERN")
p ix_flag("pattern")
p ix_flag("PATTERN")
p ixm_flag("pattern\nmore")
p ixm_flag("PATTERN\nMORE")
p x_flag("pattern")
p x_flag("PATTERN")
p xm_flag("pattern\nstillmore")
p xm_flag("PATTERN\nstillmore")
p m_flag("pattern\nmflag")
p m_flag("PATTERN\nmflag")
4 changes: 2 additions & 2 deletions test/testdata/desugar/regexp.rb.desugar-tree.exp
Expand Up @@ -3,9 +3,9 @@ class <emptyTree><<C <root>>> < (::<todo sym>)
begin
::Regexp.new("abc", 0)
<emptyTree>::<C Regexp>.new("abc")
::Regexp.new("abc", 0.|(1))
::Regexp.new("abc", 1)
<emptyTree>::<C Regexp>.new("abc", <emptyTree>::<C Regexp>::<C IGNORECASE>)
::Regexp.new("abc", 0.|(1).|(2).|(4))
::Regexp.new("abc", 7)
<emptyTree>::<C Regexp>.new("abc", 0.|(<emptyTree>::<C Regexp>::<C IGNORECASE>).|(<emptyTree>::<C Regexp>::<C EXTENDED>).|(<emptyTree>::<C Regexp>::<C MULTILINE>))
a = "a"
c = "c"
Expand Down

0 comments on commit ab2ddc2

Please sign in to comment.