[llvm] 68079ef - Teach SimplifyCFG to fold switches into lookup tables in more cases.
Owen Anderson via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 15 15:07:13 PDT 2021
Author: Owen Anderson
Date: 2021-09-15T22:07:08Z
New Revision: 68079ef0eb011c8349e5ae84b95216e5039dbc16
URL: https://github.com/llvm/llvm-project/commit/68079ef0eb011c8349e5ae84b95216e5039dbc16
DIFF: https://github.com/llvm/llvm-project/commit/68079ef0eb011c8349e5ae84b95216e5039dbc16.diff
LOG: Teach SimplifyCFG to fold switches into lookup tables in more cases.
In particular, it couldn't handle cases where lookup table constant
expressions involved bitcasts. This does not seem to come up
frequently in C++, but comes up reasonably often in Rust via
`#[derive(Debug)]`.
Originally reported by pcwalton.
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D109565
Added:
llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-bitcast.ll
llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-gep.ll
Modified:
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 590a961e02d04..2a05dd7f5012a 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -5066,9 +5066,10 @@ static bool ValidLookupTableConstant(Constant *C, const TargetTransformInfo &TTI
return false;
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
- if (!CE->isGEPWithNoNotionalOverIndexing())
- return false;
- if (!ValidLookupTableConstant(CE->getOperand(0), TTI))
+ // Pointer casts and in-bounds GEPs will not prohibit the backend from
+ // materializing the array of constants.
+ Constant *StrippedC = cast<Constant>(CE->stripInBoundsConstantOffsets());
+ if (StrippedC == C || !ValidLookupTableConstant(StrippedC, TTI))
return false;
}
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-bitcast.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-bitcast.ll
new file mode 100644
index 0000000000000..9a567f38a24b4
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-bitcast.ll
@@ -0,0 +1,42 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --scrub-attributes
+; RUN: opt -simplifycfg --switch-to-lookup -S < %s | FileCheck %s
+target triple = "x86_64-unknown-linux-gnu"
+
+ at alloc0 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"A" }>, align 1
+ at alloc1 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"B" }>, align 1
+ at alloc2 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"C" }>, align 1
+
+define { [0 x i8]*, i64 } @switch_to_lookup_bitcast(i8 %0) unnamed_addr {
+; CHECK-LABEL: @switch_to_lookup_bitcast(
+; CHECK-NEXT: start:
+; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x [0 x i8]*], [3 x [0 x i8]*]* @switch.table.switch_to_lookup_bitcast, i32 0, i8 [[TMP0:%.*]]
+; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load [0 x i8]*, [0 x i8]** [[SWITCH_GEP]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { [0 x i8]*, i64 } undef, [0 x i8]* [[SWITCH_LOAD]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { [0 x i8]*, i64 } [[TMP1]], i64 1, 1
+; CHECK-NEXT: ret { [0 x i8]*, i64 } [[TMP2]]
+;
+start:
+ switch i8 %0, label %default [
+ i8 0, label %bb0
+ i8 1, label %bb1
+ i8 2, label %bb2
+ ]
+
+bb0:
+ br label %end
+
+bb1:
+ br label %end
+
+bb2:
+ br label %end
+
+default:
+ unreachable
+
+end:
+ %.sroa.0.0 = phi [0 x i8]* [ bitcast (<{ [1 x i8] }>* @alloc0 to [0 x i8]*), %bb0 ], [ bitcast (<{ [1 x i8] }>* @alloc1 to [0 x i8]*), %bb1 ], [ bitcast (<{ [1 x i8] }>* @alloc2 to [0 x i8]*), %bb2 ]
+ %1 = insertvalue { [0 x i8]*, i64 } undef, [0 x i8]* %.sroa.0.0, 0
+ %2 = insertvalue { [0 x i8]*, i64 } %1, i64 1, 1
+ ret { [0 x i8]*, i64 } %2
+}
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-gep.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-gep.ll
new file mode 100644
index 0000000000000..0bd7ef94a18b1
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch-to-lookup-gep.ll
@@ -0,0 +1,134 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --scrub-attributes
+; RUN: opt -simplifycfg --switch-to-lookup -S < %s | FileCheck %s
+target triple = "x86_64-unknown-linux-gnu"
+
+ at alloc0 = private unnamed_addr constant <{ [2 x i8] }> <{ [2 x i8] c"A1" }>, align 1
+ at alloc1 = private unnamed_addr constant <{ [2 x i8] }> <{ [2 x i8] c"B2" }>, align 1
+ at alloc2 = private unnamed_addr constant <{ [2 x i8] }> <{ [2 x i8] c"C3" }>, align 1
+
+define { i8*, i64 } @switch_to_lookup_gep(i8 %0) unnamed_addr {
+; CHECK-LABEL: @switch_to_lookup_gep(
+; CHECK-NEXT: start:
+; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i8*], [3 x i8*]* @switch.table.switch_to_lookup_gep, i32 0, i8 [[TMP0:%.*]]
+; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i8*, i8** [[SWITCH_GEP]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i8*, i64 } undef, i8* [[SWITCH_LOAD]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { i8*, i64 } [[TMP1]], i64 1, 1
+; CHECK-NEXT: ret { i8*, i64 } [[TMP2]]
+;
+start:
+ switch i8 %0, label %default [
+ i8 0, label %bb0
+ i8 1, label %bb1
+ i8 2, label %bb2
+ ]
+
+bb0:
+ br label %end
+
+bb1:
+ br label %end
+
+bb2:
+ br label %end
+
+default:
+ unreachable
+
+end:
+ %.sroa.0.0 = phi i8* [ getelementptr inbounds (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc0, i32 0, i32 0, i32 1), %bb0 ], [ getelementptr inbounds (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc1, i32 0, i32 0, i32 1), %bb1 ], [ getelementptr inbounds (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc2, i32 0, i32 0, i32 1), %bb2 ]
+ %1 = insertvalue { i8*, i64 } undef, i8* %.sroa.0.0, 0
+ %2 = insertvalue { i8*, i64 } %1, i64 1, 1
+ ret { i8*, i64 } %2
+}
+
+define { i8*, i64 } @switch_to_lookup_gep_oob(i8 %0) unnamed_addr {
+; CHECK-LABEL: @switch_to_lookup_gep_oob(
+; CHECK-NEXT: start:
+; CHECK-NEXT: switch i8 [[TMP0:%.*]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT: i8 0, label [[END:%.*]]
+; CHECK-NEXT: i8 1, label [[BB1:%.*]]
+; CHECK-NEXT: i8 2, label [[BB2:%.*]]
+; CHECK-NEXT: ]
+; CHECK: bb1:
+; CHECK-NEXT: br label [[END]]
+; CHECK: bb2:
+; CHECK-NEXT: br label [[END]]
+; CHECK: default:
+; CHECK-NEXT: unreachable
+; CHECK: end:
+; CHECK-NEXT: [[DOTSROA_0_0:%.*]] = phi i8* [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc1, i32 0, i32 0, i32 4), [[BB1]] ], [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc2, i32 0, i32 0, i32 4), [[BB2]] ], [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc0, i32 0, i32 0, i32 4), [[START:%.*]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i8*, i64 } undef, i8* [[DOTSROA_0_0]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { i8*, i64 } [[TMP1]], i64 1, 1
+; CHECK-NEXT: ret { i8*, i64 } [[TMP2]]
+;
+start:
+ switch i8 %0, label %default [
+ i8 0, label %bb0
+ i8 1, label %bb1
+ i8 2, label %bb2
+ ]
+
+bb0:
+ br label %end
+
+bb1:
+ br label %end
+
+bb2:
+ br label %end
+
+default:
+ unreachable
+
+end:
+ %.sroa.0.0 = phi i8* [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc0, i32 0, i32 0, i32 4), %bb0 ], [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc1, i32 0, i32 0, i32 4), %bb1 ], [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc2, i32 0, i32 0, i32 4), %bb2 ]
+ %1 = insertvalue { i8*, i64 } undef, i8* %.sroa.0.0, 0
+ %2 = insertvalue { i8*, i64 } %1, i64 1, 1
+ ret { i8*, i64 } %2
+}
+
+define { i8*, i64 } @switch_to_lookup_gep_ptrtoint(i8 %0) unnamed_addr {
+; CHECK-LABEL: @switch_to_lookup_gep_ptrtoint(
+; CHECK-NEXT: start:
+; CHECK-NEXT: switch i8 [[TMP0:%.*]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT: i8 0, label [[END:%.*]]
+; CHECK-NEXT: i8 1, label [[BB1:%.*]]
+; CHECK-NEXT: i8 2, label [[BB2:%.*]]
+; CHECK-NEXT: ]
+; CHECK: bb1:
+; CHECK-NEXT: br label [[END]]
+; CHECK: bb2:
+; CHECK-NEXT: br label [[END]]
+; CHECK: default:
+; CHECK-NEXT: unreachable
+; CHECK: end:
+; CHECK-NEXT: [[DOTSROA_0_0:%.*]] = phi i8* [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc1, i32 0, i32 0, i64 ptrtoint (<{ [2 x i8] }>* @alloc0 to i64)), [[BB1]] ], [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc2, i32 0, i32 0, i64 ptrtoint (<{ [2 x i8] }>* @alloc0 to i64)), [[BB2]] ], [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc0, i32 0, i32 0, i64 ptrtoint (<{ [2 x i8] }>* @alloc0 to i64)), [[START:%.*]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i8*, i64 } undef, i8* [[DOTSROA_0_0]], 0
+; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { i8*, i64 } [[TMP1]], i64 1, 1
+; CHECK-NEXT: ret { i8*, i64 } [[TMP2]]
+;
+start:
+ switch i8 %0, label %default [
+ i8 0, label %bb0
+ i8 1, label %bb1
+ i8 2, label %bb2
+ ]
+
+bb0:
+ br label %end
+
+bb1:
+ br label %end
+
+bb2:
+ br label %end
+
+default:
+ unreachable
+
+end:
+ %.sroa.0.0 = phi i8* [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc0, i32 0, i32 0, i64 ptrtoint (<{ [2 x i8] }>* @alloc0 to i64)), %bb0 ], [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc1, i32 0, i32 0, i64 ptrtoint (<{ [2 x i8] }>* @alloc0 to i64)), %bb1 ], [ getelementptr (<{ [2 x i8] }>, <{ [2 x i8] }>* @alloc2, i32 0, i32 0, i64 ptrtoint (<{ [2 x i8] }>* @alloc0 to i64)), %bb2 ]
+ %1 = insertvalue { i8*, i64 } undef, i8* %.sroa.0.0, 0
+ %2 = insertvalue { i8*, i64 } %1, i64 1, 1
+ ret { i8*, i64 } %2
+}
More information about the llvm-commits
mailing list