diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -5066,9 +5066,10 @@ return false; if (ConstantExpr *CE = dyn_cast(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(CE->stripInBoundsConstantOffsets()); + if (StrippedC != C && !ValidLookupTableConstant(StrippedC, TTI)) return false; } diff --git a/llvm/test/Transforms/SimplifyCFG/switch-to-lookup-bitcast.ll b/llvm/test/Transforms/SimplifyCFG/switch-to-lookup-bitcast.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/switch-to-lookup-bitcast.ll @@ -0,0 +1,85 @@ +; 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" + +@alloc25 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"L" }>, align 1 +@alloc26 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"K" }>, align 1 +@alloc27 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"J" }>, align 1 +@alloc28 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"I" }>, align 1 +@alloc29 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"H" }>, align 1 +@alloc30 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"G" }>, align 1 +@alloc31 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"F" }>, align 1 +@alloc32 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"E" }>, align 1 +@alloc33 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"D" }>, align 1 +@alloc34 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"C" }>, align 1 +@alloc35 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"B" }>, align 1 +@alloc36 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"A" }>, 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 [12 x [0 x i8]*], [12 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 %bb2 [ + i8 0, label %bb14 + i8 1, label %bb4 + i8 2, label %bb5 + i8 3, label %bb6 + i8 4, label %bb7 + i8 5, label %bb8 + i8 6, label %bb9 + i8 7, label %bb10 + i8 8, label %bb11 + i8 9, label %bb12 + i8 10, label %bb13 + i8 11, label %bb1 + ] + +bb2: + unreachable + +bb4: + br label %bb14 + +bb5: + br label %bb14 + +bb6: + br label %bb14 + +bb7: + br label %bb14 + +bb8: + br label %bb14 + +bb9: + br label %bb14 + +bb10: + br label %bb14 + +bb11: + br label %bb14 + +bb12: + br label %bb14 + +bb13: + br label %bb14 + +bb1: + br label %bb14 + +bb14: + %.sroa.0.0 = phi [0 x i8]* [ bitcast (<{ [1 x i8] }>* @alloc25 to [0 x i8]*), %bb1 ], [ bitcast (<{ [1 x i8] }>* @alloc26 to [0 x i8]*), %bb13 ], [ bitcast (<{ [1 x i8] }>* @alloc27 to [0 x i8]*), %bb12 ], [ bitcast (<{ [1 x i8] }>* @alloc28 to [0 x i8]*), %bb11 ], [ bitcast (<{ [1 x i8] }>* @alloc29 to [0 x i8]*), %bb10 ], [ bitcast (<{ [1 x i8] }>* @alloc30 to [0 x i8]*), %bb9 ], [ bitcast (<{ [1 x i8] }>* @alloc31 to [0 x i8]*), %bb8 ], [ bitcast (<{ [1 x i8] }>* @alloc32 to [0 x i8]*), %bb7 ], [ bitcast (<{ [1 x i8] }>* @alloc33 to [0 x i8]*), %bb6 ], [ bitcast (<{ [1 x i8] }>* @alloc34 to [0 x i8]*), %bb5 ], [ bitcast (<{ [1 x i8] }>* @alloc35 to [0 x i8]*), %bb4 ], [ bitcast (<{ [1 x i8] }>* @alloc36 to [0 x i8]*), %start ] + %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/switch-to-lookup-gep.ll b/llvm/test/Transforms/SimplifyCFG/switch-to-lookup-gep.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/switch-to-lookup-gep.ll @@ -0,0 +1,85 @@ +; 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" + +@alloc25 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"L" }>, align 1 +@alloc26 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"K" }>, align 1 +@alloc27 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"J" }>, align 1 +@alloc28 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"I" }>, align 1 +@alloc29 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"H" }>, align 1 +@alloc30 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"G" }>, align 1 +@alloc31 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"F" }>, align 1 +@alloc32 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"E" }>, align 1 +@alloc33 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"D" }>, align 1 +@alloc34 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"C" }>, align 1 +@alloc35 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"B" }>, align 1 +@alloc36 = private unnamed_addr constant <{ [1 x i8] }> <{ [1 x i8] c"A" }>, 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 [12 x [0 x i8]*], [12 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 %bb2 [ + i8 0, label %bb14 + i8 1, label %bb4 + i8 2, label %bb5 + i8 3, label %bb6 + i8 4, label %bb7 + i8 5, label %bb8 + i8 6, label %bb9 + i8 7, label %bb10 + i8 8, label %bb11 + i8 9, label %bb12 + i8 10, label %bb13 + i8 11, label %bb1 + ] + +bb2: + unreachable + +bb4: + br label %bb14 + +bb5: + br label %bb14 + +bb6: + br label %bb14 + +bb7: + br label %bb14 + +bb8: + br label %bb14 + +bb9: + br label %bb14 + +bb10: + br label %bb14 + +bb11: + br label %bb14 + +bb12: + br label %bb14 + +bb13: + br label %bb14 + +bb1: + br label %bb14 + +bb14: + %.sroa.0.0 = phi [0 x i8]* [ getelementptr inbounds ([0 x i8], [0 x i8]* bitcast (<{ [1 x i8] }>* @alloc25 to [0 x i8]*), i32 0), %bb1 ], [ bitcast (<{ [1 x i8] }>* @alloc26 to [0 x i8]*), %bb13 ], [ bitcast (<{ [1 x i8] }>* @alloc27 to [0 x i8]*), %bb12 ], [ bitcast (<{ [1 x i8] }>* @alloc28 to [0 x i8]*), %bb11 ], [ bitcast (<{ [1 x i8] }>* @alloc29 to [0 x i8]*), %bb10 ], [ bitcast (<{ [1 x i8] }>* @alloc30 to [0 x i8]*), %bb9 ], [ bitcast (<{ [1 x i8] }>* @alloc31 to [0 x i8]*), %bb8 ], [ bitcast (<{ [1 x i8] }>* @alloc32 to [0 x i8]*), %bb7 ], [ bitcast (<{ [1 x i8] }>* @alloc33 to [0 x i8]*), %bb6 ], [ bitcast (<{ [1 x i8] }>* @alloc34 to [0 x i8]*), %bb5 ], [ bitcast (<{ [1 x i8] }>* @alloc35 to [0 x i8]*), %bb4 ], [ bitcast (<{ [1 x i8] }>* @alloc36 to [0 x i8]*), %start ] + %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 +} +